diff --git a/html/js/network/socketHandlers.js b/html/js/network/socketHandlers.js index 8677666..25b8036 100644 --- a/html/js/network/socketHandlers.js +++ b/html/js/network/socketHandlers.js @@ -515,7 +515,7 @@ const SocketHandlers = { if (won && data.payout && data.payout.amount) { var decimals = (SocketHandlers._cryptoType === 'WOW') ? 11 : 12; var amountFormatted = (data.payout.amount / Math.pow(10, decimals)).toFixed(4); - var currency = SocketHandlers._cryptoType || 'WOW'; + var currency = SocketHandlers._currencyLabel || SocketHandlers._cryptoType || 'WOW'; var multiplierText = data.payout.multiplier ? ' (' + data.payout.multiplier + 'x)' : ''; var treasureText = data.payout.treasure ? ' + Treasure bonus!' : ''; $('#messages').append($('
  • ').html( @@ -608,6 +608,7 @@ const SocketHandlers = { SocketHandlers._paymentsEnabled = !!data.paymentsEnabled; SocketHandlers._smirkEnabled = data.smirkEnabled !== false; // Default to true if not specified SocketHandlers._cryptoType = data.cryptoType || 'WOW'; + SocketHandlers._currencyLabel = data.currencyLabel || data.cryptoType || 'WOW'; // sXMR on stagenet SocketHandlers._explorerTxUrl = data.explorerTxUrl || null; // Initialize Smirk auth if enabled and not already initialized @@ -762,7 +763,7 @@ const SocketHandlers = { : '💳 Payment Required'; parts.push(reusedCopy); const displayAmount = data.humanAmount || data.amountFormatted || data.amount; - parts.push('Amount: ' + displayAmount + ' ' + (data.cryptoType || '')); + parts.push('Amount: ' + displayAmount + ' ' + (data.currencyLabel || SocketHandlers._currencyLabel || data.cryptoType || '')); const shortAddr = data.address.substring(0, 10) + '…' + data.address.slice(-6); parts.push('Address: ' + shortAddr + '' + ' '); diff --git a/html/js/ui/paymentUI.js b/html/js/ui/paymentUI.js index 615101b..1d96d69 100644 --- a/html/js/ui/paymentUI.js +++ b/html/js/ui/paymentUI.js @@ -104,7 +104,9 @@ const PaymentUI = { render: function() { if (!this.config) return; - const currency = this.config.cryptoType || 'WOW'; + // Display label (sXMR on stagenet) — distinct from cryptoType, which formatPrice + // still uses for decimals. + const currency = this.config.currencyLabel || this.config.cryptoType || 'WOW'; const hasCredits = this.userCredits >= (this.config.creditsPerGame || 1); const creditPackages = this.config.creditPackages || []; diff --git a/src/game/gameModeManager.js b/src/game/gameModeManager.js index 452690b..ea14f60 100644 --- a/src/game/gameModeManager.js +++ b/src/game/gameModeManager.js @@ -9,7 +9,9 @@ const { inferCurrencyDecimals: inferCurrencyDecimalsForSymbol, formatAtomic, formatAtomicHuman, - getDecimalDivisor + getDecimalDivisor, + gameNameFor, + currencyLabelFor } = require('./helpers/gameModeUtils'); const { ValidationError, normalizeError } = require('../utils/errors'); const paymentConfig = require('../config/paymentConfig'); @@ -68,6 +70,11 @@ class GameModeManager { return inferCurrencyDecimalsForSymbol(symbol); } + // Product name (Monerogue/Wownerogue) and network-aware currency label (sXMR on + // stagenet, XMR on mainnet, WOW for Wownero) — derived so they always track config. + get gameName() { return gameNameFor(this.cryptoType); } + get currencyLabel() { return currencyLabelFor(this.cryptoType, this.network); } + applyLegacyEnvConfig() { this.setLegacyGameMode(process.env.GAME_MODE || 'FREE'); this.cryptoType = process.env.CRYPTO_TYPE || this.cryptoType; @@ -904,7 +911,7 @@ class GameModeManager { switch (paymentType) { case 'single_game': { amount = this.singleGamePrice; - description = `Wowngeon single game entry (${this.cryptoType})`; + description = `${this.gameName} single game entry (${this.currencyLabel})`; break; } case 'credits_package': { @@ -927,7 +934,7 @@ class GameModeManager { const creditCount = selectedPackage?.credits ?? 10; const bonusCredits = selectedPackage?.bonus ?? 0; const bonusText = bonusCredits > 0 ? ` (+${bonusCredits} bonus)` : ''; - description = `Wowngeon ${creditCount}${bonusText} credits package (${this.cryptoType})`; + description = `${this.gameName} ${creditCount}${bonusText} credits package (${this.currencyLabel})`; break; } default: @@ -1147,6 +1154,8 @@ class GameModeManager { return { mode: this.gameMode, cryptoType: this.cryptoType, + currencyLabel: this.currencyLabel, // sXMR on stagenet, XMR on mainnet, WOW for Wownero + gameName: this.gameName, // Monerogue / Wownerogue network: this.network, isTestNetwork: this.isTestNetwork, testnetWarning: testnetWarning, @@ -1176,8 +1185,9 @@ class GameModeManager { allowInFreeMode: this.configSnapshot?.earlyEntry?.allowInFreeMode ?? false, allowInCreditsMode: this.configSnapshot?.earlyEntry?.allowInCreditsMode ?? false }, - // Smirk wallet integration (disabled for Monero stagenet) - smirkEnabled: process.env.SMIRK_ENABLED !== 'false', + // Smirk wallet integration. Smirk only works on mainnet, so it is forced off on + // any test network (stagenet/testnet) regardless of SMIRK_ENABLED. + smirkEnabled: process.env.SMIRK_ENABLED !== 'false' && !this.isTestNetwork, explorerTxUrl: process.env.EXPLORER_TX_URL || null }; } diff --git a/src/game/helpers/gameModeUtils.js b/src/game/helpers/gameModeUtils.js index 900f6cb..5618d56 100644 --- a/src/game/helpers/gameModeUtils.js +++ b/src/game/helpers/gameModeUtils.js @@ -30,6 +30,27 @@ const getDecimalDivisor = (decimals = DEFAULT_DECIMALS) => { return Math.pow(10, normalized); }; +// The product name for a given currency (Monero -> Monerogue, otherwise Wownerogue). +const gameNameFor = (cryptoType) => (String(cryptoType || '').toUpperCase() === 'XMR' ? 'Monerogue' : 'Wownerogue'); + +// The user-facing currency label, network-aware: Monero on a test network shows sXMR +// (stagenet) / tXMR (testnet) so it's clear the coins aren't mainnet; mainnet shows XMR. +// Wownero has no test networks, so it's always WOW. +const currencyLabelFor = (cryptoType, network) => { + const ct = String(cryptoType || '').toUpperCase(); + const net = String(network || 'mainnet').toLowerCase(); + if (ct === 'XMR' && (net === 'stagenet' || net === 'testnet')) { + return (net === 'testnet' ? 't' : 's') + 'XMR'; + } + return ct; +}; + +// Smirk wallet only works on mainnet Monero/Wownero, so it must be off on test networks. +const isTestNetworkFor = (network) => { + const net = String(network || 'mainnet').toLowerCase(); + return net === 'stagenet' || net === 'testnet'; +}; + const formatAtomic = ({ value, decimals, digits = 6 }) => { if (value === undefined || value === null) { return '0'; @@ -60,5 +81,8 @@ module.exports = { inferCurrencyDecimals, getDecimalDivisor, formatAtomic, - formatAtomicHuman + formatAtomicHuman, + gameNameFor, + currencyLabelFor, + isTestNetworkFor }; diff --git a/src/index.js b/src/index.js index bacfecd..148960e 100644 --- a/src/index.js +++ b/src/index.js @@ -492,9 +492,10 @@ app.get('/api/user/:socketId/payouts', asyncHandler(async (req, res) => { // ============================================================================= // Smirk Wallet Authentication Endpoints // ============================================================================= -// Smirk is a browser extension wallet for Wownero/Monero. -// Disable for Monero stagenet deployments (Smirk doesn't support stagenet). -const smirkEnabled = process.env.SMIRK_ENABLED !== 'false'; +// Smirk is a browser extension wallet for Wownero/Monero (mainnet only). +// Forced off on any test network (stagenet/testnet), regardless of SMIRK_ENABLED. +const { isTestNetworkFor } = require('./game/helpers/gameModeUtils'); +const smirkEnabled = process.env.SMIRK_ENABLED !== 'false' && !isTestNetworkFor(process.env.MONERO_NETWORK); if (smirkEnabled) { app.use(createAuthRoutes({ db: databaseManager })); } @@ -640,7 +641,7 @@ app.get('/verify/:gameId', asyncHandler(async (req, res) => { } // Return the server-rendered HTML verification page (see src/views/verifyPage.js). - res.send(renderVerifyPage(gameId, gameRecord)); + res.send(renderVerifyPage(gameId, gameRecord, gameModeManager.gameName)); })); // API endpoint for programmatic verification diff --git a/src/network/connectionHandler.js b/src/network/connectionHandler.js index 1010217..fb680f0 100644 --- a/src/network/connectionHandler.js +++ b/src/network/connectionHandler.js @@ -5,6 +5,7 @@ const user = require('../db/user'); const { clientIp } = require('./rateLimitContext'); +const { gameNameFor } = require('../game/helpers/gameModeUtils'); class ConnectionHandler { constructor({ io, broadcastManager, debugManager, sessionManager, rateLimiter }) { @@ -275,7 +276,7 @@ class ConnectionHandler { this.io.to(socket.id).emit('blockheight', { blockHeight: currentBlock }); // Send connection status - this.broadcastManager.sendStatusUpdate(socket.id, 'connection', 'Connected to Wownerogue server'); + this.broadcastManager.sendStatusUpdate(socket.id, 'connection', `Connected to ${gameNameFor(process.env.CRYPTO_TYPE)} server`); } _cleanupExistingMappings(socketId, clientId) { diff --git a/src/views/verifyPage.js b/src/views/verifyPage.js index b5368c8..0f646aa 100644 --- a/src/views/verifyPage.js +++ b/src/views/verifyPage.js @@ -14,7 +14,8 @@ function esc(value) { .replace(/'/g, '''); } -function renderVerifyPage(gameId, gameRecord) { +function renderVerifyPage(gameId, gameRecord, gameName) { + const name = gameName || 'Wownerogue'; const recordBlock = gameRecord ? `

    Game Record

    @@ -31,7 +32,7 @@ function renderVerifyPage(gameId, gameRecord) { - Wownerogue - Game Verification + ${esc(name)} - Game Verification -

    🔐 Wownerogue Provably Fair Verification

    +

    🔐 ${esc(name)} Provably Fair Verification

    How it works: