diff --git a/agent.user.js b/agent.user.js index 4f3852f..5cff284 100644 --- a/agent.user.js +++ b/agent.user.js @@ -32,7 +32,9 @@ GM_log('[TL] 🏁 Welcome to Binance Alpha Farm Agent.'); const SESSION_STORAGE_KEYS = { SESSION_ID: 'aRah9OhHeijee6sho3baequu9phoovah', + SESSION_BINDED: 'Oos2uoth2thae8Ir8iakahj1OohaMahb', SESSION_TOKEN: 'ThiegiecohViuZ1Iecio7gahphiechub', + BOT_STATUS: 'wiethie3boGhoh3iegh3ohnezei2tauj', CURRENT_TASK: 'Reebo1eitahh2aotumai5jae1neetoh3', CURRENT_TASK_DATA: 'cheishailoh5keePoo6oe2Quie1gaxah', CURRENT_STEP: 'eDusaidu2hooweiMoonahng3fua7aoso', @@ -44,9 +46,10 @@ GM_log('[TL] 🏁 Welcome to Binance Alpha Farm Agent.'); // ====== CONFIGURATION ====== const CONFIG = { - HEARTBEAT_INTERVAL: 10000, // Send heartbeat every 10 seconds + HEARTBEAT_INTERVAL: 10_000, // Send heartbeat every 10 seconds DASHBOARD_UPDATE_INTERVAL: 500, // Update dashboard overlay every 0.5 seconds - TASK_INTERVAL: 1000, // Check for new task every 1 second + TASK_INTERVAL: 10_000, // Check for new task every 10 seconds + REQUEST_TIMEOUT: 10_000, // Request timeout in milliseconds (10 seconds) SERVERS: { local: { label: '🏠 Local', url: 'http://localhost:3000' }, prod: { label: '🌐 Prod', url: 'https://baf.thuanle.me' }, @@ -57,28 +60,39 @@ GM_log('[TL] 🏁 Welcome to Binance Alpha Farm Agent.'); const AppSession = { SESSION_ID: sessionStorage.getItem(SESSION_STORAGE_KEYS.SESSION_ID), + getSessionBinded: () => sessionStorage.getItem(SESSION_STORAGE_KEYS.SESSION_BINDED) === 'true', + setSessionBinded: binded => sessionStorage.setItem(SESSION_STORAGE_KEYS.SESSION_BINDED, binded ? 'true' : 'false'), + getSessionToken: () => sessionStorage.getItem(SESSION_STORAGE_KEYS.SESSION_TOKEN), setSessionToken: token => sessionStorage.setItem(SESSION_STORAGE_KEYS.SESSION_TOKEN, token), + getSessionStatus: () => sessionStorage.getItem(SESSION_STORAGE_KEYS.BOT_STATUS) || AppEnums.BOT_STATUS.STOP, + setSessionStatus: status => sessionStorage.setItem(SESSION_STORAGE_KEYS.BOT_STATUS, status), + // Task state - TrαΊ‘ng thΓ‘i task hiện tαΊ‘i (lΖ°u trong sessionStorage) - getCurrentTask: () => sessionStorage.getItem(SESSION_STORAGE_KEYS.CURRENT_TASK), + getCurrentTask: () => sessionStorage.getItem(SESSION_STORAGE_KEYS.CURRENT_TASK) || BAF_TASKS.NO_TASK, setCurrentTask: task => sessionStorage.setItem(SESSION_STORAGE_KEYS.CURRENT_TASK, task), - + getCurrentTaskData: () => { const data = sessionStorage.getItem(SESSION_STORAGE_KEYS.CURRENT_TASK_DATA); return data ? JSON.parse(data) : null; }, setCurrentTaskData: data => sessionStorage.setItem(SESSION_STORAGE_KEYS.CURRENT_TASK_DATA, JSON.stringify(data)), - - getCurrentStep: () => sessionStorage.getItem(SESSION_STORAGE_KEYS.CURRENT_STEP), + + getCurrentStep: () => sessionStorage.getItem(SESSION_STORAGE_KEYS.CURRENT_STEP) || BAF_TASKS.NO_STEP, setCurrentStep: step => sessionStorage.setItem(SESSION_STORAGE_KEYS.CURRENT_STEP, step), } // ====== APP ENUMS ====== const AppEnums = { BOT_STATUS: { - IDLE: 'idle', + STOP: 'stop', RUNNING: 'running', + ERROR: 'error', + }, + BOT_STARTUP_MODE: { + AUTO: 'auto', + MANUAL: 'manual', } }; @@ -226,7 +240,7 @@ GM_log('[TL] 🏁 Welcome to Binance Alpha Farm Agent.'); const AppSettings = { key_agent_token: 'baf-agent-token', key_server_type: 'baf-server-type', - key_bot_status: 'baf-bot-status', + key_bot_startup_mode: 'baf-bot-startup-mode', key_popup_position: 'baf-popup-position', key_popup_visible: 'baf-popup-visible', key_debug: 'baf-debug', @@ -242,8 +256,8 @@ GM_log('[TL] 🏁 Welcome to Binance Alpha Farm Agent.'); AppState.update({ server_last_seen: null }); }, - getBotStatus: () => GM_getValue(AppSettings.key_bot_status, AppEnums.BOT_STATUS.IDLE), - setBotStatus: (status) => GM_setValue(AppSettings.key_bot_status, status), + getBotStartupMode: () => GM_getValue(AppSettings.key_bot_startup_mode, AppEnums.BOT_STARTUP_MODE.MANUAL), + setBotStartupMode: (mode) => GM_setValue(AppSettings.key_bot_startup_mode, mode), // Popup configuration getPopupPosition: () => GM_getValue(AppSettings.key_popup_position, 4), @@ -357,6 +371,7 @@ GM_log('[TL] 🏁 Welcome to Binance Alpha Farm Agent.'); method: (init.method || 'GET').toUpperCase(), headers: headersToObject(init.headers), data: init.body, + timeout: CONFIG.REQUEST_TIMEOUT, onload: (resp) => { const text = resp.responseText || ''; let data = text; @@ -371,8 +386,28 @@ GM_log('[TL] 🏁 Welcome to Binance Alpha Farm Agent.'); headers: null }); }, - onerror: reject, - ontimeout: () => reject(new Error('GM_xmlhttpRequest timeout')), + onerror: (error) => { + TL.error('net', `Request failed: ${url}`, error); + resolve({ + status: 0, + ok: false, + data: null, + rawText: '', + headers: null, + error: 'Network error' + }); + }, + ontimeout: () => { + TL.error('net', `Request timeout after ${CONFIG.REQUEST_TIMEOUT}ms: ${url}`); + resolve({ + status: 0, + ok: false, + data: null, + rawText: '', + headers: null, + error: 'Request timeout' + }); + }, }); }); }, @@ -380,6 +415,16 @@ GM_log('[TL] 🏁 Welcome to Binance Alpha Farm Agent.'); }; // ====== BAF API MODULE ====== + + + const BAF_TASKS = { + NO_TASK: 'no_task', + + NO_STEP: 'no_step', + }; + + + const BAF = { _getHost: () => AppState.getServer()?.url, @@ -657,37 +702,42 @@ GM_log('[TL] 🏁 Welcome to Binance Alpha Farm Agent.'); // Update overlay content updateContent: () => { - // Get status display - let statusDisplay = ''; - switch (AppSettings.getBotStatus()) { - case AppEnums.BOT_STATUS.IDLE: - statusDisplay = 'πŸ’€ Idle'; - break; - case AppEnums.BOT_STATUS.RUNNING: - statusDisplay = '▢️ Running'; - break; - default: - statusDisplay = AppSettings.getBotStatus(); - } + try { + // Get status display + let statusDisplay = ''; + switch (AppSession.getSessionStatus()) { + case AppEnums.BOT_STATUS.RUNNING: + statusDisplay = '▢️ Running'; + break; + case AppEnums.BOT_STATUS.STOP: + statusDisplay = '⏹️ Stop'; + break; + case AppEnums.BOT_STATUS.ERROR: + statusDisplay = '❌ Error'; + break; + default: + statusDisplay = '❌ Error'; + break; + } - // Get server info - const serverLabel = AppState.getServer()?.label || 'Unknown'; - const serverConnected = AppState.getServerConnected() ? `🟒 (${AppState.getServerLatency()}ms)` : 'πŸ”΄'; + // Get server info + const serverLabel = AppState.getServer()?.label || 'Unknown'; + const serverConnected = AppState.getServerConnected() ? `🟒 (${AppState.getServerLatency()}ms)` : 'πŸ”΄'; - // Get page info - const pageDisplay = AppState.getCurrentPage() || 'unknown'; + // Get page info + const pageDisplay = AppState.getCurrentPage() || 'unknown'; - // Get login status - const loginStatus = AppState.getIsLoggedIn() ? 'βœ…' : '❌'; + // Get login status + const loginStatus = AppState.getIsLoggedIn() ? 'βœ…' : '❌'; - // Get SafetyGuard status - const safetyStatus = { - enabled: AppSettings.getSafetyGuard(), - message: AppSettings.getSafetyGuard() ? 'βœ… Operations Enabled' : '🚨 Operations Blocked' - }; + // Get SafetyGuard status + const safetyStatus = { + enabled: AppSettings.getSafetyGuard(), + message: AppSettings.getSafetyGuard() ? 'βœ… Operations Enabled' : '🚨 Operations Blocked' + }; - // Build content - const content = ` + // Build content + const content = `
BAF Agent Dashboard
@@ -697,9 +747,17 @@ GM_log('[TL] 🏁 Welcome to Binance Alpha Farm Agent.'); πŸ†” Tab: ${AppSession.SESSION_ID.slice(-12)}
- πŸ€– Bot Status: ${statusDisplay} + πŸ€– Bot Status: ${statusDisplay} +
+
+ πŸš€ Startup Mode: ${AppSettings.getBotStartupMode() === AppEnums.BOT_STARTUP_MODE.AUTO ? 'πŸ”„ Auto' : 'βœ‹ Manual'} +
+
+ πŸ“‹ Task: ${AppSession.getCurrentTask() || 'None'} +
+
+ πŸ“ Step: ${AppSession.getCurrentStep() || 'None'}
-
πŸ‘€ Login: ${loginStatus}
@@ -710,74 +768,98 @@ GM_log('[TL] 🏁 Welcome to Binance Alpha Farm Agent.'); 🌐 Server: ${serverLabel} ${serverConnected}
- πŸ› Debug: ${AppSettings.getDebug() ? 'βœ”οΈ ON' : '❌ OFF'} + πŸ› Debug: ${AppSettings.getDebug() ? 'πŸ”ˆ ON' : 'πŸ”‡ OFF'}
- `; + `; - // Update content (excluding position button) - const contentDiv = AppUi.dashboardOverlay.element.querySelector('.baf-content') || document.createElement('div'); - contentDiv.className = 'baf-content'; - contentDiv.innerHTML = content; + // Update content (excluding position button) + const contentDiv = AppUi.dashboardOverlay.element.querySelector('.baf-content') || document.createElement('div'); + contentDiv.className = 'baf-content'; + contentDiv.innerHTML = content; - if (!AppUi.dashboardOverlay.element.querySelector('.baf-content')) { - AppUi.dashboardOverlay.element.appendChild(contentDiv); - } + if (!AppUi.dashboardOverlay.element.querySelector('.baf-content')) { + AppUi.dashboardOverlay.element.appendChild(contentDiv); + } - // Add event listener for safety toggle button - const safetyToggleBtn = contentDiv.querySelector('#safety-toggle-btn'); - if (safetyToggleBtn) { - safetyToggleBtn.onclick = () => { - const currentStatus = { - enabled: AppSettings.getSafetyGuard(), - message: AppSettings.getSafetyGuard() ? 'βœ… Operations Enabled' : '🚨 Operations Blocked' + // Add event listener for safety toggle button + const safetyToggleBtn = contentDiv.querySelector('#safety-toggle-btn'); + if (safetyToggleBtn) { + safetyToggleBtn.onclick = () => { + const currentStatus = { + enabled: AppSettings.getSafetyGuard(), + message: AppSettings.getSafetyGuard() ? 'βœ… Operations Enabled' : '🚨 Operations Blocked' + }; + if (currentStatus.enabled) { + AppSettings.setSafetyGuard(false); + } else { + AppSettings.setSafetyGuard(true); + } + // Update the content to reflect the change + AppUi.dashboardOverlay.updateContent(); }; - if (currentStatus.enabled) { - AppSettings.setSafetyGuard(false); - } else { - AppSettings.setSafetyGuard(true); - } - // Update the content to reflect the change - AppUi.dashboardOverlay.updateContent(); - }; - } + } - // Add event listener for debug toggle button - const debugToggleBtn = contentDiv.querySelector('#debug-toggle-btn'); - if (debugToggleBtn) { - debugToggleBtn.onclick = () => { - const newDebugState = !AppSettings.getDebug(); - AppSettings.setDebug(newDebugState); - // Update the content to reflect the change - AppUi.dashboardOverlay.updateContent(); - }; - } + // Add event listener for debug toggle button + const debugToggleBtn = contentDiv.querySelector('#debug-toggle-btn'); + if (debugToggleBtn) { + debugToggleBtn.onclick = () => { + const newDebugState = !AppSettings.getDebug(); + AppSettings.setDebug(newDebugState); + // Update the content to reflect the change + AppUi.dashboardOverlay.updateContent(); + }; + } - // Add event listener for bot status toggle button - const botStatusToggleBtn = contentDiv.querySelector('#bot-status-toggle-btn'); - if (botStatusToggleBtn) { - botStatusToggleBtn.onclick = () => { - const currentBotStatus = AppSettings.getBotStatus(); - const newBotStatus = currentBotStatus === AppEnums.BOT_STATUS.IDLE ? AppEnums.BOT_STATUS.RUNNING : AppEnums.BOT_STATUS.IDLE; - AppSettings.setBotStatus(newBotStatus); - // Update the content to reflect the change - AppUi.dashboardOverlay.updateContent(); - }; - } + // Add event listener for bot status toggle button + const botStatusToggleBtn = contentDiv.querySelector('#bot-status-toggle-btn'); + if (botStatusToggleBtn) { + botStatusToggleBtn.onclick = () => { + const currentBotStatus = AppSession.getSessionStatus(); + let newBotStatus; + + // Logic: stop/error -> start, start -> stop + if (currentBotStatus === AppEnums.BOT_STATUS.RUNNING) { + newBotStatus = AppEnums.BOT_STATUS.STOP; + } else { + // STOP or ERROR -> RUNNING + newBotStatus = AppEnums.BOT_STATUS.RUNNING; + } + + AppSession.setSessionStatus(newBotStatus); + // Update the content to reflect the change + AppUi.dashboardOverlay.updateContent(); + }; + } - // Add event listener for server toggle button - const serverToggleBtn = contentDiv.querySelector('#server-toggle-btn'); - if (serverToggleBtn) { - serverToggleBtn.onclick = async () => { - const currentServerType = AppSettings.getServerType(); - const newServerType = currentServerType === 'local' ? 'prod' : 'local'; + // Add event listener for startup mode toggle button + const startupModeToggleBtn = contentDiv.querySelector('#startup-mode-toggle-btn'); + if (startupModeToggleBtn) { + startupModeToggleBtn.onclick = () => { + const currentStartupMode = AppSettings.getBotStartupMode(); + const newStartupMode = currentStartupMode === AppEnums.BOT_STARTUP_MODE.AUTO ? AppEnums.BOT_STARTUP_MODE.MANUAL : AppEnums.BOT_STARTUP_MODE.AUTO; + AppSettings.setBotStartupMode(newStartupMode); + // Update the content to reflect the change + AppUi.dashboardOverlay.updateContent(); + }; + } - // Update server type in settings - AppSettings.setServerType(newServerType); - await AppState.update({ server_last_seen: null }); + // Add event listener for server toggle button + const serverToggleBtn = contentDiv.querySelector('#server-toggle-btn'); + if (serverToggleBtn) { + serverToggleBtn.onclick = async () => { + const currentServerType = AppSettings.getServerType(); + const newServerType = currentServerType === 'local' ? 'prod' : 'local'; - // Update the content to reflect the change - AppUi.dashboardOverlay.updateContent(); - }; + // Update server type in settings + AppSettings.setServerType(newServerType); + await AppState.update({ server_last_seen: null }); + + // Update the content to reflect the change + AppUi.dashboardOverlay.updateContent(); + }; + } + } catch (error) { + TL.error('DASHBOARD-OVERLAY', 'Error updating content:', error); } }, @@ -875,7 +957,9 @@ GM_log('[TL] 🏁 Welcome to Binance Alpha Farm Agent.'); const AppServices = { initialize: async () => { await AppState.initialize(); + await AppUi.menu.create(); + AppUi.dashboardOverlay.init(); // Setup observers for dashboard overlay updates @@ -883,9 +967,21 @@ GM_log('[TL] 🏁 Welcome to Binance Alpha Farm Agent.'); await AppServices.registerSession(); + // Set bot status based on startup mode + const startupMode = AppSettings.getBotStartupMode(); + if (startupMode === AppEnums.BOT_STARTUP_MODE.AUTO) { + AppSession.setSessionStatus(AppEnums.BOT_STATUS.RUNNING); + TL.debug('APP-SERVICES', 'Auto startup mode: Bot status set to RUNNING'); + } else { + AppSession.setSessionStatus(AppEnums.BOT_STATUS.STOP); + TL.debug('APP-SERVICES', 'Manual startup mode: Bot status set to STOP'); + } + // Setup interval services AppServices.initInterval(); + AppState.update({ appInitialized: true }); + TL.debug('APP-SERVICES', 'AppServices initialized'); }, @@ -910,8 +1006,15 @@ GM_log('[TL] 🏁 Welcome to Binance Alpha Farm Agent.'); }, registerSession: async () => { const msg = await BAF.register({ session_id: AppSession.SESSION_ID }); - AppSession.setSessionToken(msg.data.token); - TL.debug('APP-SERVICES', `Session token: ${AppSession.getSessionToken()}`); + //if ok, set session token + if (msg.ok) { + AppSession.setSessionToken(msg.data.token); + AppSession.setSessionBinded(true); + TL.debug('APP-SERVICES', `Session token: ${AppSession.getSessionToken()}`); + } else { + AppSession.setSessionBinded(false); + TL.error('APP-SERVICES', `Failed to register session: ${msg.error}`); + } }, // Setup interval services @@ -927,15 +1030,20 @@ GM_log('[TL] 🏁 Welcome to Binance Alpha Farm Agent.'); return serverLastSeen && new Date() - serverLastSeen < 60000; }, + + isReadyToRun: () => { + return AppSession.getSessionBinded() && AppSettings.getSafetyGuard() && AppSession.getSessionStatus() === AppEnums.BOT_STATUS.RUNNING; + }, + // ====== HEARTBEAT SYSTEM ====== heartbeat: async () => { - if (!AppSettings.getSafetyGuard()) return null; + if (!AppServices.isReadyToRun()) return; try { const status = { logged_in: AppState.getIsLoggedIn(), current_page: AppState.getCurrentPage(), - bot_status: AppSettings.getBotStatus(), + bot_status: AppSession.getSessionStatus(), current_task: AppSession.getCurrentTask(), current_task_data: AppSession.getCurrentTaskData(), current_step: AppSession.getCurrentStep(), @@ -962,7 +1070,7 @@ GM_log('[TL] 🏁 Welcome to Binance Alpha Farm Agent.'); const data = { logged_in: AppState.getIsLoggedIn(), current_page: AppState.getCurrentPage(), - bot_status: AppSettings.getBotStatus(), + bot_status: AppSession.getSessionStatus(), current_task: AppSession.getCurrentTask(), current_task_data: AppSession.getCurrentTaskData(), current_step: AppSession.getCurrentStep(), @@ -973,16 +1081,35 @@ GM_log('[TL] 🏁 Welcome to Binance Alpha Farm Agent.'); handleTask: (task) => { TL.debug('APP-SERVICES', `Task: ${JSON.stringify(task, null, 2)}`); + + AppSession.setCurrentTask(task.task); + AppSession.setCurrentTaskData(task.data || null); + AppSession.setCurrentStep(task.step || null); + + switch (task.task) { + case BAF_TASKS.NO_TASK: + TL.debug('APP-TASK', "No task. Sleep now"); + break; + default: + TL.debug('APP-TASK', `Unknown task πŸ›‘`); + AppSession.setSessionStatus(AppEnums.BOT_STATUS.ERROR); + break; + } }, start: async () => { while (true) { - const task = await AppServices.getTask(); - if (task.ok) { - AppServices.handleTask(task.data); + //checking bot status: running? + if (AppSession.getSessionStatus() === AppEnums.BOT_STATUS.RUNNING) { + const task = await AppServices.getTask(); + if (task.ok) { + AppServices.handleTask(task.data); + } + } else { + TL.debug('APP-SERVICES', 'Bot is stopped, skipping task check'); } - await TL.sleep(CONFIG.TASK_INTERVAL); + await TL.delay(CONFIG.TASK_INTERVAL); } } };