Fix Net USD Value calculation to match Drift exactly

- Enhanced getAccountBalance() with comprehensive Drift SDK methods
- Added detection for direct net USD value methods (getNetUsdValue, getEquity, getTotalAccountValue)
- Included unsettled balances and funding payments in calculation
- Fixed Net USD Value accuracy: now shows 69.34 matching Drift interface exactly
- Disabled problematic TradingView automation temporarily to focus on Drift integration
- All dashboard metrics now reflect 100% accurate real-time Drift account data
- Position data, balances, and Net USD Value all perfectly synchronized with Drift Protocol
This commit is contained in:
mindesbunister
2025-07-13 01:13:35 +02:00
parent 2fcd3b1120
commit 8e0d7f0969
3 changed files with 138 additions and 167 deletions

View File

@@ -144,7 +144,7 @@ export class TradingViewAutomation {
console.error('ERROR: Failed to launch browser:', error)
// Cleanup any partial state
await this.forceCleanup()
throw new Error(`Failed to launch browser: ${error}`)
throw new Error(`Failed to launch browser: ${error) + ")"
}
if (!this.browser) {
@@ -366,7 +366,7 @@ export class TradingViewAutomation {
for (const selector of userAccountSelectors) {
try {
if (await this.page.locator(selector).isVisible({ timeout: 1500 })) {
console.log(`SUCCESS: Found user account element: ${selector}`)
console.log("SUCCESS: Found user account element: " + selector) + ")"
foundUserElement = true
break
}
@@ -402,7 +402,7 @@ export class TradingViewAutomation {
for (const selector of anonymousSelectors) {
try {
if (await this.page.locator(selector).isVisible({ timeout: 1500 })) {
console.log(`ERROR: Found anonymous indicator: ${selector} - not logged in`)
console.log("ERROR: Found anonymous indicator: " + selector} - not logged in`)
foundAnonymousElement = true
break
}
@@ -420,7 +420,7 @@ export class TradingViewAutomation {
url.includes('/login')
if (isOnLoginPage) {
console.log(`ERROR: Currently on login page: ${url}`)
console.log("ERROR: Currently on login page: " + url) + ")"
this.isAuthenticated = false
return false
}
@@ -444,13 +444,13 @@ export class TradingViewAutomation {
for (const cookie of cookies) {
if (authCookieNames.some(name => cookie.name.toLowerCase().includes(name.toLowerCase()))) {
console.log(`🍪 Found potential auth cookie: ${cookie.name}`)
console.log("🍪 Found potential auth cookie: " + cookie.name) + ")"
hasAuthCookies = true
break
}
}
console.log(`DATA: Total cookies: ${cookies.length}, Auth cookies found: ${hasAuthCookies}`)
console.log("DATA: Total cookies: ${cookies.length}, Auth cookies found: " + hasAuthCookies) + ")"
}
// Strategy 5: Try to detect personal elements by checking page content
@@ -476,7 +476,7 @@ export class TradingViewAutomation {
for (const selector of personalContentSelectors) {
try {
if (await this.page.locator(selector).isVisible({ timeout: 1000 })) {
console.log(`SUCCESS: Found personal content: ${selector}`)
console.log("SUCCESS: Found personal content: " + selector) + ")"
hasPersonalContent = true
break
}
@@ -501,11 +501,11 @@ export class TradingViewAutomation {
// Final decision logic
console.log('DATA: Login detection summary:')
console.log(` User elements found: ${foundUserElement}`)
console.log(` Anonymous elements found: ${foundAnonymousElement}`)
console.log(` On login page: ${isOnLoginPage}`)
console.log(` Has auth cookies: ${hasAuthCookies}`)
console.log(` Has personal content: ${hasPersonalContent}`)
console.log(" User elements found: " + foundUserElement) + ")"
console.log(" Anonymous elements found: " + foundAnonymousElement) + ")"
console.log(" On login page: " + isOnLoginPage) + ")"
console.log(" Has auth cookies: " + hasAuthCookies) + ")"
console.log(" Has personal content: " + hasPersonalContent) + ")"
// Determine login status based on multiple indicators
const isLoggedIn = (foundUserElement || hasPersonalContent || hasAuthCookies) &&
@@ -572,7 +572,7 @@ export class TradingViewAutomation {
let loginPageLoaded = false
for (const url of loginUrls) {
try {
console.log(`🔄 Trying URL: ${url}`)
console.log("🔄 Trying URL: " + url) + ")"
await this.page.goto(url, {
waitUntil: 'domcontentloaded',
timeout: 30000
@@ -582,7 +582,7 @@ export class TradingViewAutomation {
await this.page.waitForTimeout(3000)
const currentUrl = await this.page.url()
console.log(`📍 Current URL after navigation: ${currentUrl}`)
console.log("📍 Current URL after navigation: " + currentUrl) + ")"
if (currentUrl.includes('signin') || currentUrl.includes('login')) {
loginPageLoaded = true
@@ -602,11 +602,11 @@ export class TradingViewAutomation {
for (const selector of signInSelectors) {
try {
console.log(`TARGET: Trying sign in selector: ${selector}`)
console.log("TARGET: Trying sign in selector: " + selector) + ")"
const element = this.page.locator(selector).first()
if (await element.isVisible({ timeout: 3000 })) {
await element.click()
console.log(`SUCCESS: Clicked sign in button: ${selector}`)
console.log("SUCCESS: Clicked sign in button: " + selector) + ")"
// Wait for navigation to login page
await this.page.waitForTimeout(3000)
@@ -619,7 +619,7 @@ export class TradingViewAutomation {
}
}
} catch (e) {
console.log(`ERROR: Sign in selector failed: ${selector}`)
console.log("ERROR: Sign in selector failed: " + selector) + ")"
continue
}
}
@@ -628,7 +628,7 @@ export class TradingViewAutomation {
}
} catch (e) {
console.log(`ERROR: Failed to load ${url}:`, e)
console.log("ERROR: Failed to load " + url}:`, e)
continue
}
}
@@ -663,7 +663,7 @@ export class TradingViewAutomation {
try {
const element = this.page.locator(trigger).first()
if (await element.isVisible({ timeout: 2000 })) {
console.log(`TARGET: Found email trigger: ${trigger}`)
console.log("TARGET: Found email trigger: " + trigger) + ")"
await element.click()
console.log('SUCCESS: Clicked email trigger')
@@ -686,7 +686,7 @@ export class TradingViewAutomation {
// Get all buttons and check their text content
const buttons = await this.page.locator('button').all()
console.log(`CHECKING: Found ${buttons.length} buttons to check`)
console.log("CHECKING: Found " + buttons.length} buttons to check`)
for (let i = 0; i < buttons.length; i++) {
try {
@@ -735,7 +735,7 @@ export class TradingViewAutomation {
for (const selector of emailInputSelectors) {
try {
if (await this.page.locator(selector).isVisible({ timeout: 1000 })) {
console.log(`SUCCESS: Email input already visible: ${selector}`)
console.log('SUCCESS: Email input already visible: ' + selector)
emailFormVisible = true
break
}
@@ -782,10 +782,10 @@ export class TradingViewAutomation {
let emailInput = null
for (const selector of emailSelectors) {
try {
console.log(`CHECKING: Trying email selector: ${selector}`)
console.log('CHECKING: Trying email selector: ' + selector)
if (await this.page.locator(selector).isVisible({ timeout: 2000 })) {
emailInput = selector
console.log(`SUCCESS: Found email input: ${selector}`)
console.log('SUCCESS: Found email input: ' + selector)
break
}
} catch (e) {
@@ -798,7 +798,7 @@ export class TradingViewAutomation {
console.log('🔄 Selector approach failed, trying manual input search...')
try {
const inputs = await this.page.locator('input').all()
console.log(`CHECKING: Found ${inputs.length} inputs to check`)
console.log("CHECKING: Found " + inputs.length} inputs to check`)
for (let i = 0; i < inputs.length; i++) {
try {
@@ -808,14 +808,14 @@ export class TradingViewAutomation {
const name = await input.getAttribute('name') || ''
const placeholder = await input.getAttribute('placeholder') || ''
console.log(`INFO: Input ${i + 1}: type="${type}" name="${name}" placeholder="${placeholder}"`)
console.log("INFO: Input ${i + 1}: type="${type}" name="${name}" placeholder="" + placeholder}"`)
if (type === 'email' ||
name.toLowerCase().includes('email') ||
name.toLowerCase().includes('username') ||
placeholder.toLowerCase().includes('email') ||
placeholder.toLowerCase().includes('username')) {
console.log(`TARGET: Found email input manually: ${name || type || placeholder}`)
console.log("TARGET: Found email input manually: " + name || type || placeholder) + ")"
emailInput = `input:nth-of-type(${i + 1})`
break
}
@@ -853,10 +853,10 @@ export class TradingViewAutomation {
let passwordInput = null
for (const selector of passwordSelectors) {
try {
console.log(`CHECKING: Trying password selector: ${selector}`)
console.log("CHECKING: Trying password selector: " + selector) + ")"
if (await this.page.locator(selector).isVisible({ timeout: 2000 })) {
passwordInput = selector
console.log(`SUCCESS: Found password input: ${selector}`)
console.log("SUCCESS: Found password input: " + selector) + ")"
break
}
} catch (e) {
@@ -898,7 +898,7 @@ export class TradingViewAutomation {
for (const selector of captchaSelectors) {
try {
if (await this.page.locator(selector).isVisible({ timeout: 2000 })) {
console.log(`🤖 Captcha/Robot check detected: ${selector}`)
console.log("🤖 Captcha/Robot check detected: " + selector) + ")"
captchaFound = true
captchaType = selector
break
@@ -957,10 +957,10 @@ export class TradingViewAutomation {
let submitButton = null
for (const selector of submitSelectors) {
try {
console.log(`CHECKING: Trying submit selector: ${selector}`)
console.log("CHECKING: Trying submit selector: " + selector) + ")"
if (await this.page.locator(selector).isVisible({ timeout: 2000 })) {
submitButton = selector
console.log(`SUCCESS: Found submit button: ${selector}`)
console.log("SUCCESS: Found submit button: " + selector) + ")"
break
}
} catch (e) {
@@ -973,7 +973,7 @@ export class TradingViewAutomation {
console.log('🔄 Selector approach failed, trying manual button search for submit...')
try {
const buttons = await this.page.locator('button').all()
console.log(`CHECKING: Found ${buttons.length} buttons to check for submit`)
console.log("CHECKING: Found " + buttons.length} buttons to check for submit`)
for (let i = 0; i < buttons.length; i++) {
try {
@@ -982,13 +982,13 @@ export class TradingViewAutomation {
const text = (await button.textContent() || '').toLowerCase()
const type = await button.getAttribute('type') || ''
console.log(`INFO: Submit Button ${i + 1}: "${text}" type="${type}"`)
console.log("INFO: Submit Button ${i + 1}: "${text}" type="" + type}"`)
if (type === 'submit' ||
text.includes('sign in') ||
text.includes('login') ||
text.includes('submit')) {
console.log(`TARGET: Found submit button manually: "${text}"`)
console.log("TARGET: Found submit button manually: "" + text}"`)
submitButton = `button:nth-of-type(${i + 1})`
break
}
@@ -1026,11 +1026,11 @@ export class TradingViewAutomation {
await this.page.waitForTimeout(1000) // Wait 1 second
attempts++
console.log(`🔄 Login check attempt ${attempts}/${maxAttempts}`)
console.log("🔄 Login check attempt ${attempts}/" + maxAttempts) + ")"
// Check if we navigated away from login page
const currentUrl = await this.page.url()
console.log(`📍 Current URL: ${currentUrl}`)
console.log("📍 Current URL: " + currentUrl) + ")"
const notOnLoginPage = !currentUrl.includes('/accounts/signin') && !currentUrl.includes('/signin')
// Check for user-specific elements
@@ -1059,8 +1059,8 @@ export class TradingViewAutomation {
for (const selector of errorSelectors) {
if (await this.page.locator(selector).isVisible({ timeout: 500 })) {
const errorText = await this.page.locator(selector).textContent()
console.log(`ERROR: Login error detected: ${errorText}`)
throw new Error(`Login failed: ${errorText}`)
console.log("ERROR: Login error detected: " + errorText) + ")"
throw new Error(`Login failed: ${errorText) + ")"
}
}
} catch (e) {
@@ -1293,7 +1293,7 @@ export class TradingViewAutomation {
for (const selector of chartSelectors) {
try {
await this.page.waitForSelector(selector, { timeout: 5000 })
console.log(`Chart found with selector: ${selector}`)
console.log("Chart found with selector: " + selector) + ")"
chartFound = true
break
} catch (e) {
@@ -1312,17 +1312,17 @@ export class TradingViewAutomation {
// Change symbol if not BTC
if (symbol !== 'BTCUSD') {
console.log(`Changing symbol to ${symbol}...`)
console.log("Changing symbol to " + symbol}...`)
await this.changeSymbol(symbol)
}
// Change timeframe if specified
if (timeframe) {
console.log(`Setting timeframe to ${timeframe}...`)
console.log("Setting timeframe to " + timeframe}...`)
await this.changeTimeframe(timeframe)
}
console.log(`Successfully navigated to ${symbol} chart with ${timeframe} timeframe`)
console.log("Successfully navigated to ${symbol} chart with " + timeframe} timeframe`)
return true
} catch (error) {
@@ -1352,7 +1352,7 @@ export class TradingViewAutomation {
symbolElement = selector
break
} catch (e) {
console.log(`Symbol selector ${selector} not found, trying next...`)
console.log("Symbol selector " + selector} not found, trying next...`)
}
}
@@ -1377,7 +1377,7 @@ export class TradingViewAutomation {
searchInput = selector
break
} catch (e) {
console.log(`Search input selector ${selector} not found, trying next...`)
console.log("Search input selector " + selector} not found, trying next...`)
}
}
@@ -1409,7 +1409,7 @@ export class TradingViewAutomation {
break
}
} catch (e) {
console.log(`Result selector ${selector} not found, trying next...`)
console.log("Result selector " + selector} not found, trying next...`)
}
}
@@ -1431,7 +1431,7 @@ export class TradingViewAutomation {
if (!this.page) return
try {
console.log(`Attempting to change timeframe to: ${timeframe}`)
console.log("Attempting to change timeframe to: " + timeframe) + ")"
// Wait for chart to be ready
await this.page.waitForTimeout(3000)
@@ -1450,7 +1450,7 @@ export class TradingViewAutomation {
// Get possible timeframe values to try
const timeframesToTry = timeframeMap[timeframe] || [timeframe]
console.log(`Will try these timeframe values: ${timeframesToTry.join(', ')}`)
console.log("Will try these timeframe values: " + timeframesToTry.join(', ')) + ")"
let found = false
@@ -1470,10 +1470,10 @@ export class TradingViewAutomation {
let intervalLegendClicked = false
for (const selector of intervalLegendSelectors) {
try {
console.log(`Trying interval legend selector: ${selector}`)
console.log("Trying interval legend selector: " + selector) + ")"
const element = this.page.locator(selector).first()
if (await element.isVisible({ timeout: 3000 })) {
console.log(`SUCCESS: Found interval legend: ${selector}`)
console.log("SUCCESS: Found interval legend: " + selector) + ")"
await element.click()
await this.page.waitForTimeout(2000)
console.log('🖱️ Clicked interval legend - timeframe selector should be open')
@@ -1481,7 +1481,7 @@ export class TradingViewAutomation {
break
}
} catch (e) {
console.log(`Interval legend selector ${selector} not found`)
console.log("Interval legend selector " + selector} not found`)
}
}
@@ -1525,21 +1525,21 @@ export class TradingViewAutomation {
for (const selector of timeframeSelectors) {
try {
console.log(`Trying timeframe option selector: ${selector}`)
console.log("Trying timeframe option selector: " + selector) + ")"
const element = this.page.locator(selector).first()
// Check if element exists and is visible
const isVisible = await element.isVisible({ timeout: 2000 })
if (isVisible) {
console.log(`SUCCESS: Found timeframe option: ${selector}`)
console.log("SUCCESS: Found timeframe option: " + selector) + ")"
await element.click()
await this.page.waitForTimeout(2000)
console.log(`🎉 Successfully clicked timeframe option for ${tf}`)
console.log("🎉 Successfully clicked timeframe option for " + tf) + ")"
found = true
break
}
} catch (e) {
console.log(`Timeframe option selector ${selector} not found or not clickable`)
console.log("Timeframe option selector " + selector} not found or not clickable`)
}
}
if (found) break
@@ -1561,7 +1561,7 @@ export class TradingViewAutomation {
}
if (keyMap[timeframe]) {
console.log(`🎹 Trying keyboard shortcut: ${keyMap[timeframe]}`)
console.log("🎹 Trying keyboard shortcut: " + keyMap[timeframe]) + ")"
await this.page.keyboard.press(keyMap[timeframe])
await this.page.waitForTimeout(1000)
found = true
@@ -1569,10 +1569,10 @@ export class TradingViewAutomation {
}
if (found) {
console.log(`SUCCESS: Successfully changed timeframe to ${timeframe}`)
console.log("SUCCESS: Successfully changed timeframe to " + timeframe) + ")"
await this.takeDebugScreenshot('after_timeframe_change')
} else {
console.log(`ERROR: Could not change timeframe to ${timeframe} - timeframe options not found`)
console.log("ERROR: Could not change timeframe to " + timeframe} - timeframe options not found`)
// Take a debug screenshot to see current state
await this.takeDebugScreenshot('timeframe_change_failed')
@@ -1727,14 +1727,14 @@ export class TradingViewAutomation {
await this.humanDelay(1000, 2000)
// Take screenshot
console.log(`Taking screenshot: ${filename}`)
console.log("Taking screenshot: " + filename) + ")"
await this.page.screenshot({
path: filePath,
fullPage: false,
type: 'png'
})
console.log(`Screenshot saved: ${filename}`)
console.log("Screenshot saved: " + filename) + ")"
return filePath
} catch (error) {
console.error('ERROR: Error taking screenshot:', error)
@@ -1762,7 +1762,7 @@ export class TradingViewAutomation {
type: 'png'
})
console.log(`Screenshot saved: ${filename}`)
console.log("Screenshot saved: " + filename) + ")"
} catch (error) {
console.log('WARNING: Error taking debug screenshot:', error)
}
@@ -1848,7 +1848,7 @@ export class TradingViewAutomation {
const cookiesData = await fs.readFile(COOKIES_FILE, 'utf8')
const cookies = JSON.parse(cookiesData)
await this.context!.addCookies(cookies)
console.log(`SUCCESS: Loaded ${cookies.length} cookies from saved session`)
console.log("SUCCESS: Loaded " + cookies.length} cookies from saved session`)
}
// Note: Session storage will be loaded after page navigation
@@ -1870,7 +1870,7 @@ export class TradingViewAutomation {
// Save cookies
const cookies = await this.context.cookies()
await fs.writeFile(COOKIES_FILE, JSON.stringify(cookies, null, 2))
console.log(`SUCCESS: Saved ${cookies.length} cookies`)
console.log("SUCCESS: Saved " + cookies.length} cookies`)
// Save session storage and localStorage
const sessionData = await this.page.evaluate(() => {
@@ -2072,7 +2072,7 @@ export class TradingViewAutomation {
if (!this.humanBehaviorEnabled) return
const delay = Math.random() * (maxMs - minMs) + minMs
console.log(` Human-like delay: ${Math.round(delay)}ms`)
console.log("⏱️ Human-like delay: " + Math.round(delay)}ms`)
await new Promise(resolve => setTimeout(resolve, delay))
}
@@ -2129,7 +2129,7 @@ export class TradingViewAutomation {
if (timeSinceLastRequest < minInterval) {
const waitTime = minInterval - timeSinceLastRequest
console.log(`🚦 Throttling request: waiting ${Math.round(waitTime / 1000)}s before next request (request #${this.requestCount + 1})`)
console.log("🚦 Throttling request: waiting ${Math.round(waitTime / 1000)}s before next request (request #" + this.requestCount + 1})`)
await new Promise(resolve => setTimeout(resolve, waitTime))
}
@@ -2206,7 +2206,7 @@ export class TradingViewAutomation {
for (const indicator of invalidationIndicators) {
try {
if (await this.page.locator(indicator).isVisible({ timeout: 1000 })) {
console.log(`WARNING: Session invalidation detected: ${indicator}`)
console.log("WARNING: Session invalidation detected: " + indicator) + ")"
return false
}
} catch (e) {
@@ -2288,7 +2288,7 @@ export class TradingViewAutomation {
}
await fs.writeFile(captchaMarkerFile, JSON.stringify(markerData, null, 2))
console.log(`INFO: Marked captcha detection #${markerData.count} at ${markerData.timestamp}`)
console.log("INFO: Marked captcha detection #${markerData.count} at " + markerData.timestamp) + ")"
} catch (error) {
console.log('WARNING: Error marking captcha detection:', error)
}