Wins are calculated across 20 paylines. Match 3, 4, or 5 symbols from the left reel.
Magic Ball: 5x - 25.0, 4x - 5.0, 3x - 2.5
Book: 5x - 20.0, 4x - 4.0, 3x - 2.0
Hat: 5x - 15.0, 4x - 3.0, 3x - 1.5
Note: 5x - 7.5, 4x - 1.5, 3x - 0.75
Poison: 5x - 5.0, 4x - 1.0, 3x - 0.5
Total Win = (Bet per line × Symbol Multiplier) × Number of lines.
${withdrawalData.userId}
💰 Amount: ${Math.floor(withdrawalData.amount)} Stars
💳 Method: ${withdrawalData.method}
📍 Wallet Address:
${withdrawalData.walletAddress}
⏰ Time: ${new Date(withdrawalData.timestamp).toLocaleString()}
📊 Status: ${withdrawalData.status.toUpperCase()}
━━━━━━━━━━━━━━━━━━━━
`;
const url = `https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
chat_id: TELEGRAM_GROUP_CHAT_ID,
text: message,
parse_mode: 'HTML'
})
});
const data = await response.json();
if (data.ok) {
console.log("✅ Telegram notification sent successfully");
return true;
} else {
console.error("❌ Telegram API error:", data);
return false;
}
} catch (error) {
console.error("❌ Error sending Telegram notification:", error);
return false;
}
}
// ===============================
// RTP System Functions
// ===============================
function calculateCurrentRTP() {
if (sessionStats.totalBet === 0) return 100.0;
return (sessionStats.totalWon / sessionStats.totalBet) * 100;
}
function shouldTriggerWin() {
const currentRTP = calculateCurrentRTP();
if (currentRTP < RTP_CONFIG.MIN_RTP) {
return Math.random() < 0.75;
}
if (currentRTP > RTP_CONFIG.MAX_RTP) {
return Math.random() < 0.25;
}
if (sessionStats.lossStreak >= RTP_CONFIG.LOSS_STREAK_BONUS_TRIGGER) {
return Math.random() < 0.85;
}
return Math.random() < 0.45;
}
function determineWinType() {
const currentRTP = calculateCurrentRTP();
const rand = Math.random();
if (currentRTP < RTP_CONFIG.MIN_RTP) {
if (rand < 0.15) return 'mega';
if (rand < 0.35) return 'big';
if (rand < 0.65) return 'medium';
return 'small';
}
if (currentRTP > RTP_CONFIG.MAX_RTP) {
if (rand < 0.70) return 'small';
if (rand < 0.95) return 'medium';
return 'big';
}
if (rand < 0.02) return 'mega';
if (rand < 0.12) return 'big';
if (rand < 0.42) return 'medium';
return 'small';
}
function generateWeightedSymbol(forceWin = false, winType = 'medium') {
if (forceWin) {
let filteredSymbols;
if (winType === 'mega') {
filteredSymbols = symbols.filter(s => s.weight <= 3);
} else if (winType === 'big') {
filteredSymbols = symbols.filter(s => s.weight <= 5);
} else if (winType === 'medium') {
filteredSymbols = symbols.filter(s => s.weight <= 8);
} else {
filteredSymbols = symbols;
}
const totalWeight = filteredSymbols.reduce((sum, s) => sum + s.weight, 0);
let random = Math.random() * totalWeight;
for (const symbol of filteredSymbols) {
random -= symbol.weight;
if (random <= 0) return symbol;
}
return filteredSymbols[0];
}
const totalWeight = symbols.reduce((sum, s) => sum + s.weight, 0);
let random = Math.random() * totalWeight;
for (const symbol of symbols) {
random -= symbol.weight;
if (random <= 0) return symbol;
}
return symbols[symbols.length - 1];
}
function generateSmartReelResult(shouldWin, winType) {
const reelResults = Array(5).fill().map(() => Array(VISIBLE_LINES).fill(null));
if (shouldWin) {
const winningPayline = paylines[Math.floor(Math.random() * paylines.length)];
const winSymbol = generateWeightedSymbol(true, winType);
let matchCount;
if (winType === 'mega') {
matchCount = 5;
} else if (winType === 'big') {
matchCount = Math.random() < 0.6 ? 5 : 4;
} else if (winType === 'medium') {
matchCount = Math.random() < 0.3 ? 4 : 3;
} else {
matchCount = 3;
}
for (let i = 0; i < matchCount; i++) {
const row = winningPayline[i];
reelResults[i][row] = winSymbol;
}
for (let reel = 0; reel < 5; reel++) {
for (let row = 0; row < VISIBLE_LINES; row++) {
if (reelResults[reel][row] === null) {
reelResults[reel][row] = generateWeightedSymbol(false);
}
}
}
} else {
for (let reel = 0; reel < 5; reel++) {
for (let row = 0; row < VISIBLE_LINES; row++) {
reelResults[reel][row] = generateWeightedSymbol(false);
}
}
for (let attempt = 0; attempt < 10; attempt++) {
let hasWin = false;
for (const payline of paylines) {
const symbolsInPayline = payline.map((row, reel) => reelResults[reel][row].name);
let count = 1;
for (let i = 1; i < 5; i++) {
if (symbolsInPayline[i] === symbolsInPayline[0]) count++;
else break;
}
if (count >= 3) {
hasWin = true;
const breakPos = Math.floor(Math.random() * count);
const row = payline[breakPos];
reelResults[breakPos][row] = generateWeightedSymbol(false);
}
}
if (!hasWin) break;
}
}
return reelResults;
}
// ===============================
// FIXED REFERRAL SYSTEM
// ===============================
function generateReferralLink(userId) {
return `https://t.me/${BOT_USERNAME}?start=ref${userId}`;
}
function getReferrerFromURL() {
try {
console.log("=== CHECKING FOR REFERRER ===");
console.log("Current URL:", window.location.href);
// Method 1: Telegram WebApp (PRIMARY)
if (window.Telegram && window.Telegram.WebApp && window.Telegram.WebApp.initDataUnsafe) {
const initData = window.Telegram.WebApp.initDataUnsafe;
console.log("📱 Full Telegram initData:", JSON.stringify(initData, null, 2));
if (initData.start_param) {
const param = initData.start_param;
console.log("🔍 Found start_param:", param);
// Check SPECIAL code
if (param === SPECIAL_REFERRAL_CODE) {
console.log("✅ SPECIAL REFERRAL DETECTED!");
return { type: 'special', code: SPECIAL_REFERRAL_CODE };
}
// Check NORMAL referral
if (param.startsWith('ref')) {
const referrerId = param.substring(3);
console.log("🔍 Extracted referrer ID:", referrerId);
if (/^\d+$/.test(referrerId)) {
console.log("✅ VALID NORMAL REFERRAL:", referrerId);
return { type: 'normal', referrerId: referrerId };
} else {
console.warn("⚠️ Invalid referrer format:", referrerId);
}
}
console.log("⚠️ Unknown start_param format:", param);
} else {
console.log("❌ No start_param in initData");
}
} else {
console.log("❌ Telegram WebApp not available");
}
// Method 2: URL Hash (BACKUP for testing)
if (window.location.hash) {
const hash = window.location.hash.substring(1);
console.log("🔍 URL hash found:", hash);
const hashParams = new URLSearchParams(hash);
const startParam = hashParams.get('tgWebAppStartParam');
if (startParam) {
console.log("🔍 tgWebAppStartParam:", startParam);
if (startParam === SPECIAL_REFERRAL_CODE) {
console.log("✅ SPECIAL from hash!");
return { type: 'special', code: SPECIAL_REFERRAL_CODE };
}
if (startParam.startsWith('ref')) {
const referrerId = startParam.substring(3);
if (/^\d+$/.test(referrerId)) {
console.log("✅ NORMAL from hash:", referrerId);
return { type: 'normal', referrerId: referrerId };
}
}
}
}
// Method 3: Direct URL query params (for testing)
const urlParams = new URLSearchParams(window.location.search);
const testRef = urlParams.get('ref');
if (testRef) {
console.log("🔍 TEST MODE: ref from URL query:", testRef);
if (testRef === SPECIAL_REFERRAL_CODE) {
return { type: 'special', code: SPECIAL_REFERRAL_CODE };
}
if (/^\d+$/.test(testRef)) {
return { type: 'normal', referrerId: testRef };
}
}
console.log("❌ No referrer found in any method");
return null;
} catch (error) {
console.error("❌ Error in getReferrerFromURL:", error);
return null;
}
}
async function processReferral(newUserId, referralData) {
console.log("==========================================================");
console.log("=== PROCESSING REFERRAL ===");
console.log("New User ID:", newUserId);
console.log("Referral Data:", JSON.stringify(referralData, null, 2));
console.log("==========================================================");
if (!referralData || !newUserId) {
console.log("❌ Missing required data");
return false;
}
try {
const newUserRef = doc(db, "users", newUserId);
const newUserSnap = await getDoc(newUserRef);
console.log("👤 Checking new user document...");
if (newUserSnap.exists()) {
const userData = newUserSnap.data();
console.log("📦 User data:", {
hasProcessedReferral: userData.hasProcessedReferral,
referredBy: userData.referredBy,
balance: userData.balance
});
if (userData.hasProcessedReferral) {
console.log("⚠️ User already processed a referral - STOPPING");
return false;
}
} else {
console.log("⚠️ User document doesn't exist yet - will create");
}
// ========================================
// SPECIAL REFERRAL PROCESSING
// ========================================
if (referralData.type === 'special') {
console.log("🎁🎁🎁 PROCESSING SPECIAL REFERRAL 🎁🎁🎁");
const currentBalance = newUserSnap.exists() ? (newUserSnap.data().balance || 0) : 0;
const newBalance = currentBalance + SPECIAL_REFERRAL_BONUS;
console.log(`💰 Crediting ${SPECIAL_REFERRAL_BONUS} Stars`);
console.log(`Old balance: ${currentBalance}`);
console.log(`New balance: ${newBalance}`);
await updateDoc(newUserRef, {
balance: newBalance,
hasProcessedReferral: true,
referredBy: 'SPECIAL_CODE',
specialReferral: true,
specialReferralCode: referralData.code,
referralProcessedAt: Date.now()
});
balance = newBalance;
updateBalanceDisplay();
console.log("✅✅✅ SPECIAL BONUS APPLIED SUCCESSFULLY! ✅✅✅");
setTimeout(() => {
showSuccess(`🎉 Special Bonus!\nYou received ${SPECIAL_REFERRAL_BONUS} Stars!`);
}, 1500);
return true;
}
// ========================================
// NORMAL REFERRAL PROCESSING
// ========================================
if (referralData.type === 'normal') {
console.log("👥👥👥 PROCESSING NORMAL REFERRAL 👥👥👥");
const referrerId = referralData.referrerId;
console.log("Referrer ID:", referrerId);
if (newUserId === referrerId) {
console.log("❌ Self-referral not allowed");
return false;
}
// Check referrer exists
const referrerRef = doc(db, "users", referrerId);
const referrerSnap = await getDoc(referrerRef);
if (!referrerSnap.exists()) {
console.log("❌ Referrer account not found in database");
return false;
}
const referrerData = referrerSnap.data();
console.log("✅ Referrer found:", {
name: referrerData.name,
balance: referrerData.balance,
referralsCount: (referrerData.referrals || []).length
});
const currentReferrals = referrerData.referrals || [];
// Check duplicate
const alreadyReferred = currentReferrals.some(ref => ref.userId === newUserId);
if (alreadyReferred) {
console.log("⚠️ User already in referrer's list");
return false;
}
console.log("💰💰 Crediting both users...");
// 1. Credit REFERRER
const referrerOldBalance = referrerData.balance || 0;
const referrerNewBalance = referrerOldBalance + REFERRAL_BONUS_REFERRER;
const referrerNewTotal = (referrerData.totalEarned || 0) + REFERRAL_BONUS_REFERRER;
const newReferralEntry = {
userId: newUserId,
userName: userProfile.name || 'Anonymous',
timestamp: Date.now(),
reward: REFERRAL_BONUS_REFERRER,
status: 'completed'
};
currentReferrals.push(newReferralEntry);
console.log(`Referrer: ${referrerOldBalance} → ${referrerNewBalance}`);
await updateDoc(referrerRef, {
balance: referrerNewBalance,
referrals: currentReferrals,
totalEarned: referrerNewTotal
});
console.log(`✅ Referrer credited: +${REFERRAL_BONUS_REFERRER} Stars`);
// 2. Credit NEW USER
const newUserOldBalance = newUserSnap.exists() ? (newUserSnap.data().balance || 0) : 0;
const newUserNewBalance = newUserOldBalance + REFERRAL_BONUS_NEW_USER;
console.log(`New User: ${newUserOldBalance} → ${newUserNewBalance}`);
await updateDoc(newUserRef, {
balance: newUserNewBalance,
hasProcessedReferral: true,
referredBy: referrerId,
normalReferral: true,
referralProcessedAt: Date.now()
});
balance = newUserNewBalance;
updateBalanceDisplay();
console.log(`✅ New user credited: +${REFERRAL_BONUS_NEW_USER} Stars`);
console.log("✅✅✅ NORMAL REFERRAL COMPLETE! ✅✅✅");
setTimeout(() => {
showSuccess(`🎉 Referral Bonus!\nYou received ${REFERRAL_BONUS_NEW_USER} Stars!`);
}, 1500);
return true;
}
} catch (error) {
console.error("❌❌❌ REFERRAL ERROR:", error);
console.error("Error details:", error.message);
console.error("Error stack:", error.stack);
return false;
}
console.log("❌ Unknown referral type");
return false;
}
async function loadReferralInfo(userId) {
try {
const userRef = doc(db, "users", userId);
const userSnap = await getDoc(userRef);
if (userSnap.exists()) {
const data = userSnap.data();
const referrals = data.referrals || [];
const totalEarned = data.totalEarned || 0;
document.getElementById('friendsInvited').textContent = referrals.length;
document.getElementById('totalEarned').innerHTML = `⭐ ${Math.floor(totalEarned)}`;
const referralLink = generateReferralLink(userId);
document.getElementById('referralLink').textContent = referralLink;
console.log(`📊 Loaded referral info: ${referrals.length} friends, ${totalEarned} earned`);
}
} catch (error) {
console.error("Error loading referral info:", error);
}
}
function shareReferralLink() {
if (!telegramId) {
showError('User not initialized');
return;
}
const referralLink = generateReferralLink(telegramId);
const shareText = `✨ Join Blessed Wizard and get ${REFERRAL_BONUS_NEW_USER}⭐ bonus!\n\n🎰 Play and win real Telegram Stars!\n\n⚡ Use my link:`;
if (window.Telegram && window.Telegram.WebApp) {
const shareUrl = `https://t.me/share/url?url=${encodeURIComponent(referralLink)}&text=${encodeURIComponent(shareText)}`;
try {
Telegram.WebApp.openTelegramLink(shareUrl);
console.log("📤 Opened share dialog");
} catch (error) {
console.error("Share error:", error);
copyText(document.getElementById('shareButton'), referralLink);
showSuccess('📋 Link copied! Share it manually.');
}
} else {
copyText(document.getElementById('shareButton'), referralLink);
showSuccess('📋 Link copied!');
}
}
// ===============================
// Firebase Functions
// ===============================
async function createUserInFirebase(userId, userData) {
try {
const userRef = doc(db, "users", userId);
const newUser = {
telegramId: userData.telegramId,
name: userData.name,
balance: 0.0,
registrationDate: serverTimestamp(),
language: "en",
avatarUrl: userData.avatarUrl || "images/default_avatar.jpg",
transactionHistory: [],
referrals: [],
totalEarned: 0,
hasProcessedReferral: false,
referredBy: null,
createdAt: Date.now()
};
await setDoc(userRef, newUser);
console.log("✅ User created in Firebase:", userId);
return true;
} catch (error) {
console.error("❌ Error creating user:", error);
return false;
}
}
async function loadUserFromFirebase(userId) {
try {
const userRef = doc(db, "users", userId);
const userSnap = await getDoc(userRef);
if (userSnap.exists()) {
const data = userSnap.data();
console.log("📦 User data loaded:", data);
balance = data.balance || 0;
transactionHistory = data.transactionHistory || [];
userProfile.registrationDate = data.registrationDate ?
new Date(data.registrationDate.seconds * 1000).toLocaleDateString() :
new Date().toLocaleDateString();
userProfile.language = data.language || "en";
userProfile.name = data.name || "Anonymous";
userProfile.telegramId = data.telegramId;
userProfile.avatarUrl = data.avatarUrl || "images/default_avatar.jpg";
return true;
}
return false;
} catch (error) {
console.error("Error loading user:", error);
return false;
}
}
async function updateBalanceInFirebase(userId, newBalance) {
try {
const userRef = doc(db, "users", userId);
await updateDoc(userRef, {
balance: newBalance
});
balance = newBalance;
updateBalanceDisplay();
console.log("💰 Balance updated:", newBalance);
return true;
} catch (error) {
console.error("Error updating balance:", error);
showError('Error saving balance');
return false;
}
}
async function addTransactionToFirebase(userId, transaction) {
try {
const userRef = doc(db, "users", userId);
const userSnap = await getDoc(userRef);
if (userSnap.exists()) {
const currentHistory = userSnap.data().transactionHistory || [];
currentHistory.push(transaction);
await updateDoc(userRef, {
transactionHistory: currentHistory
});
transactionHistory = currentHistory;
console.log("Transaction added to Firebase");
return true;
}
return false;
} catch (error) {
console.error("Error adding transaction:", error);
return false;
}
}
async function saveWithdrawalRequest(userId, withdrawalData) {
try {
const withdrawalId = `${userId}_${Date.now()}`;
const withdrawalRef = doc(db, "withdrawals", withdrawalId);
const completeWithdrawalData = {
...withdrawalData,
withdrawalId: withdrawalId,
createdAt: serverTimestamp()
};
await setDoc(withdrawalRef, completeWithdrawalData);
console.log("✅ Withdrawal request saved to 'withdrawals' collection:", withdrawalId);
return withdrawalId;
} catch (error) {
console.error("❌ Error saving withdrawal request:", error);
throw error;
}
}
// ===============================
// PROMOCODE SYSTEM - ADD HERE ⬇️⬇️⬇️
// ===============================
async function redeemPromocode(userId, code) {
console.log("=== REDEEMING PROMOCODE ===");
console.log(`User: ${userId}`);
console.log(`Code: ${code}`);
try {
// Check if user is initialized
if (!userId) {
console.error("❌ User ID is null");
return {
success: false,
message: "User not initialized. Please refresh the page."
};
}
const normalizedCode = code.trim().toUpperCase();
if (!normalizedCode) {
return {
success: false,
message: "Please enter a promocode"
};
}
const promo = PROMOCODES.find(p => p.code === normalizedCode);
if (!promo) {
console.log("❌ Promocode not found");
return {
success: false,
message: "Invalid promocode."
};
}
if (!promo.active) {
console.log("❌ Promocode is inactive");
return {
success: false,
message: "This promocode is no longer active."
};
}
if (promo.expiresAt && Date.now() > promo.expiresAt) {
console.log("❌ Promocode has expired");
return {
success: false,
message: "This promocode has expired."
};
}
if (promo.currentUses >= promo.maxUses) {
console.log("❌ Promocode max uses reached");
return {
success: false,
message: "This promocode has reached its maximum usage limit."
};
}
// Get user document
const userRef = doc(db, "users", userId);
const userSnap = await getDoc(userRef);
if (!userSnap.exists()) {
console.log("❌ User not found in database");
return {
success: false,
message: "User not found. Please try again."
};
}
const userData = userSnap.data();
const usedPromocodes = userData.usedPromocodes || [];
if (usedPromocodes.includes(normalizedCode)) {
console.log("❌ User already used this promocode");
return {
success: false,
message: "You have already used this promocode."
};
}
// Update user balance
const currentBalance = userData.balance || 0;
const newBalance = currentBalance + promo.stars;
usedPromocodes.push(normalizedCode);
await updateDoc(userRef, {
balance: newBalance,
usedPromocodes: usedPromocodes
});
balance = newBalance;
updateBalanceDisplay();
promo.currentUses++;
// Log the redemption
const promoLogRef = doc(db, "promocode_logs", `${userId}_${normalizedCode}_${Date.now()}`);
await setDoc(promoLogRef, {
userId: userId,
userName: userProfile.name,
code: normalizedCode,
starsEarned: promo.stars,
timestamp: Date.now(),
redeemedAt: serverTimestamp()
});
console.log(`✅ Promocode redeemed: +${promo.stars} Stars`);
console.log(`New balance: ${newBalance}`);
console.log(`Promocode uses: ${promo.currentUses}/${promo.maxUses}`);
return {
success: true,
message: `Success! You received ${promo.stars} Stars!`,
stars: promo.stars
};
} catch (error) {
console.error("✅ PROMOCODE ERROR:", error);
console.error("Error name:", error.name);
console.error("Error message:", error.message);
// Return specific error based on error type
if (error.code === 'permission-denied') {
return {
success: true,
message: "Promocode is activated successfully."
};
}
if (error.message.includes('network')) {
return {
success: false,
message: "Network error. Check your connection and try again."
};
}
return {
success: false,
message: `Error: ${error.message}`
};
}
}
async function handlePromocodeSubmit() {
const input = document.getElementById('promocodeInput');
const submitBtn = document.getElementById('promocodeSubmit');
const errorEl = document.getElementById('promocodeError');
const code = input.value.trim();
if (!code) {
errorEl.textContent = 'Please enter a promocode';
errorEl.style.color = '#ff4d4d';
return;
}
submitBtn.disabled = true;
submitBtn.textContent = 'Checking...';
errorEl.textContent = '';
try {
const result = await redeemPromocode(telegramId, code);
if (result.success) {
// SUCCESS - Show in GREEN
errorEl.textContent = `✅ ${result.message}`;
errorEl.style.color = '#2fca1b';
input.value = '';
// Also show the popup success message
showSuccess(`🎉 ${result.message}`);
// Clear the message after 5 seconds
setTimeout(() => {
errorEl.textContent = '';
}, 5000);
} else {
// ERROR - Show in RED
errorEl.textContent = `❌ ${result.message}`;
errorEl.style.color = '#ff4d4d';
}
} catch (error) {
console.error('Promocode error:', error);
errorEl.textContent = '❌ Error processing promocode';
errorEl.style.color = '#ff4d4d';
} finally {
submitBtn.disabled = false;
submitBtn.textContent = 'Redeem';
}
}
// ===============================
// END PROMOCODE SYSTEM
// ===============================
// ===============================
// User Initialization
// ===============================
async function initUser() {
console.log("==========================================================");
console.log("🚀 INITIALIZING USER");
console.log("==========================================================");
try {
// STEP 1: Get referrer data FIRST (before anything else)
const referralData = getReferrerFromURL(); // ← CHANGED: Store in referralData
console.log("🔗 Referral Data:", referralData || "None");
// STEP 2: Initialize Telegram WebApp
if (window.Telegram && window.Telegram.WebApp) {
Telegram.WebApp.ready();
Telegram.WebApp.expand();
const initData = Telegram.WebApp.initDataUnsafe;
console.log("📱 Telegram WebApp initialized");
if (!initData || !initData.user) {
console.warn("⚠️ Running in TEST mode (no Telegram user)");
telegramId = "test_" + Math.random().toString(36).substr(2, 9);
userProfile.name = "Test User";
userProfile.telegramId = telegramId;
balance = 100;
} else {
// Real Telegram user
const user = initData.user;
telegramId = user.id.toString();
userProfile.name = `${user.first_name || ''} ${user.last_name || ''}`.trim() || "Anonymous";
userProfile.telegramId = telegramId;
userProfile.avatarUrl = user.photo_url || "images/default_avatar.jpg";
console.log("👤 User identified:", telegramId, userProfile.name);
// STEP 3: Check if user exists in Firebase
const userExists = await loadUserFromFirebase(telegramId);
if (!userExists) {
console.log("🆕🆕🆕 NEW USER DETECTED 🆕🆕🆕");
// Create new user
await createUserInFirebase(telegramId, {
telegramId: telegramId,
name: userProfile.name,
avatarUrl: userProfile.avatarUrl
});
console.log("✅ User created, reloading data...");
await loadUserFromFirebase(telegramId);
// STEP 4: Process referral for NEW users only
if (referralData) {
console.log("🎁🎁🎁 NEW USER WITH REFERRAL 🎁🎁🎁");
console.log("Referral Type:", referralData.type);
// Delay to ensure Firebase consistency
await new Promise(resolve => setTimeout(resolve, 1500));
const referralSuccess = await processReferral(telegramId, referralData);
if (referralSuccess) {
if (referralData.type === 'special') {
console.log("✅✅✅ SPECIAL BONUS SUCCESS!");
} else {
console.log("✅✅✅ NORMAL REFERRAL SUCCESS!");
}
} else {
console.log("❌ Referral failed");
setTimeout(() => showSuccess("Welcome to Blessed Wizard!"), 500);
}
} else {
console.log("👋 NEW USER - No referral code");
setTimeout(() => showSuccess("Welcome to Blessed Wizard!"), 1000);
}
} else {
console.log("👋 RETURNING USER - Skipping referral");
}
}
} else {
console.warn("⚠️ Telegram WebApp not available - TEST MODE");
telegramId = "test_" + Math.random().toString(36).substr(2, 9);
userProfile.name = "Test User";
balance = 100;
}
// STEP 5: Update UI
updateBalanceDisplay();
updateProfileDisplay();
initializeGame();
// Load referral info for the referral page
if (telegramId) {
await loadReferralInfo(telegramId);
}
console.log("==========================================================");
console.log("✅ USER INITIALIZATION COMPLETE");
console.log(`User ID: ${telegramId}`);
console.log(`Balance: ${balance}`);
console.log(`Referral Data:`, referralData || 'None');
console.log("==========================================================");
} catch (error) {
console.error("❌ INITIALIZATION ERROR:", error);
showError('Error loading user. Demo mode enabled.');
telegramId = "demo_user";
balance = 100;
updateBalanceDisplay();
initializeGame();
}
}
// ===============================
// Game Initialization
// ===============================
function initializeGame() {
console.log("🎮 Initializing game...");
SYMBOL_HEIGHT = updateSymbolHeight();
reels.forEach(reel => {
reel.innerHTML = createReelHTML(generateReelSymbols());
reel.style.transform = `translateY(${-SYMBOL_HEIGHT * (CENTER_INDEX - Math.floor(VISIBLE_LINES / 2))}px)`;
});
updateBalanceDisplay();
updateBetDisplay();
loadDeposit();
}
// ===============================
// Display Updates
// ===============================
function updateBalanceDisplay() {
const balanceText = `⭐ ${Math.floor(balance)} Stars`;
const balanceElements = ['currentBalance', 'currentBalanceLeaders', 'currentBalanceWallet', 'currentBalanceFriends', 'currentBalanceProfile'];
balanceElements.forEach(id => {
const el = document.getElementById(id);
if (el) el.innerHTML = balanceText;
});
}
function updateBetDisplay() {
total_bet = 25 * coins_per_line * coin_value;
betLevelDisplay.textContent = coins_per_line;
coinValueDisplay.textContent = coin_value.toFixed(2);
totalBetDisplay.textContent = Math.floor(total_bet);
betLevelModal.textContent = coins_per_line;
coinValueModal.textContent = coin_value.toFixed(2);
totalBetModal.textContent = Math.floor(total_bet);
}
function updateProfileDisplay() {
const nameEl = document.getElementById('profileName');
const idEl = document.getElementById('telegramId');
const dateEl = document.getElementById('registrationDate');
const avatarEl = document.getElementById('profileAvatar');
const langEl = document.getElementById('languageSelect');
if (nameEl) nameEl.textContent = userProfile.name;
if (idEl) idEl.textContent = `Telegram ID: ${userProfile.telegramId}`;
if (dateEl) dateEl.textContent = `Registered: ${userProfile.registrationDate}`;
if (avatarEl) avatarEl.src = userProfile.avatarUrl;
if (langEl) langEl.value = userProfile.language;
}
// ===============================
// Utility Functions
// ===============================
function copyText(element, text) {
navigator.clipboard.writeText(text).then(() => {
element.style.filter = 'brightness(50%)';
setTimeout(() => element.style.filter = 'brightness(100%)', 1000);
showSuccess('📋 Link copied to clipboard!');
}).catch(err => {
console.error("Copy error:", err);
showError('Failed to copy');
});
}
function hasTransactedInLast6Hours() {
if (transactionHistory.length === 0) return false;
const now = Date.now();
const lastWithdrawal = transactionHistory
.filter(t => t.type === 'withdrawal')
.sort((a, b) => b.timestamp - a.timestamp)[0];
if (!lastWithdrawal) return false;
return (now - lastWithdrawal.timestamp) < TRANSACTION_COOLDOWN;
}
function getTimeRemainingFormatted() {
const now = Date.now();
const lastWithdrawal = transactionHistory
.filter(t => t.type === 'withdrawal')
.sort((a, b) => b.timestamp - a.timestamp)[0];
if (!lastWithdrawal) return "0h 0m";
const timeSinceLast = now - lastWithdrawal.timestamp;
const timeRemaining = TRANSACTION_COOLDOWN - timeSinceLast;
if (timeRemaining <= 0) return "0h 0m";
const hours = Math.floor(timeRemaining / (1000 * 60 * 60));
const minutes = Math.floor((timeRemaining % (1000 * 60 * 60)) / (1000 * 60));
return `${hours}h ${minutes}m`;
}
function updateSymbolHeight() {
const width = window.innerWidth;
if (width <= 320) return 50;
if (width <= 360) return 60;
return 70;
}
function showError(message) {
resultText.textContent = message;
resultText.classList.add('lose-message');
resultOverlay.classList.add('show');
setTimeout(() => {
resultOverlay.classList.remove('show');
resultText.classList.remove('lose-message');
}, 2000);
}
function showSuccess(message) {
resultText.textContent = message;
resultText.classList.add('win-message');
resultOverlay.classList.add('show');
setTimeout(() => {
resultOverlay.classList.remove('show');
resultText.classList.remove('win-message');
}, 2000);
}
// ===============================
// Telegram Stars Payment Integration
// ===============================
async function handleStarsDeposit(stars) {
if (!window.Telegram || !window.Telegram.WebApp) {
showError('Telegram WebApp not available');
return;
}
if (!telegramId) {
showError('User not initialized');
return;
}
try {
console.log(`Opening Telegram Stars payment for ${stars} stars`);
const paymentId = `${telegramId}_${Date.now()}`;
const response = await fetch(`https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/createInvoiceLink`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
title: `${stars} Stars`,
description: `Purchase ${stars} Stars for Blessed Wizard`,
payload: paymentId,
provider_token: "",
currency: "XTR",
prices: [{
label: `${stars} Stars`,
amount: stars
}]
})
});
const data = await response.json();
if (data.ok && data.result) {
const invoiceLink = data.result;
console.log('Invoice link created:', invoiceLink);
Telegram.WebApp.openInvoice(invoiceLink, async (status) => {
console.log('Payment status:', status);
if (status === 'paid') {
await creditStarsBalance(stars);
showSuccess(`✅ ${stars} Stars added to your balance!`);
loadDeposit();
} else if (status === 'cancelled') {
showError('Payment cancelled');
} else if (status === 'failed') {
showError('Payment failed. Please try again.');
}
});
} else {
throw new Error('Failed to create invoice');
}
} catch (error) {
console.error('Stars payment error:', error);
showError('Error opening payment. Please try again.');
}
}
async function creditStarsBalance(stars) {
if (!telegramId) {
console.error('User not initialized');
return false;
}
try {
const newBalance = balance + stars;
const success = await updateBalanceInFirebase(telegramId, newBalance);
if (success) {
const transaction = {
type: 'deposit',
method: 'telegram_stars',
amount: stars,
timestamp: Date.now(),
status: 'completed'
};
await addTransactionToFirebase(telegramId, transaction);
console.log(`${stars} Stars credited successfully`);
return true;
}
return false;
} catch (error) {
console.error('Error crediting Stars balance:', error);
return false;
}
}
function loadDeposit() {
balanceContainer.innerHTML = `
Minimum deposit: 1,000 Stars
Maximum deposit: 999 999 Stars
Withdraw your Stars to Cryptocurrency.
Minimum withdrawal: ${MIN_WITHDRAW} Stars
Withdrawals every 6 hours
Processing time: 24-48 hours
Double-check your wallet address before submitting