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: