- Fix backend to correctly display 18 Net USD Value and 6.81 SOL position - Replace failing SDK subscriptions with direct blockchain account parsing - Parse USDC balance at offset 106 (.53) and SOL position at offset 1208 (6.81 SOL) - Update balance API to return correct totalValue: 18.05 matching Drift UI - Implement direct account data fetching bypassing RPC 410 errors - Create analysis scripts for debugging account data structure - Update /api/drift/balance and /api/drift/positions endpoints Backend now correctly matches Drift UI: - Net USD Value: 18.05 ✅ - SOL Position: 6.81 SOL ✅ - USDC Balance: .53 ✅ - Unrealized PnL: 4.37 ✅
118 lines
4.6 KiB
JavaScript
118 lines
4.6 KiB
JavaScript
#!/usr/bin/env node
|
|
require('dotenv').config();
|
|
const { Connection, PublicKey } = require('@solana/web3.js');
|
|
|
|
async function analyzeAccountData() {
|
|
console.log('🔍 Deep Account Data Analysis\n');
|
|
|
|
try {
|
|
const connection = new Connection(process.env.SOLANA_RPC_URL || 'https://api.mainnet-beta.solana.com', 'confirmed');
|
|
|
|
// The account we know exists
|
|
const accountPDA = new PublicKey('7LonnWut5i3h36xyMA5jbwnGFbnzXUPY2dsPfNaSsrTk');
|
|
|
|
console.log(`📍 Analyzing account: ${accountPDA.toString()}`);
|
|
|
|
const accountInfo = await connection.getAccountInfo(accountPDA);
|
|
if (!accountInfo) {
|
|
console.log('❌ Account not found');
|
|
return;
|
|
}
|
|
|
|
console.log(`📊 Account Owner: ${accountInfo.owner.toString()}`);
|
|
console.log(`📊 Data Length: ${accountInfo.data.length} bytes`);
|
|
console.log(`📊 Lamports: ${accountInfo.lamports}`);
|
|
console.log(`📊 Executable: ${accountInfo.executable}`);
|
|
console.log(`📊 Rent Epoch: ${accountInfo.rentEpoch}\n`);
|
|
|
|
const data = accountInfo.data;
|
|
|
|
// Show hex dump of the data
|
|
console.log('🔍 Raw Data Analysis:');
|
|
console.log('First 128 bytes:');
|
|
console.log(data.slice(0, 128).toString('hex').match(/.{1,32}/g).map((line, i) =>
|
|
`${(i * 16).toString(16).padStart(4, '0')}: ${line}`
|
|
).join('\n'));
|
|
|
|
console.log('\n💰 Searching for potential balance values...');
|
|
|
|
// Look for values that could represent the $118 balance or 6.81 SOL position
|
|
// SOL has 9 decimals, USDC has 6 decimals
|
|
|
|
const targetUSDC = Math.round(118 * 1_000_000); // $118 in USDC scaled (118000000)
|
|
const targetSOL = Math.round(6.81 * 1_000_000_000); // 6.81 SOL scaled (6810000000)
|
|
|
|
console.log(`🎯 Looking for USDC balance: ${targetUSDC} (0x${targetUSDC.toString(16)})`);
|
|
console.log(`🎯 Looking for SOL position: ${targetSOL} (0x${targetSOL.toString(16)})`);
|
|
|
|
// Scan through the data for these values or close approximations
|
|
for (let offset = 0; offset < data.length - 8; offset += 1) {
|
|
try {
|
|
// Try reading as little-endian i64
|
|
const value = data.readBigInt64LE(offset);
|
|
const numberValue = Number(value);
|
|
|
|
// Check if this could be our balance values
|
|
if (Math.abs(numberValue - targetUSDC) < 1000000) { // Within $1
|
|
console.log(`💰 Potential USDC balance found at offset ${offset}: ${numberValue} (${(numberValue / 1_000_000).toFixed(6)} USDC)`);
|
|
}
|
|
|
|
if (Math.abs(numberValue - targetSOL) < 100000000) { // Within 0.1 SOL
|
|
console.log(`🪙 Potential SOL position found at offset ${offset}: ${numberValue} (${(numberValue / 1_000_000_000).toFixed(9)} SOL)`);
|
|
}
|
|
|
|
// Also check for reasonable USD amounts (between $1 and $10,000)
|
|
const asUSDC = numberValue / 1_000_000;
|
|
if (asUSDC > 1 && asUSDC < 10000) {
|
|
console.log(`💵 Potential USD value at offset ${offset}: $${asUSDC.toFixed(2)}`);
|
|
}
|
|
|
|
// Check for reasonable SOL amounts (between 0.1 and 1000 SOL)
|
|
const asSOL = numberValue / 1_000_000_000;
|
|
if (asSOL > 0.1 && asSOL < 1000) {
|
|
console.log(`⚡ Potential SOL value at offset ${offset}: ${asSOL.toFixed(6)} SOL`);
|
|
}
|
|
|
|
} catch (e) {
|
|
// Skip invalid reads
|
|
}
|
|
}
|
|
|
|
console.log('\n🔍 Examining specific important offsets...');
|
|
|
|
// Common offsets in Drift account structure
|
|
const importantOffsets = [
|
|
8, // After discriminator
|
|
40, // After authority
|
|
72, // After sub account ID and other fields
|
|
104, // Our current detection point
|
|
200, // In spot positions area
|
|
500, // Mid spot positions
|
|
1000, // Perp positions area
|
|
2000, // Mid perp positions
|
|
3000, // Late in structure
|
|
4000, // Near end
|
|
];
|
|
|
|
for (const offset of importantOffsets) {
|
|
if (offset + 8 <= data.length) {
|
|
try {
|
|
const value = data.readBigInt64LE(offset);
|
|
const numberValue = Number(value);
|
|
const asUSDC = numberValue / 1_000_000;
|
|
const asSOL = numberValue / 1_000_000_000;
|
|
|
|
console.log(`Offset ${offset.toString().padStart(4)}: ${numberValue.toString().padStart(12)} | $${asUSDC.toFixed(2).padStart(8)} | ${asSOL.toFixed(4).padStart(8)} SOL`);
|
|
} catch (e) {
|
|
console.log(`Offset ${offset.toString().padStart(4)}: [read error]`);
|
|
}
|
|
}
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('❌ Analysis failed:', error.message);
|
|
}
|
|
}
|
|
|
|
analyzeAccountData().catch(console.error);
|