mirror of
https://github.com/Such-Software/wownerogue.git
synced 2026-10-18 14:51:26 +02:00
A browser-based roguelike synchronized with crypto block timing. A run is a race against the next block: reach the exit before the block lands, or the house wins. The same codebase runs the solo dungeon, the social Tavern, and operator-selected PvP and race rulesets, with separate free and paid leaderboards. Self-hostable under the MIT License. See README.md to run it, docs/ARCHITECTURE.md for the design, and docs/DEPLOY.md to operate an instance.
47 lines
2.5 KiB
JavaScript
47 lines
2.5 KiB
JavaScript
(function (root) {
|
|
'use strict';
|
|
// Per-player nostr identity (Phase 2). Sign a global-chat message with the player's OWN Smirk
|
|
// npub (window.smirk.signNostrEvent) and emit it as `chat_signed`; the server verifies it's
|
|
// signed by this session's authenticated npub, then relays it to nostr under that npub.
|
|
//
|
|
// Returns a Promise<boolean>: true if it signed + emitted, false if Smirk signing is
|
|
// unavailable or declined, in which case the caller falls back to the normal unsigned send.
|
|
// Feature-detected end to end, so it's a no-op (always false) until the page has a connected
|
|
// Smirk wallet; wiring it into a send site is therefore always safe.
|
|
// Sign an event, granting the Nostr scope on demand. Signing FIRST means a returning user
|
|
// (scope already granted for this origin, e.g. from the game's NIP-98 login) gets a single
|
|
// approval; only a first-time origin hits NOT_AUTHORIZED and needs the one-time scope grant.
|
|
// Same pattern as SmirkAuth (html/js/network/smirkAuth.js).
|
|
function signWithScope(smirk, tmpl) {
|
|
return Promise.resolve()
|
|
.then(function () { return smirk.signNostrEvent(tmpl); })
|
|
.catch(function (err) {
|
|
var needsScope = (err && err.code === 'NOT_AUTHORIZED')
|
|
|| /nostr scope|getNostrPublicKey/i.test((err && err.message) || '');
|
|
if (!needsScope || typeof smirk.getNostrPublicKey !== 'function') throw err;
|
|
return smirk.getNostrPublicKey().then(function () { return smirk.signNostrEvent(tmpl); });
|
|
});
|
|
}
|
|
|
|
function smirkChatSign(socket, text, tag) {
|
|
try {
|
|
var smirk = root.smirk;
|
|
if (!socket || !smirk || typeof smirk.signNostrEvent !== 'function') return Promise.resolve(false);
|
|
var tmpl = {
|
|
kind: 1,
|
|
created_at: Math.floor(Date.now() / 1000),
|
|
tags: [['t', tag || 'wowngeon-global']],
|
|
content: String(text)
|
|
};
|
|
return signWithScope(smirk, tmpl).then(function (signed) {
|
|
if (!signed || !signed.id || !signed.sig || !signed.pubkey) return false;
|
|
socket.emit('chat_signed', { event: signed });
|
|
return true;
|
|
}).catch(function () { return false; });
|
|
} catch (e) {
|
|
return Promise.resolve(false);
|
|
}
|
|
}
|
|
root.smirkChatSign = smirkChatSign;
|
|
})(typeof window !== 'undefined' ? window : this);
|