diff --git a/package.json b/package.json index baa96ff..ecf23bf 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,8 @@ "rotation": "bun run src/server/scripts/rotation-walkforward.ts", "grid": "bun run src/server/scripts/grid-walkforward.ts", "db:generate": "bunx drizzle-kit generate", - "db:migrate": "bun run src/server/db/migrate.ts" + "db:migrate": "bun run src/server/db/migrate.ts", + "trump:backfill": "bun run src/server/scripts/trump-backfill.ts" }, "dependencies": { "drizzle-orm": "^0.44.0", diff --git a/src/server/scripts/trump-backfill.ts b/src/server/scripts/trump-backfill.ts new file mode 100644 index 0000000..5f38e62 --- /dev/null +++ b/src/server/scripts/trump-backfill.ts @@ -0,0 +1,87 @@ +import { parseArgs } from 'util'; +import { sql, db } from '../db/client'; +import { trumpEvents } from '../db/schema'; +import { fetchTransfers, getBlockNumber, getBlockTs } from '../signals/onchain'; +import { dedupeTruthEvents, passesNotional } from '../signals/poller'; +import { matchCoins } from '../signals/truth'; +import { COIN_KEYWORDS } from '../signals/watchlist'; +import { getCandles } from '../market/candle-store'; + +const M15 = 15 * 60 * 1000; +const { values: args } = parseArgs({ + options: { + 'from-block': { type: 'string', default: '20600000' }, // ≈ Sep 2024, vor den ersten WLFI-Treasury-Käufen + 'truth-pages': { type: 'string', default: '300' }, + }, +}); + +// ── On-chain ── +const fromBlock = Number(args['from-block']); +const head = await getBlockNumber(); +console.log(`On-chain-Scan Block ${fromBlock} → ${head} (${head - fromBlock} Blöcke, ~${Math.ceil((head - fromBlock) / 5000)} Requests)`); +let onchainCount = 0; +const STEP = 5000; +for (let from = fromBlock; from <= head; from += STEP) { + const to = Math.min(from + STEP - 1, head); + const transfers = await fetchTransfers(from, to, STEP); + for (const t of transfers) { + const ts = await getBlockTs(t.blockNumber); + let price: number | null = null; + if (t.instrument) { + const cs = await getCandles(t.instrument, ts - 24 * 3600_000, ts + M15); + price = cs.length > 0 ? cs[cs.length - 1].close : null; + } + if (!passesNotional(t.amount, price)) continue; + await db.insert(trumpEvents).values({ + source: 'onchain', token: t.symbol, instrument: t.instrument, + eventTs: new Date(ts), ref: t.txHash, notionalUsd: t.amount * price!, + }).onConflictDoNothing(); + onchainCount++; + console.log(` ${new Date(ts).toISOString()} ${t.symbol} ${t.amount.toFixed(2)} (~$${Math.round(t.amount * price!)}) ${t.txHash}`); + } + if ((from - fromBlock) % (STEP * 20) === 0) console.log(` … Block ${to}`); + await Bun.sleep(150); +} +console.log(`On-chain: ${onchainCount} Events`); + +// ── Truth (best effort, letzte N Archiv-Seiten à 10 Posts) ── +// Markup verifiziert 2026-06-12: Seite hat 10 Posts, je ein