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);
}
}
};