File size: 2,317 Bytes
c6b6c96
f667d47
c6b6c96
f667d47
c6b6c96
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f667d47
c6b6c96
 
 
 
 
 
 
 
f667d47
 
 
 
 
 
 
 
 
 
 
 
 
 
c6b6c96
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import { NextResponse } from 'next/server'
import { sendCustomEvent, isTorqueConfigured, sendTelegramAlert } from '@/lib/torque-mcp'
import { pushEvent } from '@/lib/event-store'
import { recordIntervention } from '@/lib/attribution-store'

interface BulkTarget { wallet: string; eventName: string; risk?: string; score?: number }

export async function POST(req: Request) {
  const body = await req.json()
  const { targets }: { targets: BulkTarget[] } = body

  if (!Array.isArray(targets) || targets.length === 0) {
    return NextResponse.json({ error: 'targets array required' }, { status: 400 })
  }
  if (!isTorqueConfigured()) {
    return NextResponse.json({ error: 'TORQUE_INGEST_KEY not configured' }, { status: 503 })
  }

  const results = await Promise.allSettled(
    targets.map(async (t) => {
      const result = await sendCustomEvent(t.wallet, t.eventName, {
        risk: t.risk,
        score: t.score,
        detectedBy: 'flowstate-bulk-rescue',
        timestamp: new Date().toISOString(),
      })
      if (result.success && result.eventId) {
        pushEvent({
          ingestionId: result.eventId,
          wallet: t.wallet,
          eventName: t.eventName,
          risk: t.risk,
          score: t.score,
          firedAt: new Date().toISOString(),
          source: 'manual',
        })
        if (t.score) recordIntervention(t.wallet, t.eventName, t.score)
      }
      return { wallet: t.wallet, success: result.success, eventId: result.eventId, error: result.error }
    })
  )

  const fired = results.filter(r => r.status === 'fulfilled' && (r.value as any).success).length
  const details = results.map(r => r.status === 'fulfilled' ? r.value : { success: false, error: String((r as any).reason) })

  // Telegram alert when bulk rescue fires ≥5 critical wallets
  if (targets.length >= 5) {
    const confirmedIds = details
      .filter((d: any) => d.success && d.eventId)
      .map((d: any) => d.eventId.slice(0, 8))
      .slice(0, 3)
      .join(', ')
    await sendTelegramAlert(
      `🚨 Bulk Rescue fired — ${targets.length} critical wallets\n` +
      `✅ ${fired}/${targets.length} Torque events confirmed\n` +
      `📋 IDs: ${confirmedIds}${fired > 3 ? '...' : ''}`
    )
  }

  return NextResponse.json({ fired, total: targets.length, details })
}