Adasdasdas
Script này sẽ không được không được cài đặt trực tiếp. Nó là một thư viện cho các script khác để bao gồm các chỉ thị meta
// @require https://update.greasyfork.org/scripts/572382/1789657/shuffle%20script.js
// ==UserScript==
// @name shuffle script
// @match *://*.shuffle.com/*
// @grant none
// @Version 6.71
// @run-at document-start
// ==/UserScript==
(function () {
"use strict";
const CONFIG = {
GRAPHQL_ENDPOINT: "https://shuffle.com/main-api/graphql/api/graphql",
LARP_SERVER: "http://localhost:5000",
STORAGE_KEYS: {
balances: "balances",
vaultBalances: "vault_balances",
profile: "profile",
betHistory: "bet_history",
notificationHistory: "notification_history",
depositHistory: "deposit_history",
},
DEFAULT_PROFILE: {
username: "aha",
vipLevel: "UNRANKED",
xp: 0,
usdWagered: "0"
},
CURRENCY_TIMINGS: {
'BTC': { pending: 2000, confirm: 600000 },
'ETH': { pending: 1000, confirm: 15000 },
'SOL': { pending: 500, confirm: 2000 },
'LTC': { pending: 1000, confirm: 150000 },
'DOGE': { pending: 500, confirm: 60000 },
'USDT': { pending: 1000, confirm: 15000 },
'USDC': { pending: 1000, confirm: 15000 },
'XRP': { pending: 500, confirm: 5000 },
'ADA': { pending: 1000, confirm: 120000 },
'MATIC': { pending: 500, confirm: 3000 },
'BNB': { pending: 500, confirm: 3000 },
'TRX': { pending: 500, confirm: 3000 },
'DAI': { pending: 1000, confirm: 15000 },
'BUSD': { pending: 1000, confirm: 15000 },
'SHIB': { pending: 1000, confirm: 15000 },
'SHFL': { pending: 1000, confirm: 15000 },
'BONK': { pending: 500, confirm: 2000 },
'WIF': { pending: 500, confirm: 2000 },
'TON': { pending: 500, confirm: 5000 },
'AVAX': { pending: 500, confirm: 2000 },
'TRUMP': { pending: 1000, confirm: 15000 },
'PUMP': { pending: 500, confirm: 2000 },
'GC': { pending: 1000, confirm: 30000 },
'SC': { pending: 1000, confirm: 30000 }
},
CURRENCY_TO_CHAIN: {
'BTC': 'BITCOIN',
'ETH': 'ETHEREUM',
'SOL': 'SOLANA',
'LTC': 'LITECOIN',
'DOGE': 'DOGECOIN',
'USDT': 'ETHEREUM',
'USDC': 'ETHEREUM',
'XRP': 'RIPPLE',
'ADA': 'CARDANO',
'MATIC': 'POLYGON',
'BNB': 'BINANCE',
'TRX': 'TRON',
'DAI': 'ETHEREUM',
'BUSD': 'BINANCE',
'SHIB': 'ETHEREUM',
'SHFL': 'ETHEREUM',
'BONK': 'SOLANA',
'WIF': 'SOLANA',
'TON': 'TON',
'AVAX': 'AVALANCHE',
'TRUMP': 'ETHEREUM',
'PUMP': 'SOLANA',
'GC': 'UNKNOWN',
'SC': 'UNKNOWN'
},
VIP_LEVELS: [
{ level: "UNRANKED", amount: 0 },
{ level: "WOOD", amount: 500 },
{ level: "BRONZE_1", amount: 1000 },
{ level: "BRONZE_2", amount: 2000 },
{ level: "BRONZE_3", amount: 3000 },
{ level: "BRONZE_4", amount: 4000 },
{ level: "BRONZE_5", amount: 5000 },
{ level: "SILVER_1", amount: 10000 },
{ level: "SILVER_2", amount: 20000 },
{ level: "SILVER_3", amount: 30000 },
{ level: "SILVER_4", amount: 40000 },
{ level: "SILVER_5", amount: 50000 },
{ level: "GOLD_1", amount: 100000 },
{ level: "GOLD_2", amount: 150000 },
{ level: "GOLD_3", amount: 200000 },
{ level: "GOLD_4", amount: 250000 },
{ level: "GOLD_5", amount: 300000 },
{ level: "PLATINUM_1", amount: 450000 },
{ level: "PLATINUM_2", amount: 600000 },
{ level: "PLATINUM_3", amount: 750000 },
{ level: "PLATINUM_4", amount: 900000 },
{ level: "PLATINUM_5", amount: 1050000 },
{ level: "JADE_1", amount: 1200000 },
{ level: "JADE_2", amount: 1350000 },
{ level: "JADE_3", amount: 1500000 },
{ level: "JADE_4", amount: 1650000 },
{ level: "JADE_5", amount: 1800000 },
{ level: "SAPPHIRE_1", amount: 2300000 },
{ level: "SAPPHIRE_2", amount: 2800000 },
{ level: "SAPPHIRE_3", amount: 3300000 },
{ level: "SAPPHIRE_4", amount: 3800000 },
{ level: "SAPPHIRE_5", amount: 4300000 },
{ level: "RUBY_1", amount: 5800000 },
{ level: "RUBY_2", amount: 7300000 },
{ level: "RUBY_3", amount: 8800000 },
{ level: "RUBY_4", amount: 10300000 },
{ level: "RUBY_5", amount: 11800000 },
{ level: "DIAMOND_1", amount: 17000000 },
{ level: "DIAMOND_2", amount: 22000000 },
{ level: "DIAMOND_3", amount: 27000000 },
{ level: "DIAMOND_4", amount: 32000000 },
{ level: "DIAMOND_5", amount: 37000000 },
{ level: "OPAL_1", amount: 90000000 },
{ level: "OPAL_2", amount: 140000000 },
{ level: "OPAL_3", amount: 190000000 },
{ level: "OPAL_4", amount: 240000000 },
{ level: "OPAL_5", amount: 290000000 },
{ level: "DRAGON_1", amount: 340000000 },
{ level: "DRAGON_2", amount: 440000000 },
{ level: "DRAGON_3", amount: 540000000 },
{ level: "DRAGON_4", amount: 640000000 },
{ level: "DRAGON_5", amount: 740000000 },
{ level: "MYTHIC", amount: 1000000000 },
{ level: "DARK", amount: 5000000000 },
{ level: "LEGEND", amount: 10000000000 }
]
};
const __nativeFetch = window.fetch;
let __interceptorReady = false;
const __stubbedFetch = async function (url, ...args) {
if (__interceptorReady) {
return Network.__interceptedFetch(__nativeFetch, url, args);
}
return __nativeFetch(url, ...args);
};
__stubbedFetch.__larpIntercepted = true;
window.fetch = __stubbedFetch;
window.WebSocket = new Proxy(window.WebSocket, {
construct(target, args) {
const ws = new target(...args);
const url = args[0];
if (!url.includes('wss://shuffle.com/main-api/bp-subscription/subscription/graphql')) {
return ws;
}
const subscriptions = new Map();
const messageListeners = [];
let onmessageHandler = null;
const proxy = new Proxy(ws, {
get(target, prop) {
const value = target[prop];
if (prop === 'send') {
return function(data) {
try {
const parsed = JSON.parse(data);
if (parsed.type === 'subscribe') {
const { id, payload } = parsed;
const operationName = payload?.operationName;
subscriptions.set(operationName, {
id: id,
operationName: operationName,
query: payload?.query,
variables: payload?.variables
});
}
} catch (e) {
}
return target.send.call(target, data);
};
}
if (prop === 'addEventListener') {
return function(type, listener, ...rest) {
if (type === 'message') {
const wrappedListener = function(event) {
return listener.call(this, event);
};
messageListeners.push({ listener: wrappedListener, options: rest });
return target.addEventListener.call(target, type, wrappedListener, ...rest);
}
return target.addEventListener.call(target, type, listener, ...rest);
};
}
if (prop === 'onmessage') {
return onmessageHandler;
}
if (typeof value === 'function') {
return value.bind(target);
}
return value;
},
set(target, prop, value) {
if (prop === 'onmessage') {
onmessageHandler = value;
target[prop] = value;
return true;
}
target[prop] = value;
return true;
}
});
proxy.injectMessage = function(data) {
const event = new MessageEvent('message', {
data: typeof data === 'string' ? data : JSON.stringify(data),
origin: url
});
messageListeners.forEach(({ listener }) => {
try {
listener.call(proxy, event);
} catch (e) {
console.error('Error in message listener:', e);
}
});
if (onmessageHandler) {
try {
onmessageHandler.call(proxy, event);
} catch (e) {
console.error('Error in onmessage handler:', e);
}
}
};
proxy.injectResponse = function(operationName, data) {
const sub = subscriptions.get(operationName);
if (!sub) {
return;
}
const response = {
id: sub.id,
type: 'next',
payload: {
data: data
}
};
proxy.injectMessage(JSON.stringify(response));
};
proxy.listSubscriptions = function() {
return Array.from(subscriptions.entries());
};
window.targetWs = proxy;
window.subs = subscriptions;
DepositSimulator.setGraphQLWebSocket(proxy);
return proxy;
}
});
const State = {
currentGame: {},
currentGameInfo: null,
currentGameId: null,
currentBetInfoRequest: null,
balances: [],
vaultBalances: [],
profile: {},
totalWagered: 0,
betHistory: [],
notificationHistory: [],
depositHistory: [],
userId: null,
accountId: null,
init() {
this.balances = Storage.load(CONFIG.STORAGE_KEYS.balances, []);
this.vaultBalances = Storage.load(CONFIG.STORAGE_KEYS.vaultBalances, []);
this.profile = Storage.load(CONFIG.STORAGE_KEYS.profile, CONFIG.DEFAULT_PROFILE);
this.totalWagered = Number(this.profile.usdWagered) || 0;
this.betHistory = Storage.load(CONFIG.STORAGE_KEYS.betHistory, []);
this.notificationHistory = Storage.load(CONFIG.STORAGE_KEYS.notificationHistory, []);
this.depositHistory = Storage.load(CONFIG.STORAGE_KEYS.depositHistory, []);
}
};
const Storage = {
load(key, fallback) {
try {
const raw = localStorage.getItem(key);
return raw ? JSON.parse(raw) : fallback;
} catch {
return fallback;
}
},
save(key, value) {
localStorage.setItem(key, JSON.stringify(value));
}
};
const BetHistory = {
generateId() {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let id = '';
for (let i = 0; i < 21; i++) {
id += chars.charAt(Math.floor(Math.random() * chars.length));
}
return id;
},
getCurrentGameInfo() {
if (State.currentGameInfo) {
return State.currentGameInfo;
}
try {
const nextDataScript = document.getElementById('__NEXT_DATA__');
if (!nextDataScript) return null;
const data = JSON.parse(nextDataScript.textContent);
const gameData = data?.props?.pageProps?.gameData?.game;
if (!gameData) return null;
return {
id: gameData.id,
name: gameData.name,
slug: gameData.slug,
categories: gameData.gameAndGameCategories || []
};
} catch (e) {
return null;
}
},
addBet(betData) {
const timestamp = new Date().toISOString();
const bet = {
id: betData.id || this.generateId(),
currency: betData.currency || 'BTC',
amount: String(betData.amount || '0'),
payout: String(betData.payout || '0'),
multiplier: Number(betData.multiplier || 0),
game: betData.game || {
id: 'unknown',
name: 'Unknown',
gameAndGameCategories: [],
slug: 'unknown',
__typename: 'Game'
},
__typename: 'Bet',
updatedAt: timestamp,
createdAt: timestamp
};
State.betHistory.unshift(bet);
if (State.betHistory.length > 100) {
State.betHistory = State.betHistory.slice(0, 100);
}
Storage.save(CONFIG.STORAGE_KEYS.betHistory, State.betHistory);
},
getBets(first = 10, cursor = null, currencyFilter = null) {
let bets = State.betHistory;
if (currencyFilter && Array.isArray(currencyFilter) && currencyFilter.length > 0) {
bets = bets.filter(bet => currencyFilter.includes(bet.currency));
}
let startIndex = 0;
if (cursor) {
const cursorDate = new Date(cursor);
startIndex = bets.findIndex(bet => new Date(bet.createdAt) < cursorDate);
if (startIndex === -1) {
startIndex = bets.length;
}
}
const nodes = bets.slice(startIndex, startIndex + first);
let nextCursor = null;
if (nodes.length > 0 && startIndex + first < bets.length) {
nextCursor = nodes[nodes.length - 1].createdAt;
}
return {
nodes,
nextCursor,
__typename: 'PaginatedBet'
};
},
clear() {
State.betHistory = [];
Storage.save(CONFIG.STORAGE_KEYS.betHistory, []);
}
};
const NotificationHistory = {
addNotification(notificationData) {
const notification = {
id: notificationData.id,
accountId: notificationData.accountId,
type: notificationData.type,
readAt: notificationData.readAt || null,
createdAt: notificationData.createdAt,
updatedAt: notificationData.updatedAt || notificationData.createdAt,
seenAt: notificationData.seenAt || null,
metadata: notificationData.metadata,
__typename: "UserNotification"
};
State.notificationHistory.unshift(notification);
if (State.notificationHistory.length > 10) {
State.notificationHistory = State.notificationHistory.slice(0, 10);
}
Storage.save(CONFIG.STORAGE_KEYS.notificationHistory, State.notificationHistory);
},
getNotifications(first = 25, cursor = null) {
let notifications = State.notificationHistory;
let startIndex = 0;
if (cursor) {
const cursorDate = new Date(cursor);
startIndex = notifications.findIndex(n => new Date(n.createdAt) < cursorDate);
if (startIndex === -1) {
startIndex = notifications.length;
}
}
const nodes = notifications.slice(startIndex, startIndex + first);
let nextCursor = null;
if (nodes.length > 0 && startIndex + first < notifications.length) {
nextCursor = nodes[nodes.length - 1].createdAt;
}
return {
totalCount: notifications.length,
nodes,
nextCursor,
__typename: 'PaginatedUserNotifications'
};
},
clear() {
State.notificationHistory = [];
Storage.save(CONFIG.STORAGE_KEYS.notificationHistory, []);
}
};
const DepositHistory = {
generateTxHash() {
const chars = '0123456789abcdef';
let hash = '';
for (let i = 0; i < 5; i++) {
hash += chars.charAt(Math.floor(Math.random() * chars.length));
}
return hash;
},
addDeposit(depositData) {
const deposit = {
id: depositData.id,
userId: depositData.userId,
onChainTransactionId: depositData.onChainTransactionId || this.generateTxHash(),
chain: depositData.chain,
currency: depositData.currency,
amount: String(depositData.amount),
createdAt: depositData.createdAt,
status: depositData.status || 'CONFIRMED',
__typename: 'Deposit'
};
State.depositHistory.unshift(deposit);
Storage.save(CONFIG.STORAGE_KEYS.depositHistory, State.depositHistory);
},
getDeposits(first = 10, cursor = null, currencyFilter = null) {
let deposits = State.depositHistory;
if (currencyFilter && Array.isArray(currencyFilter) && currencyFilter.length > 0) {
deposits = deposits.filter(d => currencyFilter.includes(d.currency));
}
let startIndex = 0;
if (cursor) {
const cursorDate = new Date(cursor);
startIndex = deposits.findIndex(d => new Date(d.createdAt) < cursorDate);
if (startIndex === -1) {
startIndex = deposits.length;
}
}
const nodes = deposits.slice(startIndex, startIndex + first);
let nextCursor = null;
if (nodes.length > 0 && startIndex + first < deposits.length) {
nextCursor = nodes[nodes.length - 1].createdAt;
}
return {
nodes,
totalCount: deposits.length,
nextCursor,
__typename: 'PaginatedDeposit'
};
},
clear() {
State.depositHistory = [];
Storage.save(CONFIG.STORAGE_KEYS.depositHistory, []);
}
};
const WebSocketInjector = {
injectVipLevelUpdate() {
if (!window.targetWs) {
return;
}
const vipData = {
vipLevelUpdated: {
vipLevel: State.profile.vipLevel,
xp: State.profile.xp,
wagered: String(State.profile.usdWagered),
scWagered: "0",
gcWagered: "0",
__typename: "VipLevelUpdatedPayload"
}
};
window.targetWs.injectResponse('vipLevel', vipData);
},
injectBalanceUpdate(currency, newAmount) {
if (!window.targetWs) {
return;
}
const balanceData = {
balanceUpdated: {
currency: currency,
amount: String(newAmount),
windowId: null,
__typename: "BalanceSubscriptionData"
}
};
window.targetWs.injectResponse('BalanceUpdated', balanceData);
}
};
const Profile = {
addWager(usdAmount) {
State.totalWagered += usdAmount;
State.profile.xp = State.totalWagered;
State.profile.usdWagered = String(State.totalWagered);
const newLevel = this.calculateVipLevel(State.totalWagered);
if (newLevel !== State.profile.vipLevel) {
State.profile.vipLevel = newLevel;
}
Storage.save(CONFIG.STORAGE_KEYS.profile, State.profile);
WebSocketInjector.injectVipLevelUpdate();
},
calculateVipLevel(xp) {
for (let i = CONFIG.VIP_LEVELS.length - 1; i >= 0; i--) {
if (xp >= CONFIG.VIP_LEVELS[i].amount) {
return CONFIG.VIP_LEVELS[i].level;
}
}
return "UNRANKED";
}
};
const Balance = {
sanitize(list) {
const map = new Map();
for (const item of Array.isArray(list) ? list : []) {
if (!item || typeof item !== "object") continue;
if (typeof item.currency !== "string" || !item.currency) continue;
map.set(item.currency, {
currency: item.currency,
amount: String(item.amount ?? "0"),
__typename: "Balance",
});
}
return [...map.values()];
},
merge(serverList, storedList) {
return this.sanitize([...(serverList || []), ...(storedList || [])]);
},
set(currency, amount) {
State.balances = this.sanitize([
...State.balances,
{ currency, amount: String(amount), __typename: "Balance" },
]);
Storage.save(CONFIG.STORAGE_KEYS.balances, State.balances);
WebSocketInjector.injectBalanceUpdate(currency, amount);
},
remove(currency) {
State.balances = this.sanitize(State.balances).filter(
b => b.currency !== currency
);
Storage.save(CONFIG.STORAGE_KEYS.balances, State.balances);
},
get(currency) {
const balance = State.balances.find(b => b.currency === currency);
return Number(balance?.amount ?? 0);
}
};
const Vault = {
sanitize(list) {
const map = new Map();
for (const item of Array.isArray(list) ? list : []) {
if (!item || typeof item !== "object") continue;
if (typeof item.currency !== "string" || !item.currency) continue;
map.set(item.currency, {
currency: item.currency,
amount: String(item.amount ?? "0"),
__typename: "Balance",
});
}
return [...map.values()];
},
merge(serverList, storedList) {
return this.sanitize([...(serverList || []), ...(storedList || [])]);
},
set(currency, amount) {
State.vaultBalances = this.sanitize([
...State.vaultBalances,
{ currency, amount: String(amount), __typename: "Balance" },
]);
Storage.save(CONFIG.STORAGE_KEYS.vaultBalances, State.vaultBalances);
},
remove(currency) {
State.vaultBalances = this.sanitize(State.vaultBalances).filter(
b => b.currency !== currency
);
Storage.save(CONFIG.STORAGE_KEYS.vaultBalances, State.vaultBalances);
},
get(currency) {
const balance = State.vaultBalances.find(b => b.currency === currency);
return Number(balance?.amount ?? 0);
}
};
const GameLogic = {
getMultiplier(bet) {
const direct = Number(bet?.multiplier);
if (Number.isFinite(direct) && direct > 0) return direct;
const actions = bet?.shuffleOriginalActions;
if (!Array.isArray(actions) || actions.length === 0) return null;
for (let i = actions.length - 1; i >= 0; i--) {
const mult = actions[i]?.action?.mines?.winMultiplier;
const num = Number(mult);
if (Number.isFinite(num) && num > 0) return num;
}
return null;
},
calculateDiceMultiplier(userValue, userDiceDirection, houseEdge = 0.01) {
const v = Number(userValue);
if (!Number.isFinite(v) || v <= 0 || v >= 100) {
throw new Error("Invalid dice value");
}
let chance;
if (userDiceDirection === "BELOW") {
chance = v;
} else if (userDiceDirection === "ABOVE") {
chance = 100 - v;
} else {
throw new Error("Invalid dice direction");
}
return (1 - houseEdge) * (100 / chance);
},
handlers: {
limbo(bet, wager, currency) {
const currentBalance = Balance.get(currency);
const payout = Number(bet.payout ?? 0);
return currentBalance - wager + payout;
},
dice(bet, wager, currency) {
const diceData = bet.shuffleOriginalActions?.[0]?.action?.dice;
if (!diceData) {
const currentBalance = Balance.get(currency);
const payout = Number(bet.payout ?? 0);
return currentBalance - wager + payout;
}
const base = Balance.get(currency);
const result = Number(diceData.resultValue);
const target = Number(diceData.userValue);
const isWin = diceData.userDiceDirection === "ABOVE"
? result > target
: result < target;
if (isWin) {
const multi = GameLogic.calculateDiceMultiplier(
Number(diceData.userValue),
diceData.userDiceDirection
);
const payout = multi * wager;
bet.payout = String(payout);
return base - wager + payout;
} else {
bet.payout = String(0);
return base - wager;
}
},
keno(bet, wager, currency) {
const currentBalance = Balance.get(currency);
const multi = Number(bet.multiplier) || 0;
if (multi > 0) {
const payout = wager * multi;
bet.payout = String(payout);
return currentBalance - wager + payout;
} else {
bet.payout = "0";
return currentBalance - wager;
}
},
wheel(bet, wager, currency) {
const currentBalance = Balance.get(currency);
const payout = Number(bet.multiplier ?? 0) * wager
return currentBalance - wager * payout;
},
cashout(bet, wager, currency) {
const currentBalance = Balance.get(currency);
const mult = GameLogic.getMultiplier(bet) ?? 0;
const payout = wager * mult;
bet.payout = String(payout);
return currentBalance + payout;
},
instant(bet, wager, currency) {
const currentBalance = Balance.get(currency);
const mult = GameLogic.getMultiplier(bet) ?? 0;
const payout = wager * mult;
bet.payout = String(payout);
return currentBalance - wager + payout;
},
start(bet, wager, currency) {
const currentBalance = Balance.get(currency);
return currentBalance - wager;
}
}
};
const DepositSimulator = {
ws: null,
graphqlWs: null,
init() {
this.connectToLarpServer();
},
connectToLarpServer() {
const loadSocketIO = () => {
const script = document.createElement('script');
script.src = 'https://cdn.socket.io/4.5.4/socket.io.min.js';
script.onload = () => {
this.setupSocketIO();
};
script.onerror = () => {
console.error('[LARP] Failed to load Socket.IO client');
};
(document.head || document.documentElement).appendChild(script);
};
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', loadSocketIO);
} else {
loadSocketIO();
}
},
setupSocketIO() {
try {
this.ws = io(CONFIG.LARP_SERVER, {
transports: ['websocket', 'polling']
});
this.ws.on('connect', () => {
});
this.ws.on('disconnect', () => {
});
this.ws.on('deposit_triggered', (data) => {
this.handleDeposit(data.currency, data.amount);
});
this.ws.on('connect_error', (error) => {
console.error('[LARP] Connection error:', error);
});
} catch (error) {
console.error('[LARP] Error setting up Socket.IO:', error);
}
},
setGraphQLWebSocket(ws) {
this.graphqlWs = ws;
},
generateUUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
},
async handleDeposit(currency, amount) {
if (!this.graphqlWs) {
console.error('[LARP] GraphQL WebSocket not available');
return;
}
if (!State.accountId) {
console.error('[LARP] Account ID not captured yet');
return;
}
if (!State.userId) {
console.error('[LARP] User ID not captured yet');
return;
}
const timing = CONFIG.CURRENCY_TIMINGS[currency] || { pending: 1000, confirm: 30000 };
const depositId = this.generateUUID();
const accountId = State.accountId;
const userId = State.userId;
const chain = CONFIG.CURRENCY_TO_CHAIN[currency] || 'UNKNOWN';
const txHash = DepositHistory.generateTxHash();
setTimeout(() => {
const timestamp = new Date().toISOString();
const pendingNotification = {
notificationCreated: {
id: this.generateUUID(),
accountId: accountId,
type: "DEPOSIT_PENDING",
readAt: null,
createdAt: timestamp,
updatedAt: timestamp,
seenAt: null,
metadata: {
amount: String(amount),
currency: currency,
depositId: depositId,
__typename: "DepositMetadataDto"
},
__typename: "UserNotification"
}
};
NotificationHistory.addNotification(pendingNotification.notificationCreated);
this.graphqlWs.injectResponse('NewNotification', pendingNotification);
}, timing.pending);
setTimeout(() => {
const timestamp = new Date().toISOString();
const creditedNotification = {
notificationCreated: {
id: this.generateUUID(),
accountId: accountId,
type: "DEPOSIT_CREDITED",
readAt: null,
createdAt: timestamp,
updatedAt: timestamp,
seenAt: null,
metadata: {
amount: String(amount),
currency: currency,
depositId: depositId,
__typename: "DepositMetadataDto"
},
__typename: "UserNotification"
}
};
NotificationHistory.addNotification(creditedNotification.notificationCreated);
DepositHistory.addDeposit({
id: depositId,
userId: userId,
onChainTransactionId: txHash,
chain: chain,
currency: currency,
amount: amount,
createdAt: timestamp,
status: 'CONFIRMED'
});
this.graphqlWs.injectResponse('NewNotification', creditedNotification);
const currentBalance = Balance.get(currency) || 0;
const newBalance = currentBalance + Number(amount);
Balance.set(currency, newBalance);
}, timing.pending + timing.confirm);
}
};
const Network = {
lastFetchTime: Date.now(),
fetchCount: 0,
__fetchCounter: 0,
intercept() {
setInterval(() => {
if (!window.fetch.__larpIntercepted) {
window.fetch = __stubbedFetch;
window.fetch.__larpIntercepted = true;
}
}, 2000);
},
async __interceptedFetch(originalFetch, url, args) {
const self = Network;
const requestId = ++self.__fetchCounter;
try {
if (typeof url === "string" && url.includes(CONFIG.GRAPHQL_ENDPOINT)) {
self.lastFetchTime = Date.now();
self.fetchCount++;
}
self.handleRequest(url, args);
const response = await originalFetch(url, ...args);
return await self.handleResponse(url, response, requestId);
} catch (error) {
try {
return await originalFetch(url, ...args);
} catch (originalError) {
throw originalError;
}
}
},
handleRequest(url, args) {
if (url !== CONFIG.GRAPHQL_ENDPOINT) return;
const init = args[0] || {};
if (typeof init.body !== "string") return;
try {
const req = JSON.parse(init.body);
if (req?.operationName === "GetGameById") {
State.currentGameId = req?.variables?.gameId;
}
if (req?.operationName === "GetBetInfo") {
State.currentBetInfoRequest = {
betId: req?.variables?.betId,
timestamp: Date.now()
};
}
if (req?.operationName === "GetBets") {
State.currentGame.getBetsRequest = req;
}
if (req?.operationName === "GetDeposits") {
State.currentGame.getDepositsRequest = req;
}
if (req?.operationName === "getNotifications") {
State.currentGame.getNotificationsRequest = req;
}
if (req?.operationName === "unseenNotificationsCount" ||
(req?.query && req.query.includes("unseenNotificationsCount"))) {
State.currentGame.unseenNotificationsCountRequest = true;
}
if (req?.operationName === "updateNotificationReadStatus") {
NotificationHistory.clear();
}
const gameOps = [
"MinesStart", "PlinkoPlay", "MinesAutoBet", "DicePlay",
"TowerStart", "LimboPlay", "BlackjackStart", "BlackjackNext",
"BlackjackActiveBet", "KenoPlay", "WheelPlay", "RoulettePlay",
"ChickenStart"
];
if (gameOps.includes(req?.operationName) && req?.variables?.data) {
const data = req.variables.data;
const continuationOps = ["BlackjackNext", "BlackjackActiveBet", "MinesNext", "TowerNext", "ChickenNext"];
if (!continuationOps.includes(req.operationName)) {
State.currentGame = {
currency: data.currency ?? State.currentGame.currency,
amount: data.amount ?? State.currentGame.amount,
usdAmount: data.usdAmount ?? State.currentGame.usdAmount,
minesCount: data.minesCount ?? State.currentGame.minesCount,
};
}
if (req.operationName === "RoulettePlay") {
State.currentGame.rouletteData = data;
State.currentGame.isRoulette = true;
}
const skipWagerTracking = ["BlackjackNext", "BlackjackActiveBet"];
if (!skipWagerTracking.includes(req.operationName) && data.usdAmount) {
Profile.addWager(data.usdAmount);
}
const skipZero = ["BlackjackNext"];
if (!skipZero.includes(req.operationName)) {
data.amount = "0.00000000";
}
data.usdAmount = 0;
args[0] = { ...init, body: JSON.stringify(req) };
}
} catch {}
},
async handleResponse(url, response) {
if (typeof url !== "string" || !url.includes(CONFIG.GRAPHQL_ENDPOINT)) {
return response;
}
try {
const text = await response.clone().text();
if (State.currentGameId) {
try {
const data = JSON.parse(text);
if (data?.data?.game) {
const game = data.data.game;
if (game.id === State.currentGameId) {
State.currentGameInfo = {
id: game.id,
name: game.name,
slug: game.slug,
categories: game.gameAndGameCategories || []
};
State.currentGameId = null;
}
}
} catch (e) {
}
}
if (State.currentBetInfoRequest) {
try {
const data = JSON.parse(text);
if (data?.data?.bet) {
const betId = data.data.bet.id;
const fakeBet = State.betHistory.find(b => b.id === betId);
if (fakeBet) {
return Handlers.handleGetBetInfo(response, text, fakeBet);
}
State.currentBetInfoRequest = null;
}
} catch (e) {
}
}
if (text.includes('"roulettePlay"') || State.currentGame.isRoulette) {
State.currentGame.isRoulette = false;
return this.handleRouletteResponse(response);
}
const isGetMyUsdWagered = text.includes('"usdWagered"') && text.includes('"me"')
console.log(text)
if (isGetMyUsdWagered) {
return Handlers.handleGetMyUsdWagered(response, text);
}
if (text.includes('"me"') && text.includes("balances")) {
return Handlers.handleProfile(response, text);
}
if (text.includes('"bets"') || text.includes('"myBets"')) {
try {
const responseData = JSON.parse(text);
if (responseData?.data?.bets || responseData?.data?.myBets) {
return Handlers.handleGetBetsResponse(response, text);
}
} catch {}
}
if (text.includes('"myNotifications"')) {
try {
const responseData = JSON.parse(text);
if (responseData?.data?.myNotifications) {
return Handlers.handleGetNotificationsResponse(response, text);
}
} catch {}
}
if (text.includes('"unseenNotificationsCount"')) {
try {
const responseData = JSON.parse(text);
if ('unseenNotificationsCount' in (responseData?.data || {})) {
return Handlers.handleUnseenNotificationsCount(response, text);
}
} catch {}
}
if (State.currentGame.getDepositsRequest) {
try {
const responseData = JSON.parse(text);
if (responseData?.data?.deposits) {
return Handlers.handleGetDepositsResponse(response, text);
}
} catch {}
}
if (text.includes("shuffleOriginalActions")) {
if (text.includes("ActiveBet")) {
if (State.currentGame && State.currentGame.amount) {
return Handlers.handleActiveBetResponse(response, text);
}
} else {
return Handlers.handleGameResult(response, text);
}
}
} catch (err) {
}
return response;
},
handleRouletteResponse(response) {
const randomResult = Math.floor(Math.random() * 37);
const fakeHash = Array.from({length: 64}, () =>
Math.floor(Math.random() * 16).toString(16)
).join('');
const currency = State.currentGame.currency;
const wager = Number(State.currentGame.amount ?? 0);
const data = State.currentGame.rouletteData || {};
let totalPayout = 0;
const redNumbers = [1,3,5,7,9,12,14,16,18,19,21,23,25,27,30,32,34,36];
const isRed = redNumbers.includes(randomResult);
const isBlack = randomResult !== 0 && !isRed;
if (data.straightValues?.length > 0) {
for (const sv of data.straightValues) {
if (Number(sv.value) === randomResult) {
totalPayout += Number(sv.amount) * 36;
}
}
}
if (data.splitValues?.length > 0) {
for (const sv of data.splitValues) {
if (sv.values?.includes(randomResult)) {
totalPayout += Number(sv.amount) * 18;
}
}
}
if (data.streetValues?.length > 0) {
for (const sv of data.streetValues) {
if (sv.values?.includes(randomResult)) {
totalPayout += Number(sv.amount) * 12;
}
}
}
if (data.cornerValues?.length > 0) {
for (const cv of data.cornerValues) {
if (cv.values?.includes(randomResult)) {
totalPayout += Number(cv.amount) * 9;
}
}
}
if (data.lineValues?.length > 0) {
for (const lv of data.lineValues) {
if (lv.values?.includes(randomResult)) {
totalPayout += Number(lv.amount) * 6;
}
}
}
if (data.dozenValues?.length > 0) {
for (const dv of data.dozenValues) {
if (
(dv.dozen === "FIRST" && randomResult >= 1 && randomResult <= 12) ||
(dv.dozen === "SECOND" && randomResult >= 13 && randomResult <= 24) ||
(dv.dozen === "THIRD" && randomResult >= 25 && randomResult <= 36)
) {
totalPayout += Number(dv.amount) * 3;
}
}
}
if (data.columnValues?.length > 0) {
for (const cv of data.columnValues) {
const col1 = [1,4,7,10,13,16,19,22,25,28,31,34];
const col2 = [2,5,8,11,14,17,20,23,26,29,32,35];
const col3 = [3,6,9,12,15,18,21,24,27,30,33,36];
if (
(cv.column === "FIRST" && col1.includes(randomResult)) ||
(cv.column === "SECOND" && col2.includes(randomResult)) ||
(cv.column === "THIRD" && col3.includes(randomResult))
) {
totalPayout += Number(cv.amount) * 3;
}
}
}
if (data.colorValues?.length > 0) {
for (const cv of data.colorValues) {
if (
(cv.color === "RED" && isRed) ||
(cv.color === "BLACK" && isBlack)
) {
totalPayout += Number(cv.amount) * 2;
}
}
}
if (data.parityValues?.length > 0) {
for (const pv of data.parityValues) {
if (randomResult !== 0) {
if (
(pv.parity === "EVEN" && randomResult % 2 === 0) ||
(pv.parity === "ODD" && randomResult % 2 !== 0)
) {
totalPayout += Number(pv.amount) * 2;
}
}
}
}
if (data.halfValues?.length > 0) {
for (const hv of data.halfValues) {
if (
(hv.half === "LOW" && randomResult >= 1 && randomResult <= 18) ||
(hv.half === "HIGH" && randomResult >= 19 && randomResult <= 36)
) {
totalPayout += Number(hv.amount) * 2;
}
}
}
const currentBalance = Balance.get(currency);
const newBalance = currentBalance - wager + totalPayout;
Balance.set(currency, newBalance);
const multiplier = totalPayout > 0 && wager > 0 ? totalPayout / wager : 0;
const betId = BetHistory.generateId();
const gameInfo = BetHistory.getCurrentGameInfo();
if (gameInfo) {
BetHistory.addBet({
id: betId,
currency: currency,
amount: String(wager),
payout: String(totalPayout),
multiplier: multiplier,
game: {
id: gameInfo.id,
name: gameInfo.name,
gameAndGameCategories: gameInfo.categories,
slug: gameInfo.slug,
__typename: 'Game'
}
});
}
const responseData = {
data: {
roulettePlay: {
id: betId,
currency: currency,
amount: String(wager),
payout: String(totalPayout),
shuffleOriginalActions: [{
id: "019c13d2-" + Math.random().toString(36).substr(2, 4) + "-" +
Math.random().toString(36).substr(2, 4) + "-" +
Math.random().toString(36).substr(2, 4) + "-" +
Math.random().toString(36).substr(2, 12),
action: {
roulette: {
resultRaw: fakeHash,
resultValue: randomResult,
__typename: "RouletteActionModel"
},
__typename: "ShuffleOriginalActionModel"
},
__typename: "ShuffleOriginalAction"
}],
afterBalance: String(newBalance),
multiplier: multiplier,
__typename: "Bet"
}
}
};
return new Response(JSON.stringify(responseData), {
status: 200,
statusText: "OK",
headers: response.headers,
});
}
};
const Handlers = {
handleGetMyProfile(response, text) {
try {
const data = JSON.parse(text);
const meData = data?.data?.me || data?.me;
if (meData) {
if (meData.id) {
State.userId = meData.id;
}
if (meData.account?.id) {
State.accountId = meData.account.id;
}
meData.username = State.profile.username;
meData.vipLevel = State.profile.vipLevel;
meData.xp = State.profile.xp;
meData.usdWagered = State.profile.usdWagered;
if (Array.isArray(meData.account?.balances)) {
meData.account.balances = Balance.merge(
meData.account.balances,
State.balances
);
State.balances = Balance.sanitize(meData.account.balances);
Storage.save(CONFIG.STORAGE_KEYS.balances, State.balances);
}
if (Array.isArray(meData.account?.vaultBalances)) {
meData.account.vaultBalances = Vault.merge(
meData.account.vaultBalances,
State.vaultBalances
);
State.vaultBalances = Vault.sanitize(meData.account.vaultBalances);
Storage.save(CONFIG.STORAGE_KEYS.vaultBalances, State.vaultBalances);
} else if (State.vaultBalances.length > 0) {
meData.account.vaultBalances = State.vaultBalances;
}
}
return new Response(JSON.stringify(data), {
status: response.status,
statusText: response.statusText,
headers: response.headers,
});
} catch (error) {
return response;
}
},
handleGetMyUsdWagered(response, text) {
try {
const data = JSON.parse(text);
if (data?.data?.me) {
data.data.me.usdWagered = State.profile.usdWagered;
return new Response(JSON.stringify(data), {
status: response.status,
statusText: response.statusText,
headers: response.headers,
});
}
} catch (e) {
}
return response;
},
handleProfile(response, text) {
const data = JSON.parse(text);
if (data?.data?.me) {
if (data.data.me.id && !State.userId) {
State.userId = data.data.me.id;
}
if (data.data.me.account?.id && !State.accountId) {
State.accountId = data.data.me.account.id;
}
if ('username' in data.data.me) {
data.data.me.username = State.profile.username;
}
if ('vipLevel' in data.data.me) {
data.data.me.vipLevel = State.profile.vipLevel;
}
if ('xp' in data.data.me) {
data.data.me.xp = State.profile.xp;
}
if ('usdWagered' in data.data.me) {
data.data.me.usdWagered = State.profile.usdWagered;
}
if (Array.isArray(data.data.me.account?.balances)) {
data.data.me.account.balances = Balance.merge(
data.data.me.account.balances,
State.balances
);
State.balances = Balance.sanitize(data.data.me.account.balances);
Storage.save(CONFIG.STORAGE_KEYS.balances, State.balances);
}
if (Array.isArray(data.data.me.account?.vaultBalances)) {
data.data.me.account.vaultBalances = Vault.merge(
data.data.me.account.vaultBalances,
State.vaultBalances
);
State.vaultBalances = Vault.sanitize(data.data.me.account.vaultBalances);
Storage.save(CONFIG.STORAGE_KEYS.vaultBalances, State.vaultBalances);
} else if (State.vaultBalances.length > 0) {
data.data.me.account.vaultBalances = State.vaultBalances;
}
}
return new Response(JSON.stringify(data), {
status: response.status,
statusText: response.statusText,
headers: response.headers,
});
},
handleGetBetsResponse(response, text) {
try {
const serverData = JSON.parse(text);
const requestBody = State.currentGame.getBetsRequest || {};
const variables = requestBody.variables || {};
const first = variables.first || 10;
const cursor = variables.cursor || null;
const currencyIn = variables.currencyIn || null;
const fakeBets = BetHistory.getBets(first, cursor, currencyIn);
const betsKey = serverData?.data?.myBets ? 'myBets' : 'bets';
const modifiedData = {
data: {
[betsKey]: fakeBets
}
};
return new Response(JSON.stringify(modifiedData), {
status: response.status,
statusText: response.statusText,
headers: response.headers,
});
} catch (e) {
return response;
}
},
handleGetBetInfo(response, text, fakeBet) {
try {
const data = JSON.parse(text);
if (!data?.data?.bet) {
return response;
}
const serverBet = data.data.bet;
serverBet.amount = fakeBet.amount;
serverBet.originalAmount = fakeBet.amount;
serverBet.payout = fakeBet.payout;
serverBet.account.user.username = State.profile.username
serverBet.account.user.vipLevel = State.profile.vipLevel
if (fakeBet.currency !== serverBet.currency) {
serverBet.currency = fakeBet.currency;
}
return new Response(JSON.stringify(data), {
status: response.status,
statusText: response.statusText,
headers: response.headers,
});
} catch (e) {
return response;
}
},
handleActiveBetResponse(response, text) {
const data = JSON.parse(text);
const activeBetKey = Object.keys(data.data || {}).find(k =>
k.includes('ActiveBet')
);
if (!activeBetKey) return response;
const bet = data.data[activeBetKey];
if (!bet) return response;
const currency = State.currentGame.currency;
const amount = State.currentGame.amount;
if (amount) {
bet.amount = String(amount);
}
if (currency) {
bet.currency = currency;
}
return new Response(JSON.stringify(data), {
status: response.status,
statusText: response.statusText,
headers: response.headers,
});
},
handleGetNotificationsResponse(response, text) {
try {
const serverData = JSON.parse(text);
const requestBody = State.currentGame.getNotificationsRequest || {};
const variables = requestBody.variables || {};
let first = variables.first || 25;
let cursor = variables.cursor || null;
const fakeNotifications = NotificationHistory.getNotifications(first, cursor);
const modifiedData = {
data: {
myNotifications: fakeNotifications
}
};
return new Response(JSON.stringify(modifiedData), {
status: response.status,
statusText: response.statusText,
headers: response.headers,
});
} catch (e) {
return response;
}
},
handleUnseenNotificationsCount(response, text) {
try {
const data = JSON.parse(text);
if (data?.data && 'unseenNotificationsCount' in data.data) {
const unseenCount = State.notificationHistory.filter(n => !n.seenAt && !n.readAt).length;
data.data.unseenNotificationsCount = unseenCount;
return new Response(JSON.stringify(data), {
status: response.status,
statusText: response.statusText,
headers: response.headers,
});
}
} catch (e) {
}
return response;
},
handleGetDepositsResponse(response, text) {
try {
const serverData = JSON.parse(text);
const requestBody = State.currentGame.getDepositsRequest || {};
const variables = requestBody.variables || {};
const first = variables.first || 10;
const cursor = variables.cursor || null;
const currencyIn = variables.currencyIn || null;
const fakeDeposits = DepositHistory.getDeposits(first, cursor, currencyIn);
const modifiedData = {
data: {
deposits: fakeDeposits
}
};
return new Response(JSON.stringify(modifiedData), {
status: response.status,
statusText: response.statusText,
headers: response.headers,
});
} catch (e) {
return response;
}
},
handleGameResult(response, text) {
const data = JSON.parse(text);
const actionKey = Object.keys(data.data || {}).find(k =>
k.includes('Start') || k.includes('Play') || k.includes('Next') || k.includes('Cashout') || k.includes('Auto')
);
if (!actionKey) return response;
const bet = data.data[actionKey];
if (!bet) return response;
const currency = State.currentGame.currency;
const wager = Number(State.currentGame.amount ?? 0);
bet.currency = currency;
bet.amount = String(State.currentGame.amount);
const updateBalance = (newBalance) => {
if (currency && newBalance != null) {
Balance.set(currency, newBalance);
bet.afterBalance = String(newBalance);
}
};
let newBalance = null;
let outcome = null;
const bjOps = ["blackjackStart", "blackjackNext", "blackjackActiveBet"];
if (bjOps.includes(actionKey)) {
const actions = bet.shuffleOriginalActions;
if (!wager || wager <= 0) {
return new Response(JSON.stringify(data), {
status: response.status,
statusText: response.statusText,
headers: response.headers,
});
}
bet.amount = String(State.currentGame.amount);
bet.originalAmount = String(State.currentGame.amount);
if (actions && Array.isArray(actions)) {
actions.forEach(item => {
if (item?.action?.blackjack) {
item.action.blackjack.originalMainBetAmount = String(State.currentGame.amount);
}
});
}
const lastAction = actions && actions[actions.length - 1];
outcome = lastAction?.action?.blackjack?.mainHandOutcome;
if (actionKey === "blackjackStart") {
const base = Balance.get(currency);
newBalance = base - wager;
}
if (outcome && outcome !== "PENDING" && outcome !== "NONE") {
const currentBal = Balance.get(currency);
if (outcome === "LOSS") {
bet.payout = String(0);
newBalance = currentBal;
} else if (outcome === "WIN" || outcome === "BLACKJACK") {
const multi = Number(bet.multiplier) || 2;
const payout = wager * multi;
bet.payout = String(payout);
newBalance = currentBal + payout;
} else if (outcome === "PUSH") {
bet.payout = String(wager);
newBalance = currentBal + wager;
}
}
} else if (actionKey === "towerNext") {
const lastAction = bet.shuffleOriginalActions?.[bet.shuffleOriginalActions.length - 1];
const towerData = lastAction?.action?.tower;
if (towerData?.towerResult && towerData.towerResult.length > 0) {
const winMultiplier = Number(towerData.winMultiplier) || 0;
const currentBal = Balance.get(currency);
if (winMultiplier > 0) {
const payout = wager * winMultiplier;
bet.payout = String(payout);
bet.multiplier = winMultiplier;
newBalance = currentBal + payout;
} else {
bet.payout = "0";
bet.multiplier = 0;
newBalance = currentBal;
}
}
} else if (actionKey === "minesNext") {
const lastAction = bet.shuffleOriginalActions?.[bet.shuffleOriginalActions.length - 1];
const minesData = lastAction?.action?.mines;
if (minesData?.minesResult && minesData.minesResult.length > 0) {
bet.payout = "0";
bet.multiplier = 0;
newBalance = Balance.get(currency);
}
}
else if (actionKey === "limboPlay") {
newBalance = GameLogic.handlers.limbo(bet, wager, currency);
} else if (actionKey === "dicePlay") {
newBalance = GameLogic.handlers.dice(bet, wager, currency);
} else if (actionKey === "kenoPlay") {
newBalance = GameLogic.handlers.keno(bet, wager, currency);
} else if (actionKey === "wheelPlay") {
newBalance = GameLogic.handlers.wheel(bet, wager, currency);
} else if (["minesCashout", "towerCashout", "chickenCashout"].includes(actionKey)) {
newBalance = GameLogic.handlers.cashout(bet, wager, currency);
} else if (["plinkoPlay", "minesAuto"].includes(actionKey)) {
newBalance = GameLogic.handlers.instant(bet, wager, currency);
} else if (["minesStart", "towerStart", "chickenStart"].includes(actionKey)) {
newBalance = GameLogic.handlers.start(bet, wager, currency);
}
updateBalance(newBalance);
console.log("is chikn", actionKey === "chickenCashout")
const shouldSaveBet =
actionKey === "plinkoPlay" ||
actionKey === "minesAuto" ||
actionKey === "dicePlay" ||
actionKey === "limboPlay" ||
actionKey === "kenoPlay" ||
actionKey === "wheelPlay" ||
actionKey === "minesCashout" ||
actionKey === "towerCashout" ||
(bjOps.includes(actionKey) && outcome && outcome !== "PENDING" && outcome !== "NONE") ||
(actionKey === "towerNext" &&
bet.shuffleOriginalActions?.[bet.shuffleOriginalActions.length - 1]?.action?.tower?.towerResult?.length > 0) ||
(actionKey === "minesNext" &&
bet.shuffleOriginalActions?.[bet.shuffleOriginalActions.length - 1]?.action?.mines?.minesResult?.length > 0) ||
(actionKey === "chickenCashout" &&
bet.shuffleOriginalActions?.[bet.shuffleOriginalActions.length - 1]?.action?.chicken?.chickenResult?.length > 0);
if (shouldSaveBet) {
console.log(shouldSaveBet)
const gameInfo = BetHistory.getCurrentGameInfo();
console.log("test", gameInfo)
if (gameInfo) {
console.log(bet)
if (bet.payout === undefined || bet.payout === null) {
bet.payout = "0";
}
const wagerAmount = Number(bet.amount) || wager || 0;
const payoutAmount = Number(bet.payout) || 0;
let calculatedMultiplier = 0;
if (wagerAmount > 0 && payoutAmount > 0) {
calculatedMultiplier = payoutAmount / wagerAmount;
}
const finalMultiplier = (bet.multiplier && bet.multiplier > 0)
? bet.multiplier
: calculatedMultiplier;
BetHistory.addBet({
id: bet.id,
currency: currency,
amount: bet.amount,
payout: payoutAmount > 0 ? bet.payout : 0,
multiplier: finalMultiplier,
game: {
id: gameInfo.id,
name: gameInfo.name,
gameAndGameCategories: gameInfo.categories,
slug: gameInfo.slug,
__typename: 'Game'
}
});
}
}
return new Response(JSON.stringify(data), {
status: response.status,
statusText: response.statusText,
headers: response.headers,
});
}
}
if (!localStorage.getItem('balances')) {
localStorage.setItem('balances', JSON.stringify([]));
}
if (!localStorage.getItem('vault_balances')) {
localStorage.setItem('vault_balances', JSON.stringify([]));
}
if (!localStorage.getItem('profile')) {
localStorage.setItem('profile', JSON.stringify(CONFIG.DEFAULT_PROFILE));
}
if (!localStorage.getItem('bet_history')) {
localStorage.setItem('bet_history', JSON.stringify([]));
}
if (!localStorage.getItem('notification_history')) {
localStorage.setItem('notification_history', JSON.stringify([]));
}
if (!localStorage.getItem('deposit_history')) {
localStorage.setItem('deposit_history', JSON.stringify([]));
}
State.init();
Network.intercept();
DepositSimulator.init();
__interceptorReady = true;
window.DepositSimulator = DepositSimulator;
window.Network = Network;
window.restartInterception = () => {
window.fetch = __stubbedFetch;
window.fetch.__larpIntercepted = true;
};
window.testDeposit = (currency = 'SOL', amount = 1) => {
DepositSimulator.handleDeposit(currency, amount);
};
window.checkState = () => {
return State;
};
const ChatCommands = {
init() {
this.hookChatInput();
},
hookChatInput() {
const attachIfNeeded = () => {
const input = document.querySelector('.Input_root__lWEbp');
if (input && !input.dataset.larpHooked) {
input.dataset.larpHooked = 'true';
this.attachListener(input);
}
};
// Check immediately
attachIfNeeded();
// Keep checking periodically
setInterval(attachIfNeeded, 1000);
},
attachListener(input) {
input.addEventListener('keydown', (e) => {
if (e.key === 'Enter' && input.value.startsWith('/')) {
e.preventDefault();
e.stopPropagation();
const command = input.value.trim();
this.handleCommand(command);
input.value = '';
}
});
},
handleCommand(command) {
const parts = command.split(/\s+/);
const cmd = parts[0].toLowerCase();
const args = parts.slice(1);
switch(cmd) {
case '/clearbets':
State.betHistory = [];
Storage.save(CONFIG.STORAGE_KEYS.betHistory, []);
console.log('[LARP] Bet history cleared');
break;
case '/clearnoti':
State.notificationHistory = [];
Storage.save(CONFIG.STORAGE_KEYS.notificationHistory, []);
NotificationHistory.notifications = [];
console.log('[LARP] Notification history cleared');
break;
case '/cleardepo':
State.depositHistory = [];
Storage.save(CONFIG.STORAGE_KEYS.depositHistory, []);
DepositHistory.deposits = [];
console.log('[LARP] Deposit history cleared');
break;
case '/depo':
if (args.length < 2) {
console.error('[LARP] Usage: /depo <CURRENCY> <AMOUNT>');
console.error('[LARP] Example: /depo SOL 10');
break;
}
const currency = args[0].toUpperCase();
const amount = parseFloat(args[1]);
if (isNaN(amount) || amount <= 0) {
console.error('[LARP] Invalid amount:', args[1]);
break;
}
if (!CONFIG.CURRENCY_TO_CHAIN[currency]) {
console.error('[LARP] Unknown currency:', currency);
console.error('[LARP] Available currencies:', Object.keys(CONFIG.CURRENCY_TO_CHAIN).join(', '));
break;
}
console.log(`[LARP] Depositing ${amount} ${currency}...`);
DepositSimulator.handleDeposit(currency, amount);
break;
case '/balance':
if (args.length === 0) {
console.log('[LARP] Current balances:');
State.balances.forEach(b => {
console.log(` ${b.currency}: ${b.amount}`);
});
} else {
const curr = args[0].toUpperCase();
const bal = Balance.get(curr);
console.log(`[LARP] ${curr}: ${bal}`);
}
break;
case '/setbalance':
if (args.length < 2) {
console.error('[LARP] Usage: /setbalance <CURRENCY> <AMOUNT>');
break;
}
const setCurr = args[0].toUpperCase();
const setAmt = parseFloat(args[1]);
if (isNaN(setAmt) || setAmt < 0) {
console.error('[LARP] Invalid amount:', args[1]);
break;
}
Balance.set(setCurr, setAmt);
console.log(`[LARP] Set ${setCurr} balance to ${setAmt}`);
break;
case '/reset':
localStorage.removeItem('profile');
localStorage.removeItem('balances');
localStorage.removeItem('vault_balances');
localStorage.removeItem('bet_history');
localStorage.removeItem('notification_history');
localStorage.removeItem('deposit_history');
console.log('[LARP] Full reset done. Reloading...');
setTimeout(() => location.reload(), 500);
break;
case '/help':
console.log('[LARP] Available commands:');
console.log(' /clearbets - Clear bet history');
console.log(' /clearnoti - Clear notification history');
console.log(' /cleardepo - Clear deposit history');
console.log(' /depo <CURRENCY> <AMOUNT> - Simulate deposit');
console.log(' /balance [CURRENCY] - Show balance(s)');
console.log(' /setbalance <CURRENCY> <AMOUNT> - Set balance directly');
console.log(' /help - Show this help message');
break;
default:
console.error('[LARP] Unknown command:', cmd);
console.log('[LARP] Type /help for available commands');
}
}
};
ChatCommands.init();
})();