Files
trading_bot_v3/app/api/wallet/balance/route.js
mindesbunister ac50d9622c Enhance trading system: real wallet validation, auto-discovery, and hot reloading
- Update trade validation to use real wallet balances from /api/wallet/balance
- Enhance wallet API to auto-discover all major SPL tokens (USDC, USDT, etc.)
- Improve AIAnalysisPanel to better extract and pass AI values to TradeModal
- Configure Docker Compose for hot reloading with proper volume mounts
- Remove hardcoded balance fallbacks in favor of live wallet data

Result: Trading validation now uses accurate real-time wallet balances
2025-07-16 11:37:20 +02:00

155 lines
5.8 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { NextResponse } from 'next/server'
import { Connection, Keypair, PublicKey } from '@solana/web3.js'
import { getAssociatedTokenAddress, getAccount, TOKEN_PROGRAM_ID } from '@solana/spl-token'
export async function GET() {
try {
console.log('💰 Fetching real Solana wallet balance...')
// Check if wallet is configured
if (!process.env.SOLANA_PRIVATE_KEY) {
return NextResponse.json({
success: false,
error: 'Wallet not configured',
message: 'SOLANA_PRIVATE_KEY not found in environment'
}, { status: 503 })
}
// Initialize connection and keypair
const rpcUrl = process.env.SOLANA_RPC_URL || 'https://api.mainnet-beta.solana.com'
const connection = new Connection(rpcUrl, 'confirmed')
const privateKeyArray = JSON.parse(process.env.SOLANA_PRIVATE_KEY)
const keypair = Keypair.fromSecretKey(new Uint8Array(privateKeyArray))
// Get SOL balance
const balance = await connection.getBalance(keypair.publicKey)
const solBalance = balance / 1000000000 // Convert lamports to SOL
// Get current SOL price with fallback
let solPrice = 168.11 // Fallback price from our current market data
let change24h = 0
try {
const priceResponse = await fetch(
'https://api.coingecko.com/api/v3/simple/price?ids=solana&vs_currencies=usd&include_24hr_change=true'
)
if (priceResponse.ok) {
const priceData = await priceResponse.json()
if (priceData.solana?.usd) {
solPrice = priceData.solana.usd
change24h = priceData.solana.usd_24h_change || 0
console.log(`💰 Using live SOL price: $${solPrice}`)
} else {
console.log(`⚠️ Using fallback SOL price: $${solPrice} (CoinGecko data invalid)`)
}
} else {
console.log(`⚠️ Using fallback SOL price: $${solPrice} (CoinGecko rate limited)`)
}
} catch (priceError) {
console.log(`⚠️ Using fallback SOL price: $${solPrice} (CoinGecko error: ${priceError.message})`)
}
const usdValue = solBalance * solPrice
console.log(`💎 Real wallet: ${solBalance.toFixed(4)} SOL ($${usdValue.toFixed(2)})`)
// Check for other token balances - DISCOVER ALL TOKENS
const positions = [
{
symbol: 'SOL',
price: solPrice,
change24h: change24h,
volume24h: 0,
amount: solBalance,
usdValue: usdValue
}
]
let totalValue = usdValue
try {
// Check for specific known tokens using associated token addresses (less RPC intensive)
console.log('<27> Checking for known SPL tokens...')
// Known token metadata for discovery
const knownTokens = [
{ symbol: 'USDC', mint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', decimals: 6, price: 1.0 },
{ symbol: 'USDT', mint: 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB', decimals: 6, price: 1.0 },
{ symbol: 'RAY', mint: '4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R', decimals: 6, price: 0.5 },
{ symbol: 'mSOL', mint: 'mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So', decimals: 9, price: 180.0 },
{ symbol: 'wSOL', mint: 'So11111111111111111111111111111111111111112', decimals: 9, price: solPrice },
{ symbol: 'BONK', mint: 'DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263', decimals: 5, price: 0.00002 },
{ symbol: 'JUP', mint: 'JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN', decimals: 6, price: 0.8 },
{ symbol: 'ORCA', mint: 'orcaEKTdK7LKz57vaAYr9QeNsVEPfiu6QeMU1kektZE', decimals: 6, price: 0.3 },
{ symbol: 'SRM', mint: 'SRMuApVNdxXokk5GT7XD5cUUgXMBCoAz2LHeuAoKWRt', decimals: 6, price: 0.05 },
{ symbol: 'STEP', mint: 'StepAscQoEioFxxWGnh2sLBDFp9d8rvKz2Yp39iDpyT', decimals: 9, price: 0.01 }
]
// Check each known token one by one
for (const token of knownTokens) {
try {
const tokenMint = new PublicKey(token.mint)
const associatedTokenAddress = await getAssociatedTokenAddress(
tokenMint,
keypair.publicKey
)
// Get the token account
const tokenAccount = await getAccount(connection, associatedTokenAddress)
const tokenBalance = Number(tokenAccount.amount) / Math.pow(10, token.decimals)
if (tokenBalance > 0.000001) { // Only show meaningful balances
const tokenUsdValue = tokenBalance * token.price
totalValue += tokenUsdValue
positions.push({
symbol: token.symbol,
mint: token.mint,
price: token.price,
change24h: 0,
volume24h: 0,
amount: tokenBalance,
usdValue: tokenUsdValue
})
console.log(`💎 Found ${token.symbol}: ${tokenBalance.toFixed(6)} ($${tokenUsdValue.toFixed(2)})`)
}
} catch (error) {
// Token account doesn't exist - this is normal if wallet doesn't hold this token
console.log(` No ${token.symbol} balance found`)
}
}
console.log(`✅ Token discovery complete: Found ${positions.length} token positions`)
} catch (tokenError) {
console.log(`⚠️ Error discovering tokens: ${tokenError.message}`)
}
return NextResponse.json({
success: true,
balance: {
totalValue: totalValue,
availableBalance: totalValue,
positions: positions
},
wallet: {
publicKey: keypair.publicKey.toString(),
solBalance: solBalance,
usdValue: totalValue
},
timestamp: Date.now()
})
} catch (error) {
console.error('❌ Wallet balance API error:', error)
return NextResponse.json({
success: false,
error: 'Failed to fetch wallet balance',
message: error.message
}, { status: 500 })
}
}