#!/usr/bin/env python3 """ Seed the kol_wallets table with publicly attributed on-chain addresses. Why this exists: The talks-vs-trades divergence module can only fire on KOLs whose wallets we know. As of 2026-05-24 only 3 KOLs had wallets configured, which is why we had ~3 divergence detections across the whole dataset. Adding a new wallet here REQUIRES: 1. Public attribution — Arkham label, the KOL's own X bio, a public investigation by ZachXBT / Inspex / similar, or the KOL's ENS clearly visible in transactions. 2. The `handle` field MUST exactly match a `handle` value in app/services/kol_substack.py KOL_FEEDS — otherwise the divergence scanner cannot match "post by handle X" against "wallet activity by handle X". 3. The `source_url` must link to that public attestation. Don't add speculative addresses, even if "everyone knows" — misattribution damages both the KOL and our credibility. Idempotent: runs UPSERT-style. Existing rows for (handle, address) are preserved; only new ones are inserted. Usage: DATABASE_URL='sqlite+aiosqlite:///./trumpsignal.db' \\ venv/bin/python scripts/seed_kol_wallets.py """ from __future__ import annotations import asyncio import sys from datetime import datetime, timezone from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) from sqlalchemy import select from app.database import AsyncSessionLocal from app.models import KolWallet # ──────────────────────────────────────────────────────────────────────────── # Verified seed list. # # Each entry MUST have a working source_url. If you can't link to a public # attestation, DON'T add it. # # To find more candidates yourself: # • https://platform.arkhamintelligence.com/ — search by handle, click # "labels" tab. Labels prefixed with "Entity:" are Arkham-verified. # • https://etherscan.io/labelcloud — Etherscan public label registry. # • ZachXBT investigations on X — he posts the underlying tx evidence. # • Many KOLs put their address in their X bio or pinned tweet. # # When the KOL's handle in KOL_FEEDS doesn't match the on-chain handle here, # add it under the handle that's IN KOL_FEEDS — divergence join is by handle. # ──────────────────────────────────────────────────────────────────────────── SEED_WALLETS: list[dict] = [ # ── Already in DB (kept here so the script is self-documenting) ────── { "handle": "cryptohayes", "chain": "ethereum", "address": "0xa86e3d1c80a750a310b484fb9bdc470753a7506f", "label": "Arthur Hayes (main)", "source_url": "https://etherscan.io/address/0xa86e3d1c80a750a310b484fb9bdc470753a7506f", }, { "handle": "cryptohayes", "chain": "ethereum", "address": "0x534a0076fb7c2b1f83fa21497429ad7ad3bd7587", "label": "Arthur Hayes (secondary)", "source_url": "https://etherscan.io/address/0x534a0076fb7c2b1f83fa21497429ad7ad3bd7587", }, { "handle": "andrewkang", "chain": "ethereum", "address": "0xff3879b8a363aed92a6eaba8f61f1a96a9ec3c1e", "label": "Andrew Kang (beanwhale.eth)", "source_url": "https://etherscan.io/address/0xff3879b8a363aed92a6eaba8f61f1a96a9ec3c1e", }, { "handle": "murad", "chain": "ethereum", "address": "0x93f019699ef400df7dc3477dbb6400ed9445a657", "label": "Murad Mahmudov (via ZachXBT investigation)", "source_url": "https://www.blocmates.com/news-posts/24million-in-memecoins-zachxbt-unveils-murad-mahmudov-s-alleged-wallets", }, # ── Add new VERIFIED entries below this line ───────────────────────── # # Template — copy, replace fields, push only after verifying source_url: # # { # "handle": "", # "chain": "ethereum", # or "solana", "base", "arbitrum" # "address": "0x...", # "label": "", # "source_url": "", # }, # # Candidates to research (NOT seeded — verify before adding): # # • niccarter — Nic Carter has spoken openly about his wallet # history on podcasts; check Coin Center filings. # • pomp — Pompliano has a public BTC-only treasury; less # useful for ETH-side divergence detection. # • dragonfly — Dragonfly Capital portfolio wallets often # labeled on Arkham as "Dragonfly Fund". # • placeholder — Placeholder VC fund wallets per their public # investment disclosures. # • eugene — Eugene Ng Ah Sio — verify before adding. # # Also worth tracking even if not in KOL_FEEDS (would need to add the # corresponding feed entry first or they'll never have post-side data): # # • justinsuntron — Tron founder, very active ETH trader, well-labeled. # • cobie — Jordan Fish, address known via Arkham labels. # • gcr / sam — anon traders, no reliably verifiable address. ] async def main() -> int: inserted = 0 skipped = 0 async with AsyncSessionLocal() as session: for entry in SEED_WALLETS: # Idempotency: skip if (handle, address) already present. existing = await session.execute( select(KolWallet).where( KolWallet.handle == entry["handle"], KolWallet.address == entry["address"].lower(), ) ) if existing.scalar_one_or_none(): skipped += 1 continue row = KolWallet( handle=entry["handle"], chain=entry["chain"], address=entry["address"].lower(), label=entry["label"], source_url=entry["source_url"], active=True, added_at=datetime.now(timezone.utc).replace(tzinfo=None), ) session.add(row) inserted += 1 print(f" + {entry['handle']:18s} {entry['address']} ({entry['label']})") await session.commit() print() print(f"Inserted {inserted} wallets, skipped {skipped} existing.") print() print("Next step: edit SEED_WALLETS above and re-run. Each new wallet") print("MUST cite a public attestation in source_url — see the docstring.") return 0 if __name__ == "__main__": raise SystemExit(asyncio.run(main()))