flowstate / src /app /api /helius /analyze /route.ts
muthuk1's picture
feat: Helius real on-chain wallet analysis
9e22644
import { NextResponse } from 'next/server'
import { fetchWalletSignals, isHeliusConfigured } from '@/lib/helius'
import { calculateChurnScore } from '@/lib/agent-engine'
import { sendCustomEvent, isTorqueConfigured } from '@/lib/torque-mcp'
import { pushEvent } from '@/lib/event-store'
import { recordIntervention } from '@/lib/attribution-store'
export async function POST(req: Request) {
const { address, autoFire = false } = await req.json()
if (!address || typeof address !== 'string') {
return NextResponse.json({ error: 'address required' }, { status: 400 })
}
if (!isHeliusConfigured()) {
return NextResponse.json({ error: 'HELIUS_API_KEY not configured' }, { status: 503 })
}
const signals = await fetchWalletSignals(address)
if (!signals) {
return NextResponse.json({ error: 'Failed to fetch wallet data from Helius' }, { status: 502 })
}
const { score, risk, signals: detectedSignals } = calculateChurnScore({
daysInactive: signals.daysInactive,
volumeDropPct: signals.volumeDropPct,
uniqueProtocols: signals.uniqueProtocols,
currentStreak: signals.currentStreak,
hasLiquidation: signals.hasLiquidation,
})
let torqueResult: { fired: boolean; eventId?: string; eventName?: string } = { fired: false }
if (autoFire && isTorqueConfigured() && (risk === 'critical' || risk === 'high' || risk === 'medium')) {
const eventName = risk === 'critical' || risk === 'high' ? 'churn_risk_high' : 'churn_risk_medium'
const result = await sendCustomEvent(address, eventName, {
risk, score,
daysInactive: signals.daysInactive,
protocols: signals.protocols,
source: 'helius_live',
detectedBy: 'flowstate-helius-scan',
})
if (result.success && result.eventId) {
pushEvent({
ingestionId: result.eventId,
wallet: address,
eventName,
risk,
score,
firedAt: new Date().toISOString(),
source: 'scan',
})
recordIntervention(address, eventName, score)
torqueResult = { fired: true, eventId: result.eventId, eventName }
}
}
return NextResponse.json({
address,
signals,
score,
risk,
detectedSignals,
torque: torqueResult,
})
}