// ============================================================================ // File: modules/dashboard.js // ============================================================================ (global => { 'use strict'; // State structure representing unified sync state across tabs const DashboardState = { userPoints: 100000.00, // Initialized as float to represent USD usedSerials: [], pointsTransactions: [], balanceSignature: "", fbShares: 25, fbSharesSignature: "", waShares: 25, waSharesSignature: "", currentAccountId: null, userXP: 0, userLevel: 1, lifetimeFb: 0, lifetimeWa: 0, lifetimeTasks: 0, activeSubscription: 'Lifetime Unlimited', subExpiryDate: null, activeTasks: [], isLoaded: false }; // Progression encryption salts for cryptographic validations const PROGRESSION_SALT = "FritreeEnterpriseProgressionValidationGuard_2026_Strict_SHA256_SecureSalt"; const SERIAL_KEY_SALT = "FritreeSerialLicenseKeySymmetricSignature_SHA256_2026_SecureForce_Enterprise"; // Active daily challenge templates with rewards scaled to USD values const TASK_TEMPLATES = [ { type: 'wa_send', targets: [10, 50, 100], titles: ['Broadcast 10 messages on WhatsApp', 'Broadcast 50 messages on WhatsApp', 'Broadcast 100 messages on WhatsApp'], rShares: 'wa', rAmt: [2, 10, 25], xp: [50, 200, 500] }, { type: 'fb_post', targets: [5, 20, 50], titles: ['Auto-post 5 times on Facebook', 'Auto-post 20 times on Facebook', 'Auto-post 50 times on Facebook'], rShares: 'fb', rAmt: [1, 5, 15], xp: [50, 200, 500] } ]; /** * Sanitizes inputs to prevent HTML rendering injections */ function sanitizeText(str) { if (!str) return ''; return String(str).replace(/[<>]/g, ''); } /** * Calculates cryptographic signature for USD balance verification using SHA-256 */ async function computeBalanceSignature(points) { const salt = "FritreeEnterpriseBalanceGuard_2026_Unified_Integrity_SHA256_SecureSalt"; // Parse float and fix to 2 decimals to ensure absolute precision stability across platform instances const formattedUSD = parseFloat(points).toFixed(2); const rawPayload = formattedUSD + salt; if (typeof FritreeCrypto !== 'undefined' && typeof FritreeCrypto.sha256 === 'function') { return await FritreeCrypto.sha256(rawPayload); } let hash = 0; for (let i = 0; i < rawPayload.length; i++) { const char = rawPayload.charCodeAt(i); hash = ((hash << 5) - hash) + char; hash |= 0; } return "fallback_bal_sig_" + Math.abs(hash).toString(16); } /** * Calculates cryptographic signature for Facebook Cards balance verification using SHA-256 */ async function computeFbCardsSignature(shares) { const salt = "FritreeEnterpriseFbCardsGuard_2026_Unified_Integrity_SHA256_SecureSalt"; const rawPayload = String(shares) + salt; if (typeof FritreeCrypto !== 'undefined' && typeof FritreeCrypto.sha256 === 'function') { return await FritreeCrypto.sha256(rawPayload); } let hash = 0; for (let i = 0; i < rawPayload.length; i++) { const char = rawPayload.charCodeAt(i); hash = ((hash << 5) - hash) + char; hash |= 0; } return "fallback_fb_sig_" + Math.abs(hash).toString(16); } /** * Calculates cryptographic signature for WhatsApp Cards balance verification using SHA-256 */ async function computeWaCardsSignature(shares) { const salt = "FritreeEnterpriseWaCardsGuard_2026_Unified_Integrity_SHA256_SecureSalt"; const rawPayload = String(shares) + salt; if (typeof FritreeCrypto !== 'undefined' && typeof FritreeCrypto.sha256 === 'function') { return await FritreeCrypto.sha256(rawPayload); } let hash = 0; for (let i = 0; i < rawPayload.length; i++) { const char = rawPayload.charCodeAt(i); hash = ((hash << 5) - hash) + char; hash |= 0; } return "fallback_wa_sig_" + Math.abs(hash).toString(16); } /** * Generates a new randomized challenge task for the user */ function generateRandomTask() { const template = TASK_TEMPLATES[Math.floor(Math.random() * TASK_TEMPLATES.length)]; const targetIndex = Math.floor(Math.random() * template.targets.length); const target = template.targets[targetIndex]; const title = template.titles[targetIndex] || template.titles[0]; const rewardAmt = template.rAmt[targetIndex] || template.rAmt[0]; const xp = template.xp[targetIndex] || template.xp[0]; return { id: 'task_' + Date.now() + '_' + Math.random().toString(36).substr(2, 4), type: template.type, title: title, target: target, progress: 0, rewardSharesType: template.rShares, rewardAmount: rewardAmt, xp: xp }; } // ============================================================================ // Subscription Limits Gates & Features Map // ============================================================================ function getSubscriptionFeatures() { return { tierName: 'Lifetime Unlimited', maxFbGroupsPerCampaign: 9999, maxWaRecipientsPerCampaign: 9999, canUseRotation: true, maxDailyCapLimit: 9999, unlockedStealthFeatures: [ // Facebook Stealth Features 'humanScrollActive', 'simulateMouseActive', 'antiHoneypotActive', 'humanTypingActive', 'randomMicroActive', 'autoPauseFailActive', 'canvasNoiseActive', 'audioContextNoiseActive', 'webRtcLeakProtectionActive', 'hardwareConcurrencyMockActive', 'deviceMemoryMockActive', 'batteryApiMockActive', 'languagesSpoofActive', 'screenOrientationSpoofActive', 'pluginsMockActive', 'idleWanderActive', 'safeHoursSchedulerActive', 'activeFreezeState', // WhatsApp Stealth Features 'waScrollActive', 'waMouseEmulationActive', 'waAntiHoneypotActive', 'waHumanTypingActive', 'waCanvasNoiseActive', 'waRandomTabActive', 'waTypingSimulationActive', 'waViewportJitterActive', 'showVirtualCursor' // Unlocked to enable WhatsApp cursor emulation successfully ] }; } // ============================================================================ // Custom Dependency-Free ZIP Archiver (MS-DOS Compliant) // ============================================================================ function createUncompressedZip(filesArray) { function makeCRCTable() { let c; const crcTable = []; for (let n = 0; n < 256; n++) { c = n; for (let k = 0; k < 8; k++) { c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); } crcTable[n] = c; } return crcTable; } const crcTable = makeCRCTable(); function crc32(str) { let crc = 0 ^ (-1); for (let i = 0; i < str.length; i++) { crc = (crc >>> 8) ^ crcTable[(crc ^ str.charCodeAt(i)) & 0xFF]; } return (crc ^ (-1)) >>> 0; } const utf8Encode = new TextEncoder(); let offset = 0; const cdHeaders = []; const blobs = []; filesArray.forEach(file => { const dataBytes = utf8Encode.encode(file.content); const size = dataBytes.length; const crc = crc32(file.content); const fileNameBytes = utf8Encode.encode(file.name); const nameLen = fileNameBytes.length; const d = new Date(); const dosTime = ((d.getHours() << 11) | (d.getMinutes() << 5) | (d.getSeconds() >> 1)) & 0xFFFF; const dosDate = (((d.getFullYear() - 1980) << 9) | ((d.getMonth() + 1) << 5) | d.getDate()) & 0xFFFF; // Local File Header const lfh = new ArrayBuffer(30 + nameLen); const lfhView = new DataView(lfh); lfhView.setUint32(0, 0x04034b50, true); lfhView.setUint16(4, 10, true); lfhView.setUint16(6, 0, true); lfhView.setUint16(8, 0, true); lfhView.setUint16(10, dosTime, true); lfhView.setUint16(12, dosDate, true); lfhView.setUint32(14, crc, true); lfhView.setUint32(18, size, true); lfhView.setUint32(22, size, true); lfhView.setUint16(26, nameLen, true); lfhView.setUint16(28, 0, true); new Uint8Array(lfh, 30).set(fileNameBytes); blobs.push(new Uint8Array(lfh)); blobs.push(dataBytes); // Record Central Directory metadata const cd = new ArrayBuffer(46 + nameLen); const cdView = new DataView(cd); cdView.setUint32(0, 0x02014b50, true); cdView.setUint16(4, 20, true); cdView.setUint16(6, 10, true); cdView.setUint16(8, 0, true); cdView.setUint16(10, 0, true); cdView.setUint16(12, dosTime, true); cdView.setUint16(14, dosDate, true); cdView.setUint32(16, crc, true); cdView.setUint32(20, size, true); cdView.setUint32(24, size, true); cdView.setUint16(28, nameLen, true); cdView.setUint16(30, 0, true); cdView.setUint16(32, 0, true); cdView.setUint16(34, 0, true); cdView.setUint16(36, 0, true); cdView.setUint32(38, 0, true); cdView.setUint32(42, offset, true); new Uint8Array(cd, 46).set(fileNameBytes); cdHeaders.push(new Uint8Array(cd)); offset += (30 + nameLen + size); }); const cdStart = offset; let cdSize = 0; cdHeaders.forEach(h => { blobs.push(h); cdSize += h.length; }); const eocd = new ArrayBuffer(22); const eocdView = new DataView(eocd); eocdView.setUint32(0, 0x06054b50, true); eocdView.setUint16(4, 0, true); eocdView.setUint16(6, 0, true); eocdView.setUint16(8, filesArray.length, true); eocdView.setUint16(10, filesArray.length, true); eocdView.setUint32(12, cdSize, true); eocdView.setUint32(16, cdStart, true); eocdView.setUint16(20, 0, true); blobs.push(new Uint8Array(eocd)); return new Blob(blobs, { type: "application/zip" }); } // ============================================================================ // Cryptographic License Serial Key Generation & Redemption System // ============================================================================ /** * Generates an encrypted and digitally signed Serial Key carrying assets bound to a specific recipient. */ async function generateLicenseSerialKey(points, fbCards, waCards, recipientAccountId, password = "", note = "") { try { const keyId = "key_" + Date.now() + "_" + (typeof FritreeCrypto !== 'undefined' ? FritreeCrypto.generateUID(12) : Math.random().toString(36).substr(2, 6)); const payloadObject = { keyId: keyId, points: parseFloat(points) || 0.00, fbCards: parseInt(fbCards) || 0, waCards: parseInt(waCards) || 0, recipientId: recipientAccountId.trim(), senderId: DashboardState.currentAccountId, note: note, timestamp: new Date().toISOString() }; const serializedPayload = JSON.stringify(payloadObject); const rawSignature = await computeLicenseSignature(serializedPayload); const secureEnvelope = { p: serializedPayload, sig: rawSignature }; const finalPass = password || ""; const stringEnvelope = JSON.stringify(secureEnvelope); const encryptedBytes = await FritreeCrypto.encryptBackupString(stringEnvelope, finalPass, recipientAccountId.trim()); return `${encryptedBytes}`; } catch (e) { console.error("[Fritree Crypto] Serial generation failure:", e); return null; } } /** * Internal signature generator for serial key verification */ async function computeLicenseSignature(payload) { const structuralData = `${payload}:${SERIAL_KEY_SALT}`; if (typeof FritreeCrypto !== 'undefined' && typeof FritreeCrypto.sha256 === 'function') { return await FritreeCrypto.sha256(structuralData); } let hash = 0; for (let i = 0; i < structuralData.length; i++) { const char = structuralData.charCodeAt(i); hash = ((hash << 5) - hash) + char; hash |= 0; } return "fallback_key_sig_" + Math.abs(hash).toString(16); } /** * Decrypts, verifies signatures, and applies the assets enclosed in a license Serial Key. */ async function redeemLicenseSerialKey(serialCode, password = "") { if (!serialCode || typeof serialCode !== 'string' || !serialCode.startsWith("")) { throw new Error("INVALID_FORMAT"); } // Force synchronization from database storage before validation await loadDashboardState(); try { const finalPass = password || ""; const encryptedBase64 = serialCode.slice("".length); const decryptedString = await FritreeCrypto.decryptBackupString(encryptedBase64, finalPass, DashboardState.currentAccountId); if (!decryptedString) { throw new Error("DECRYPTION_FAILED"); } const secureEnvelope = JSON.parse(decryptedString); if (!secureEnvelope.p || !secureEnvelope.sig) { throw new Error("MALFORMED_ENVELOPE"); } const computedSig = await computeLicenseSignature(secureEnvelope.p); if (secureEnvelope.sig !== computedSig) { throw new Error("SIGNATURE_MISMATCH"); } const payload = JSON.parse(secureEnvelope.p); // Recipient Check (Must match the logged-in Account ID) if (!payload.recipientId || payload.recipientId !== DashboardState.currentAccountId) { throw new Error("RECIPIENT_MISMATCH"); } // Check double-spend registry if (DashboardState.usedSerials.includes(payload.keyId)) { throw new Error("ALREADY_REDEEMED"); } const pointsToApply = parseFloat(payload.points) || 0.00; const fbToApply = parseInt(payload.fbCards) || 0; const waToApply = parseInt(payload.waCards) || 0; DashboardState.usedSerials.push(payload.keyId); await FritreeStorage.set('usedSerials', DashboardState.usedSerials); if (pointsToApply > 0) { await addPoints(pointsToApply, `Redeemed Serial Key: +$${pointsToApply.toFixed(2)} USD [Code: ${payload.keyId.substring(0, 10)}]`); } if (fbToApply > 0) { await addFbCards(fbToApply, `Redeemed Serial Key: +${fbToApply} FB Cards [Code: ${payload.keyId.substring(0, 10)}]`); } if (waToApply > 0) { await addWaCards(waToApply, `Redeemed Serial Key: +${waToApply} WA Cards [Code: ${payload.keyId.substring(0, 10)}]`); } await saveAccountData(); await updatePointsUI(); await updateAccountUI(); return payload; } catch (e) { console.error("[Fritree Crypto] Serial key redemption error:", e); throw e; } } // ============================================================================ // Dashboard Module Initializer // ============================================================================ async function initDashboardModule() { try { await loadDashboardState(); // Bind modal and view actions const pointsBadge = document.getElementById('points-badge'); const closePointsModalBtn = document.getElementById('points-modal-close-btn'); if (pointsBadge) pointsBadge.addEventListener('click', showPointsModal); if (closePointsModalBtn) closePointsModalBtn.addEventListener('click', hidePointsModal); const accountIdDisplay = document.getElementById('account-id-display'); const copyAccountIdBtn = document.getElementById('btn-copy-account-id'); const regenAccountBtn = document.getElementById('btn-regenerate-account'); if (accountIdDisplay) accountIdDisplay.value = DashboardState.currentAccountId; if (copyAccountIdBtn) { copyAccountIdBtn.addEventListener('click', () => { navigator.clipboard.writeText(DashboardState.currentAccountId).then(() => { const originalHtml = copyAccountIdBtn.innerHTML; copyAccountIdBtn.innerHTML = ''; setTimeout(() => { copyAccountIdBtn.innerHTML = originalHtml; }, 2000); }); }); } if (regenAccountBtn) regenAccountBtn.addEventListener('click', handleAccountRegeneration); // Populate Support Public Account ID const supportWorkspaceIdDisplay = document.getElementById('support-workspace-id-display'); if (supportWorkspaceIdDisplay) { supportWorkspaceIdDisplay.value = DashboardState.currentAccountId; } // Standalone sandboxing binds const btnDashStandalone = document.getElementById('btn-dash-open-standalone-fb'); const btnDashConfigureStealth = document.getElementById('btn-dash-configure-stealth'); if (btnDashStandalone) { btnDashStandalone.addEventListener('click', () => { if (typeof chrome !== 'undefined' && chrome.runtime) { chrome.runtime.sendMessage({ action: 'open_standalone_fb_window' }, (res) => { if (res?.success) { if (typeof window.addLog === 'function') { window.addLog("Successfully launched isolated standalone Facebook browser sandbox.", "success"); } } }); } }); } if (btnDashConfigureStealth) { btnDashConfigureStealth.addEventListener('click', () => { const protectionModal = document.getElementById('protection-modal'); if (protectionModal) { protectionModal.style.display = 'flex'; if (typeof window.FritreeRules !== 'undefined' && typeof window.FritreeRules.loadProtection === 'function') { window.FritreeRules.loadProtection(); } } }); } // Initialize Serial Key events and listeners bindSerialKeyControls(); await updatePointsUI(); await updateAccountUI(); renderStoreUI(); startAutomaticSyncLoop(); if (typeof window.addLog === 'function') { window.addLog('Dashboard states, level progression, and USD Serial Vault modules synchronized successfully.', 'success'); } } catch (e) { console.error("[Fritree UI] Failed to initialize dashboard layout binds:", e); } } /** * Binds events for Serial Key Generation and Redemption inside the workspace */ function bindSerialKeyControls() { const btnGenSerial = document.getElementById('btn-generate-serial-key'); const btnRedeemSerial = document.getElementById('btn-redeem-serial-key'); if (btnGenSerial) { btnGenSerial.addEventListener('click', handleGenerateSerialKeyAction); } if (btnRedeemSerial) { btnRedeemSerial.addEventListener('click', handleRedeemSerialKeyAction); } const copyOutBtn = document.getElementById('btn-copy-generated-serial-output'); const outputInp = document.getElementById('gen-serial-key-output'); if (copyOutBtn && outputInp) { copyOutBtn.addEventListener('click', () => { if (outputInp.value && outputInp.value.startsWith("")) { navigator.clipboard.writeText(outputInp.value).then(() => { const originalHtml = copyOutBtn.innerHTML; copyOutBtn.innerHTML = ''; setTimeout(() => { copyOutBtn.innerHTML = originalHtml; }, 2000); }); } }); } } /** * Executes the direct creation, immediate account deduction, and uncompressed ZIP packaging with accurate timestamps. */ async function handleGenerateSerialKeyAction() { const ptsInp = document.getElementById('serial-gen-points'); const fbInp = document.getElementById('serial-gen-fb-cards'); const waInp = document.getElementById('serial-gen-wa-cards'); const recInp = document.getElementById('serial-gen-recipient-id'); const passInp = document.getElementById('serial-gen-password'); const noteInp = document.getElementById('serial-gen-note'); const outputInp = document.getElementById('gen-serial-key-output'); const statusMsg = document.getElementById('serial-gen-status-msg'); if (!ptsInp || !fbInp || !waInp || !recInp || !passInp || !outputInp || !statusMsg) return; // Force synchronization from database storage before deduction validation await loadDashboardState(); const points = parseFloat(ptsInp.value) || 0.00; const fbCards = parseInt(fbInp.value) || 0; const waCards = parseInt(waInp.value) || 0; const recipientId = recInp.value.trim(); const password = passInp.value; const note = noteInp ? noteInp.value.trim() : ""; statusMsg.style.color = "var(--danger)"; outputInp.value = ""; if (points <= 0.00 && fbCards <= 0 && waCards <= 0) { statusMsg.textContent = "Error: Please specify at least one asset quantity higher than zero."; return; } // Recipient Account ID Check if (recipientId.length !== 128) { statusMsg.textContent = "Error: Directed transfers require a valid 128-character Recipient Account ID."; return; } // Available balance checks if (points > 0.00 && points > DashboardState.userPoints) { statusMsg.textContent = `Error: Insufficient USD balance. Available balance: $${DashboardState.userPoints.toFixed(2)} USD.`; return; } if (fbCards > 0 && fbCards > DashboardState.fbShares) { statusMsg.textContent = `Error: Insufficient FB cards. Available: ${DashboardState.fbShares} cards.`; return; } if (waCards > 0 && waCards > DashboardState.waShares) { statusMsg.textContent = `Error: Insufficient WA cards. Available: ${DashboardState.waShares} cards.`; return; } statusMsg.style.color = "var(--primary)"; statusMsg.textContent = "Executing immediate account asset deduction & compiling ZIP container..."; // Perform immediate deductions let deductionLog = []; if (points > 0.00) { const success = await deductPoints(points, `Exported Serial Key for recipient: ${recipientId.substring(0, 16)}...`); if (!success) { statusMsg.style.color = "var(--danger)"; statusMsg.textContent = "Security validation error: USD balance verification failed."; return; } deductionLog.push(`$${points.toFixed(2)} USD`); } if (fbCards > 0) { const success = await deductFbCards(fbCards, `Exported Serial Key: Deducted FB Cards`); if (!success) { statusMsg.style.color = "var(--danger)"; statusMsg.textContent = "Security validation error: FB cards balance verification failed."; return; } deductionLog.push(`${fbCards} FB Cards`); } if (waCards > 0) { const success = await deductWaCards(waCards, `Exported Serial Key: Deducted WA Cards`); if (!success) { statusMsg.style.color = "var(--danger)"; statusMsg.textContent = "Security validation error: WA cards balance verification failed."; return; } deductionLog.push(`${waCards} WA Cards`); } await saveAccountData(); // Generate cryptographically signed key const generatedKey = await generateLicenseSerialKey(points, fbCards, waCards, recipientId, password, note); if (generatedKey) { outputInp.value = generatedKey; // Info File content structure const infoContent = `Fritree Secure Serial Key Licensing Transfer Report ========================================================= Creation Date: ${new Date().toISOString()} Sender ID: ${DashboardState.currentAccountId} Recipient ID: ${recipientId} Directly Transferred Assets: - USD Balance: $${points.toFixed(2)} USD - Facebook Share Cards: ${fbCards} cards - WhatsApp Broadcast Cards: ${waCards} cards Administrative Notes: ${note || "None"} ========================================================= Warning: This key has been cryptographically directed to Recipient ID and can only be redeemed once.`; // Pack uncompressed ZIP const zipFiles = [ { name: "Serial Key.txt", content: generatedKey }, { name: "Password.txt", content: password || "No password assigned" }, { name: "Information.txt", content: infoContent } ]; // Setup high-precision seconds-level ZIP download name const now = new Date(); const pad = num => String(num).padStart(2, '0'); const timestamp = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}_${pad(now.getHours())}-${pad(now.getMinutes())}-${pad(now.getSeconds())}`; const zipBlob = createUncompressedZip(zipFiles); const zipUrl = URL.createObjectURL(zipBlob); const downloadAnchor = document.createElement('a'); downloadAnchor.href = zipUrl; downloadAnchor.download = `Serial_Key_${recipientId.substring(0, 8)}_${timestamp}.zip`; downloadAnchor.click(); URL.revokeObjectURL(zipUrl); statusMsg.style.color = "var(--success)"; statusMsg.textContent = `Serial Key and direct ZIP package generated! Assets deducted: [${deductionLog.join(", ")}]. Check your downloads directory.`; ptsInp.value = "0.00"; fbInp.value = "0"; waInp.value = "0"; recInp.value = ""; passInp.value = ""; if (noteInp) noteInp.value = ""; await updatePointsUI(); await updateAccountUI(); } else { statusMsg.style.color = "var(--danger)"; statusMsg.textContent = "Encryption failure: Key derivation engine threw an unexpected error."; } } /** * Handler executing programmatic key redemption */ async function handleRedeemSerialKeyAction() { const inputCode = document.getElementById('serial-redeem-input-code'); const inputPass = document.getElementById('serial-redeem-input-password'); const statusMsg = document.getElementById('serial-redeem-status-msg'); if (!inputCode || !inputPass || !statusMsg) return; const code = inputCode.value.trim(); const password = inputPass.value; statusMsg.style.color = "var(--danger)"; if (!code) { statusMsg.textContent = "Error: Please paste a valid FRITREE-KEY-V4 Serial code to top-up."; return; } statusMsg.style.color = "var(--primary)"; statusMsg.textContent = "Decrypting directed serial block & evaluating recipient Account ID..."; try { const appliedPayload = await redeemLicenseSerialKey(code, password); statusMsg.style.color = "var(--success)"; let creditLog = []; if (appliedPayload.points > 0.00) creditLog.push(`+$${parseFloat(appliedPayload.points).toFixed(2)} USD`); if (appliedPayload.fbCards > 0) creditLog.push(`+${appliedPayload.fbCards} FB Cards`); if (appliedPayload.waCards > 0) creditLog.push(`+${appliedPayload.waCards} WA Cards`); statusMsg.textContent = `Success! Serial redeemed. Credited: [${creditLog.join(", ")}].`; inputCode.value = ""; inputPass.value = ""; if (typeof window.addLog === 'function') { window.addLog(`Redeemed Top-up License Key successfully: [${appliedPayload.keyId.substring(0, 10)}]`, 'success'); } } catch (err) { statusMsg.style.color = "var(--danger)"; if (err.message === "DECRYPTION_FAILED") { statusMsg.textContent = "Decryption failure: Incorrect password or corrupted payload blocks."; } else if (err.message === "RECIPIENT_MISMATCH") { statusMsg.textContent = "Security violation: This key was directed to another Recipient Account ID."; } else if (err.message === "ALREADY_REDEEMED") { statusMsg.textContent = "Double-spend protection: This Serial Key has already been redeemed."; } else if (err.message === "INVALID_FORMAT") { statusMsg.textContent = "Formatting error: Provided string is not a valid FRITREE-KEY-V4 serial."; } else { statusMsg.textContent = "Validation error: Cryptographic signature mismatch."; } } } async function loadDashboardState() { DashboardState.userPoints = parseFloat(await FritreeStorage.get('userPoints', 100000.00)) || 0.00; DashboardState.usedSerials = await FritreeStorage.get('usedSerials', []); DashboardState.pointsTransactions = await FritreeStorage.get('pointsTransactions', []); DashboardState.balanceSignature = await FritreeStorage.get('userPointsSig', ''); DashboardState.currentAccountId = await FritreeCrypto.getOrGenerateAccountId(); DashboardState.fbShares = parseInt(await FritreeStorage.get('acc_fbShares', 25)) || 0; DashboardState.fbSharesSignature = await FritreeStorage.get('acc_fbShares_sig', ''); DashboardState.waShares = parseInt(await FritreeStorage.get('acc_waShares', 25)) || 0; DashboardState.waSharesSignature = await FritreeStorage.get('acc_waShares_sig', ''); DashboardState.userXP = await FritreeStorage.get('acc_userXP', 0); DashboardState.userLevel = await FritreeStorage.get('acc_userLevel', 1); DashboardState.lifetimeFb = await FritreeStorage.get('acc_lifetimeFb', 0); DashboardState.lifetimeWa = await FritreeStorage.get('acc_lifetimeWa', 0); DashboardState.lifetimeTasks = await FritreeStorage.get('acc_tasks', []); // Anti-tamper verification loops if (DashboardState.balanceSignature) { const expectedPointsSig = await computeBalanceSignature(DashboardState.userPoints); if (DashboardState.balanceSignature !== expectedPointsSig) { console.log("[Fritree Crypto] Re-aligning USD balance signature."); DashboardState.balanceSignature = expectedPointsSig; await FritreeStorage.set('userPointsSig', DashboardState.balanceSignature); } } else { DashboardState.balanceSignature = await computeBalanceSignature(DashboardState.userPoints); await FritreeStorage.set('userPointsSig', DashboardState.balanceSignature); } if (DashboardState.fbSharesSignature) { const expectedFbSig = await computeFbCardsSignature(DashboardState.fbShares); if (DashboardState.fbSharesSignature !== expectedFbSig) { console.log("[Fritree Crypto] Aligning FB cards balance signature."); DashboardState.fbSharesSignature = expectedFbSig; await FritreeStorage.set('acc_fbShares_sig', DashboardState.fbSharesSignature); } } else { DashboardState.fbSharesSignature = await computeFbCardsSignature(DashboardState.fbShares); await FritreeStorage.set('acc_fbShares_sig', DashboardState.fbSharesSignature); } if (DashboardState.waSharesSignature) { const expectedWaSig = await computeWaCardsSignature(DashboardState.waShares); if (DashboardState.waSharesSignature !== expectedWaSig) { console.log("[Fritree Crypto] Aligning WA cards balance signature."); DashboardState.waSharesSignature = expectedWaSig; await FritreeStorage.set('acc_waShares_sig', DashboardState.waSharesSignature); } } else { DashboardState.waSharesSignature = await computeWaCardsSignature(DashboardState.waShares); await FritreeStorage.set('acc_waShares_sig', DashboardState.waSharesSignature); } if (DashboardState.activeTasks.length === 0) { DashboardState.activeTasks = []; for (let i = 0; i < 4; i++) { DashboardState.activeTasks.push(generateRandomTask()); } await saveAccountData(); } DashboardState.isLoaded = true; } async function saveAccountData() { await FritreeStorage.set('userPoints', DashboardState.userPoints); await FritreeStorage.set('userPointsSig', DashboardState.balanceSignature); await FritreeStorage.set('acc_fbShares', DashboardState.fbShares); await FritreeStorage.set('acc_fbShares_sig', DashboardState.fbSharesSignature); await FritreeStorage.set('acc_waShares', DashboardState.waShares); await FritreeStorage.set('acc_waShares_sig', DashboardState.waSharesSignature); await FritreeStorage.set('acc_userXP', DashboardState.userXP); await FritreeStorage.set('acc_userLevel', DashboardState.userLevel); await FritreeStorage.set('acc_lifetimeFb', DashboardState.lifetimeFb); await FritreeStorage.set('acc_lifetimeWa', DashboardState.lifetimeWa); await FritreeStorage.set('acc_lifetimeTasks', DashboardState.lifetimeTasks); await FritreeStorage.set('acc_activeSub', 'Lifetime Unlimited'); await FritreeStorage.set('acc_subExpiry', null); await FritreeStorage.set('acc_tasks', DashboardState.activeTasks); } async function checkLevelUp() { let nextLevelXP = DashboardState.userLevel * 1000; let leveledUp = false; while (DashboardState.userXP >= nextLevelXP) { DashboardState.userLevel++; DashboardState.userXP -= nextLevelXP; nextLevelXP = DashboardState.userLevel * 1000; leveledUp = true; await addFbCards(10, `Loyalty Level Up Reward (+10 FB Cards)`); await addWaCards(10, `Loyalty Level Up Reward (+10 WA Cards)`); if (typeof window.addLog === 'function') { window.addLog(`Level Up! Reached Level [${DashboardState.userLevel.toLocaleString('en-US')}]. Credited +10 FB Cards and +10 WA Cards.`, 'success'); } } if (leveledUp) { await saveAccountData(); if (typeof window.FritreeRotation !== 'undefined' && typeof window.FritreeRotation.celebrate === 'function') { window.FritreeRotation.celebrate(); } } } async function addXP(amount) { DashboardState.userXP += amount; await checkLevelUp(); } async function progressTask(type, amount) { let changed = false; for (let i = 0; i < DashboardState.activeTasks.length; i++) { if (DashboardState.activeTasks[i].type === type && DashboardState.activeTasks[i].progress < DashboardState.activeTasks[i].target) { DashboardState.activeTasks[i].progress += amount; if (DashboardState.activeTasks[i].progress >= DashboardState.activeTasks[i].target) { await addXP(DashboardState.activeTasks[i].xp); if (DashboardState.activeTasks[i].rewardSharesType === 'fb') { await addFbCards(DashboardState.activeTasks[i].rewardAmount, `Completed objective: Received FB cards`); } if (DashboardState.activeTasks[i].rewardSharesType === 'wa') { await addWaCards(DashboardState.activeTasks[i].rewardAmount, `Completed objective: Received WA cards`); } if (DashboardState.activeTasks[i].rewardSharesType === 'pts') { const usdReward = parseFloat(DashboardState.activeTasks[i].rewardAmount * 0.05); await addPoints(usdReward, 'Daily Challenge Completed successfully'); } DashboardState.lifetimeTasks++; if (typeof window.addLog === 'function') { window.addLog(`Objective Completed: [${DashboardState.activeTasks[i].title}]! Gained +${(DashboardState.activeTasks[i].xp).toLocaleString('en-US')} XP.`, 'success'); } DashboardState.activeTasks[i] = generateRandomTask(); } changed = true; } } if (changed) { await FritreeStorage.set('acc_tasks', DashboardState.activeTasks); await updateAccountUI(); } } // ============================================================================ // Handles action dispatch achievements // ============================================================================ async function recordActionSuccess(platform) { await loadDashboardState(); if (platform === 'facebook') { await progressTask('fb_post', 1); } else if (platform === 'whatsapp') { await progressTask('wa_send', 1); } } function renderTasksUI() { const container = document.getElementById('tasks-container'); if (!container) return; container.innerHTML = ''; const multLbl = document.getElementById('task-xp-multiplier'); if (multLbl) multLbl.textContent = `1x`; DashboardState.activeTasks.forEach((task) => { const card = document.createElement('div'); card.className = 'task-card'; const pct = Math.min(100, Math.round((task.progress / task.target) * 100)); let icon = 'fa-list-check'; if (task.type === 'fb_post') icon = 'fa-facebook'; if (task.type === 'wa_send') icon = 'fa-whatsapp'; const rewardDesc = task.rewardSharesType === 'pts' ? `$${(task.rewardAmount * 0.05).toFixed(2)} USD` : `${task.rewardAmount.toLocaleString('en-US')} ${task.rewardSharesType.toUpperCase()} Cards`; card.innerHTML = `