10x every page: real interactions, kill fake content, wire everything
- ChatWidget: remove illegal seeds, real localStorage per-handle chat, honest bot replies about market/forum/funds - ForumBoard: wire to real forumState (loadForum/addThread/vote), kill fake stats and illegal seed posts - Home page: privacy features list reflects reality, footer links real - Links: kill all alert() calls, replace fake onions with real clearnet privacy resources + internal route grid - Support: per-coin copied state, env-driven addresses, real BTC addr - Inner circle: wire to AccountContext, tier system from LUX balance, remove hardcoded admin/shadow credentials and fake trading signals - Drop box: real sealed-note localStorage system, honest about no anonymous upload capability, real file picker with receipt - Messages: fully functional per-handle localStorage chat, AI-style contextual bot replies, clear history, honest about local storage - Wallets: pivot from fake PayPal accounts to Digital Access Passes, wire Buy Now to cart via ShopProduct interface - Testimonials: wire submit form to localStorage, interactive star rating 1-10, display submitted reviews above the fold - Raffle: use real merchant BTC address, real per-handle entry storage, honest LUX-only prize disclaimer, fix 0x address - Drops/Lotto: real number picker 1-49 with Quick Pick, ticket submission, match display against drawn numbers, demo disclaimer - Sanctuary: real 4-4-6-2 breathing timer, meditation passage with timer, candle-lighting with localStorage notes - Game: full playable Void Pong with canvas physics, CPU AI, scoring, rally counter, localStorage high score - Security analysis: honest architecture breakdown with real grades, layer-by-layer analysis, practical OPSEC guide, fiction banner - Trust: compute real scores from actual localStorage data (LUX, USD, forum posts, testimonials), FAQ accordion Made-with: Cursor
This commit is contained in:
@@ -1,38 +1,114 @@
|
||||
const USD_KEY = "cyberlux-usd-store-credit";
|
||||
const TX_KEY = "cyberlux-btc-claimed-txids";
|
||||
/**
|
||||
* Per-account USD balance (from verified Bitcoin deposits), LUX loyalty points,
|
||||
* and claimed txids — all keyed by CyberLux handle (same origin = one account).
|
||||
*/
|
||||
|
||||
export function loadUsdStoreCredit(): number {
|
||||
if (typeof window === "undefined") return 0;
|
||||
export type AccountLedgerRow = {
|
||||
usd: number;
|
||||
lux: number;
|
||||
claimedTxids: string[];
|
||||
};
|
||||
|
||||
const LEDGER_KEY = "cyberlux-account-ledger-v1";
|
||||
/** Pre–per-account migration keys (device-wide). */
|
||||
const LEGACY_USD_KEY = "cyberlux-usd-store-credit";
|
||||
const LEGACY_TX_KEY = "cyberlux-btc-claimed-txids";
|
||||
|
||||
function emptyRow(): AccountLedgerRow {
|
||||
return { usd: 0, lux: 0, claimedTxids: [] };
|
||||
}
|
||||
|
||||
function loadLedgerMap(): Record<string, AccountLedgerRow> {
|
||||
if (typeof window === "undefined") return {};
|
||||
try {
|
||||
const raw = localStorage.getItem(USD_KEY);
|
||||
if (!raw) return 0;
|
||||
const n = Number.parseFloat(raw);
|
||||
return Number.isFinite(n) ? Math.round(n * 100) / 100 : 0;
|
||||
const raw = localStorage.getItem(LEDGER_KEY);
|
||||
if (!raw) return {};
|
||||
const o = JSON.parse(raw) as Record<string, unknown>;
|
||||
if (!o || typeof o !== "object") return {};
|
||||
const out: Record<string, AccountLedgerRow> = {};
|
||||
for (const [k, v] of Object.entries(o)) {
|
||||
if (!k || typeof v !== "object" || v === null) continue;
|
||||
const row = v as Record<string, unknown>;
|
||||
const usd = typeof row.usd === "number" && Number.isFinite(row.usd) ? Math.max(0, Math.round(row.usd * 100) / 100) : 0;
|
||||
const lux = typeof row.lux === "number" && Number.isFinite(row.lux) ? Math.max(0, Math.floor(row.lux)) : 0;
|
||||
const claimedTxids = Array.isArray(row.claimedTxids)
|
||||
? row.claimedTxids.map((t) => String(t)).filter((t) => /^[a-fA-F0-9]{64}$/.test(t))
|
||||
: [];
|
||||
out[k.toLowerCase()] = { usd, lux, claimedTxids: [...new Set(claimedTxids)] };
|
||||
}
|
||||
return out;
|
||||
} catch {
|
||||
return 0;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
export function saveUsdStoreCredit(usd: number): void {
|
||||
function saveLedgerMap(m: Record<string, AccountLedgerRow>): void {
|
||||
if (typeof window === "undefined") return;
|
||||
const safe = Math.max(0, Math.round(usd * 100) / 100);
|
||||
localStorage.setItem(USD_KEY, String(safe));
|
||||
localStorage.setItem(LEDGER_KEY, JSON.stringify(m));
|
||||
}
|
||||
|
||||
export function loadClaimedTxids(): string[] {
|
||||
if (typeof window === "undefined") return [];
|
||||
function accountKey(username: string): string {
|
||||
return username.trim().toLowerCase();
|
||||
}
|
||||
|
||||
export function getLedgerRow(username: string | null): AccountLedgerRow {
|
||||
if (!username) return emptyRow();
|
||||
const map = loadLedgerMap();
|
||||
return map[accountKey(username)] ?? emptyRow();
|
||||
}
|
||||
|
||||
export function setLedgerRow(username: string, row: AccountLedgerRow): void {
|
||||
const map = loadLedgerMap();
|
||||
map[accountKey(username)] = {
|
||||
usd: Math.max(0, Math.round(row.usd * 100) / 100),
|
||||
lux: Math.max(0, Math.floor(row.lux)),
|
||||
claimedTxids: [...new Set(row.claimedTxids.filter((t) => /^[a-fA-F0-9]{64}$/.test(t)))],
|
||||
};
|
||||
saveLedgerMap(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* One-time: move old device-wide USD + txids into this handle’s ledger, then clear legacy keys.
|
||||
*/
|
||||
export function migrateLegacyDeviceLedgerIfNeeded(username: string): void {
|
||||
if (typeof window === "undefined" || !username.trim()) return;
|
||||
const key = accountKey(username);
|
||||
const map = loadLedgerMap();
|
||||
const existing = map[key] ?? emptyRow();
|
||||
if (existing.usd > 0 || existing.claimedTxids.length > 0) return;
|
||||
|
||||
let legacyUsd = 0;
|
||||
try {
|
||||
const raw = localStorage.getItem(TX_KEY);
|
||||
if (!raw) return [];
|
||||
const parsed = JSON.parse(raw) as unknown;
|
||||
if (!Array.isArray(parsed)) return [];
|
||||
return parsed.map((x) => String(x)).filter((t) => /^[a-fA-F0-9]{64}$/.test(t));
|
||||
const raw = localStorage.getItem(LEGACY_USD_KEY);
|
||||
if (raw) {
|
||||
const n = Number.parseFloat(raw);
|
||||
if (Number.isFinite(n)) legacyUsd = Math.max(0, Math.round(n * 100) / 100);
|
||||
}
|
||||
} catch {
|
||||
return [];
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
|
||||
export function saveClaimedTxids(txids: string[]): void {
|
||||
if (typeof window === "undefined") return;
|
||||
localStorage.setItem(TX_KEY, JSON.stringify([...new Set(txids)]));
|
||||
let legacyTx: string[] = [];
|
||||
try {
|
||||
const raw = localStorage.getItem(LEGACY_TX_KEY);
|
||||
if (raw) {
|
||||
const parsed = JSON.parse(raw) as unknown;
|
||||
if (Array.isArray(parsed)) {
|
||||
legacyTx = parsed.map((t) => String(t)).filter((t) => /^[a-fA-F0-9]{64}$/.test(t));
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
|
||||
if (legacyUsd <= 0 && legacyTx.length === 0) return;
|
||||
|
||||
map[key] = {
|
||||
usd: legacyUsd,
|
||||
lux: 0,
|
||||
claimedTxids: [...new Set(legacyTx)],
|
||||
};
|
||||
saveLedgerMap(map);
|
||||
localStorage.removeItem(LEGACY_USD_KEY);
|
||||
localStorage.removeItem(LEGACY_TX_KEY);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user