- Fixed layout conflicts by removing minimal layout.tsx in favor of complete layout.js - Restored original AI Analysis page with full TradingView integration - Connected enhanced screenshot API to real TradingView automation service - Fixed screenshot gallery to handle both string and object formats - Added image serving API route for screenshot display - Resolved hydration mismatch issues with suppressHydrationWarning - All navigation pages working (Analysis, Trading, Automation, Settings) - TradingView automation successfully capturing screenshots from AI and DIY layouts - Docker Compose v2 compatibility ensured Working features: - Homepage with hero section and status cards - Navigation menu with Trading Bot branding - Real TradingView screenshot capture - AI-powered chart analysis - Multi-layout support (AI + DIY module) - Screenshot gallery with image serving - API endpoints for balance, status, screenshots, trading
117 lines
4.6 KiB
JavaScript
117 lines
4.6 KiB
JavaScript
import { Connection, PublicKey } from '@solana/web3.js'
|
|
import { DriftClient, convertToNumber, QUOTE_PRECISION, BASE_PRECISION, PRICE_PRECISION } from '@drift-labs/sdk'
|
|
import { Wallet } from '@coral-xyz/anchor'
|
|
import dotenv from 'dotenv'
|
|
|
|
async function testAccountDataDecoding() {
|
|
console.log('🔍 Testing account data decoding at correct PDA...')
|
|
|
|
const connection = new Connection(process.env.SOLANA_RPC_URL || 'https://api.mainnet-beta.solana.com')
|
|
|
|
// The PDA that the SDK found
|
|
const correctPDA = new PublicKey('7LonnWut5i3h36xyMA5jbwnGFbnzXUPY2dsPfNaSsrTk')
|
|
|
|
console.log(`📍 Examining account at: ${correctPDA.toString()}`)
|
|
|
|
try {
|
|
// Get account info
|
|
const accountInfo = await connection.getAccountInfo(correctPDA)
|
|
if (!accountInfo) {
|
|
console.log('❌ Account not found')
|
|
return
|
|
}
|
|
|
|
console.log(`📊 Account data length: ${accountInfo.data.length} bytes`)
|
|
console.log(`📊 Account owner: ${accountInfo.owner.toString()}`)
|
|
|
|
const walletPublicKey = new PublicKey('3dG7wayp7b9NBMo92D2qL2sy1curSC4TTmskFpaGDrtA') // Hardcode for now
|
|
|
|
const wallet = new Wallet({
|
|
publicKey: walletPublicKey,
|
|
signTransaction: async (tx) => tx,
|
|
signAllTransactions: async (txs) => txs
|
|
})
|
|
|
|
const driftClient = new DriftClient({
|
|
connection,
|
|
wallet,
|
|
env: 'mainnet-beta',
|
|
opts: { commitment: 'confirmed' }
|
|
})
|
|
|
|
console.log('🔍 Attempting to decode account data...')
|
|
|
|
try {
|
|
// Try to decode the account data using Drift's UserAccount structure
|
|
const userAccount = driftClient.program.account.user.coder.accounts.decode(
|
|
'user',
|
|
accountInfo.data
|
|
)
|
|
|
|
console.log('✅ Successfully decoded user account data!')
|
|
|
|
// Log basic account info
|
|
console.log(`👤 Authority: ${userAccount.authority.toString()}`)
|
|
console.log(`🆔 Sub Account ID: ${userAccount.subAccountId}`)
|
|
|
|
// Check spot positions
|
|
console.log('\\n💰 Spot Positions:')
|
|
if (userAccount.spotPositions && Array.isArray(userAccount.spotPositions)) {
|
|
let totalSpotValue = 0
|
|
for (let i = 0; i < Math.min(userAccount.spotPositions.length, 10); i++) {
|
|
const spotPosition = userAccount.spotPositions[i]
|
|
if (spotPosition.scaledBalance && !spotPosition.scaledBalance.isZero()) {
|
|
const balance = convertToNumber(spotPosition.scaledBalance, QUOTE_PRECISION)
|
|
totalSpotValue += balance
|
|
console.log(` Market ${i}: $${balance.toFixed(2)}`)
|
|
}
|
|
}
|
|
console.log(`📊 Total spot value: $${totalSpotValue.toFixed(2)}`)
|
|
}
|
|
|
|
// Check perp positions
|
|
console.log('\\n📈 Perp Positions:')
|
|
if (userAccount.perpPositions && Array.isArray(userAccount.perpPositions)) {
|
|
let totalPerpValue = 0
|
|
for (let i = 0; i < Math.min(userAccount.perpPositions.length, 10); i++) {
|
|
const perpPosition = userAccount.perpPositions[i]
|
|
if (perpPosition.baseAssetAmount && !perpPosition.baseAssetAmount.isZero()) {
|
|
const size = convertToNumber(perpPosition.baseAssetAmount, BASE_PRECISION)
|
|
const quoteAmount = convertToNumber(perpPosition.quoteEntryAmount, QUOTE_PRECISION)
|
|
console.log(` Market ${i}: Size ${size.toFixed(4)}, Quote ${quoteAmount.toFixed(2)}`)
|
|
totalPerpValue += Math.abs(quoteAmount)
|
|
}
|
|
}
|
|
console.log(`📊 Total perp value: $${totalPerpValue.toFixed(2)}`)
|
|
}
|
|
|
|
// Check if we can calculate total collateral
|
|
console.log('\\n💎 Account Metrics:')
|
|
console.log(` Name: ${userAccount.name ? Buffer.from(userAccount.name).toString().replace(/\\0/g, '') : 'Unnamed'}`)
|
|
console.log(` Max Margin Ratio: ${userAccount.maxMarginRatio}`)
|
|
console.log(` Next Order ID: ${userAccount.nextOrderId}`)
|
|
console.log(` Last Active Slot: ${userAccount.lastActiveSlot}`)
|
|
|
|
} catch (decodeError) {
|
|
console.error('❌ Failed to decode account data:', decodeError)
|
|
|
|
// Try to extract raw data
|
|
console.log('🔍 Examining raw account data...')
|
|
const data = accountInfo.data
|
|
console.log(`First 32 bytes: ${data.slice(0, 32).toString('hex')}`)
|
|
console.log(`Last 32 bytes: ${data.slice(-32).toString('hex')}`)
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('❌ Error examining account:', error)
|
|
}
|
|
}
|
|
|
|
// Load environment
|
|
dotenv.config()
|
|
|
|
// Run the test
|
|
testAccountDataDecoding()
|
|
.then(() => console.log('✅ Test completed'))
|
|
.catch(error => console.error('❌ Test failed:', error))
|