import { eq } from 'drizzle-orm' import { pollBreakout } from '@trumpsignal/backend/breakout' import { createDatabase, subscriptions } from '@trumpsignal/database' import { createContext } from '@trumpsignal/backend/context' import { readConfig } from '@trumpsignal/backend/config' import { createServices } from '@trumpsignal/backend/services' import { reanalyze, backtestBatch, backtestPost, backfillImpact, } from '@trumpsignal/backend/operations' import { decryptApiKey, encryptApiKey } from '@trumpsignal/core/crypto' const config = readConfig(), database = createDatabase(config.database_url), c = createContext(database, config), s = createServices(c), [command, arg] = process.argv.slice(2) try { let result: unknown switch (command) { case 'breakout': result = await pollBreakout(c, s.state) break case 'preflight': await database.pool.query('SELECT 1') result = { database: true, encryption_key_configured: config.encryption_key.length >= 32, ingest_configured: !!config.ingest_api_key, telegram_configured: s.telegram.configured(), ai_configured: !!(config.ai_api_key || config.anthropic_api_key), } break case 'seed-wallets': result = await s.kol.seed() break case 'truth-backfill': result = await s.truth.cnn(true) break case 'kol-feeds': result = await s.kol.pollFeeds() break case 'kol-x': result = await s.kol.pollX() break case 'onchain': result = await s.onchain.poll() break case 'divergence': result = await s.kol.divergence(Number(arg) || 30) break case 'macro': result = await s.macro.poll() break case 'backfill-prices': result = await backfillImpact(c, arg ?? 'BTC') break case 'reanalyze': result = await reanalyze(c, s, { limit: Number(arg) || 500, dry_run: process.env.DRY_RUN !== 'false', delay_secs: 0.5, legacy_signals: true, }) break case 'backtest': result = await backtestPost(c, Number(arg)) break case 'backtest-batch': result = await backtestBatch(c, Number(arg) || 50) break case 'reencrypt-keys': { const old = process.env.OLD_ENCRYPTION_KEY ?? config.encryption_key, dry = process.env.DRY_RUN !== 'false', rows = await c.db.select().from(subscriptions) let changed = 0 for (const row of rows) { if (!row.hl_api_key) continue const key = await decryptApiKey(row.hl_api_key, old, config.environment) if (!dry) await c.db .update(subscriptions) .set({ hl_api_key: await encryptApiKey(key, config.encryption_key) }) .where(eq(subscriptions.id, row.id)) changed++ } result = { dry_run: dry, keys_processed: changed } break } default: throw new Error( 'Commands: preflight, seed-wallets, truth-backfill, kol-feeds, kol-x, onchain, divergence, macro, backfill-prices, reanalyze, backtest, backtest-batch, reencrypt-keys', ) } process.stdout.write(JSON.stringify(result ?? { ok: true }, null, 2) + '\n') } finally { await database.pool.end() await database.lockPool.end() }