diff --git a/.github/workflows/daily_report.yml b/.github/workflows/daily_report.yml new file mode 100644 index 0000000..ee2880d --- /dev/null +++ b/.github/workflows/daily_report.yml @@ -0,0 +1,120 @@ +name: Daily Crypto Intelligence Report + +on: + schedule: + # 7:00 UTC = 8:00 CET (Poland winter time), report posts by ~8:10 AM + - cron: '0 7 * * *' + # 13:00 UTC = 14:00 CET — Alpha pipeline (US open + Asia evening) + - cron: '0 13 * * *' + # 1:00 UTC = 02:00 CET — Alpha pipeline (US evening + Asia morning) + - cron: '0 1 * * *' + # Every 15 minutes — wallet tracker (monitors alpha wallets for new buys) + - cron: '*/15 * * * *' + workflow_dispatch: # Allow manual trigger + +jobs: + daily-report: + runs-on: ubuntu-latest + if: github.event.schedule == '0 7 * * *' || github.event_name == 'workflow_dispatch' + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: claude/crypto-intelligence-system-8oO0s + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Run daily morning report + env: + + XAI_API_KEY: ${{ secrets.XAI_API_KEY }} + HELIUS_RPC_URL: ${{ secrets.HELIUS_RPC_URL }} + run: python3 daily_morning_report.py + + - name: Run wallet scan (RPC) + env: + + HELIUS_RPC_URL: ${{ secrets.HELIUS_RPC_URL }} + run: python3 run_scan_rpc.py + continue-on-error: true + + - name: Commit scan results + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add -A memory/ + git diff --staged --quiet || git commit -m "Auto: daily scan results $(date -u +%Y-%m-%d)" + git push + continue-on-error: true + + alpha-pipeline: + runs-on: ubuntu-latest + if: github.event.schedule == '0 13 * * *' || github.event.schedule == '0 1 * * *' + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: claude/crypto-intelligence-system-8oO0s + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Run trending scan + env: + + XAI_API_KEY: ${{ secrets.XAI_API_KEY }} + HELIUS_RPC_URL: ${{ secrets.HELIUS_RPC_URL }} + run: python3 scan_trending_new.py + timeout-minutes: 5 + + - name: Run alpha wallet scanner + env: + + HELIUS_RPC_URL: ${{ secrets.HELIUS_RPC_URL }} + run: python3 alpha_wallet_scanner.py + timeout-minutes: 15 + continue-on-error: true + + - name: Commit pipeline results + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add -A memory/ + git diff --staged --quiet || git commit -m "Auto: alpha pipeline results $(date -u +%Y-%m-%d_%H:%M)" + git push + continue-on-error: true + + wallet-tracker: + runs-on: ubuntu-latest + if: github.event.schedule == '*/15 * * * *' + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: claude/crypto-intelligence-system-8oO0s + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Track alpha wallets for new buys + env: + + HELIUS_RPC_URL: ${{ secrets.HELIUS_RPC_URL }} + run: python3 wallet_tracker.py + timeout-minutes: 3 + + - name: Commit tracker state + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add -A memory/wallet_tracker_state.json memory/wallet_tracker_alerts.jsonl + git diff --staged --quiet || git commit -m "Auto: wallet tracker $(date -u +%H:%M)" + git push + continue-on-error: true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2540e28 --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +__pycache__/ +*.pyc +.env +dd_reports/ +logs/ +.pids/ +memory/wallet_last_sigs.json +memory/wallet_signals.jsonl +memory/x_signals.jsonl +memory/x_last_check.json +memory/bought_mints.json +memory/ultra_signals.jsonl +memory/positions.json +memory/scam_blacklist.json +memory/failed_mints.json +memory/trades_log.jsonl diff --git a/alpha_wallet_scanner.py b/alpha_wallet_scanner.py new file mode 100644 index 0000000..21cbaaf --- /dev/null +++ b/alpha_wallet_scanner.py @@ -0,0 +1,548 @@ +#!/usr/bin/env python3 +""" +Alpha Wallet Scanner — For each new trending CA, finds early buyers with +asymmetric profits (500%+) who bought in size, and adds them to the alpha wallet list. + +Pipeline: scan_trending_new.py → [scan_queue.json] → alpha_wallet_scanner.py → [smart_wallets.json] + +Two modes: + - RPC mode (works anywhere): getTokenLargestAccounts (top 20) + getSignaturesForAddress + - Enhanced API mode (VPS only): /v0/addresses/{addr}/transactions for full history +""" + +import json +import os +import re +import subprocess +import sys +import time +from datetime import datetime, timezone, timedelta +from urllib.request import Request, urlopen +from urllib.error import HTTPError, URLError + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) + +# Load env +env_path = os.path.join(SCRIPT_DIR, '.env') +if os.path.exists(env_path): + with open(env_path) as f: + for line in f: + line = line.strip() + if '=' in line and not line.startswith('#'): + key, val = line.split('=', 1) + os.environ[key] = val + +HELIUS_RPC = os.environ.get('HELIUS_RPC_URL', '') +XAI_API_KEY = os.environ.get('XAI_API_KEY', '') +SCAN_QUEUE = os.path.join(SCRIPT_DIR, 'memory', 'scan_queue.json') +SMART_WALLETS = os.path.join(SCRIPT_DIR, 'memory', 'smart_wallets.json') +TOKENS_FILE = os.path.join(SCRIPT_DIR, 'memory', 'tokens.json') +ALPHA_SCAN_LOG = os.path.join(SCRIPT_DIR, 'memory', 'alpha_scans.jsonl') + +# Known addresses to exclude +KNOWN_PROGRAMS = { + 'TokenkegQfeE2cNFBpZjxo3WcsKrpLBCq4SzZhScigCZ', # SPL Token + 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb', # Token-2022 + 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL', # ATA + 'So11111111111111111111111111111111111111112', # Wrapped SOL + '11111111111111111111111111111111', # System Program + 'pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA', # PumpSwap AMM + 'ComputeBudget111111111111111111111111111111', + 'Vote111111111111111111111111111111111111111', +} + +# Minimum thresholds for alpha wallets +MIN_PROFIT_MULTIPLE = 5.0 # 500% minimum profit +MIN_PROFIT_USD = 1000 # At least $1K profit +MIN_SOL_BALANCE = 1.0 # Must have some SOL (not dust wallet) +MAX_TOKENS_HELD = 2000 # Not a spray-and-pray bot (>2000 tokens) + +# Rate limiting +RPC_DELAY = 0.5 # Seconds between RPC calls (free tier safe) + + +def rpc_call(method, params): + """Make a Solana RPC call via Helius.""" + if not HELIUS_RPC: + return None + try: + payload = json.dumps({ + 'jsonrpc': '2.0', 'id': 1, + 'method': method, 'params': params, + }).encode() + req = Request(HELIUS_RPC, data=payload, headers={'Content-Type': 'application/json'}) + with urlopen(req, timeout=15) as resp: + data = json.loads(resp.read()) + if 'error' in data: + print(f" RPC error ({method}): {data['error']}") + return None + return data.get('result') + except Exception as e: + print(f" RPC exception ({method}): {e}") + return None + + +def get_top_holders(mint, count=20): + """Get top token holders via getTokenLargestAccounts and resolve to wallet addresses.""" + print(f" Getting top {count} holders for {mint[:20]}...") + + result = rpc_call('getTokenLargestAccounts', [mint]) + if not result: + return [] + + accounts = result.get('value', []) + if not accounts: + return [] + + holders = [] + for acc in accounts[:count]: + time.sleep(RPC_DELAY) + + token_account = acc['address'] + balance = float(acc.get('uiAmount', 0) or 0) + + # Resolve token account → wallet owner + info = rpc_call('getAccountInfo', [token_account, {'encoding': 'jsonParsed'}]) + if not info or not info.get('value'): + continue + + parsed = info['value'].get('data', {}).get('parsed', {}).get('info', {}) + owner = parsed.get('owner', '') + + if not owner or owner in KNOWN_PROGRAMS: + continue + + holders.append({ + 'wallet': owner, + 'token_account': token_account, + 'balance': balance, + }) + + print(f" Resolved {len(holders)} holder wallets") + return holders + + +def get_wallet_info(wallet): + """Get SOL balance for a wallet. Token count skipped (Helius free tier blocks programId filter).""" + time.sleep(RPC_DELAY) + balance_result = rpc_call('getBalance', [wallet]) + sol_balance = (balance_result.get('value', 0) if balance_result else 0) / 1e9 + + return { + 'sol_balance': sol_balance, + 'token_count': 0, # Not available on free tier + 'top_holdings': [], + } + + +def estimate_pnl(wallet, mint, current_price, holder_balance): + """ + Estimate PnL for a wallet on a specific token. + Scans recent transactions to find buy entries. + Returns: {buy_amount_sol, buy_price_avg, current_value, profit_usd, profit_multiple, still_holding} + """ + time.sleep(RPC_DELAY) + sigs_result = rpc_call('getSignaturesForAddress', [wallet, {'limit': 100}]) + if not sigs_result: + return None + + # Filter to non-error transactions + valid_sigs = [s for s in sigs_result if not s.get('err')] + + # Parse transactions to find buys/sells of this token + total_bought_sol = 0 + total_sold_sol = 0 + buy_count = 0 + sell_count = 0 + earliest_buy_time = None + + for sig_info in valid_sigs[:15]: # Check last 15 txs for speed + sig = sig_info['signature'] + block_time = sig_info.get('blockTime', 0) + + time.sleep(RPC_DELAY) + tx = rpc_call('getTransaction', [sig, {'encoding': 'jsonParsed', 'maxSupportedTransactionVersion': 0}]) + if not tx: + continue + + meta = tx.get('meta', {}) + if meta.get('err'): + continue + + # Check if this tx involves our mint + pre_balances = meta.get('preTokenBalances', []) + post_balances = meta.get('postTokenBalances', []) + + wallet_pre = 0 + wallet_post = 0 + for b in pre_balances: + if b.get('mint') == mint and b.get('owner') == wallet: + wallet_pre = float(b.get('uiTokenAmount', {}).get('uiAmount', 0) or 0) + for b in post_balances: + if b.get('mint') == mint and b.get('owner') == wallet: + wallet_post = float(b.get('uiTokenAmount', {}).get('uiAmount', 0) or 0) + + if wallet_pre == 0 and wallet_post == 0: + continue # TX doesn't involve this token for this wallet + + # Calculate SOL change (cost of buy or proceeds of sell) + pre_sol = 0 + post_sol = 0 + account_keys = tx.get('transaction', {}).get('message', {}).get('accountKeys', []) + for i, key in enumerate(account_keys): + pubkey = key.get('pubkey', '') if isinstance(key, dict) else key + if pubkey == wallet: + pre_sol = (meta.get('preBalances', [0]*(i+1))[i]) / 1e9 + post_sol = (meta.get('postBalances', [0]*(i+1))[i]) / 1e9 + break + + sol_change = post_sol - pre_sol + token_change = wallet_post - wallet_pre + + if token_change > 0: + # BUY: tokens increased, SOL decreased + total_bought_sol += abs(sol_change) + buy_count += 1 + if earliest_buy_time is None or block_time < earliest_buy_time: + earliest_buy_time = block_time + elif token_change < 0: + # SELL: tokens decreased, SOL increased + total_sold_sol += abs(sol_change) + sell_count += 1 + + if buy_count == 0: + return None + + # Calculate PnL + current_value_usd = holder_balance * current_price if current_price else 0 + realized_sol = total_sold_sol + cost_sol = total_bought_sol + + # Estimate USD values (use current SOL price as approximation) + sol_price = 85.0 # Approximate — will be fetched live in production + cost_usd = cost_sol * sol_price + realized_usd = realized_sol * sol_price + unrealized_usd = current_value_usd + total_pnl_usd = realized_usd + unrealized_usd - cost_usd + profit_multiple = (realized_usd + unrealized_usd) / cost_usd if cost_usd > 0 else 0 + + return { + 'buy_count': buy_count, + 'sell_count': sell_count, + 'cost_sol': round(cost_sol, 4), + 'cost_usd': round(cost_usd, 2), + 'realized_sol': round(realized_sol, 4), + 'realized_usd': round(realized_usd, 2), + 'unrealized_usd': round(unrealized_usd, 2), + 'total_pnl_usd': round(total_pnl_usd, 2), + 'profit_multiple': round(profit_multiple, 2), + 'still_holding': holder_balance > 0, + 'earliest_buy_time': earliest_buy_time, + } + + +def score_wallet(wallet_info, pnl, source_count=0, x_mentions=0): + """ + Score a wallet for alpha potential. + Higher score = more interesting wallet to track. + """ + score = 0 + + sol = wallet_info.get('sol_balance', 0) + tokens = wallet_info.get('token_count', 0) + + # Profit-based scoring + if pnl: + multiple = pnl.get('profit_multiple', 0) + profit_usd = pnl.get('total_pnl_usd', 0) + + if multiple >= 50: + score += 80 # 50x+ = elite + elif multiple >= 20: + score += 60 # 20x+ = great + elif multiple >= 10: + score += 45 # 10x+ = very good + elif multiple >= 5: + score += 30 # 5x+ = good (minimum threshold) + + if profit_usd >= 50000: + score += 40 # $50K+ profit = whale + elif profit_usd >= 10000: + score += 25 # $10K+ profit = significant + elif profit_usd >= 1000: + score += 10 # $1K+ profit = notable + + if pnl.get('still_holding'): + score += 15 # Still in = conviction + + # Early buyer bonus (bought in first hour) + if pnl.get('earliest_buy_time'): + age_hours = (time.time() - pnl['earliest_buy_time']) / 3600 + if age_hours > 24 and multiple >= 5: + score += 20 # Held for 24h+ with 5x+ = diamond hands + + # SOL balance (funded wallet = serious trader) + if sol >= 100: + score += 20 + elif sol >= 50: + score += 15 + elif sol >= 10: + score += 10 + elif sol >= MIN_SOL_BALANCE: + score += 5 + + # Token count scoring (only if available — Helius free tier can't fetch) + if tokens > 0: + if 20 <= tokens <= 200: + score += 10 # Active, focused trader + elif tokens > 500: + score -= 10 # Spray-and-pray + elif tokens > MAX_TOKENS_HELD: + score -= 20 # Likely bot + + # Multi-source detection + score += source_count * 10 + + # X mentions + score += x_mentions * 15 + + return score + + +def scan_token(ca, token_info=None): + """ + Full alpha wallet scan for a single token CA. + Returns list of alpha wallets found. + """ + now = datetime.now(timezone.utc) + symbol = (token_info or {}).get('symbol', ca[:12]) + current_price = (token_info or {}).get('price_usd', 0) + + print(f"\n{'='*60}") + print(f"SCANNING: ${symbol} ({ca[:30]}...)") + print(f" MC: ${(token_info or {}).get('mc', 0):,.0f} | Price: ${current_price}") + print(f"{'='*60}") + + # Step 1: Get top holders + holders = get_top_holders(ca) + if not holders: + print(" No holders found, skipping") + return [] + + # Step 2: Enrich each holder with wallet info + print(f"\n Enriching {len(holders)} holders...") + alpha_candidates = [] + + for i, h in enumerate(holders): + wallet = h['wallet'] + balance = h['balance'] + print(f"\n [{i+1}/{len(holders)}] {wallet[:20]}... | Balance: {balance:,.0f}") + + # Get wallet info + info = get_wallet_info(wallet) + sol = info['sol_balance'] + token_count = info['token_count'] + print(f" SOL: {sol:.2f}") + + # Quick filter: skip dust wallets + if sol < MIN_SOL_BALANCE: + print(f" SKIP: dust wallet (SOL < {MIN_SOL_BALANCE})") + continue + + # Step 3: Estimate PnL (expensive — only for promising wallets) + pnl = None + if sol >= 0.5: + print(f" Estimating PnL...") + pnl = estimate_pnl(wallet, ca, current_price, balance) + if pnl: + print(f" PnL: {pnl['profit_multiple']:.1f}x | " + f"Cost: {pnl['cost_sol']:.2f} SOL (${pnl['cost_usd']:.0f}) | " + f"Realized: ${pnl['realized_usd']:.0f} | " + f"Unrealized: ${pnl['unrealized_usd']:.0f} | " + f"Total: ${pnl['total_pnl_usd']:.0f}") + + # Filter: 500%+ profit AND meaningful size + if pnl['profit_multiple'] >= MIN_PROFIT_MULTIPLE and pnl['total_pnl_usd'] >= MIN_PROFIT_USD: + print(f" *** ALPHA WALLET DETECTED ***") + elif pnl['profit_multiple'] >= 3.0 and pnl['total_pnl_usd'] >= 500: + print(f" ** Notable (3x+, $500+) **") + + # Score the wallet + wallet_score = score_wallet(info, pnl) + + alpha_candidates.append({ + 'wallet': wallet, + 'sol_balance': sol, + 'token_count': token_count, + 'token_balance': balance, + 'pnl': pnl, + 'score': wallet_score, + 'scanned_for': ca, + 'scanned_symbol': symbol, + 'scanned_at': now.isoformat(), + }) + + # Step 4: Rank and filter + alpha_candidates.sort(key=lambda x: x['score'], reverse=True) + + # Filter to alpha-grade wallets + alpha_wallets = [ + w for w in alpha_candidates + if w['score'] >= 40 # Minimum score threshold + and (not w['pnl'] or w['pnl']['profit_multiple'] >= 3.0 or w['sol_balance'] >= 20) + ] + + print(f"\n RESULTS: {len(alpha_wallets)} alpha wallets from {len(holders)} holders") + for w in alpha_wallets[:5]: + pnl = w.get('pnl') + pnl_str = f"{pnl['profit_multiple']:.1f}x (${pnl['total_pnl_usd']:,.0f})" if pnl else "N/A" + print(f" {w['wallet'][:20]}... | Score: {w['score']} | " + f"SOL: {w['sol_balance']:.1f} | PnL: {pnl_str}") + + return alpha_wallets + + +def update_smart_wallets(new_wallets): + """Add new alpha wallets to the smart_wallets.json registry.""" + if os.path.exists(SMART_WALLETS): + with open(SMART_WALLETS) as f: + data = json.load(f) + else: + data = {"wallets": []} + + existing = {w.get('address', '') for w in data.get('wallets', [])} + + added = 0 + for w in new_wallets: + if w['wallet'] in existing: + # Update score if higher + for ew in data['wallets']: + if ew.get('address') == w['wallet']: + old_score = ew.get('alpha_score', 0) + if w['score'] > old_score: + ew['alpha_score'] = w['score'] + ew['last_scan'] = w['scanned_at'] + continue + + data['wallets'].append({ + 'address': w['wallet'], + 'chain': 'solana', + 'label': f"Alpha #{len(data['wallets'])+1} (from ${w['scanned_symbol']})", + 'source': f"alpha_scanner:{w['scanned_symbol']}", + 'alpha_score': w['score'], + 'sol_balance': w['sol_balance'], + 'token_count': w['token_count'], + 'discovered_via': w['scanned_for'], + 'discovered_at': w['scanned_at'], + 'status': 'active, auto_discovered', + 'pnl_data': w.get('pnl'), + }) + existing.add(w['wallet']) + added += 1 + + os.makedirs(os.path.dirname(SMART_WALLETS), exist_ok=True) + with open(SMART_WALLETS, 'w') as f: + json.dump(data, f, indent=2) + + return added + + +def main(): + import argparse + parser = argparse.ArgumentParser(description='Alpha wallet scanner') + parser.add_argument('--token', help='Single token CA to scan (skips queue)') + parser.add_argument('--name', help='Token symbol', default='TOKEN') + args = parser.parse_args() + + now = datetime.now(timezone.utc) + print(f"[{now.isoformat()}] Starting alpha wallet scanner...") + + if args.token: + # Single token mode — skip queue + tokens = [{'ca': args.token, 'symbol': args.name, 'mc': 0}] + print(f"Single token mode: ${args.name} ({args.token[:30]}...)") + else: + # Load scan queue + if not os.path.exists(SCAN_QUEUE): + print("No scan queue found. Run scan_trending_new.py first.") + return + + with open(SCAN_QUEUE) as f: + queue = json.load(f) + + tokens = queue.get('tokens', []) + if not tokens: + print("Empty scan queue.") + return + + print(f"Tokens in queue: {len(tokens)}") + + all_alpha_wallets = [] + for t in tokens: + ca = t['ca'] + symbol = t.get('symbol', '?') + mc = t.get('mc', 0) + + # Fetch current token info from DexScreener + token_info = None + try: + from urllib.request import Request, urlopen + req = Request(f"https://api.dexscreener.com/tokens/v1/solana/{ca}", + headers={'Accept': 'application/json', 'User-Agent': 'Mozilla/5.0'}) + with urlopen(req, timeout=10) as resp: + data = json.loads(resp.read()) + if data and isinstance(data, list) and len(data) > 0: + p = data[0] + token_info = { + 'symbol': p.get('baseToken', {}).get('symbol', symbol), + 'mc': p.get('marketCap', mc), + 'price_usd': float(p.get('priceUsd', 0) or 0), + 'liquidity': (p.get('liquidity') or {}).get('usd', 0), + } + except Exception as e: + print(f" DexScreener error for {symbol}: {e}") + token_info = {'symbol': symbol, 'mc': mc, 'price_usd': 0} + + alpha_wallets = scan_token(ca, token_info) + all_alpha_wallets.extend(alpha_wallets) + + # Save alpha wallets + if all_alpha_wallets: + added = update_smart_wallets(all_alpha_wallets) + print(f"\n{'='*60}") + print(f"TOTAL: {len(all_alpha_wallets)} alpha wallets found, {added} new added to registry") + + # Log + log_entry = { + 'timestamp': now.isoformat(), + 'tokens_scanned': len(tokens), + 'alpha_wallets_found': len(all_alpha_wallets), + 'new_wallets_added': added, + 'top_wallets': [{ + 'wallet': w['wallet'][:20], + 'score': w['score'], + 'symbol': w['scanned_symbol'], + } for w in sorted(all_alpha_wallets, key=lambda x: x['score'], reverse=True)[:5]], + } + os.makedirs(os.path.dirname(ALPHA_SCAN_LOG), exist_ok=True) + with open(ALPHA_SCAN_LOG, 'a') as f: + f.write(json.dumps(log_entry) + '\n') + + else: + print("\nNo alpha wallets found in this scan.") + + # Update token registry status + if os.path.exists(TOKENS_FILE): + with open(TOKENS_FILE) as f: + registry = json.load(f) + for t in registry.get('tokens', []): + for qt in tokens: + if t['ca'] == qt['ca']: + t['scan_status'] = 'alpha_scanned' + t['alpha_wallets_found'] = len([w for w in all_alpha_wallets if w['scanned_for'] == qt['ca']]) + with open(TOKENS_FILE, 'w') as f: + json.dump(registry, f, indent=2) + + +if __name__ == "__main__": + main() diff --git a/analyze_jester.py b/analyze_jester.py new file mode 100644 index 0000000..7563202 --- /dev/null +++ b/analyze_jester.py @@ -0,0 +1,464 @@ +#!/usr/bin/env python3 +""" +JESTER Token Holder Analysis +Mint: 6WdHhpRY7vL8SQ69bd89tAj3sk8jsjBrCLDUTZSNpump +""" + +import json, time, os, sys, ssl +from urllib.request import Request, urlopen +from datetime import datetime, timezone + +# SSL context for Helius +SSL_CTX = ssl.create_default_context() +SSL_CTX.check_hostname = False +SSL_CTX.verify_mode = ssl.CERT_NONE + +with open('/home/user/Cute-Panel/.env') as f: + for line in f: + line = line.strip() + if '=' in line and not line.startswith('#'): + key, val = line.split('=', 1) + os.environ[key] = val + +RPC = os.environ['HELIUS_RPC_URL'] +MINT = '6WdHhpRY7vL8SQ69bd89tAj3sk8jsjBrCLDUTZSNpump' +BUTTCOIN_MINT = 'Cm6fNnMk7NfzStP9CZpsQA2v3jjzbcYGAxdJySmHpump' +RPC_DELAY = 0.5 +KNOWN_PROGRAMS = { + 'JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4': 'Jupiter v6', + 'JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcPX7a': 'Jupiter v4', + '675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8': 'Raydium AMM', + 'whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc': 'Orca Whirlpool', + '6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P': 'Pump.fun', + 'pumpkinsEq8xENVZE6QgTS93EN4r9iKvNxNALS1ooyp': 'Pump.fun Swap', +} + +call_count = 0 + +def rpc(method, params): + global call_count + call_count += 1 + payload = json.dumps({'jsonrpc': '2.0', 'id': call_count, 'method': method, 'params': params}).encode() + req = Request(RPC, data=payload, headers={'Content-Type': 'application/json'}) + try: + with urlopen(req, timeout=30, context=SSL_CTX) as resp: + data = json.loads(resp.read()) + if 'error' in data: + print(f" [RPC ERROR] {method}: {data['error']}") + return None + return data.get('result') + except Exception as e: + print(f" [RPC EXCEPTION] {method}: {e}") + return None + +def sol(lamports): + return lamports / 1_000_000_000 + +# ============================================================ +# STEP 1: Get top 20 holders +# ============================================================ +print("=" * 80) +print("STEP 1: FETCHING TOP 20 JESTER HOLDERS") +print("=" * 80) +print(f"Mint: {MINT}\n") +sys.stdout.flush() + +result = rpc('getTokenLargestAccounts', [MINT]) +if not result or 'value' not in result: + print("FATAL: Could not fetch token accounts") + sys.exit(1) + +accounts = result['value'] +print(f"Found {len(accounts)} largest token accounts\n") + +holders = [] +for i, acc in enumerate(accounts): + token_account = acc['address'] + balance = float(acc.get('uiAmount', 0) or 0) + if balance == 0: + raw = acc.get('amount', '0') + decimals = acc.get('decimals', 6) + balance = int(raw) / (10 ** decimals) + + time.sleep(RPC_DELAY) + info = rpc('getAccountInfo', [token_account, {'encoding': 'jsonParsed'}]) + if not info or not info.get('value'): + print(f" [{i+1}] Could not resolve owner for {token_account}") + continue + + try: + owner = info['value']['data']['parsed']['info']['owner'] + except (KeyError, TypeError): + print(f" [{i+1}] Could not parse owner for {token_account}") + continue + + holders.append({ + 'wallet': owner, + 'balance': balance, + 'token_account': token_account, + 'rank': i + 1, + 'cross_holdings': {}, + 'jester_txs': [], + 'status': 'UNKNOWN', + 'estimated_pnl': None, + 'sol_balance': 0, + }) + print(f" [{i+1:2d}] {owner[:16]}...{owner[-8:]} | Balance: {balance:>18,.2f} JESTER") + sys.stdout.flush() + +print(f"\nResolved {len(holders)} holders") + +# ============================================================ +# STEP 2: SOL balances + TX analysis +# ============================================================ +print("\n" + "=" * 80) +print("STEP 2: SOL BALANCES + JESTER TX ANALYSIS") +print("=" * 80) +sys.stdout.flush() + +for h in holders: + time.sleep(RPC_DELAY) + bal = rpc('getBalance', [h['wallet']]) + h['sol_balance'] = sol(bal['value']) if bal and 'value' in bal else 0 + +# Print SOL summary +for h in holders: + flag = "" + if h['sol_balance'] >= 10: flag = " *** WHALE ***" + elif h['sol_balance'] >= 5: flag = " ** LARGE **" + elif h['sol_balance'] >= 1: flag = " * ACTIVE *" + print(f" #{h['rank']:2d} | {h['wallet'][:20]}...{h['wallet'][-6:]} | SOL: {h['sol_balance']:>10.4f}{flag}") +sys.stdout.flush() + +print("\n" + "-" * 60) +print("TRANSACTION ANALYSIS (15 txs per holder)") +print("-" * 60) +sys.stdout.flush() + +for h in holders: + wallet = h['wallet'] + time.sleep(RPC_DELAY) + sigs_result = rpc('getSignaturesForAddress', [wallet, {'limit': 20}]) + if not sigs_result: + h['status'] = 'NO_DATA' + print(f"\n #{h['rank']:2d} {wallet[:20]}... -> NO SIGNATURES") + sys.stdout.flush() + continue + + h['tx_count'] = len(sigs_result) + jester_related = [] + checked = 0 + + for sig_info in sigs_result[:15]: + sig = sig_info['signature'] + block_time = sig_info.get('blockTime', 0) + time.sleep(RPC_DELAY) + tx = rpc('getTransaction', [sig, {'encoding': 'jsonParsed', 'maxSupportedTransactionVersion': 0}]) + checked += 1 + if not tx: + continue + + tx_json = json.dumps(tx) + if MINT not in tx_json: + continue + + meta = tx.get('meta', {}) + pre_bals = meta.get('preBalances', []) + post_bals = meta.get('postBalances', []) + + account_keys = [] + msg = tx.get('transaction', {}).get('message', {}) + if 'accountKeys' in msg: + for ak in msg['accountKeys']: + account_keys.append(ak.get('pubkey', '') if isinstance(ak, dict) else ak) + + wallet_idx = None + for idx, key in enumerate(account_keys): + if key == wallet: + wallet_idx = idx + break + + sol_change = 0 + if wallet_idx is not None and wallet_idx < len(pre_bals) and wallet_idx < len(post_bals): + sol_change = sol(post_bals[wallet_idx] - pre_bals[wallet_idx]) + + pre_token = meta.get('preTokenBalances', []) + post_token = meta.get('postTokenBalances', []) + + jester_pre = jester_post = 0 + for tb in pre_token: + if tb.get('mint') == MINT and tb.get('owner') == wallet: + jester_pre = float(tb.get('uiTokenAmount', {}).get('uiAmount', 0) or 0) + for tb in post_token: + if tb.get('mint') == MINT and tb.get('owner') == wallet: + jester_post = float(tb.get('uiTokenAmount', {}).get('uiAmount', 0) or 0) + + token_change = jester_post - jester_pre + tx_time = datetime.fromtimestamp(block_time, tz=timezone.utc).strftime('%Y-%m-%d %H:%M') if block_time else '?' + action = 'BUY' if token_change > 0 else 'SELL' if token_change < 0 else 'INTERACT' + + programs = [KNOWN_PROGRAMS[k] for k in account_keys if k in KNOWN_PROGRAMS] + + jester_related.append({ + 'sig': sig[:16], + 'time': tx_time, + 'action': action, + 'token_change': token_change, + 'sol_change': sol_change, + 'programs': programs, + 'block_time': block_time + }) + + h['jester_txs'] = jester_related + + # Status + sells = [t for t in jester_related if t['action'] == 'SELL'] + buys = [t for t in jester_related if t['action'] == 'BUY'] + if h['balance'] <= 0: + h['status'] = 'EXITED' + elif sells and buys: + h['status'] = 'TRADING' + elif sells: + h['status'] = 'SELLING' + elif buys: + h['status'] = 'ACCUMULATING' + elif jester_related: + h['status'] = 'HOLDING' + else: + h['status'] = 'HOLDING (no recent JESTER txs)' + + # PnL + sol_spent = sum(abs(t['sol_change']) for t in jester_related if t['action'] == 'BUY') + sol_recv = sum(abs(t['sol_change']) for t in jester_related if t['action'] == 'SELL') + if sol_spent > 0 or sol_recv > 0: + h['estimated_pnl'] = { + 'spent': sol_spent, 'received': sol_recv, + 'net': sol_recv - sol_spent, + 'note': f'{len(jester_related)} JESTER txs / {checked} checked' + } + + print(f"\n #{h['rank']:2d} | {wallet[:20]}...{wallet[-6:]} | {h['status']}") + print(f" SOL: {h['sol_balance']:.4f} | JESTER: {h['balance']:,.2f} | Checked {checked} txs, {len(jester_related)} JESTER-related") + for t in jester_related: + prog = ', '.join(t['programs']) if t['programs'] else '' + print(f" {t['time']} | {t['action']:>8} | Tokens: {t['token_change']:>+18,.2f} | SOL: {t['sol_change']:>+10.4f} | {prog}") + if h['estimated_pnl']: + p = h['estimated_pnl'] + print(f" PnL: Spent {p['spent']:.4f} SOL, Received {p['received']:.4f} SOL, Net {p['net']:+.4f} SOL ({p['note']})") + sys.stdout.flush() + +# ============================================================ +# STEP 3: Cross-holdings (SOL >= 5.0 deep, SOL >= 1.0 Buttcoin only) +# ============================================================ +print("\n" + "=" * 80) +print("STEP 3: CROSS-HOLDINGS CHECK") +print("=" * 80) +sys.stdout.flush() + +wealthy = [h for h in holders if h['sol_balance'] >= 5.0] +mid = [h for h in holders if 1.0 <= h['sol_balance'] < 5.0] +print(f" Deep scan (SOL >= 5.0): {len(wealthy)} wallets") +print(f" Quick Buttcoin check (1.0 <= SOL < 5.0): {len(mid)} wallets") + +for h in wealthy: + wallet = h['wallet'] + print(f"\n Deep scan: {wallet[:20]}...{wallet[-6:]} (SOL: {h['sol_balance']:.2f})") + sys.stdout.flush() + + # Buttcoin check + time.sleep(RPC_DELAY) + result = rpc('getTokenAccountsByOwner', [wallet, {'mint': BUTTCOIN_MINT}, {'encoding': 'jsonParsed'}]) + if result and result.get('value'): + for acc in result['value']: + try: + amt = float(acc['account']['data']['parsed']['info']['tokenAmount']['uiAmount'] or 0) + if amt > 0: + h['cross_holdings']['Buttcoin'] = amt + print(f" -> HOLDS Buttcoin: {amt:,.2f}") + except: pass + else: + print(f" -> No Buttcoin") + + # Check recent txs for other tokens this wallet interacts with + time.sleep(RPC_DELAY) + sigs = rpc('getSignaturesForAddress', [wallet, {'limit': 10}]) + other_tokens = {} + if sigs: + for si in sigs[:8]: + time.sleep(RPC_DELAY) + tx = rpc('getTransaction', [si['signature'], {'encoding': 'jsonParsed', 'maxSupportedTransactionVersion': 0}]) + if not tx: continue + meta = tx.get('meta', {}) + for tbl in [meta.get('preTokenBalances', []), meta.get('postTokenBalances', [])]: + for tb in tbl: + m = tb.get('mint', '') + if m and m != MINT and m != BUTTCOIN_MINT and tb.get('owner') == wallet: + ua = float(tb.get('uiTokenAmount', {}).get('uiAmount', 0) or 0) + if ua > 0: + other_tokens[m] = max(other_tokens.get(m, 0), ua) + + if other_tokens: + h['cross_holdings']['other_mints'] = other_tokens + print(f" -> {len(other_tokens)} other tokens in recent txs:") + for m, a in sorted(other_tokens.items(), key=lambda x: -x[1])[:5]: + print(f" {m[:20]}...{m[-8:]} | {a:,.2f}") + sys.stdout.flush() + +# Quick Buttcoin for mid wallets +for h in mid: + time.sleep(RPC_DELAY) + result = rpc('getTokenAccountsByOwner', [h['wallet'], {'mint': BUTTCOIN_MINT}, {'encoding': 'jsonParsed'}]) + if result and result.get('value'): + for acc in result['value']: + try: + amt = float(acc['account']['data']['parsed']['info']['tokenAmount']['uiAmount'] or 0) + if amt > 0: + h['cross_holdings']['Buttcoin'] = amt + print(f" {h['wallet'][:20]}... HOLDS Buttcoin: {amt:,.2f}") + except: pass + +# ============================================================ +# STEP 4: FINAL REPORT +# ============================================================ +print("\n" + "=" * 80) +print("=" * 80) +print(" FINAL REPORT: JESTER HOLDER ANALYSIS") +print("=" * 80) +print("=" * 80) + +holders.sort(key=lambda x: x['balance'], reverse=True) +total_supply_scanned = sum(h['balance'] for h in holders) + +print(f"\n Mint: {MINT}") +print(f" Holders analyzed: {len(holders)}") +print(f" Total JESTER in top {len(holders)}: {total_supply_scanned:,.2f}") +print(f" RPC calls: {call_count}") + +# --- HOLDER TABLE --- +print("\n" + "=" * 80) +print(" COMPLETE HOLDER TABLE") +print("=" * 80) +for h in holders: + cross_str = "" + if 'Buttcoin' in h['cross_holdings']: + cross_str += f"Buttcoin:{h['cross_holdings']['Buttcoin']:,.0f} " + om = h['cross_holdings'].get('other_mints', {}) + if om: + cross_str += f"+{len(om)} tokens " + if not cross_str: cross_str = "-" + print(f" #{h['rank']:2d} | {h['wallet'][:24]}...{h['wallet'][-6:]} | JESTER: {h['balance']:>15,.2f} | SOL: {h['sol_balance']:>8.4f} | {h['status']:<30s} | {cross_str}") + +# --- STILL HOLDING --- +print("\n" + "-" * 60) +print(" STILL HOLDING JESTER") +print("-" * 60) +holding = [h for h in holders if h['balance'] > 0] +for h in holding: + print(f" #{h['rank']:2d} | {h['wallet']} | {h['balance']:>15,.2f} JESTER | SOL: {h['sol_balance']:.4f} | {h['status']}") + +# --- EXITED --- +print("\n" + "-" * 60) +print(" EXITED (sold all JESTER)") +print("-" * 60) +exited = [h for h in holders if h['balance'] <= 0] +if exited: + for h in exited: + print(f" #{h['rank']:2d} | {h['wallet']} | SOL: {h['sol_balance']:.4f}") +else: + print(" None among top 20") + +# --- SELLERS --- +print("\n" + "-" * 60) +print(" SELLERS (actively selling)") +print("-" * 60) +sellers = [h for h in holders if 'SELL' in h['status']] +if sellers: + for h in sellers: + total_sold = sum(abs(t['token_change']) for t in h['jester_txs'] if t['action'] == 'SELL') + print(f" #{h['rank']:2d} | {h['wallet'][:30]}... | Sold ~{total_sold:,.0f} JESTER recently | Still holds {h['balance']:,.0f}") +else: + print(" None detected") + +# --- ACCUMULATORS --- +print("\n" + "-" * 60) +print(" ACCUMULATORS (buying more)") +print("-" * 60) +accum = [h for h in holders if 'ACCUM' in h['status']] +if accum: + for h in accum: + total_bought = sum(t['token_change'] for t in h['jester_txs'] if t['action'] == 'BUY') + print(f" #{h['rank']:2d} | {h['wallet'][:30]}... | Bought ~{total_bought:,.0f} JESTER recently | Holds {h['balance']:,.0f}") +else: + print(" None detected") + +# --- TRADERS --- +print("\n" + "-" * 60) +print(" TRADERS (buying AND selling)") +print("-" * 60) +traders = [h for h in holders if h['status'] == 'TRADING'] +if traders: + for h in traders: + print(f" #{h['rank']:2d} | {h['wallet'][:30]}... | Holds {h['balance']:,.0f} JESTER | SOL: {h['sol_balance']:.4f}") +else: + print(" None detected") + +# --- PnL --- +print("\n" + "-" * 60) +print(" PnL ESTIMATES (visible transactions only)") +print("-" * 60) +pnl_list = [(h, h['estimated_pnl']) for h in holders if h['estimated_pnl']] +pnl_list.sort(key=lambda x: x[1]['net'], reverse=True) +if pnl_list: + for h, p in pnl_list: + emoji = "PROFIT" if p['net'] > 0 else "LOSS" + print(f" #{h['rank']:2d} | {h['wallet'][:30]}... | Net: {p['net']:+.4f} SOL ({emoji}) | Spent: {p['spent']:.4f} | Received: {p['received']:.4f} | {p['note']}") +else: + print(" No PnL data from visible transactions") + +# --- CONVERGENCE --- +print("\n" + "-" * 60) +print(" CROSS-HOLDINGS / CONVERGENCE") +print("-" * 60) + +buttcoin_h = [h for h in holders if 'Buttcoin' in h.get('cross_holdings', {})] +if buttcoin_h: + print(f"\n BUTTCOIN: {len(buttcoin_h)} JESTER holders also hold Buttcoin") + for h in buttcoin_h: + print(f" {h['wallet']} | Buttcoin: {h['cross_holdings']['Buttcoin']:,.2f} | JESTER: {h['balance']:,.2f}") +else: + print(f"\n BUTTCOIN: No convergence found") + +# Find shared mints among wealthy holders +all_other = {} +for h in holders: + om = h['cross_holdings'].get('other_mints', {}) + for m in om: + if m not in all_other: + all_other[m] = [] + all_other[m].append(h['wallet']) + +shared = {m: ws for m, ws in all_other.items() if len(ws) >= 2} +if shared: + print(f"\n SHARED TOKENS (held by 2+ JESTER holders):") + for m, ws in sorted(shared.items(), key=lambda x: -len(x[1])): + print(f" {m} -> {len(ws)} holders:") + for w in ws: + print(f" {w[:30]}...") +else: + print(f"\n No shared token convergence among scanned wallets") + +# --- WHALES --- +print("\n" + "-" * 60) +print(" WHALE / NOTABLE WALLETS") +print("-" * 60) +for h in sorted(holders, key=lambda x: -x['sol_balance']): + if h['sol_balance'] >= 10: + print(f" WHALE | {h['wallet']} | SOL: {h['sol_balance']:>10.2f} | JESTER: {h['balance']:>15,.2f} | {h['status']}") + elif h['sol_balance'] >= 5: + print(f" LARGE | {h['wallet']} | SOL: {h['sol_balance']:>10.2f} | JESTER: {h['balance']:>15,.2f} | {h['status']}") + elif h['sol_balance'] >= 1: + print(f" ACTIVE | {h['wallet']} | SOL: {h['sol_balance']:>10.2f} | JESTER: {h['balance']:>15,.2f} | {h['status']}") + +print("\n" + "=" * 80) +print("ANALYSIS COMPLETE") +print("=" * 80) diff --git a/analyze_token.py b/analyze_token.py new file mode 100644 index 0000000..ddba9df --- /dev/null +++ b/analyze_token.py @@ -0,0 +1,561 @@ +#!/usr/bin/env python3 +"""Full on-chain analysis for a Solana token.""" + +import json, time, urllib.request, urllib.error, os, sys +from datetime import datetime, timezone, timedelta +from collections import defaultdict + +# ── Config ────────────────────────────────────────────────────────────── +MINT = "HXvQAQwytoLngKWQtge3oJnLHsaLwTxPbX48DctLpump" +RPC_DELAY = 0.3 + +# Load env +from dotenv import load_dotenv +load_dotenv("/home/user/Cute-Panel/.env") +RPC = os.environ["HELIUS_RPC_URL"] + +ALPHA_WALLETS = [] +try: + with open("/home/user/Cute-Panel/memory/smart_wallets.json") as f: + sw = json.load(f) + for w in sw.get("wallets", []): + if w.get("chain") == "solana" and w.get("address", "unknown") != "unknown": + ALPHA_WALLETS.append({"address": w["address"], "label": w.get("label", "")}) +except Exception as e: + print(f"[WARN] Could not load smart_wallets.json: {e}") + +TOKEN_PROGRAM = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + +# ── Helpers ───────────────────────────────────────────────────────────── +call_count = 0 +def rpc(method, params=None): + global call_count + call_count += 1 + if call_count > 1: + time.sleep(RPC_DELAY) + body = json.dumps({"jsonrpc":"2.0","id":1,"method":method,"params":params or []}).encode() + req = urllib.request.Request(RPC, body, {"Content-Type":"application/json"}) + try: + with urllib.request.urlopen(req, timeout=30) as r: + resp = json.loads(r.read()) + if "error" in resp: + print(f" [RPC ERROR] {method}: {resp['error']}") + return None + return resp.get("result") + except Exception as e: + print(f" [RPC EXCEPTION] {method}: {e}") + return None + +def fetch_json(url): + req = urllib.request.Request(url, headers={"User-Agent":"Mozilla/5.0"}) + with urllib.request.urlopen(req, timeout=15) as r: + return json.loads(r.read()) + +def lamports_to_sol(l): + return l / 1e9 if l else 0 + +def fmt(n): + if n is None: return "N/A" + if abs(n) >= 1e9: return f"${n/1e9:.2f}B" + if abs(n) >= 1e6: return f"${n/1e6:.2f}M" + if abs(n) >= 1e3: return f"${n/1e3:.1f}K" + return f"${n:.2f}" + +def age_str(ts_ms): + if not ts_ms: return "N/A" + delta = datetime.now(timezone.utc) - datetime.fromtimestamp(ts_ms/1000, tz=timezone.utc) + d = delta.days + h = delta.seconds // 3600 + m = (delta.seconds % 3600) // 60 + parts = [] + if d: parts.append(f"{d}d") + if h: parts.append(f"{h}h") + if m: parts.append(f"{m}m") + return " ".join(parts) if parts else "<1m" + +# ════════════════════════════════════════════════════════════════════════ +# SECTION 1: DexScreener Token Info +# ════════════════════════════════════════════════════════════════════════ +print("=" * 80) +print(" SECTION 1: DEXSCREENER TOKEN INFO") +print("=" * 80) + +dex_url = f"https://api.dexscreener.com/tokens/v1/solana/{MINT}" +try: + dex_data = fetch_json(dex_url) +except Exception as e: + print(f"[ERROR] DexScreener fetch failed: {e}") + dex_data = [] + +token_name = "UNKNOWN" +token_symbol = "UNKNOWN" +token_price = 0 +token_mc = 0 +token_liq = 0 +pair_created = None + +if dex_data and len(dex_data) > 0: + # Pick the pair with highest liquidity + pairs = sorted(dex_data, key=lambda x: x.get("liquidity", {}).get("usd", 0) or 0, reverse=True) + p = pairs[0] + bt = p.get("baseToken", {}) + token_name = bt.get("name", "?") + token_symbol = bt.get("symbol", "?") + token_price = float(p.get("priceUsd", 0) or 0) + token_mc = p.get("marketCap", 0) or p.get("fdv", 0) or 0 + token_liq = (p.get("liquidity") or {}).get("usd", 0) or 0 + vol24 = (p.get("volume") or {}).get("h24", 0) or 0 + vol1h = (p.get("volume") or {}).get("h1", 0) or 0 + buys24 = (p.get("txns") or {}).get("h24", {}).get("buys", 0) or 0 + sells24 = (p.get("txns") or {}).get("h24", {}).get("sells", 0) or 0 + buys1h = (p.get("txns") or {}).get("h1", {}).get("buys", 0) or 0 + sells1h = (p.get("txns") or {}).get("h1", {}).get("sells", 0) or 0 + pc5m = (p.get("priceChange") or {}).get("m5", 0) or 0 + pc1h = (p.get("priceChange") or {}).get("h1", 0) or 0 + pc6h = (p.get("priceChange") or {}).get("h6", 0) or 0 + pc24h = (p.get("priceChange") or {}).get("h24", 0) or 0 + pair_created = p.get("pairCreatedAt") + pair_addr = p.get("pairAddress", "?") + dex_id = p.get("dexId", "?") + + print(f"\n Token: {token_name} ({token_symbol})") + print(f" Mint: {MINT}") + print(f" DEX: {dex_id}") + print(f" Pair: {pair_addr}") + print(f" Price: ${token_price:.10f}") + print(f" Market Cap: {fmt(token_mc)}") + print(f" Liquidity: {fmt(token_liq)}") + print(f" Vol (1h): {fmt(vol1h)}") + print(f" Vol (24h): {fmt(vol24)}") + print(f" Age: {age_str(pair_created)}") + print(f" Buys/Sells (1h): {buys1h} / {sells1h} (ratio: {buys1h/(sells1h or 1):.2f})") + print(f" Buys/Sells (24h): {buys24} / {sells24} (ratio: {buys24/(sells24 or 1):.2f})") + print(f" Price Change (5m): {pc5m:+.2f}%") + print(f" Price Change (1h): {pc1h:+.2f}%") + print(f" Price Change (6h): {pc6h:+.2f}%") + print(f" Price Change (24h): {pc24h:+.2f}%") + + if len(pairs) > 1: + print(f"\n ({len(pairs)} pairs found, showing top by liquidity)") +else: + print("\n [WARN] No DexScreener data returned") + +# ════════════════════════════════════════════════════════════════════════ +# SECTION 2: Top 20 Holders +# ════════════════════════════════════════════════════════════════════════ +print("\n" + "=" * 80) +print(" SECTION 2: TOP 20 HOLDERS") +print("=" * 80) + +# Step 1: Get largest token accounts +largest = rpc("getTokenLargestAccounts", [MINT]) +holders = [] +if largest and "value" in largest: + accounts = largest["value"][:20] + print(f"\n Found {len(accounts)} token accounts. Resolving owners...") + + for i, acc in enumerate(accounts): + ata = acc["address"] + raw_amount = int(acc.get("amount", 0)) + decimals = acc.get("decimals", 6) + balance = raw_amount / (10 ** decimals) if decimals else raw_amount + + # Get owner via getAccountInfo + info = rpc("getAccountInfo", [ata, {"encoding": "jsonParsed"}]) + owner = "UNKNOWN" + if info and info.get("value"): + parsed = info["value"].get("data", {}) + if isinstance(parsed, dict): + pi = parsed.get("parsed", {}).get("info", {}) + owner = pi.get("owner", "UNKNOWN") + + # Get SOL balance of owner + sol_bal = 0 + if owner != "UNKNOWN": + bal_res = rpc("getBalance", [owner]) + if bal_res and "value" in bal_res: + sol_bal = lamports_to_sol(bal_res["value"]) + + holders.append({ + "rank": i + 1, + "ata": ata, + "owner": owner, + "token_balance": balance, + "sol_balance": sol_bal + }) + + # Print table + supply_pct = 0 + if token_mc and token_price: + total_supply = token_mc / token_price if token_price else 0 + else: + total_supply = 0 + + print(f"\n {'#':>3} | {'Owner':^46} | {'Token Bal':>14} | {'SOL':>10} | Flags") + print(" " + "-" * 100) + for h in holders: + flags = [] + if h["sol_balance"] > 10: flags.append("WHALE") + if h["sol_balance"] < 1 and h["owner"] != "UNKNOWN": flags.append("DUST") + pct = "" + if total_supply > 0: + pct = f" ({h['token_balance']/total_supply*100:.1f}%)" + flag_str = " ".join(flags) + bal_str = f"{h['token_balance']:,.0f}{pct}" + print(f" {h['rank']:>3} | {h['owner'][:46]:46} | {bal_str:>14} | {h['sol_balance']:>10.3f} | {flag_str}") + + whales = [h for h in holders if h["sol_balance"] > 10] + dust = [h for h in holders if h["sol_balance"] < 1 and h["owner"] != "UNKNOWN"] + print(f"\n Summary: {len(whales)} whales (>10 SOL), {len(dust)} dust wallets (<1 SOL)") +else: + print("\n [ERROR] Could not fetch largest accounts") + +# ════════════════════════════════════════════════════════════════════════ +# SECTION 3: PnL Estimation for Holders with SOL >= 1.0 +# ════════════════════════════════════════════════════════════════════════ +print("\n" + "=" * 80) +print(" SECTION 3: PnL ESTIMATION (holders with SOL >= 1.0)") +print("=" * 80) + +eligible = [h for h in holders if h["sol_balance"] >= 1.0 and h["owner"] != "UNKNOWN"] +print(f"\n {len(eligible)} holders eligible for PnL scan") + +pnl_results = [] +for h in eligible: + owner = h["owner"] + print(f"\n Scanning #{h['rank']}: {owner[:20]}...{owner[-8:]}") + + # Get recent signatures + sigs_res = rpc("getSignaturesForAddress", [owner, {"limit": 50}]) + if not sigs_res: + print(f" [SKIP] No signatures found") + continue + + total_bought_tokens = 0 + total_sold_tokens = 0 + total_sol_spent = 0 + total_sol_received = 0 + tx_count = 0 + buy_count = 0 + sell_count = 0 + earliest_time = None + + for sig_info in sigs_res[:50]: + sig = sig_info.get("signature") + if not sig: continue + + tx = rpc("getTransaction", [sig, {"encoding": "jsonParsed", "maxSupportedTransactionVersion": 0}]) + if not tx: continue + tx_count += 1 + + meta = tx.get("meta", {}) + if not meta or meta.get("err"): continue + + pre_balances = meta.get("preTokenBalances", []) + post_balances = meta.get("postTokenBalances", []) + + # Find this mint in pre/post balances for this owner + pre_amount = 0 + post_amount = 0 + found_mint = False + + for b in pre_balances: + if b.get("mint") == MINT and b.get("owner") == owner: + pre_amount = float(b.get("uiTokenAmount", {}).get("uiAmount", 0) or 0) + found_mint = True + for b in post_balances: + if b.get("mint") == MINT and b.get("owner") == owner: + post_amount = float(b.get("uiTokenAmount", {}).get("uiAmount", 0) or 0) + found_mint = True + + if not found_mint: + continue + + diff = post_amount - pre_amount + + # Estimate SOL cost from pre/post SOL balances + pre_sol = meta.get("preBalances", []) + post_sol = meta.get("postBalances", []) + acct_keys = tx.get("transaction", {}).get("message", {}).get("accountKeys", []) + + owner_idx = None + for idx, key in enumerate(acct_keys): + k = key.get("pubkey", key) if isinstance(key, dict) else key + if k == owner: + owner_idx = idx + break + + sol_diff = 0 + if owner_idx is not None and owner_idx < len(pre_sol) and owner_idx < len(post_sol): + sol_diff = lamports_to_sol(post_sol[owner_idx] - pre_sol[owner_idx]) + + block_time = tx.get("blockTime") + if block_time and (earliest_time is None or block_time < earliest_time): + earliest_time = block_time + + if diff > 0: # BUY + total_bought_tokens += diff + total_sol_spent += abs(sol_diff) # sol_diff is negative for buys + buy_count += 1 + elif diff < 0: # SELL + total_sold_tokens += abs(diff) + total_sol_received += sol_diff # sol_diff is positive for sells + sell_count += 1 + + # Current value + current_tokens = h["token_balance"] + current_value_usd = current_tokens * token_price if token_price else 0 + cost_usd = total_sol_spent * 85 # rough SOL price estimate from context + realized_usd = total_sol_received * 85 + total_pnl = current_value_usd + realized_usd - cost_usd + multiple = (current_value_usd + realized_usd) / cost_usd if cost_usd > 0 else 0 + + result = { + "rank": h["rank"], + "owner": owner, + "buys": buy_count, + "sells": sell_count, + "sol_spent": total_sol_spent, + "sol_received": total_sol_received, + "tokens_bought": total_bought_tokens, + "tokens_sold": total_sold_tokens, + "current_tokens": current_tokens, + "current_value_usd": current_value_usd, + "cost_usd": cost_usd, + "realized_usd": realized_usd, + "total_pnl": total_pnl, + "multiple": multiple, + "earliest_time": earliest_time, + "txs_scanned": tx_count + } + pnl_results.append(result) + + pnl_sign = "+" if total_pnl >= 0 else "" + print(f" Txs scanned: {tx_count} | Buys: {buy_count} | Sells: {sell_count}") + print(f" SOL spent: {total_sol_spent:.4f} | SOL received: {total_sol_received:.4f}") + print(f" Current holding: {current_tokens:,.0f} tokens = {fmt(current_value_usd)}") + print(f" Est. cost: {fmt(cost_usd)} | Realized: {fmt(realized_usd)}") + print(f" Est. PnL: {pnl_sign}{fmt(total_pnl)} | Multiple: {multiple:.1f}x") + if earliest_time: + dt = datetime.fromtimestamp(earliest_time, tz=timezone.utc) + print(f" Earliest tx: {dt.strftime('%Y-%m-%d %H:%M UTC')}") + +# PnL leaderboard +if pnl_results: + print(f"\n --- PnL Leaderboard ---") + pnl_sorted = sorted(pnl_results, key=lambda x: x["total_pnl"], reverse=True) + for r in pnl_sorted: + sign = "+" if r["total_pnl"] >= 0 else "" + print(f" #{r['rank']:>2} {r['owner'][:16]}... | {sign}{fmt(r['total_pnl'])} ({r['multiple']:.1f}x) | {r['buys']}B/{r['sells']}S | Holds: {r['current_tokens']:,.0f}") + +# ════════════════════════════════════════════════════════════════════════ +# SECTION 4: Mint Activity (last 100 signatures) +# ════════════════════════════════════════════════════════════════════════ +print("\n" + "=" * 80) +print(" SECTION 4: MINT ACTIVITY ANALYSIS (last 100 txs)") +print("=" * 80) + +mint_sigs = rpc("getSignaturesForAddress", [MINT, {"limit": 100}]) +if mint_sigs: + now = datetime.now(timezone.utc) + one_hour_ago = now - timedelta(hours=1) + one_day_ago = now - timedelta(hours=24) + + txs_1h = 0 + txs_24h = 0 + unique_wallets = set() + buy_pressure_sol = 0 + sell_pressure_sol = 0 + total_buys = 0 + total_sells = 0 + largest_buy = {"sol": 0, "sig": "", "wallet": ""} + largest_sell = {"sol": 0, "sig": "", "wallet": ""} + + sig_times = [] + for s in mint_sigs: + bt = s.get("blockTime") + if bt: + dt = datetime.fromtimestamp(bt, tz=timezone.utc) + sig_times.append(dt) + if dt >= one_hour_ago: + txs_1h += 1 + if dt >= one_day_ago: + txs_24h += 1 + + print(f"\n Total signatures fetched: {len(mint_sigs)}") + print(f" Txs in last 1 hour: {txs_1h}") + print(f" Txs in last 24 hours: {txs_24h}") + if sig_times: + print(f" Oldest tx in batch: {min(sig_times).strftime('%Y-%m-%d %H:%M UTC')}") + print(f" Newest tx in batch: {max(sig_times).strftime('%Y-%m-%d %H:%M UTC')}") + + # Parse a subset of recent txs for buy/sell analysis (limit to save RPC calls) + parse_count = min(30, len(mint_sigs)) + print(f"\n Parsing {parse_count} recent txs for buy/sell analysis...") + + for sig_info in mint_sigs[:parse_count]: + sig = sig_info.get("signature") + if not sig: continue + + tx = rpc("getTransaction", [sig, {"encoding": "jsonParsed", "maxSupportedTransactionVersion": 0}]) + if not tx: continue + meta = tx.get("meta", {}) + if not meta or meta.get("err"): continue + + pre_balances = meta.get("preTokenBalances", []) + post_balances = meta.get("postTokenBalances", []) + pre_sol = meta.get("preBalances", []) + post_sol = meta.get("postBalances", []) + acct_keys = tx.get("transaction", {}).get("message", {}).get("accountKeys", []) + + # Find all owners interacting with this mint + owners_pre = {} + owners_post = {} + for b in pre_balances: + if b.get("mint") == MINT: + o = b.get("owner", "") + owners_pre[o] = float(b.get("uiTokenAmount", {}).get("uiAmount", 0) or 0) + for b in post_balances: + if b.get("mint") == MINT: + o = b.get("owner", "") + owners_post[o] = float(b.get("uiTokenAmount", {}).get("uiAmount", 0) or 0) + + all_owners = set(list(owners_pre.keys()) + list(owners_post.keys())) + for o in all_owners: + if not o: continue + unique_wallets.add(o) + pre_tok = owners_pre.get(o, 0) + post_tok = owners_post.get(o, 0) + diff = post_tok - pre_tok + + # Find SOL change + o_idx = None + for idx, key in enumerate(acct_keys): + k = key.get("pubkey", key) if isinstance(key, dict) else key + if k == o: + o_idx = idx + break + sol_change = 0 + if o_idx is not None and o_idx < len(pre_sol) and o_idx < len(post_sol): + sol_change = lamports_to_sol(post_sol[o_idx] - pre_sol[o_idx]) + + if diff > 0: # BUY + total_buys += 1 + sol_cost = abs(sol_change) + buy_pressure_sol += sol_cost + if sol_cost > largest_buy["sol"]: + largest_buy = {"sol": sol_cost, "sig": sig[:20], "wallet": o} + elif diff < 0: # SELL + total_sells += 1 + sol_gained = sol_change + sell_pressure_sol += sol_gained + if sol_gained > largest_sell["sol"]: + largest_sell = {"sol": sol_gained, "sig": sig[:20], "wallet": o} + + print(f"\n Unique wallets (in parsed txs): {len(unique_wallets)}") + print(f" Total buys: {total_buys}") + print(f" Total sells: {total_sells}") + print(f" Buy pressure: {buy_pressure_sol:.4f} SOL") + print(f" Sell pressure: {sell_pressure_sol:.4f} SOL") + net = buy_pressure_sol - sell_pressure_sol + direction = "NET BUY" if net > 0 else "NET SELL" + print(f" Net pressure: {net:+.4f} SOL ({direction})") + + if largest_buy["sol"] > 0: + print(f"\n Largest buy: {largest_buy['sol']:.4f} SOL by {largest_buy['wallet'][:20]}... (tx: {largest_buy['sig']}...)") + if largest_sell["sol"] > 0: + print(f" Largest sell: {largest_sell['sol']:.4f} SOL by {largest_sell['wallet'][:20]}... (tx: {largest_sell['sig']}...)") +else: + print("\n [ERROR] Could not fetch mint signatures") + +# ════════════════════════════════════════════════════════════════════════ +# SECTION 5: Alpha Wallet Cross-Reference +# ════════════════════════════════════════════════════════════════════════ +print("\n" + "=" * 80) +print(" SECTION 5: ALPHA WALLET CROSS-REFERENCE") +print("=" * 80) + +if ALPHA_WALLETS: + print(f"\n Checking {len(ALPHA_WALLETS)} tracked alpha wallets for {token_symbol} holdings...") + found_holders = [] + + for aw in ALPHA_WALLETS: + addr = aw["address"] + label = aw["label"] + + # getTokenAccountsByOwner with mint filter + result = rpc("getTokenAccountsByOwner", [ + addr, + {"mint": MINT}, + {"encoding": "jsonParsed"} + ]) + + if result and result.get("value"): + for acc in result["value"]: + parsed = acc.get("account", {}).get("data", {}).get("parsed", {}).get("info", {}) + tok_amount = parsed.get("tokenAmount", {}) + ui_amount = float(tok_amount.get("uiAmount", 0) or 0) + if ui_amount > 0: + value_usd = ui_amount * token_price + found_holders.append({ + "address": addr, + "label": label, + "balance": ui_amount, + "value_usd": value_usd + }) + print(f"\n *** MATCH: {label}") + print(f" Wallet: {addr}") + print(f" Balance: {ui_amount:,.0f} {token_symbol}") + print(f" Value: {fmt(value_usd)}") + + if not found_holders: + print(f"\n No alpha wallets currently hold {token_symbol}.") + else: + print(f"\n === {len(found_holders)} ALPHA WALLET(S) HOLD {token_symbol} ===") + + # Also check if any top holders are alpha wallets + holder_owners = {h["owner"] for h in holders} + alpha_addrs = {aw["address"] for aw in ALPHA_WALLETS} + overlap = holder_owners & alpha_addrs + if overlap: + print(f"\n [ALERT] Alpha wallets in top 20 holders:") + for addr in overlap: + lbl = next((aw["label"] for aw in ALPHA_WALLETS if aw["address"] == addr), "") + h = next((h for h in holders if h["owner"] == addr), None) + if h: + print(f" #{h['rank']}: {lbl} ({addr[:20]}...) - {h['token_balance']:,.0f} tokens") +else: + print("\n No alpha wallets loaded.") + +# ════════════════════════════════════════════════════════════════════════ +# FINAL SUMMARY +# ════════════════════════════════════════════════════════════════════════ +print("\n" + "=" * 80) +print(" FINAL SUMMARY") +print("=" * 80) +print(f"\n Token: {token_name} ({token_symbol})") +print(f" Price: ${token_price:.10f}") +print(f" MC: {fmt(token_mc)}") +print(f" Liquidity: {fmt(token_liq)}") +print(f" Age: {age_str(pair_created)}") +if holders: + top_holder_pct = holders[0]['token_balance'] / total_supply * 100 if total_supply > 0 else 0 + top5_pct = sum(h['token_balance'] for h in holders[:5]) / total_supply * 100 if total_supply > 0 else 0 + print(f" Top holder: {top_holder_pct:.1f}% of supply") + print(f" Top 5: {top5_pct:.1f}% of supply") + print(f" Whales: {len(whales)} (>10 SOL)") +if pnl_results: + profitable = [r for r in pnl_results if r["total_pnl"] > 0] + print(f" Profitable holders: {len(profitable)}/{len(pnl_results)} scanned") +if mint_sigs: + print(f" Activity (1h): {txs_1h} txs") + print(f" Activity (24h): {txs_24h} txs") + print(f" Buy/Sell: {total_buys}/{total_sells} ({direction})") +if found_holders: + print(f" ALPHA SIGNAL: {len(found_holders)} tracked wallet(s) hold this token!") +else: + print(f" ALPHA SIGNAL: None of our tracked wallets hold this") + +print(f"\n Total RPC calls: {call_count}") +print(f" Analysis complete at {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M:%S UTC')}") +print("=" * 80) diff --git a/auto_deploy.sh b/auto_deploy.sh new file mode 100644 index 0000000..4683fca --- /dev/null +++ b/auto_deploy.sh @@ -0,0 +1,68 @@ +#!/bin/bash +# Auto-deploy: pull latest code from GitHub, start/restart daemons +cd /opt/cute-panel || exit 1 + +# Fetch latest +git fetch origin claude/crypto-intelligence-system-8oO0s 2>/dev/null + +LOCAL=$(git rev-parse HEAD) +REMOTE=$(git rev-parse origin/claude/crypto-intelligence-system-8oO0s) + +if [ "$LOCAL" != "$REMOTE" ]; then + echo "[$(date)] New code detected, deploying..." + git pull origin claude/crypto-intelligence-system-8oO0s + chmod +x *.sh *.py 2>/dev/null || true + + # Fix #4: Syntax check before restart (prevent broken code from taking down daemons) + SYNTAX_OK=true + for pyfile in signal_bus.py scan_x_alpha.py monitor_wallets.py trade_executor.py scan_trending_wallets.py scan_early_buyers.py; do + if [ -f "$pyfile" ]; then + if ! python3 -c "import py_compile; py_compile.compile('$pyfile', doraise=True)" 2>/dev/null; then + echo "[$(date)] SYNTAX ERROR in $pyfile — aborting deploy!" + SYNTAX_OK=false + fi + fi + done + + if [ "$SYNTAX_OK" = true ]; then + systemctl restart crypto-wallet-monitor 2>/dev/null + systemctl restart crypto-x-scanner 2>/dev/null + systemctl restart crypto-trending-scanner 2>/dev/null + echo "[$(date)] Deploy complete. All 3 daemons restarted." + + # Check for pending early buyer scan trigger + if [ -f "scan_trigger.json" ]; then + echo "[$(date)] Scan trigger detected, launching early buyer scan in background..." + nohup bash run_full_scan.sh >> /tmp/scan_bg.log 2>&1 & + echo "[$(date)] Scan started (PID: $!)." + rm -f scan_trigger.json + fi + else + echo "[$(date)] Deploy ABORTED due to syntax errors. Daemons NOT restarted." + git checkout -- . 2>/dev/null # Revert broken code + fi +else + echo "[$(date)] Up to date." +fi + +# Ensure daemons are enabled and running (auto-start on first deploy) +if ! systemctl is-enabled crypto-wallet-monitor &>/dev/null; then + echo "[$(date)] Enabling crypto-wallet-monitor..." + systemctl enable --now crypto-wallet-monitor 2>/dev/null +fi +if ! systemctl is-enabled crypto-x-scanner &>/dev/null; then + echo "[$(date)] Enabling crypto-x-scanner..." + systemctl enable --now crypto-x-scanner 2>/dev/null +fi +if ! systemctl is-enabled crypto-trending-scanner &>/dev/null; then + echo "[$(date)] Enabling crypto-trending-scanner..." + systemctl enable --now crypto-trending-scanner 2>/dev/null +fi + +# Restart if dead +for svc in crypto-wallet-monitor crypto-x-scanner crypto-trending-scanner; do + if ! systemctl is-active "$svc" &>/dev/null; then + echo "[$(date)] $svc dead, restarting..." + systemctl restart "$svc" + fi +done diff --git a/aztec_claim_dashboard.html b/aztec_claim_dashboard.html new file mode 100644 index 0000000..d668a9e --- /dev/null +++ b/aztec_claim_dashboard.html @@ -0,0 +1,1190 @@ + + + + + +AZTEC Supply & Governance Dashboard + + + +
+ +
+
Az
+
+

AZTEC Supply & Governance Dashboard

+
Token: 0xa27e...62d2 | 16,741 ICO vaults
+
+
+
Live On-Chain
+
Loading...
+
+
+ + +
+ How it works: 16,741 ICO participants each have a personal Token Vault (ERC-1167 proxy). + At TGE (Feb 11), 100% of ICO tokens became transferable. Holders withdraw from vaults to wallets. + Some deposited into the Governance contract to vote (15-day lock to withdraw). +
+ + +
+
+
+
Circulating Supply (tokens out of vaults)
+
--.-%
+
+
+
TGE Status
+
LIVE - Withdrawals Open
+
+
+
+
+
+
+
+ 0% + Loading... + 100% +
+
+
+
+
Circulating
+
--
+
--
+
+
+
In Governance (voting)
+
--
+
--
+
+
+
Locked (vaults + vesting)
+
--
+
--
+
+
+
+
+
ICO Allocation
+
--
+
14.95% of supply (16,741 vaults)
+
+
+
Uniswap V4 Pool
+
--
+
--
+
+
+
Token Holders
+
--
+
via ethplorer API
+
+
+
+ + +
+
+
AZTEC Price
+
+
$--
+
--
+
+
+
Market Cap: --
+
FDV: --
+
+
+
+
15-Day Withdrawal Lock (from TGE vote)
+
--d --h --m
+
TGE executed: Feb 11, 2026 ~14:40 UTC
+
+
+ + +
+
+
+
Governance Withdrawals Per Hour
+
Net outflow from governance contract (last 24h)
+
+
+
+
Peak Hour
+
--
+
+
+
24h Total
+
--
+
+
+
+
+
+
+
Loading hourly data (24 RPC calls)...
+
+
+
+ + +
+
Full Token Distribution (10.35B Supply)
+
+ +
+
+ + +
+
+ Governance Contract + 0x1102...b75e +
+
+ AZTEC Token + 0xa27e...62d2 +
+
+ Uniswap V4 Pool + 0x0000...08a90 +
+
+ Chain + Ethereum Mainnet +
+
+ ICO Participants + 16,741 +
+
+ ETH Raised + 19,476 ETH (~$61.3M) +
+
+ Sale Date + Dec 2-6, 2025 +
+
+ TGE Execution + Feb 11, 2026 +
+
+ + +
+ + + + diff --git a/cross_reference.py b/cross_reference.py new file mode 100644 index 0000000..63a91f9 --- /dev/null +++ b/cross_reference.py @@ -0,0 +1,283 @@ +#!/usr/bin/env python3 +""" +Cross-Reference Engine — Connects wallet data with X intelligence and other tokens. + +For each alpha wallet: + 1. Check holdings across ALL tokens in our registry (convergence detection) + 2. Search X/Twitter for wallet address or associated handles + 3. Score wallet based on multi-token presence + X mentions + 4. Update wallet rankings + +Can also cross-reference top N holders of token A against token B (batch mode). +""" + +import json +import os +import subprocess +import sys +import time +from datetime import datetime, timezone +from urllib.request import Request, urlopen +from urllib.error import HTTPError, URLError + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) + +env_path = os.path.join(SCRIPT_DIR, '.env') +if os.path.exists(env_path): + with open(env_path) as f: + for line in f: + line = line.strip() + if '=' in line and not line.startswith('#'): + key, val = line.split('=', 1) + os.environ[key] = val + +HELIUS_RPC = os.environ.get('HELIUS_RPC_URL', '') +XAI_API_KEY = os.environ.get('XAI_API_KEY', '') +SMART_WALLETS = os.path.join(SCRIPT_DIR, 'memory', 'smart_wallets.json') +TOKENS_FILE = os.path.join(SCRIPT_DIR, 'memory', 'tokens.json') +XREF_LOG = os.path.join(SCRIPT_DIR, 'memory', 'cross_reference_results.json') + +RPC_DELAY = 1.0 + +KNOWN_PROGRAMS = { + 'TokenkegQfeE2cNFBpZjxo3WcsKrpLBCq4SzZhScigCZ', + 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb', + 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL', + 'So11111111111111111111111111111111111111112', + '11111111111111111111111111111111', + 'pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA', +} + + +def rpc_call(method, params): + if not HELIUS_RPC: + return None + try: + payload = json.dumps({'jsonrpc': '2.0', 'id': 1, 'method': method, 'params': params}).encode() + req = Request(HELIUS_RPC, data=payload, headers={'Content-Type': 'application/json'}) + with urlopen(req, timeout=15) as resp: + data = json.loads(resp.read()) + if 'error' in data: + return None + return data.get('result') + except Exception: + return None + + +def get_top_holders(mint, count=20): + """Get top holders for a token, resolve to wallet addresses.""" + result = rpc_call('getTokenLargestAccounts', [mint]) + if not result: + return [] + + holders = [] + for acc in result.get('value', [])[:count]: + time.sleep(RPC_DELAY) + info = rpc_call('getAccountInfo', [acc['address'], {'encoding': 'jsonParsed'}]) + if not info or not info.get('value'): + continue + owner = info['value'].get('data', {}).get('parsed', {}).get('info', {}).get('owner', '') + if owner and owner not in KNOWN_PROGRAMS: + holders.append({ + 'wallet': owner, + 'balance': float(acc.get('uiAmount', 0) or 0), + }) + return holders + + +def cross_reference_holders(token_a_mint, token_b_mint, token_a_name='A', token_b_name='B'): + """Find wallets that hold both token A and token B.""" + print(f"\nCross-referencing ${token_a_name} vs ${token_b_name}...") + + holders_a = get_top_holders(token_a_mint) + time.sleep(1) + holders_b = get_top_holders(token_b_mint) + + wallets_a = {h['wallet']: h['balance'] for h in holders_a} + wallets_b = {h['wallet']: h['balance'] for h in holders_b} + + overlap = set(wallets_a.keys()) & set(wallets_b.keys()) + + results = [] + for wallet in overlap: + results.append({ + 'wallet': wallet, + f'{token_a_name}_balance': wallets_a[wallet], + f'{token_b_name}_balance': wallets_b[wallet], + }) + + print(f" ${token_a_name}: {len(holders_a)} holders | ${token_b_name}: {len(holders_b)} holders | Overlap: {len(overlap)}") + return results + + +def batch_cross_reference(target_mint, target_name, comparison_mints): + """ + Cross-reference top holders of target token against ALL comparison tokens. + Returns wallets that appear in multiple tokens. + """ + print(f"\n{'='*60}") + print(f"BATCH CROSS-REFERENCE: ${target_name} vs {len(comparison_mints)} tokens") + print(f"{'='*60}") + + # Get target holders + target_holders = get_top_holders(target_mint) + target_wallets = {h['wallet']: h['balance'] for h in target_holders} + print(f" ${target_name}: {len(target_holders)} top holders resolved") + + # For each comparison token, check overlap + wallet_appearances = {} # wallet -> list of tokens they hold + for wallet in target_wallets: + wallet_appearances[wallet] = [{ + 'token': target_name, + 'mint': target_mint, + 'balance': target_wallets[wallet], + }] + + for mint_info in comparison_mints: + mint = mint_info['ca'] + name = mint_info.get('symbol', mint[:12]) + + print(f"\n Checking ${name} ({mint[:20]}...)...") + time.sleep(1) + + comp_holders = get_top_holders(mint) + comp_wallets = {h['wallet']: h['balance'] for h in comp_holders} + + overlap = set(target_wallets.keys()) & set(comp_wallets.keys()) + if overlap: + print(f" OVERLAP: {len(overlap)} wallets") + for wallet in overlap: + wallet_appearances[wallet].append({ + 'token': name, + 'mint': mint, + 'balance': comp_wallets[wallet], + }) + + # Rank by number of tokens held + multi_token = {w: tokens for w, tokens in wallet_appearances.items() if len(tokens) >= 2} + + print(f"\n RESULTS:") + print(f" Wallets in 2+ tokens: {len(multi_token)}") + + for wallet, tokens in sorted(multi_token.items(), key=lambda x: len(x[1]), reverse=True): + token_list = ', '.join(f"${t['token']}" for t in tokens) + print(f" {wallet[:20]}... | {len(tokens)} tokens: {token_list}") + + return multi_token + + +def search_wallet_on_x(wallet_address): + """Search X/Twitter for mentions of a wallet address.""" + if not XAI_API_KEY: + return [] + + resp = None + try: + payload = json.dumps({ + "model": "grok-4-1-fast", + "tools": [{"type": "x_search"}], + "input": f"Search X/Twitter for any mentions of this Solana wallet address: {wallet_address}. Look for: 1) Any account that has posted this address 2) Any alpha caller or whale watcher mentioning it 3) Any labels (whale, insider, smart money) 4) Associated Twitter handles if any. Also search for the first 20 characters: {wallet_address[:20]}", + }).encode() + req = Request( + "https://api.x.ai/v1/responses", + data=payload, + headers={ + 'Content-Type': 'application/json', + 'Authorization': f'Bearer {XAI_API_KEY}', + }, + ) + with urlopen(req, timeout=120) as resp_obj: + data = json.loads(resp_obj.read()) + + text = data.get('output_text', '') + if not text: + for out in data.get('output', []): + if out.get('type') == 'message': + for c in out.get('content', []): + if c.get('type') in ('output_text', 'text'): + text = c.get('text', '') + + if text: + return [{'source': 'grok_x', 'text': text[:500]}] + except Exception as e: + print(f" X search error: {e}") + + return [] + + +def main(): + """Run cross-reference on all tokens in the scan queue or registry.""" + import argparse + parser = argparse.ArgumentParser(description='Cross-reference token holders') + parser.add_argument('--token', help='Specific token CA to analyze') + parser.add_argument('--name', help='Token name/symbol', default='TARGET') + parser.add_argument('--against', help='Comma-separated CAs to cross-reference against') + parser.add_argument('--all', action='store_true', help='Cross-ref against all tokens in registry') + parser.add_argument('--x-search', action='store_true', help='Also search wallets on X') + args = parser.parse_args() + + now = datetime.now(timezone.utc) + + if args.token: + # Single token cross-reference + target = args.token + name = args.name + + if args.against: + # Against specific tokens + comp_cas = args.against.split(',') + comp_mints = [{'ca': ca.strip(), 'symbol': f'Token{i+1}'} for i, ca in enumerate(comp_cas)] + elif args.all: + # Against all tokens in registry + if os.path.exists(TOKENS_FILE): + with open(TOKENS_FILE) as f: + reg = json.load(f) + comp_mints = [ + {'ca': t['ca'], 'symbol': t.get('symbol', t['ca'][:12])} + for t in reg.get('tokens', []) + if t['ca'] != target and t.get('chain') == 'solana' + ] + else: + print("No tokens registry found.") + return + else: + print("Specify --against CAs or --all") + return + + results = batch_cross_reference(target, name, comp_mints) + + # Optionally search X for multi-token wallets + if args.x_search and results: + print(f"\n Searching X for {len(results)} multi-token wallets...") + for wallet, tokens in sorted(results.items(), key=lambda x: len(x[1]), reverse=True)[:5]: + print(f"\n X search for {wallet[:20]}...") + x_results = search_wallet_on_x(wallet) + if x_results: + for r in x_results: + print(f" X: {r['text'][:200]}") + time.sleep(3) + + # Save results + output = { + 'timestamp': now.isoformat(), + 'target': {'mint': target, 'name': name}, + 'compared_against': len(comp_mints), + 'multi_token_wallets': { + w: [{'token': t['token'], 'balance': t['balance']} for t in tokens] + for w, tokens in results.items() + }, + } + os.makedirs(os.path.dirname(XREF_LOG), exist_ok=True) + with open(XREF_LOG, 'w') as f: + json.dump(output, f, indent=2) + print(f"\nResults saved to {XREF_LOG}") + + else: + print("Usage:") + print(" python3 cross_reference.py --token --name --all") + print(" python3 cross_reference.py --token --name --against ") + print(" Add --x-search to also search wallets on X/Twitter") + + +if __name__ == "__main__": + main() diff --git a/crypto_intel_2026-02-08.md b/crypto_intel_2026-02-08.md new file mode 100644 index 0000000..f9f224e --- /dev/null +++ b/crypto_intel_2026-02-08.md @@ -0,0 +1,518 @@ +# Crypto Intelligence Briefing — February 8, 2026 + +**Session #1 v2 (FULL) | With Live X/Twitter Intelligence via Grok | Market Regime: EXTREME FEAR / CAPITULATION** + +--- + +## Section 1: Memory Review & Previous Session Follow-Up + +**First session — no prior memory.** All memory systems initialized today. This report establishes the baseline for all future sessions. + +**Running Stats:** 0 recommendations, 0 wins, 0 losses, no EV calibration data yet. + +**Key Context for Baseline:** We are entering this system during one of the most severe crypto selloffs since FTX. BTC dropped from $126K ATH (Oct 2025) to $60K intraday on Feb 5 — a 52% drawdown. The Fear & Greed Index hit 7. Weekly RSI is sub-30 for the first time since mid-2022. Bitcoin's entity-adjusted realized loss hit a record $3.2B on Feb 5. This is the environment we begin operating in. + +--- + +## Section 2: Market Structure Snapshot + +### Prices (Feb 8, 2026) +| Asset | Price | 24h Change | From ATH | +|-------|-------|-----------|----------| +| BTC | $69,542 | +0.84% | -44.8% | +| ETH | $2,080 | +2.0% | -58.4% | +| SOL | $87.06 | — | -70.3% | +| XRP | $1.85 | — | -49.5% | +| HYPE | $32.98 | — | -44.5% | + +### Market Structure +- **Total Market Cap:** $2.39T (24h volume: $271B) +- **BTC Dominance:** 58.7% (rising — risk-off signal) +- **ETH Dominance:** 10.4% (near cycle lows) +- **Fear & Greed Index:** 7-11 (EXTREME FEAR) + +### Flow Data (Updated with Live X Intelligence) +- **BTC ETF Flows:** CRITICAL REVERSAL SIGNAL — BTC spot ETFs saw **+$330M net inflows on Feb 7**, breaking the sustained outflow streak post-crash. This is the first meaningful positive flow since the capitulation. Prior: $6.18B net outflows over 3 months, $1.33B outflow in the prior week. **If inflows sustain 2-3 more days, this confirms regime change.** [Source: X posts from ETF flow trackers] +- **Funding Rates:** BTC funding flipped **negative** (-0.0034% to -0.006%) — shorts paying longs. This is a classic bottom signal post-deleveraging. SOL perps at -0.0282% (bearish tilt). [Source: X @CryptoQuant, @CoinGlass data] +- **Open Interest:** BTC OI crashed ~23% during the $60K dip, now stabilizing around $82B. The deleveraging is largely complete. SOL OI at $0.81B. [Source: X] +- **Liquidations:** $756K in last 90min (70% shorts: $530K vs longs $225K). The prior cascade hit $1.8B in longs during the BTC $60K test on Feb 5. Shorts are now the vulnerable side. +- **Stablecoin Supply:** BULLISH — $267M USDC minted on Ethereum (supply now $50.11B). TRON saw $1B USDT mint (week total $3B+). Solana had $275M USDC burn but prior +$848M mint. Fresh dry powder entering the system. [Source: X @whale_alert] +- **Options:** $2.1B BTC options expiry (34K contracts), put/call ratio 0.59 (calls favored). Max pain at $82K. Heavy OI at $100K and $70K strikes. Options market skews cautiously bullish. +- **BTC Supply in Loss:** 8.9M BTC at a loss — 4th highest in history, comparable to 2015/2019/2022 bear market bottoms. +- **Whale Alert:** $246M BTC whale inflow to Binance (dip buy or sell prep — watch). Vitalik donated ~$6-10M ETH. Dormant BTC wallet (5+ years inactive) just activated. "Trump insider whale" dumped 6,599 BTC (~$500M) per X reports — fueling crash narrative. +- **Trend Research Update:** Dumped $44M ETH at a loss per X reports. Position health factor needs monitoring. + +### Hyperliquid Metrics (Live X Intelligence) +- **Open Interest:** $12.7B (down from $15B+), stabilizing +- **Daily Volume:** Regularly exceeds $10B +- **Monthly Fees:** $4M+ | Captured >30% perp DEX market share (5 straight weeks of growth) +- **Perp DEX volumes** hit SECOND-HIGHEST ON RECORD (only behind Oct 10, 2025) per DefiLlama +- **HYPE Holders:** 160K+ | $960M cumulative revenue, buybacks funded +- **Trader Positioning:** BEARS DOMINANT on Hyperliquid. Largest position is a 3x BTC short ($70.9K liquidation, 3x bigger than next). Whale 0x94d3 has $5.11M short with +$4.8M unrealized PnL. Whale 0x4e31 shorting BTC 3x leverage $3.53M at $70.7K entry. **When Hyperliquid top traders are unanimously short, watch for the squeeze.** +- **Notable:** HYPE slashed Feb unlock by 90% (1.2M → 140K tokens), triggering 50% rally. + +### Direction Assessment (Web + Grok Convergence) +The plumbing is shifting from pure capitulation to **early bottom-fishing with caution**: +- **BULLISH signals:** ETF inflows flipped positive (+$330M), negative funding (shorts paying), 23% OI deleveraging complete, $3B+ stablecoin mints as dry powder, options put/call at 0.59 (calls favored) +- **BEARISH signals:** Hyperliquid top traders unanimously short, "Trump insider whale" dumped $500M BTC, spot CVD still weak, macro headwinds persist +- **Short-term (1-3 days):** Bullish relief rally to $73-75K probable if $70K holds — liquidation clusters overhead, ETF flows need to confirm +- **Medium-term (4-7 days):** Neutral/cautious — macro volatility, dealer hedging flows. Bears trapped at max leverage but spot demand still weak +- **The key tell:** Hyperliquid whales are max short while ETF flows just flipped positive. One side is wrong. If ETF inflows sustain, the short squeeze could be violent. If they don't, shorts print. + +--- + +## Section 3: Ecosystem & DeFi Intelligence + +### TVL Overview +- **Total DeFi TVL:** ~$96-105B (down from $120B peak but only -12%, outperforming token prices) +- **ETH in DeFi:** 25.3M ETH (1.6M ETH added in past week — people are deploying, not fleeing) +- **Liquidatable Positions:** Only $53M within 20% of current price (vs $340M during similar drop last year — DeFi is better collateralized) + +### Chain Rankings by TVL +1. **Ethereum:** $55.5B (dominant, ~58% share) +2. **Solana:** ~$8.8B +3. **BSC** +4. **Bitcoin** +5. **Tron** +6. **Base** +7. **Arbitrum** +8. **Hyperliquid L1:** $1.5B (337% TVL growth — standout) +9. **Polygon** +10. **Avalanche/Sui** + +### Protocol Highlights +- **Aave:** #1 protocol by TVL at $28.15B. Revenue sharing announced Jan 2, 2026. SEC investigation closed without action Dec 2025. V4 launching in 2026 with cross-chain unified liquidity. AAVE at ~$114-178. +- **Lido:** $28B+ TVL. stETH remains dominant liquid staking derivative. +- **EigenLayer:** $17.5B TVL, $128M+ in rewards paid to operators. Restaking narrative maturing. + +### L2 Landscape +- **Base:** #1 L2 by activity. 60%+ of all L2 transactions. 43.5% of L2 TVL. Leveraging Coinbase's 100M+ users. +- **Arbitrum:** #1 L2 by DeFi TVL at ~44% share. Stable but not growing. +- **Consolidation:** 21Shares predicts most L2s won't survive 2026. Smaller rollups seeing 61% usage drops. Top 3 (Base, Arbitrum, Optimism) processing 90% of transactions. + +### Live X DeFi Intelligence (Grok Sub-Agent: The Cartographer) +- **Aave dominance growing:** Rose from 25% to 34% of Ethereum lending TVL over past 12 months. Capital flight to trusted balance sheets in risk-off. +- **Perp DEX volume near ATH:** Second-highest on record per DefiLlama — leverage demand outpacing spot. +- **Top stablecoin yields (7-day, via DeFi Warhol on X):** + - YuzuMoneyX: Highest leveraged yields, TVL +23% + - Hyperwavefi: 42.38% (Hyperliquid MM/liquidations), TVL +6.8% + - Liquity: 37.87%, TVL -23.7% + - SmarDex: 20.27% (Hyperliquid funding arb), TVL -12.3% + - MidasRWA mRe7YIELD: 14.74% + - Superstate: 13.98% +- **New launch watch:** Decibel (Aptos perp DEX) — Season 0 pre-deposit live (min 50 USDC, time-weighted points for TGE airdrop). Opens Feb 10 UTC. +- **Under-the-radar:** Folks Finance on Algorand hit $52.44M TVL (#2 protocol on chain), cross-chain expansion. +- **RWA inflows:** Multiplifi and Theo Network (thBILL/thGOLD) seeing quiet deposits during DeFi contraction — positioning ahead of RWA repricing. + +### Key Trend: DeFi Resilience +DeFi TVL fell only 12% while token prices crashed 30-50%. This divergence means more ETH and more stablecoins are being deployed into DeFi even as prices fall. The sector is maturing — better collateralization, real yield, and growing institutional usage. Perp DEX volumes near ATH confirm leverage demand is alive. This is bullish for DeFi tokens on a 3-6 month horizon. + +--- + +## Section 4: Solana Trenches Report + +### Network State +- **SOL Price:** $87.06 (down 70% from $293 ATH) +- **DeFi TVL:** $8.8B (held up relative to price decline) +- **DEX Volume:** $1.5T+ YTD in 2025, crushing Ethereum +- **Stablecoin Supply:** ~$17B on Solana +- **SOL ETFs:** Launched Nov 2025 (Bitwise BSOL on NYSE, 21Shares TSOL on Cboe) + +### Ecosystem Developments +- **Alpenglow Upgrade:** Major consensus overhaul targeting 150ms finality (down from 12s). Mainnet targeted H1 2026. +- **Firedancer:** Production rollout in 2026 — major performance upgrade. +- **Standard Chartered:** Cut 2026 target to $250 but sees SOL reaching $2,000 by 2030. Sees shift from "memecoins to micropayments." +- **Key DeFi:** Jupiter ($700M+ daily volume), Kamino (~7.5% staking rewards), Pyth (380+ price feeds, powers 95% of Solana DeFi TVL). + +### Live X Solana Intelligence (Grok Sub-Agent: The Degen) +**X Sentiment:** Cautionary, heavily skewed toward scam warnings and fake airdrop phishing. No massive organic pumps — lots of self-promo from new launches. Jupiter stealing the spotlight. + +**Trending on X today (Feb 8):** +- $PENGU (Pudgy Penguins) +3.15% — frequent top-of-list mentions +- $SIREN — #1 on some daily trend trackers +- $ICEBEAR — +21.7% on DexScreener, arctic meme theme +- $BNKR — +39% today +- $LUMEN — +23.5% +- $Fartcoin — persistent meme mentions +- XRP spot flows spiking +2,860% — rising risk appetite signal + +**New launches with some legitimacy:** +- $CUKE (CA: `ELh9nHbFLfXJ3XdXnPPLNAJM1NzAg6HPb7MUvVJKyeHh`) — LP locked 12 months via Streamflow, community vibes +- $FLIP Casino — Creator tokens locked 6 months, 7 games live, burns on bets +- SolsticeFi: $301M TVL in $USX, 3.28% APY, $SLX airdrop for holders — only legit-looking Solana DeFi airdrop on X today + +**TRAPS AND SCAMS (from X today):** +- Sophon: TVL crashed from $8M to $3M in 3 days despite $45M raise. $5 daily DEX volume, $100M FDV. Zero traction. +- Unnamed Solana DeFi protocol: 90% TVL vanished overnight — suspected insider rug via burner wallets + kill switch +- Massive fake airdrop phishing wave: $TULSA, $BFS, BlackSwan, $HYB, $USOR — ALL SCAM SITES. Do not connect wallets. +- GameFi phishing: Fake links use "bot flagged" screen to trick users into connecting rich wallets + +### Memecoin Meta +- 11.9M+ tokens created via Pump.fun since launch +- Current meta is shifting: memecoins still active but the narrative is evolving toward utility +- X sentiment strongly cautionary — scam fatigue setting in +- Caution: In extreme fear environments, memecoin liquidity dries up fast. Most Solana trench plays are zero in this regime. + +### Assessment +SOL at $87 with Alpenglow + Firedancer upgrades coming, ETF approval already secured, and $17B in stablecoins is interesting on a 6-12 month view. Short-term, it's correlated to BTC and will chop. The memecoin meta is cooling — the next Solana narrative is institutional-grade infrastructure and micropayments. + +--- + +## Section 5: Alpha Signals + +### Signal 1: HYPE — Defying Gravity +Hyperliquid slashed its February unlock by 90% and the token rallied 50% while everything else bled. With $1.5B TVL, 337% TVL growth, $10B daily volume, and a $644M buyback fund, HYPE is one of the few tokens with actual revenue backing (>$4M/month in fees). The HIP-4 proposal opening prediction markets is a new catalyst. Next major unlock: March 6 ($309M for core contributors — watch this closely). + +### Signal 2: ONDO — RWA Paradox +Ondo's tokenized equities volume is up 2,695% YTD yet the ONDO token is down 80%. The $1.94B unlock on Jan 18 crushed price to $0.28. BUT: MetaMask integration (Feb 3) gives access to 200+ tokenized stocks for millions of users. Ondo Summit drew BlackRock, Goldman, WisdomTree. The supply overhang is the issue, not demand. Once unlock selling is absorbed, this has significant upside. Testing $0.20-$0.32 demand floor. + +### Signal 3: Airdrop Season — Lighter, OpenSea (SEA), Monad +- **Lighter:** Largest decentralized perps DEX by 30-day volume, running points program. Token likely in 2026. +- **OpenSea SEA:** Token launching Q1 2026, 50% to community, majority via airdrop claim. +- **Monad:** $244M raised from Paradigm + DragonFly. Testnet live. EVM-compatible L1 with 10K TPS. One of the most anticipated launches. +- **MetaMask/Linea:** Points program converting to tokens + fee discounts. + +### Signal 4: VC Money is Still Flowing (Grok: The Rat, Live X) +Week 1 February: $251.9-258M in crypto VC funding despite the carnage: +- **Anchorage Digital: $100M** (Tether-led) — institutional custody +- **TRM Labs: $70M** ($1B valuation) — crypto compliance/intelligence +- **Konnex World: $15M** (LD Capital/Cogitent) — physical labor on-chain +- January rounds: Rain, BitGo, BlackOpal, LMAX, Alpaca, Tres, 3iQ, Propy, Mesh +- **Pattern:** VCs are loading compliance/custody/infra plays while retail panics. This is a STRONG contrarian signal — sophisticated money betting on the infrastructure layer, not the token layer. + +### Signal 5: Jupiter JUPUARY Airdrop (Live X) +Per X posts: Jupiter confirmed snapshot on Jan 30 for JUPUARY 2026. 200M JUP airdrop + 200M to stakers. Sellers get 3x penalty. 300M locked. If you held/staked JUP before Jan 30, check eligibility. + +### Signal 6: Stealth Alpha from X (Grok: The Rat) +Low-engagement posts (<20 likes) from credible accounts surfacing: +- **$ANONYMOUS** — No site/team/description, 2.4K holders at $336K MC on pure vibes. CA: `APCwYR7NjV9ZMk2Lx86p9ZQQaeCCDd44DJG1MJbWpump`. Pure degen. +- **$BUTTCOIN** — Insider sniper wallet up 250K from $29 buy. Track wallet: `AowTUid5daQr9EqwazF7hDm3jBTQSisv6LaHGhQL8k92` for dump signal. +- **ProveX** — Stealth app live at app.provex.com, flagged by single low-engagement post. ZK/privacy play? +- **Decibel (Aptos perps)** — Pre-deposit opens Feb 10, time-weighted points for TGE airdrop. Early perp narrative play. +- **On-chain DD tool:** @nikshepsvn used Claude to trace tx flows as alpha method. Fresh approach most ignore. + +### Signal 7: Berachain Uncertainty +BERA facing 41.7% circulating supply unlock on Feb 6. Nova Digital (Brevan Howard) has contractual right to reclaim $25M investment. Mixed signals. High risk, unclear reward. + +--- + +## Section 6: Smart Wallet Activity + +**Session 1 — Initializing Database** + +### Notable Wallets Discovered Today +1. **"White Whale"** — Top Hyperliquid trader, $50M+ profit in 30 days. Strategy: avoids contrarian positions, follows momentum. Need to identify on-chain wallet. +2. **"James Wynn"** — High-profile Hyperliquid trader. Track positions for directional signals. +3. **"Trend Research"** — Deposited $1.8B ETH on Aave, borrowed $958M in stablecoins. This is a massive leveraged long on ETH. If ETH drops further, this creates liquidation cascading risk. If ETH recovers, this wallet prints. +4. **Hardware Wallet Phishing Victim** — Lost $284M. Not alpha but a reminder: operational security is everything. + +### New Wallets from Live X (Grok: The Plumber) +5. **Hyperliquid Whale 0x4e31** — Shorting BTC 3x leverage, $3.53M at $70.7K entry. Directional signal: bearish. +6. **Hyperliquid Whale 0x94d3** — $5.11M BTC short, +$4.8M unrealized PnL. The most profitable current short. +7. **"Trump Insider Whale"** — Dumped 6,599 BTC (~$500M) per X reports. Political insider? +8. **$BUTTCOIN Sniper** — Wallet `AowTUid5daQr9EqwazF7hDm3jBTQSisv6LaHGhQL8k92` — up 250K from $29 buy. Track for dump timing. + +### Action Items for Next Session +- Identify White Whale's on-chain wallet address via Hypurrscan +- Track Trend Research's Aave position health factor (they dumped $44M ETH at loss per X) +- Monitor 0x4e31 and 0x94d3 Hyperliquid shorts — if they close, bullish signal +- Investigate "Trump insider whale" BTC dump — political connection? +- Check Arkham for labeled wallets making significant moves during the capitulation + +--- + +## Section 7: Risk Radar + +### CRITICAL RISKS + +**1. Continued ETF Outflows (SEVERITY: HIGH)** +$6.18B outflows over 3 months. Only IBIT still receiving inflows. If BlackRock reverses, there is no institutional bid. This is the single most important metric to monitor daily. + +**2. $732M Token Unlocks in February (SEVERITY: HIGH)** +- HYPE: $306M (but slashed 90% — now only ~$30M effective) +- ZRO: $44M+ +- JUP: $44M+ (larger cliff of 200M JUP on Feb 28) +- MOVE: Feb 9 unlock for early backers +- BERA: 41.7% of circulating supply unlocked Feb 6 + +**3. Exploit/Hack Pace (SEVERITY: HIGH)** +$400M stolen in January alone. CrossCurve $3M bridge exploit in Feb. Truebit $26.5M hack. The pace is accelerating. Same attacker hit both Truebit and Sparkle. North Korean hackers stole $2.02B in 2025. Cross-chain bridges remain the weakest link. + +**4. Macro: U.S.-Iran Tensions + Hawkish Fed (SEVERITY: MEDIUM-HIGH)** +Kevin Warsh as Fed Chair = hawkish. DXY above 97.5. Oil volatility from U.S.-Iran tensions. These are not crypto-specific but they're driving the risk-off environment. + +**5. 44% of BTC Supply Underwater (SEVERITY: MEDIUM)** +Creates a supply overhang where any rally faces selling from underwater holders trying to get out at breakeven. This dampens recovery speed. + +**6. Trend Research Aave Position (SEVERITY: MEDIUM)** +$1.8B ETH collateral, $958M borrowed. If ETH drops significantly from here, cascading liquidation risk on Aave. Monitor health factor. + +### NEW RISKS FROM LIVE X (Grok: The Paranoid) + +**8. Exchange Manipulation (SEVERITY: HIGH)** +Binance ETH/USDT saw $100 pumps/dumps 40x in seconds, liquidating $1.3B longs ($7B total liquidations). X users calling it "pure crime" — manipulator printed/destroyed $13B value per minute. Mass calls to withdraw from Binance. Self-custody is paramount. + +**9. Audit Illusion (SEVERITY: MEDIUM-HIGH)** +Per X analysis: Balancer (11 audits) was hacked for $128M. Cetus (audited) lost $223M from a math library bug. Step Finance lost $30M via phished treasury keys. "Audited" does not mean safe. Audit is necessary but not sufficient. + +**10. HYPE Pre-Unlock Pump Pattern (SEVERITY: MEDIUM)** +X users flagging that HYPE's pump coincided suspiciously with pre-team-unlock timing. Pattern: team/insiders pump token before their unlock to maximize exit value. Watch March 6 closely. + +### AVOID +- Any Solana memecoin without at least 2 weeks of consistent volume +- ALL "airdrop claim" links on X — massive phishing wave ($TULSA, $BFS, BlackSwan, $HYB, $USOR all scams) +- Berachain ecosystem tokens until unlock selling is absorbed +- Cross-chain bridge interactions (exploit risk elevated) +- Any token with >10% of supply unlocking this month +- Sophon — $45M raised but $5/day DEX volume, zero traction + +--- + +## Section 8: Today's Recommendations + +### BUYS TODAY + +#### Conviction Buys (1-3 Month Horizon) + +**1. HYPE (Hyperliquid) at $32.98 ($8.1B mcap)** +**Thesis:** HYPE is the standout performer in this bear market for a reason. Real revenue ($4M+/month fees), 337% TVL growth to $1.5B, $10B daily volume, 90% unlock reduction, $644M buyback fund, and expanding into prediction markets (HIP-4). This is a protocol with actual product-market fit generating real cash flow in a market starved for fundamentals. +**Catalyst:** HIP-4 prediction markets launch, continued fee growth, March unlock only $30M effective +**Target:** $48 (+45%) +**Invalidation:** Loss of $24 (break below 200-day MA and Jan low) +**Allocation:** 8% +**Smart Wallets:** White Whale (top HL trader) actively using platform +**EV Calculation:** +- Bull: 25% chance of +80% (prediction markets take off, BTC recovers) = +20.0% +- Base: 50% chance of +20% (steady growth, market stabilizes) = +10.0% +- Bear: 25% chance of -30% (March unlock dumps, broader market continues down) = -7.5% +- **EV: +22.5%** + +**2. ETH (Ethereum) at $2,080 ($250B mcap)** +**Thesis:** ETH is down 58% from ATH while DeFi TVL on Ethereum actually grew in ETH terms. 1.6M ETH added to DeFi in the past week alone. L2 activity consolidating around Ethereum ecosystem (Base + Arbitrum = 90% of L2 activity). Weekly RSI sub-30 for first time since mid-2022 — historically preceded major bottoms within 3-6 months. Institutional players like Trend Research are actively leveraged long. +**Catalyst:** Pectra upgrade, L2 growth, DeFi real yield narrative, potential ETH ETF flow reversal +**Target:** $3,200 (+54%) +**Invalidation:** Sustained break below $1,800 +**Allocation:** 15% +**Smart Wallets:** Trend Research $1.8B position on Aave +**EV Calculation:** +- Bull: 25% chance of +80% (macro pivot, institutional re-entry) = +20.0% +- Base: 45% chance of +25% (gradual recovery over 3 months) = +11.25% +- Bear: 30% chance of -25% (continued bear, tests $1,500) = -7.5% +- **EV: +23.75%** + +**3. AAVE at ~$150 ($2.2B mcap)** +**Thesis:** #1 DeFi protocol by TVL ($28B). SEC investigation closed. Revenue sharing with token holders announced. V4 launching 2026 with cross-chain liquidity. In bear markets, DeFi lending protocols benefit from increased borrowing demand (for shorting, hedging). Aave is the blue-chip DeFi play and it's down 60%+ from 2025 highs. +**Catalyst:** V4 launch, revenue sharing implementation, bear market drives lending demand +**Target:** $250 (+67%) +**Invalidation:** Below $100 (loss of key support, DeFi TVL collapse) +**Allocation:** 6% +**Smart Wallets:** Multiple institutional users on-chain +**EV Calculation:** +- Bull: 20% chance of +100% (V4 success, DeFi renaissance) = +20.0% +- Base: 50% chance of +30% (steady TVL, revenue sharing kicks in) = +15.0% +- Bear: 30% chance of -35% (broader market drags it down further) = -10.5% +- **EV: +24.5%** + +#### Narrative Buys (Emerging Narratives) + +**1. ONDO at $0.28 ($0.44B mcap) — RWA Tokenization** +**Narrative:** Real World Asset tokenization is the institutional crypto narrative. BlackRock, Goldman, WisdomTree all present at Ondo Summit. MetaMask integration = distribution to millions. Tokenized equity volume up 2,695%. The token was crushed by $1.94B unlock but is approaching a demand floor. +**Upside:** If RWA narrative recaptures attention and unlock selling is absorbed: 5-10x from current levels is achievable within 12 months +**Exit Criteria:** Exit if token breaks below $0.18 (structural breakdown) or if RWA TVL stagnates +**EV Calculation:** +- Bull: 20% chance of +400% (RWA goes mainstream, supply absorbed) = +80.0% +- Base: 40% chance of +50% (gradual recovery as unlock pressure fades) = +20.0% +- Bear: 40% chance of -50% (continued unlock selling, market doesn't recover) = -20.0% +- **EV: +80.0%** (high variance — size accordingly, max 3% allocation) + +**2. SOL at $87 — Infrastructure Evolution** +**Narrative:** Solana is transitioning from "memecoin casino" to "institutional-grade infrastructure." Alpenglow (150ms finality), Firedancer, SOL ETFs approved, $17B stablecoins, Standard Chartered sees $2,000 by 2030. At $87, you're buying the infrastructure narrative at memecoin-bust prices. +**Upside:** $200+ if infrastructure narrative takes hold and BTC stabilizes +**Exit Criteria:** Exit below $60 (structural bear below COVID crash recovery level) +**EV Calculation:** +- Bull: 25% chance of +130% (infra narrative, BTC recovery, $200) = +32.5% +- Base: 40% chance of +40% (stabilization, gradual recovery to $120) = +16.0% +- Bear: 35% chance of -40% (continued bear, tests $50) = -14.0% +- **EV: +34.5%** + +#### Trench Plays (High Risk/High Reward) + +**1. Lighter Exchange Airdrop Farm — $0 capital at risk (time only)** +Lighter is the largest decentralized perps exchange by 30-day volume, running an explicit points program that will almost certainly convert to a token airdrop. Based on Hyperliquid Season 1 ($6.2B valuation airdrop), active traders on Lighter could receive significant allocations. +**Realistic Upside:** $1K-$100K depending on activity level +**Maximum Allocation:** Time investment only, trade with normal capital +**EV:** Positive by definition (time cost only, potential for significant airdrop) + +**2. OpenSea SEA Token Claim — Q1 2026** +50% of supply going to community, majority via initial airdrop. If you've used OpenSea historically, check eligibility. If not, start using the platform now for potential inclusion in secondary distribution. +**EV:** Free optionality for existing users + +**3. Monad Testnet Farming** +$244M raised from Paradigm + DragonFly. Testnet live. Deep interaction = likely high airdrop allocation. EVM-compatible L1 with 10K TPS. One of the most well-funded upcoming launches. +**Maximum Allocation:** Time only (testnet is free) +**EV:** Positive — high funding suggests high valuation at launch + +#### Yield Plays (Risk-Adjusted) + +**1. Aave V3 USDC/USDT Lending — Ethereum** +- **APY:** 4-7% on stablecoins +- **Yield Source:** Real borrowing demand (institutional + leverage traders) +- **Risk:** Smart contract risk (Aave is heavily audited, $28B TVL battle-tested) +- **Annualized EV:** ~5% after accounting for ~0.5% annualized smart contract risk +- **Assessment:** Best risk-adjusted stablecoin yield in DeFi. Park idle capital here during uncertainty. + +**2. Lido stETH Staking** +- **APY:** ~4-8% depending on vault strategy +- **Yield Source:** Ethereum validator rewards + DeFi yield optimization +- **Risk:** stETH depeg risk in extreme scenarios, smart contract risk +- **Annualized EV:** ~5-6% net of risks +- **Assessment:** If you're holding ETH, it should be staked via Lido. No reason to hold naked ETH. + +**3. Jito Liquid Staking — Solana** +- **APY:** ~7%+ with MEV rewards +- **Yield Source:** Solana validator rewards + MEV extraction +- **Risk:** SOL price risk, smart contract risk +- **Annualized EV:** ~6% net of risks (higher than Lido due to MEV component) +- **Assessment:** If holding SOL, stake via Jito for MEV-enhanced returns. + +### SELLS TODAY + +**1. SELL: BERA (Berachain)** +**Reason:** 41.7% of circulating supply just unlocked Feb 6. Nova Digital (Brevan Howard) has contractual right to reclaim $25M investment. Massive sell pressure with thin liquidity in a bear market. The "Bera Builds Businesses" narrative is early-stage and unproven. Wait for unlock selling to be fully absorbed (4-8 weeks minimum). +**EV of Holding:** +- Bull: 15% chance of +60% = +9.0% +- Base: 35% chance of -10% = -3.5% +- Bear: 50% chance of -50% = -25.0% +- **EV: -19.5%** — Negative EV, clear sell. + +**2. SELL/REDUCE: Any altcoin with >10% supply unlock in February** +Specifically: MOVE (Feb 9 unlock for early backers), XDCE (5.36% supply unlocked Feb 5). In a bear market, unlock selling is amplified. Reduce positions ahead of unlocks and re-enter after selling pressure is absorbed. + +**3. SELL: Overexposed memecoin positions** +In extreme fear environments with BTC dominance at 58.7% and rising, memecoins bleed disproportionately. Unless you have strong conviction in a specific community token, reduce memecoin exposure to <5% of portfolio. The meta is shifting away from memes. + +#### Short Candidates + +**1. SHORT: BTC range trade — Short at $73K-$75K resistance** +**Thesis:** BTC is in a dead-cat bounce pattern. The Feb 5 flush to $60K cleared leveraged longs but hasn't generated sustained buying. ETF outflows continue. 44% of supply is underwater creating a supply overhang. Rally to $73K-$75K meets resistance from sellers who got trapped on the way down. +**Squeeze Risk:** MODERATE — if IBIT sees a big inflow day, shorts get squeezed. Size conservatively. +**Sizing:** Max 3% of portfolio, tight stop at $78K +**EV Calculation:** +- Bull: 25% chance of -15% (squeeze to $78K, stop hit) = -3.75% +- Base: 45% chance of +12% (retrace to $65K) = +5.4% +- Bear: 30% chance of +25% (retest of $60K) = +7.5% +- **EV: +9.15%** + +--- + +## Section 9: The Interesting Stuff + +### The $284M Phishing Attack +A single investor lost $284M on January 16 after someone impersonating Trezor customer support tricked them into revealing their recovery seed phrase. This was 71% of all January theft. The target wasn't a smart contract — it was a human. Social engineering is now the dominant attack vector, not code exploits. + +### DeFi's Quiet Strength +While crypto Twitter panics about prices, DeFi TVL only dropped 12% despite a 30-50% crash in underlying token prices. In ETH terms, DeFi TVL actually grew. This means more capital is being deployed into productive on-chain use. The sector is silently maturing while everyone focuses on price charts. + +### The White Whale Mystery +A single pseudonymous trader on Hyperliquid has made $50M+ in 30 days. They don't trade contrarian — they follow momentum. They're the top performer on the platform. Nobody knows who they are. Their activity should be tracked as a directional signal. + +### HYPE's Unlock Power Move +Hyperliquid cut their February team token unlock by 90%. This is unprecedented — most protocols ignore the optics of team unlocks during bear markets. HYPE's team is signaling alignment with holders. The token rallied 50% while the market dropped 5%. Game theory at work. + +### Ondo's Paradox +Tokenized equity trading volume is up 2,695% but the ONDO token is down 80%. This is a textbook case of value accrual disconnect — the protocol's products are succeeding but the token's economics (massive unlocks) are destroying price. If you believe in RWA tokenization, ONDO at $0.28 after a $1.94B unlock is either a generational buy or a structural trap. The answer depends entirely on whether token holders are done selling. + +### 88% of Airdrops Lose Value in 3 Months +This stat from airdrop researchers should anchor expectations. The airdrop meta has shifted from "free money" to "points-based farming that requires consistent effort for uncertain payoff." The edge now goes to deep farmers who build genuine on-chain footprints, not Sybil attackers. + +### The Contrarian View (Grok: The Mirror — Live X) +The Mirror challenges our consensus with evidence from X: +1. **RWA hype may be overblown:** Yields are sub-5% post-fees vs direct T-bills. BlackRock/Franklin versions are just wrapped TradFi coupons, not revolutionary. KYC walls throttle adoption. ONDO may underperform despite narrative strength. *Our response:* Valid concern — we sized ONDO at only 3% with tight stop at $0.18 for this exact reason. +2. **AI crypto is vaporware:** Centralized giants (OpenAI, Google) hoarding compute. On-chain AI too slow for real models. Token incentives reward spam over utility. *Our response:* Agree — no AI token recommendations in our portfolio. +3. **Memecoins are a pure casino:** 99% rug to zero by March. Insider vs retail with zero staying power in risk-off. *Our response:* Agree — we've said reduce memecoin exposure to <5%. +4. **BTC $150K calls are premature:** Persistent inflation/yield spikes crush "digital gold." Alts bleed harder in rotation fails. *Our response:* Partially agree — that's why our BTC short is on the table at $73-75K. +5. **Biggest surprise risk:** Unexpected Binance delisting wave for privacy/RWA tokens on "terror finance" probe could tank narratives 50% overnight. *Our response:* Adding to watchlist. Low probability but catastrophic if it happens. +6. **Widely hated with improving fundamentals:** HEX/PLS/PLSX — 20%+ staking APRs compounding, on-chain TVL steady despite founder legal FUD. If SEC case resolves, shorts squeezed. *Our response:* Too speculative and dependent on a single legal outcome. Pass for now, but noting. + +### XRP Spot Flows Spike +2,860% +Per live X data, XRP spot flows surged dramatically today. Rising risk appetite signal in a token that's been relatively quiet. Worth monitoring whether this represents institutional positioning or retail FOMO. + +--- + +## Section 10: Summary with Recommendations + +### The Big Picture +We are in a late-stage capitulation environment. BTC fell 52% from its October 2025 ATH to the Feb 5 low of $60K. Fear & Greed is at single digits. Weekly RSI is at levels that have historically preceded major bottoms within 3-6 months. Record realized losses suggest real capitulation has occurred. + +**BUT** — the ETF outflow trend hasn't reversed, the Fed is hawkish, and 44% of BTC supply is underwater creating persistent sell pressure. This is NOT a "buy everything and close your eyes" moment. It's a "selectively accumulate high-conviction assets with clear invalidation levels" moment. + +### What Changed Today (Key New Intelligence from Grok) +1. **ETF inflows flipped positive** (+$330M on Feb 7) — this is THE signal to watch. If it sustains, the regime changes. +2. **Funding rates negative** — shorts paying longs for the first time post-crash. Deleveraging complete. +3. **Hyperliquid whales unanimously short** — creates squeeze potential if ETF inflows continue. +4. **$3B+ stablecoin mints** — fresh dry powder entering system. Money isn't leaving crypto, it's repositioning. +5. **"Trump insider whale" dumped $500M BTC** — political dimension to the sell-off. +6. **Massive Solana phishing wave** — fake airdrop scam sites proliferating. Security risk elevated. +7. **VCs loaded $252M in week 1 of Feb** into custody/compliance/infra — smart money betting on infrastructure while retail panics. +8. **Perp DEX volumes near all-time high** — leverage demand is alive. Hyperliquid captured >30% market share. + +### Dominant Themes +1. **Capitulation is underway** — but bottom formation takes time, not a single event +2. **DeFi resilience** — TVL holding up, real yield protocols outperforming +3. **Infrastructure > Speculation** — the next cycle narrative is forming around stablecoin rails, RWA tokenization, and institutional DeFi +4. **Unlock season** — $732M in February unlocks creating persistent sell pressure across multiple tokens + +### Condensed Recommendations + +**BUY (Total allocation: ~35%)** +| Token | Price | Allocation | EV | Timeframe | +|-------|-------|-----------|-----|-----------| +| ETH | $2,080 | 15% | +23.75% | 1-3 months | +| HYPE | $32.98 | 8% | +22.5% | 1-3 months | +| AAVE | ~$150 | 6% | +24.5% | 1-3 months | +| ONDO | $0.28 | 3% | +80.0% | 3-6 months | +| SOL | $87 | 3% | +34.5% | 3-6 months | + +**SELL** +| Token | Action | Reason | +|-------|--------|--------| +| BERA | Sell all | EV: -19.5%, massive unlock | +| MOVE | Reduce | Feb 9 unlock | +| Memecoins | Reduce to <5% | Bear market, dominance rising | + +**SHORT** (CAUTION: ETF inflows flipping + negative funding makes this riskier than earlier today) +| Token | Entry | Stop | EV | +|-------|-------|------|-----| +| BTC | $73K-$75K | $78K | +9.15% | + +NOTE: Hyperliquid whales are max short. If ETF inflows sustain, they get squeezed and BTC rips through $75K. Reduce short conviction from 3% to 2% given new flow data. + +**FARM (Time Only)** +- Lighter (perps DEX points program) +- Monad testnet +- OpenSea SEA claim (Q1 2026) +- MetaMask/Linea points + +**YIELD** +- Idle stablecoins → Aave V3 (4-7%) +- ETH holdings → Lido stETH (4-8%) +- SOL holdings → Jito (7%+) + +**WATCH** +- BTC ETF daily flows (the reversal signal) +- HYPE March 6 unlock ($309M — will they reduce this too?) +- ONDO price action at $0.20 support +- Trend Research Aave health factor +- White Whale Hyperliquid positioning + +### Overall Positioning Stance +**DEFENSIVE WITH SELECTIVE ACCUMULATION.** Keep 60-65% in stablecoins earning yield on Aave. Deploy 30-35% into conviction positions (ETH, HYPE, AAVE, ONDO, SOL) with clear invalidation levels. Keep 3-5% dry for opportunistic trench plays. Do NOT use leverage in this environment. The goal is to survive the capitulation and be positioned for the recovery with fundamentally strong assets. + +The bottom is forming. It's not here yet. Accumulate the right assets at the right pace. + +--- + +*Report compiled: February 8, 2026 | Session #1 v2 (Full Social Intelligence) | Next session: February 9, 2026* +*Intelligence sources: Grok API (grok-4-1-fast with live X search — 6 sub-agents, 76KB raw social data), Web search, DeFiLlama, CoinGecko, CoinGlass, CoinDesk, CNBC, The Block, CryptoTicker, Hypurrscan* +*Grok API: ACTIVE — xAI Responses API with x_search tool, grok-4-1-fast model* +*X Search calls: 36 total across 6 sub-agents (keyword + semantic search)* diff --git a/crypto_intel_2026-02-09.md b/crypto_intel_2026-02-09.md new file mode 100644 index 0000000..bfa0181 --- /dev/null +++ b/crypto_intel_2026-02-09.md @@ -0,0 +1,435 @@ +# Crypto Intelligence Briefing — February 9, 2026 + +**Session #2 | With Live X/Twitter Intelligence via Grok (5 sub-agents, 40+ X searches) | Market Regime: EXTREME FEAR / EARLY BOTTOM FORMATION** + +--- + +## Section 1: Memory Review & Previous Session Follow-Up + +**Session #1 (Feb 8) Recommendations — Price Updates:** + +| Token | Entry (Feb 8) | Current | Change | Status | +|-------|--------------|---------|--------|--------| +| ETH | $2,080 | $2,062 | -0.9% | HOLD — within range | +| HYPE | $32.98 | $32.44 | -1.6% | HOLD — outperforming market | +| AAVE | ~$150 | $112.31 | -25.1% | WARNING — approaching $100 invalidation | +| ONDO | $0.28 | $0.25 | -10.7% | HOLD — halfway to $0.18 invalidation | +| SOL | $87.06 | $85.36 | -1.9% | HOLD — within range | +| BERA (SELL) | — | — | — | Correct call — continued bleeding post-unlock | +| BTC short ($73-75K) | Not triggered | $70,391 | — | Never reached entry — BTC stayed below $73K | + +**Running Stats:** 5 buy recs, 0 triggered trades (monitoring only), 0 wins, 0 losses. AAVE is the most concerning position — down 25% in 24 hours. + +**Critical Update — Trend Research Aave Position:** +Session 1 flagged Trend Research's $1.8B leveraged ETH position on Aave as a risk. **They have now CLOSED their entire position** — liquidated 651,757 ETH for $1.74B, realizing approximately **$750M in losses**. They potentially sold near the bottom. This is a massive deleveraging event that removes one of our key systemic risk factors. + +**Smart Wallet Scan Completed (Feb 9):** +RPC wallet scan of all 7 Solana alpha wallets completed. Key findings below in Section 6. + +--- + +## Section 2: Market Structure Snapshot + +### Prices (Feb 9, 2026) +| Asset | Price | 24h Change | From ATH | From Feb 8 | +|-------|-------|-----------|----------|------------| +| BTC | $70,391 | +1.17% | -44.2% | +1.2% | +| ETH | $2,062 | -0.82% | -58.8% | -0.9% | +| SOL | $85.36 | -2.17% | -71.0% | -1.9% | +| HYPE | $32.44 | +4.71% | — | -1.6% | +| AAVE | $112.31 | -0.10% | — | -25.1% | +| ONDO | $0.25 | -4.31% | — | -10.7% | + +### Market Structure +- **Total Market Cap:** $2.46T (down from $2.49T yesterday) +- **24h Volume:** $105.4B +- **BTC Dominance:** 57.2% (down from 58.7% — slight easing) +- **ETH Dominance:** 10.1% (still near cycle lows) +- **Fear & Greed Index:** 14 (EXTREME FEAR) — up from 7-11 yesterday. Still sub-15. +- **Active Cryptocurrencies:** 18,947 + +### Flow Data (Updated with Live X Intelligence) + +- **BTC ETF Flows:** CONFLICTING SIGNALS. + - **Grok (X data):** Feb 8 saw +$371M net (IBIT led with $232M). Total ETF assets: $89.43B. ETFs hold 7.36% of BTC supply. + - **Web research:** Weekly net was -$358.5M with massive daily swings. Feb 1: -$509.7M. Feb 3: +$561.9M. Feb 4: -$272M. + - **Assessment:** Daily flows are whipsawing. The +$330M on Feb 7 and +$371M on Feb 8 suggest institutional buying on dips, but the weekly aggregate is still net negative. **Watch for 3+ consecutive days of inflows to confirm regime change.** + +- **Funding Rates:** BTC funding data sparse. SOL at -0.0233% (slightly negative = bearish lean). Negative funding = shorts paying longs = historically bullish. + +- **Liquidations:** $770M crypto-wide in last 24h. BTC heatmap shows $72K shorts swept. Market now in choppy consolidation after the flush. + +- **Stablecoin Supply:** BULLISH — $2B+ USDT minted on TRON (leading chain). $300M USDC unknown-to-unknown transfer. Fresh dry powder continues entering. + +- **Whale Activity (Critical — from Grok X search):** + +| Move | Amount | Signal | +|------|--------|--------| +| BTC accumulator addresses | +66,940 BTC (Feb 6) | **CYCLE HIGH inflow** — mega bullish | +| Serial Binance dip-buyer (profitable since 2015) | +9,000 BTC ($716M) | Smart money loading | +| ETH whale 0x28eF... | Withdrew 50,415 ETH ($104.5M) from exchange | Accumulation | +| ETH whales | 60K ETH ($126M) withdrawn from Binance over 40h | Accumulation | +| 734 BTC ($52M) | Coinbase Institutional → Unknown | Withdrawal (bullish) | +| 1,398 BTC ($98.8M) | Unknown → Coinbase Institutional | Deposit (bearish) | +| Hyperliquid whale | 15x long ETH, $4.13M at $2,087 | Leveraged bull bet | +| Trend Research | Closed $1.8B Aave position, -$750M loss | Deleveraging complete | + +**THE KEY WHALE SIGNAL:** 66,940 BTC accumulator inflow on Feb 6 is a CYCLE HIGH. A serial dip-buyer who has been profitable since 2015 loaded $716M worth. This is the strongest on-chain accumulation signal since the $60K dip. + +### Hyperliquid Metrics (Live X Intelligence) +- **HYPE:** $32.44 (+4.71% 24h, outperforming) +- **Platform TVL:** $1.56B (DeFiLlama) +- **Hyperlend TVL:** $329.98M (54% utilization, $178.87M borrowed) +- **Open Interest:** $4.8B +- **Volume:** +99% week-over-week +- **HYPE Assistance Fund:** Bought ~39K HYPE (~$1.2M) in last 24h +- **Top Trader:** +$29M PnL (87.5% win rate), 5x long HYPE ($46M position) +- **Notable:** Aster DEX doing $24.7B daily volume — surpassing Hyperliquid. Competition heating up. +- **Perp DEX volumes:** $70B total across all platforms — 2nd highest EVER. + +### Direction Assessment (Web + Grok Convergence) + +The market is in **late-stage capitulation transitioning to early bottom formation**: + +- **BULLISH signals:** 66.9K BTC accumulator inflow (cycle high), ETF inflows on specific days (+$371M Feb 8), $2B+ stablecoin mints, negative funding, Fear & Greed at 14 (doubled from 7), perp DEX volumes near ATH, whales aggressively accumulating ETH +- **BEARISH signals:** Weekly ETF aggregate still net negative, BTC dominance high (57.2%), AAVE -25% in 24h, Trend Research forced to close $750M losing position, 80% of X sentiment expects more downside +- **Short-term (1-3 days):** Choppy consolidation $68-73K. The $72K short liquidation sweep suggests resistance there. +- **Medium-term (1-2 weeks):** Cautiously bullish IF ETF inflows continue. The whale accumulation data is the strongest bull signal. +- **The key tell:** Smart money (whales, serial dip-buyers) is loading at levels where retail is selling. This divergence historically precedes bottoms. But weekly ETF flows haven't confirmed yet. + +--- + +## Section 3: Ecosystem & DeFi Intelligence + +### TVL Overview +- **Total DeFi TVL:** ~$98.8B (DeFiLlama) — down from ~$105B last week +- **ETH in DeFi:** 25.3M ETH (still growing in ETH terms despite price decline) +- **Liquidatable positions:** Only $53M within 20% of current price (well-collateralized) + +### Chain Rankings by TVL +1. **Ethereum:** $56.90B (dominant) +2. **Solana:** $6.48B (down from $8.8B) +3. **BSC:** $5.52B +4. **Bitcoin:** $5.30B +5. **Tron:** $4.12B +6. **Base:** $4.05B +7. **Plasma:** $2.93B (new entrant) +8. **Arbitrum:** $2.19B +9. **Hyperliquid L1:** $1.56B +10. **Polygon:** $1.14B + +### Protocol Highlights +- **Aave V3:** USDC lending at $1.24B+, supply APY 4-7%. Aave DAO shut down underperforming deployments (zkSync, Metis, Soneium). Consolidating under Aave Labs. Wound down Avara and Family wallet. +- **Lido:** Launched V3 with customizable stVaults — major upgrade allowing tailored staking strategies. +- **Uniswap:** Bitwise filed Uniswap ETF S-1. If approved, first DeFi protocol ETF. +- **Perp DEX volumes:** $70B total (2nd highest EVER). Aster doing $24.7B daily — surpassing Hyperliquid. N1 mainnet launched. dYdX pushed affiliate commissions to 50%. +- **MegaETH:** Mainnet launch/TGE with ecosystem apps: PrismFi (DeFi hub), Euphoria (one-tap trading), Valhalla (perps DEX), Cap Money (stablecoin airdrop — 12M cUSD). + +### Live X DeFi Intelligence (Grok Sub-Agent: The Cartographer) +- **Quiet Finance:** New stablecoin yield protocol advertising 9-24% APY (automated low-risk strategies). Points for potential airdrop. Watch but verify. +- **Base:** PredictBase Super Bowl market hit $75K volume. Aerodrome LP farming with high APY. AI agents building on Base ecosystem. +- **Hyperlend:** $330M TVL, 54% utilization, $5.83M annualized fees. The lending arm of Hyperliquid ecosystem is growing fast. +- **Token unlocks this week:** $64M (largest: $15.71M CONX on Feb 13). $246M by end of February. + +### Key Trend: Perp DEX Arms Race +Perp DEX volumes hit $70B (2nd highest ever) with a new challenger — Aster — doing $24.7B daily, surpassing Hyperliquid on some days. The leverage economy is alive and growing despite the crash. This validates HYPE's thesis but introduces competition risk. + +--- + +## Section 4: Solana Trenches Report + +### Network State +- **SOL Price:** $85.36 (down 71% from $294 ATH) +- **DeFi TVL:** $6.48B (down from $8.8B — following price) +- **24h Change:** -2.17% + +### Trending on X Today (Feb 9) +- **$RENDER, $BONK, $WIF** (>$200M MC): Whale accumulation, net inflows over 3 months +- **$SOULGUY:** Recovered from $15K lows post-rug via community takeover (CTO), eyeing $200M ATH +- **$BBB:** Big whale buys, "smart money loading" — CA: `DHFdTfTr2dwdVxo9cjiKE7Xjnm7W4BX7cByy8v1mpump` +- **$NOCOIN:** DCA play amid rug environment + +### New Launches with Traction +- **$OPAL:** Fresh pump.fun launch, whale shilling — CA: `2PzS5SYYWjUFvzXNFaMmRkpjkxGX6R5v8DnKYtdcpump` +- **$OrcaAI:** AI-marine narrative (whale strike prevention tech) — CA: `6A1EANii6U3PH64KDsfcLYFMB8AQd1ww8DGEgaa5pump` +- **$WOLF (Alfa):** LP locked, organic growth claims +- **$GPU:** Upcoming 5% airdrop but scam warnings issued + +### Scam/Rug Alerts +- **$PEPERC:** Elaborate rug at ~$7K MC with fake GitHub "Perforkator" risk engine — CA: `9aMRGjjC8Ji83dSwbVVR72RFuFAfbpF9tAie3aghpump` +- **BOBO cabal:** Farming/rugging $WOJAK on Solana; multiple prior rugs +- **Pump.fun:** $5.5B RICO lawsuit brewing over on-chain liability for rugs/scams. 98% of memecoins flagged as fraud/rugs. Potential platform-defining legal precedent. +- **$LIBRA** (Milei promo rug): 114K wallets rekt — political token rug +- **MetaYield DeFi rug:** $752 ETH stolen + +### Jupiter Updates +- **SushiSwap launching on Solana via Jupiter Ultra** — native swaps + cross-chain routing +- **Jupiter Global physical card** integration via Jup Mobile app +- Jupiter continues to dominate as the routing layer for all Solana DeFi + +### Firedancer Update +Ongoing delays and criticism. Promised 1M+ TPS since 2022, now runnable but network sustaining ~1.8K TPS. Few nodes migrating. Progress but slower than expected. + +### Our Smart Wallet Scan (RPC, Feb 9) +From our 7 Solana alpha wallets: +- **hellkatai #2 (AI Meme):** 813 SOL whale — buying $CHUD, $Computa, $APEX, $SARANG +- **hellkatai #3 (Non-Sniper):** 0.9 SOL, $327K portfolio — 10x $Buttcoin buys, new $LABUBU buy +- **hellkatai #4 (BUTTCOIN Winner):** Active sniper, flips 5-10 tokens/day +- **hellkatai #6 (TOP):** 284 SOL, 1,222 tokens — spray-and-pray style, holds $PENGUIN, $BC, $Pnut +- **PISS Trader:** 94 SOL, 343 tokens (mostly dead rugpulls) +- **Convergence: $Buttcoin** ($28.3M MC) held by 3/7 wallets — strongest multi-wallet signal +- **Convergence: $JESTER** ($90K MC) held by 3/7 wallets — micro-cap convergence + +### Assessment +Solana trenches are brutal in this environment. Pump.fun facing a $5.5B lawsuit. 98% rug rate. The only interesting plays are the convergence tokens from smart wallet analysis (Buttcoin) and the shift toward Jupiter Ultra as the dominant DeFi primitive. Avoid new launches unless on-chain DD confirms legitimate tokenomics. + +--- + +## Section 5: Alpha Signals + +### Signal 1: AAVE — Down 25% But Not Dead (UPDATED) +AAVE crashed from ~$150 to $112 in 24 hours. This is a violent correction but the fundamentals haven't changed: $56.9B Ethereum DeFi TVL, Aave V3 at $1.24B+ USDC lending, 4-7% real yield. The DAO is actively consolidating (shutting down underperforming chains, winding down Avara). Bitwise filed a Uniswap ETF — if DeFi ETFs gain traction, AAVE benefits. **Invalidation at $100 is 11% away.** This is either a screaming buy or about to break. + +### Signal 2: BTC Whale Accumulation — Cycle High +66,940 BTC flowed into accumulator addresses on Feb 6 — the highest single-day accumulation this cycle. A serial dip-buyer who has been profitable since 2015 loaded 9,000 BTC ($716M). When smart money buys this aggressively at Fear & Greed 14, it historically signals a local bottom within 1-2 weeks. + +### Signal 3: MegaETH Ecosystem Launch +MegaETH launched mainnet + TGE with a full ecosystem: PrismFi (DeFi hub), Euphoria (one-tap trading), Valhalla (perps DEX), Cap Money (12M cUSD stablecoin airdrop). New L1/L2 launches during bear markets can produce outsized returns if the ecosystem gains traction. Watch TVL growth. + +### Signal 4: VC Money Still Flowing (Grok: The Rat) +New VC rounds from Feb 3-9: +- **Miden:** $25M (a16z Crypto, 1kx, Hack VC) — ZK rollup with testnet live, airdrop farming possible +- **ORO:** $6M seed (a16z CSX, Delphi Ventures, NEAR Foundation) — privacy data for AI, TEEs + ZK +- **Opinionlabs:** $20M (Hack VC, Jump Crypto) — prediction markets +- **Pattern:** VCs continue funding ZK/privacy/prediction infra during the crash. This is the 2nd week of $200M+ VC deployment during extreme fear. + +### Signal 5: Jupiter Ultra + SushiSwap = Solana DeFi Consolidation +SushiSwap launching on Solana via Jupiter Ultra is a validation play. Jupiter is becoming the Uniswap of Solana — the default routing layer. JUP token holders benefit from this growing moat. + +### Signal 6: Stealth Alpha from X (Grok: The Rat — Low Engagement) +- **$KIMBER (Kimberlite):** Tokenized rough diamonds RWA, real backing. 0 likes, Feb 8. Early. +- **$SCRT (Secret Network):** Privacy infra, confidential computation. Multiple 0-2 like posts. Privacy narrative building. +- **$BIGTROUT:** Early stage, rising interest from our tracked wallets. 12 likes, Feb 8. +- **Miden testnet:** Confirmed content rewards (0.2% supply for top creators + OG NFTs). 0-219 like range. + +### Signal 7: Perp DEX Arms Race — New Players +Aster doing $24.7B daily (surpassing Hyperliquid). N1 mainnet launched. dYdX pushed affiliate commissions to 50%. The perp DEX sector is growing despite the crash, validating the thesis, but competition means HYPE's moat may be narrower than assumed. + +--- + +## Section 6: Smart Wallet Activity + +### Wallet Scan Results (RPC, Feb 9) + +| Wallet | SOL Balance | Tokens | Top Holdings | +|--------|-------------|--------|--------------| +| PISS Top Trader | 94 SOL | 343 | $USD1 ($158M MC), $TDCCP ($71M MC) | +| hellkatai #1 | 0.1 SOL | 53 | $SPYx ($17M MC), $DHC ($4.2M MC) | +| hellkatai #2 (AI Meme) | 813 SOL | 35 | $NVDAx ($20M MC), $APEX ($273K MC) | +| hellkatai #3 (Non-Sniper) | 0.9 SOL | 40 | $Buttcoin ($28.6M MC), $WOJAK ($13.5M MC) | +| hellkatai #4 (BUTTCOIN) | 9.7 SOL | 42 | $USD1 ($158M MC), $Buttcoin ($28.5M MC) | +| hellkatai #5 (Sniper) | 12.8 SOL | 207 | $BC ($63.6M MC), $TSLAx ($53.8M MC) | +| hellkatai #6 (TOP) | 284 SOL | 1,222 | $PENGUIN ($79M MC), $BC ($63.6M MC) | + +### Token Convergence (Held by 3+ Wallets) +- **$Buttcoin** (MC: $28.6M) — 3/7 wallets (#3, #4, #5) +- **$JESTER** — 3/7 wallets (#1, #3, #6) +- **$CARABAO** — 3/7 wallets +- 5 additional tokens held by 2/7 wallets + +### New Whale Intelligence (from Grok X Search) +- **ETH Whale 0x28eF...:** Withdrew 50,415 ETH ($104.5M) from exchange, redistributed to 0x3E13... (now holds 50,155 ETH) +- **BTC Accumulators:** 66,940 BTC inflow on Feb 6 — cycle high +- **Hyperliquid whale:** 15x long ETH at $2,087, $4.13M position — high-conviction leveraged bull +- **Trend Research:** CLOSED entire Aave position. 651,757 ETH liquidated for $1.74B. ~$750M realized loss. Potential bottom signal (forced seller exhausted). + +### Action Items +- Track Hyperliquid 15x ETH long whale — liquidation level matters +- Monitor if Trend Research re-enters (would be very bullish) +- Watch Buttcoin convergence — if additional wallets start buying, signal strengthens + +--- + +## Section 7: Risk Radar + +### CRITICAL RISKS + +**1. ETF Flow Volatility (SEVERITY: HIGH)** +Daily flows are whipsawing: -$509M, +$562M, -$272M, +$371M. No consistent direction. U.S. spot BTC ETFs are net sellers in 2026 per CryptoQuant. If the daily positive flows don't sustain, there is no institutional bid floor. + +**2. AAVE Approaching Invalidation (SEVERITY: HIGH — PERSONAL)** +AAVE fell 25% in 24h from ~$150 to $112. Our invalidation level is $100, which is 11% away. If AAVE breaks $100, exit immediately. The consolidation (shutting down chains, winding down Avara) could be interpreted as retreat rather than focus. + +**3. Token Unlocks — $64M This Week, $246M by Month End (SEVERITY: MEDIUM-HIGH)** +- $15.71M CONX on Feb 13 (largest this week) +- $246M total by end of February +- In bear markets, unlock selling is amplified. Avoid holding tokens with imminent unlocks. + +**4. Pump.fun $5.5B RICO Lawsuit (SEVERITY: MEDIUM-HIGH — Solana ecosystem)** +If the lawsuit gains traction, it could redefine on-chain liability for token launch platforms. This could kill the memecoin meta on Solana or force platforms to implement KYC. Watch legal proceedings. + +**5. China Bans Yuan-Pegged Stablecoins (SEVERITY: MEDIUM)** +8 Chinese regulators banned yuan-pegged stablecoins and RWA tokenization. This could fragment the RWA narrative and reduce Asian capital flowing into DeFi. Negative for ONDO. + +**6. Aster Competition for Hyperliquid (SEVERITY: MEDIUM)** +Aster DEX doing $24.7B daily volume — surpassing Hyperliquid on some days. If HYPE's market share erodes, the revenue-based valuation thesis weakens. Monitor weekly market share data. + +**7. South Korea Targeting Whale Manipulation (SEVERITY: LOW-MEDIUM)** +Post-Bithumb's 620K BTC glitch (which crashed BTC to $55K), regulators are targeting whale pumping and fake support. Could increase exchange scrutiny. + +### NEW RISKS FROM LIVE X (Grok: The Paranoid) +**8. Regulatory Acceleration** +- Aptos futures launched (prereq for spot ETF under SEC generic standards) +- SEC "Project Crypto" — SuperApp for simplified licensing +- CFTC expanding stablecoin rules to national trust banks for BTC derivatives collateral +- **Assessment:** Regulatory environment is actually becoming MORE favorable, not less. This is a positive risk update. + +### AVOID +- New Solana memecoins from pump.fun (98% rug rate per X) +- $PEPERC and BOBO cabal tokens (confirmed rugs) +- Any "airdrop claim" links — phishing wave continues +- $GPU (scam warnings despite airdrop tease) +- Tokens with >10% supply unlocking this month + +--- + +## Section 8: The Contrarian View (Grok: The Mirror) + +### Consensus View +The overwhelming sentiment on X is **deeply bearish**. 80% expect further downside. Fear & Greed at multi-year lows. Retail is capitulating. The prevailing narrative is "this is only 50% off ATH, normal bears go 85-90% — there's much more to fall." + +### Evidence the Consensus is Wrong +1. **Whale accumulation at cycle highs** — 66,940 BTC accumulated on Feb 6 alone. Serial dip-buyer (profitable since 2015) loaded $716M. Smart money is buying exactly where retail is selling. +2. **ETH whale withdrawals** — 60K ETH ($126M) pulled from Binance in 40 hours. 50,415 ETH ($104.5M) withdrawn by a single wallet. Whales are de-custodying, not selling. +3. **Perp DEX volumes near ATH** — $70B across platforms. If crypto was dying, leverage demand would collapse. It's growing. +4. **DeFi TVL resilient** — Only 12% drawdown despite 30-50% price crash. More ETH being deployed into DeFi, not less. +5. **VC deploying $200M+/week** into infra during panic — sophisticated money betting on the build phase + +### Most Hated Tokens with Improving Fundamentals +- **$USELESS:** Prolonged accumulation pattern, historically strong in recovery pumps +- **$Beam:** 2.8M MC (ATH 8.7M), growing holders, nuclear energy tokenization utility incoming +- **$CC, $KITE:** Near ATH despite crash — utility in AI/DeFi/on-chain finance + +### Most Loved Token That Might Be Overvalued +- **$HYPE:** Despite strong fundamentals, it "punished holders despite no emissions." Consolidating $28-38. The Aster competition threat is real. If HYPE loses perp DEX market share, the revenue thesis weakens. Not a sell, but warrants reduced conviction. + +### Surprise Risks +- **South Korea Bithumb glitch aftermath** — regulators targeting whale pumping could spread to other exchanges +- **"Black Swan time bomb"** — X accounts flagging unnamed systemic risk (unspecified) +- **Trend Research forced closure** — The $750M loss from closing their $1.8B Aave position shows even smart money can blow up in this environment + +--- + +## Section 9: Today's Recommendations + +### UPDATED BUYS + +#### Conviction Buys (1-3 Month Horizon) + +**1. ETH at $2,062 ($249B mcap) — HOLD/ADD** +**Update from Session 1:** ETH down 0.9% from entry. Thesis intact. New bullish data: 60K ETH withdrawn from Binance by whales (accumulation), Trend Research's $750M loss removes a liquidation cascade risk. Lido V3 launched. Bitwise filed Uniswap ETF. +**Target:** $3,200 (+55%) +**Invalidation:** Below $1,800 +**Allocation:** 15% +**EV: +23.75%** (unchanged) + +**2. HYPE at $32.44 ($7.7B mcap) — HOLD (reduced conviction)** +**Update:** HYPE outperforming (+4.71% 24h) but Aster competition is a new risk. Assistance fund bought 39K HYPE ($1.2M). Top trader has +$29M PnL with 5x long HYPE ($46M). Perp DEX volumes near ATH validates sector but competition dilutes moat. +**Target:** $45 (lowered from $48) +**Invalidation:** $24 +**Allocation:** 6% (reduced from 8%) +**EV: +18%** (reduced due to competition risk) + +**3. AAVE at $112 ($1.7B mcap) — HOLD WITH TIGHT STOP** +**Update:** Down 25% from session 1 entry. DAO shutting down underperforming deployments (zkSync, Metis). Consolidation could be bullish (focus) or bearish (retreat). $100 invalidation is 11% away. V3 USDC lending at $1.24B+. Real yield 4-7%. +**Target:** $200 (+78%) +**Invalidation:** $100 (HARD STOP — exit immediately) +**Allocation:** 4% (reduced from 6%) +**EV: +15%** (reduced due to momentum) + +**4. ONDO at $0.25 ($1.2B mcap) — HOLD, WATCHING CLOSELY** +**Update:** Down 10.7% from entry. China RWA ban is a headwind. $0.18 invalidation is 28% away. RWA adoption still growing but geopolitical fragmentation risk. +**Target:** $0.80 (+220%) +**Invalidation:** $0.18 +**Allocation:** 2% (reduced from 3%) +**EV: +60%** (reduced due to China risk) + +**5. SOL at $85 ($48.5B mcap) — HOLD** +**Update:** Down 1.9%, within noise. Jupiter Ultra + SushiSwap validation. Firedancer delays are concerning but Alpenglow still on track. DeFi TVL down to $6.48B (price-driven, not capital flight). +**Target:** $180 (+112%) +**Invalidation:** $60 +**Allocation:** 3% +**EV: +30%** (unchanged) + +#### NEW Signal: MegaETH Ecosystem (Research Phase) +MegaETH launched mainnet + TGE with Cap Money airdropping 12M cUSD. PrismFi, Euphoria, Valhalla building on top. Too early to size but worth monitoring TVL trajectory over next 7 days. + +### Narrative Buys (Unchanged from Session 1) +- **Lighter Exchange airdrop farming** — time only, $0 capital +- **Monad testnet farming** — time only +- **Miden testnet farming** — NEW, $25M from a16z, content rewards confirmed + +### SELLS + +**1. SELL: AAVE if $100 breaks** — hard invalidation, no hesitation +**2. SELL: ONDO if $0.18 breaks** — structural breakdown +**3. REDUCE: Memecoin exposure** — Pump.fun lawsuit + 98% rug rate. Keep <3% of portfolio. + +### Yield Plays (Unchanged) +- Idle stablecoins → Aave V3 USDC (4-7% APY) +- ETH → Lido stETH V3 (customizable vaults now) +- SOL → Jito (7%+ with MEV) + +### WATCH LIST +- BTC ETF daily flows (need 3+ consecutive inflow days) +- AAVE at $100 invalidation level +- Aster vs Hyperliquid market share +- Trend Research — do they re-enter? (would be mega bullish) +- Buttcoin convergence from wallet scan (3/7 wallets) +- MegaETH TVL trajectory +- Pump.fun RICO lawsuit developments + +--- + +## Section 10: Summary + +### What Changed Since Session 1 (Key Intelligence) + +1. **MASSIVE whale accumulation** — 66,940 BTC (cycle high), $716M serial dip-buyer, 60K ETH Binance withdrawals. Smart money loading aggressively. +2. **Trend Research CLOSED** their $1.8B Aave position at $750M loss. Major deleveraging event. Removes our #1 systemic cascade risk. +3. **AAVE crashed 25%** — approaching $100 invalidation. Most vulnerable position. +4. **Perp DEX volumes $70B** (2nd highest ever) — sector validated but Aster threatening HYPE's moat. +5. **Fear & Greed 14** (up from 7) — extreme fear persisting but improving at the margin. +6. **China banned yuan-pegged stablecoins** — headwind for RWA narrative (ONDO). +7. **Pump.fun facing $5.5B RICO lawsuit** — could redefine Solana memecoin meta. +8. **VCs deployed $200M+ more** into ZK/privacy/prediction infra. Smart money building. +9. **Lido V3 launched**, SushiSwap → Solana via Jupiter Ultra, Uniswap ETF filed. +10. **Wallet scan completed** — $Buttcoin convergence confirmed (3/7 wallets), $JESTER micro-cap convergence. + +### Overall Positioning Stance + +**DEFENSIVE WITH SELECTIVE ACCUMULATION — UNCHANGED.** + +The whale accumulation data is the strongest bull signal this cycle, but weekly ETF flows haven't confirmed the bottom. Keep 60-65% in stablecoins on Aave. Maintain positions but tighten stops: + +**Updated Allocation:** +| Token | Allocation | Change | +|-------|-----------|--------| +| ETH | 15% | — | +| HYPE | 6% | -2% (competition risk) | +| AAVE | 4% | -2% (momentum + stop proximity) | +| SOL | 3% | — | +| ONDO | 2% | -1% (China RWA ban) | +| Stablecoins (yielding) | 65% | +5% | +| Dry powder | 5% | — | + +**Total risk exposure: 30% (down from 35%).** + +The bottom is forming. Whales are buying. Retail is selling. But we don't need to be heroes — let the ETF flows confirm direction before adding. If AAVE hits $100, exit. If BTC ETFs show 3+ consecutive inflow days, add to ETH and SOL. + +--- + +*Report compiled: February 9, 2026 | Session #2 | Next session: February 10, 2026* +*Intelligence sources: Grok API (grok-4-1-fast with X search — 5 sub-agents, 40+ X searches), CoinGecko, DeFiLlama, DexScreener, Alternative.me F&G, Web search* +*Wallet scan: 7 Solana wallets via Helius RPC (mainnet.helius-rpc.com)* +*Previous recommendations tracked: 5 buys, 1 sell, 0 triggered trades* diff --git a/crypto_intel_2026-02-10.md b/crypto_intel_2026-02-10.md new file mode 100644 index 0000000..5105cdd --- /dev/null +++ b/crypto_intel_2026-02-10.md @@ -0,0 +1,251 @@ +# Crypto Intelligence Briefing — February 10, 2026 + +**Session #3 | 5 Grok X searches + Live Market Data + JESTER Deep Dive (428 RPC calls) | Market Regime: EXTREME FEAR (9/100) / POST-LIQUIDATION ACCUMULATION** + +--- + +## Section 1: Memory Review & Previous Session Follow-Up + +**Session #2 (Feb 9) Recommendations — Price Updates:** + +| Token | Entry (Feb 8) | Yesterday | Current | Total Change | Status | +|-------|--------------|-----------|---------|-------------|--------| +| ETH | $2,080 | $2,062 | $2,020 | -2.9% | HOLD — approaching $1,800 invalidation zone | +| HYPE | $32.98 | $32.44 | $30.15 | -8.6% | WARNING — down 8.6%, watching $25 support | +| AAVE | ~$150 | $112 | $109 | -27.3% | DANGER — approaching $100 invalidation | +| ONDO | $0.28 | $0.25 | $0.247 | -11.8% | HOLD — near $0.18 invalidation | +| SOL | $87.06 | $85.36 | $84.77 | -2.6% | HOLD — within range | +| BTC short ($73-75K) | Not triggered | $70,391 | $69,211 | — | Never triggered — BTC continues lower | + +**Running Stats:** 5 buy recs, 0 triggered trades, 0 wins, 0 losses. AAVE and HYPE are concerning — both trending lower. + +**New Alpha Pipeline — LIVE:** +Yesterday we built and tested 3 new scripts. Results from live testing: +- **Trending Scanner**: Found 57 CAs (first run) + 32 CAs (second run) = 89 unique tokens +- **Alpha Wallet Scanner**: Detected 7 new wallets with 9x-734x PnL +- **Total tracked wallets**: 17 (10 original + 7 auto-discovered) +- Pipeline now automated: twice-daily at 14:00 CET and 02:00 CET + +--- + +## Section 2: Market Structure & Macro + +**BTC: $69,211 (-0.78% 24h) | MC: $1.384T** +- **Extreme Fear** dominates — Fear & Greed Index at **9** (lowest reading this cycle) +- Post-liquidation phase: $704M BTC/ETH liquidated past 24h, $2.2B on Feb 5 (241K BTC hit exchanges) +- Holding critical $68K-$70K support after choppy consolidation +- Worst-case scenario: Analysts eyeing $37K as "generational bottom" (~52% from $126K ATH) +- Mining hashprice at record lows (~$0.03/TH) — miner capitulation risk +- **Bullish signal**: ETF inflows +$131-145M (2nd straight green day despite extreme fear) + +**ETH: $2,020 (-1.13% 24h) | MC: $244B** +- Rejected $2,100 resistance; $2,000 is pivotal support +- Stablecoin tx volume up 200% in 18 months despite -30% price — narrative lag +- **Whale alert**: New $33M ETH long (16,270 ETH, 20x leverage) on Hyperliquid — liq at $1,438 +- Counter: Gambler 0x15a4 shorting 3K ETH ($6M) after $1.3M loss on previous short +- ETH ETF inflows: +$57M + +**SOL: $84.77 (+0.37% 24h) | MC: $48.1B | TVL: $6.52B** +- Slight green while BTC/ETH red — relative strength +- TVL holding at $6.52B (DeFiLlama) +- Step Finance exploit: $40M loss via social engineering (Feb 9) — not smart contract, phishing attack on exec + +--- + +## Section 3: DeFi Intelligence + +**Exploits & Security:** +- **Step Finance (~$40M)**: Treasury wallets compromised via phishing on executive device during APAC hours. Not a smart contract exploit. Operations paused, some funds recovered. +- **CrossCurve/EYWA Bridge (~$1.44M)**: Ongoing from early Feb. Stablecoins + CRV variants stolen. 72-hour whitehat window. + +**TVL Milestones:** +- ston.fi (TON): $650M TVL — major TON DeFi player +- JustLendDAO (TRON): $5.98B TVL +- Perp DEX volumes near all-time highs (2nd highest day on record) +- RWA active TVL 6x since 2025 start (tokenized gold/commodities/stocks) + +**Yield Environment:** +- Yields remain "dust" due to low altcoin valuations +- multiplifi: USDC/USDT 5% APY, BTC 2% APY (CEX funding arb) +- TVL manipulation warning from Morpho CEO — easy inflation loops via stables/lending/aggregators + +--- + +## Section 4: Solana Trenches — Memecoin Alpha + +**DexScreener Top Boosted (Solana):** + +| Token | Boosts | Notes | +|-------|--------|-------| +| NYAN CAT | 1500 | 2014 BitcoinTalk nostalgia play | +| SIREN CALL | 510 | Market intelligence narrative | +| MILK | 500 | "First System of Survival" | +| Chill Penguin | 500 | Animal meta | +| SkynetSociety | 500 | Autonomous AI society | +| TOILET COIN | 200 | Degen pure play | +| Zhdun | 140 | Going viral on X again | +| ROCK | 100 | "just a rock" — our scanner found this! | + +**Pump.fun Fresh Launches with Social Momentum:** +1. **$GUANYU** — Relaunching tomorrow (Feb 11, 15:00 GMT). Heavy promo, whitepaper, airdrop. 100s of likes. +2. **$INU** (DPhV41VfKySPyvcu5omtAs2HtYuRAEt9z8ARCGDgpump) — Dev alloc 2%, no bundles, 50+ likes +3. **$XENO** (Fd1EYQ5UdShwZv4wCsYYV8RLgQmWdovEMGJqspfCpump) — 41 likes, growing community +4. **$DIDGE** (FR2vmXwbi63Bq3WYYZ8dVzbBqWxMrTc7RBnJU18spump) — Early pump at $3.5K MC, fair launch + +**Our Scanner Overlap**: $ROCK (boosted 100 on DexScreener) was independently found by `scan_trending_new.py` yesterday with Score 85 and MC $309K. Alpha scanner found 4 wallets with 9x-28x PnL on it. **Scanner validated.** + +--- + +## Section 5: JESTER Deep Dive — 428 RPC Calls + +**$JESTER** (6WdHhpRY7vL8SQ69bd89tAj3sk8jsjBrCLDUTZSNpump) + +Previously flagged as convergence signal: 3/7 tracked wallets held JESTER. Today we ran a full deep dive on the top 20 holders. + +### Holder Structure — EXTREMELY BULLISH + +| Status | Count | Description | +|--------|-------|-------------| +| ACCUMULATING | 10 | Actively buying more JESTER | +| HOLDING | 9 | Diamond hands, no recent sells | +| TRADING (MM) | 1 | #1 holder — bot/market maker | +| SELLING | 0 | **Zero sellers** | +| EXITED | 0 | **Zero exits** | + +### Key Whales (SOL >= 10) + +| Wallet | SOL | JESTER | Status | Notes | +|--------|-----|--------|--------|-------| +| `H5jMAE...pHdZApgh` | 153.9 | 29M | HOLDING | Passive whale, 2 other tokens | +| `fNrJmJ...qiXuRFrJ` | 97.3 | 13.5M | HOLDING | 1 other token | +| `EwTNPY...87csKgtt` | 90.1 | 23.5M | HOLDING | 2 other tokens | +| `C3nLTN...GEcYd9hP` | 58.0 | 11.8M | HOLDING | 2 other tokens | +| `14KbXM...rbaD9nZe` | 47.7 | 22.5M | HOLDING | 1 other token | +| `AmNQzp...Pt9XAE1u` | 39.5 | 21M | HOLDING | Bonk variant held | +| `E27ZvE...DNLxkzNZ` | 25.0 | 11.4M | HOLDING | 3 other tokens | +| `7TQfNA...TntrmXXk` | 12.3 | 19.6M | ACCUMULATING | Bought 4.4M more on Feb 9 for 6 SOL | + +### Recent Accumulators (last 48h) + +- **Holder #2**: ALL-IN — spent 34.5 SOL buying 36.6M JESTER, zero SOL remaining +- **Holder #16**: 18.9 SOL on Feb 9 — 3 rapid Jupiter swaps +- **Holder #17**: 11.8 SOL including Orca Whirlpool buys +- **Holder #10**: Whale adding 4.4M more (6 SOL) despite already holding 19.6M + +### Notable Findings + +1. **#1 Holder** (`2Aj1MJG...`): 126M JESTER (25% of top-20 supply) — classified as TRADING. Small buys/sells via Jupiter v6. Likely a market maker or bot. +2. **#18 Holder** (`7cbguG...`): Received exactly 12M JESTER on Dec 27, 2025 for ~0 SOL. **Likely team/insider allocation.** +3. **No Buttcoin convergence**: None of the 20 JESTER holders also hold $Buttcoin. +4. **No shared cross-holdings**: Each whale's other tokens are unique — no clustering pattern. + +### JESTER vs JESTERGOON — X Intelligence + +| | JESTER | JESTERGOON | +|---|--------|------------| +| CA | `6WdHhpRY...pump` | `9gPMDSwf...pump` | +| MC (Feb 8) | ~$90K | ~$483K (ATH $499K) | +| X Traction | Low (1 caller) | High (6+ callers, 4-15x gains) | +| Narrative | JESTERMAXXING meme | JESTERGOONING — "official new meta of 2026" | + +**Assessment**: JESTERGOON has significantly more social momentum and volume. The "jestermaxxing" meme itself is going viral ("peak fun", "in 2026 we are jestergooning") but JESTERGOON token is capturing more of that mindshare. JESTER holder structure is extremely strong (0 exits, 10 accumulators) but JESTERGOON may be the better trade for momentum. + +--- + +## Section 6: Smart Wallet Updates + +**Auto-Discovered Alpha Wallets (7 new from scanner):** + +| Wallet | From | PnL | Multiple | SOL | Score | +|--------|------|-----|----------|-----|-------| +| `ND8nFkaHP9k...` | $Maximoto | $1,284 | 76.5x | 15.0 | 115 | +| `GjPSeaLm72Q...` | $POKEMON30 | $1,445 | 68.5x | 2.3 | 110 | +| `EqQZvQDWr1c...` | $ROCK | $2,390 | 28.3x | 12.3 | 95 | +| `Fj2uMrBaHkM...` | $POKEMON30 | $1,117 | 9.8x | 16.1 | 65 | +| `Ci8oK32uRq1...` | $ROCK | $4,137 | 9.1x | 4.1 | 60 | +| `3AGkLzoHJ6p...` | $ROCK | $2,940 | 9.2x | 8.4 | 60 | +| `FnRQiKnfcud...` | $ROCK | $6,820 | airdrop? | 64.7 | 40 | + +**Original Wallets (from @hellkatai — still unverified on-chain):** +- `DP7G43V...` — +$240K PnL (TOP PERFORMER, priority when VPS resumes) +- `gasTzr94...` — $70K+ on $PISS (verified) +- 5 others need on-chain scan on VPS + +**Total: 17 wallets tracked** (10 manual + 7 auto) + +--- + +## Section 7: Risk Radar + +**HIGH RISK — TODAY:** +- **White House Stablecoin Summit (~1PM ET)**: Banks (JPMorgan, BoA) vs crypto (Coinbase, Circle, Ripple). Stalemate could trigger FUD. Banks fear deposit drain from stablecoin yields. Watch USDC ecosystem + COIN stock. + +**MEDIUM RISK:** +- CPI Data (Feb 13) — macro volatility catalyst +- Binance delistings: RVV/YALA today, ACA/CHESS Feb 13 +- Bithumb "ghost BTC" scandal ($4B discrepancy) — trust erosion +- AAVE approaching $100 invalidation — our rec is at -27% since entry + +**LOW RISK:** +- Consensus Hong Kong opens today (potential announcements) +- Robinhood earnings today (crypto revenue exposure) +- BTC mining hashprice at record lows — miner sell pressure possible + +--- + +## Section 8: Contrarian & Regime Analysis + +**Regime: POST-LIQUIDATION ACCUMULATION** + +The market is in the deepest fear territory of this cycle (FGI = 9). Historically: +- FGI < 10 events in 2022: Preceded 30-60% rallies within 3-6 months +- $2.2B liquidation cascade on Feb 5 was the largest since FTX collapse +- ETF inflows turning positive during extreme fear = institutional accumulation + +**Contrarian Signal**: When everyone is scared, the asymmetric bet is long. BUT — don't catch falling knives. Wait for: +1. BTC weekly close above $72K (confirms support) +2. ETH holding $2,000 on weekly close +3. VIX settling below 20 + +**Smart money is accumulating**: ETF inflows positive 2 days straight. Whale opens $33M ETH long. Our auto-discovered wallets are still buying memes despite the carnage. + +--- + +## Section 9: Recommendations Update + +| # | Position | Entry | Current | Change | Action | +|---|----------|-------|---------|--------|--------| +| 1 | ETH | $2,080 | $2,020 | -2.9% | HOLD — reduce if $1,950 breaks | +| 2 | HYPE | $32.98 | $30.15 | -8.6% | REDUCE 25% — momentum lost | +| 3 | AAVE | ~$150 | $109 | -27.3% | EXIT — below our stop zone | +| 4 | ONDO | $0.28 | $0.247 | -11.8% | HOLD — near invalidation | +| 5 | SOL | $87 | $84.77 | -2.6% | HOLD — relative outperformer | + +**New Recs:** +- **WAIT**: Don't add new positions until FGI > 15 or BTC weekly close > $72K +- **WATCH $JESTERGOON**: Strong social momentum + meme going viral. Not a buy yet — wait for pullback to confirm support +- **WATCH $GUANYU**: Relaunching Feb 11 on pump.fun — pre-launch social buzz is high + +**Risk Allocation:** Reduce from 30% to **20%** due to AAVE exit. + +--- + +## Section 10: System Status & Schedule + +**Active Automation:** + +| Schedule | Service | Status | +|----------|---------|--------| +| Every 5 min | auto_deploy.sh | VPS down — GitHub Actions backup active | +| 8:00 AM CET | daily_morning_report.py | Active | +| 14:00 CET | run_alpha_pipeline.sh | NEW — trending → alpha → cross-ref | +| 02:00 CET | run_alpha_pipeline.sh | NEW — same pipeline, US evening | +| 24/7 daemon | monitor_wallets.py | VPS down — paused | +| 24/7 daemon | scan_x_alpha.py | VPS down — paused | +| 24/7 daemon | scan_trending_wallets.py | VPS down — paused | + +**VPS Note:** VPS temporarily stopped. Ran report manually from Claude Code. GitHub Actions will handle 14:00 and 02:00 scans. When VPS resumes, `auto_deploy.sh` will pull latest code and restart all services automatically. + +--- + +*Report generated: Feb 10, 2026 ~19:00 CET | Data sources: Grok X search (5 queries), CoinGecko, DeFiLlama, DexScreener, alternative.me FGI, Helius RPC (428 JESTER calls)* diff --git a/crypto_intel_2026-02-11.md b/crypto_intel_2026-02-11.md new file mode 100644 index 0000000..a6e6cb4 --- /dev/null +++ b/crypto_intel_2026-02-11.md @@ -0,0 +1,306 @@ +# Crypto Intelligence Briefing — February 11, 2026 + +**Session #4 | 5 Research Agents + 60-Token Alpha Scan (3000+ RPC calls) + 5 Grok X Searches | Market Regime: EXTREME FEAR (12/100) / CAPITULATION ZONE** + +--- + +## Section 1: Memory Review & Previous Session Follow-Up + +**Session #3 (Feb 10) Recommendations — Price Updates:** + +| Token | Entry (Feb 8) | Yesterday | Current | Total Change | Status | +|-------|--------------|-----------|---------|-------------|--------| +| ETH | $2,080 | $2,020 | $2,025 | -2.6% | HOLD — bouncing off $2,000 support | +| HYPE | $32.98 | $30.15 | — | ~-10% | WARNING — continued weakness | +| AAVE | ~$150 | $109 | — | ~-28% | EXITED last session | +| ONDO | $0.28 | $0.247 | — | ~-12% | HOLD — approaching invalidation | +| SOL | $87.06 | $84.77 | $83.00 | -4.7% | HOLD — dropped below $85 | +| BTC | — | $69,211 | $67,400 | — | -2.6% from yesterday | + +**Running Stats:** 5 buy recs, 1 exit (AAVE), 0 triggered trades. Portfolio bleeding in extreme fear. + +**Alpha Pipeline Results (TODAY):** +- **Trending Scanner**: 60 unique CAs found across DexScreener + GeckoTerminal +- **Alpha Wallet Scanner**: 15 new alpha wallets from top 10 tokens, extended scan of 41 more tokens running +- **Total tracked wallets**: 32 (17 previous + 15 new today) +- **JESTER update**: MC +161% to $235K, 0 exits from top 20, holder structure intact + +--- + +## Section 2: Market Structure & Macro + +**BTC: $67,400 (-2.89% 24h) | MC: $1.35T | Dominance: 57.65%** +- **Extreme Fear** — Fear & Greed Index at **12** (was 6 over weekend, lowest EVER recorded) +- Stablecoin dominance surged to 10.3% (FTX-era levels) +- 24h range: $66,500 - $71,000 (whipsawed both ways) +- Weekly context: $9 BILLION in liquidations over past week +- Mining crisis: BTC trading 22% BELOW production cost ($87K). Miners sent 24K BTC to exchanges Feb 5 +- Hash Ribbon inverted since Nov 29. Difficulty dropped 11.16% — steepest since 2021 China ban +- ETF flows: +$144.9M (Feb 10), +$471.1M (Feb 7) — first back-to-back inflows in a month +- BUT: $1.7B net outflows over recent weeks. 62% of all ETF inflows now underwater + +**ETH: $2,025 (-2.67% 24h) | MC: $243.7B** +- Below $2K intraday, bounced back. $2,000 is THE line +- ETH ETFs snapped $1.75B exit streak with +$110M inflows (led by FETH + Grayscale Mini) +- Whale: $33M ETH long still open (liq at $1,438) + +**SOL: $83 (-4.94% 24h) | MC: $47.5B | TVL: $7-8B** +- Dropped below $85 support — now -72% from ATH ($293) +- Standard Chartered cut SOL target from $310 to $250 +- Whale alert: 625K SOL ($50.9M) moved between Coinbase wallets Feb 5 — accumulation signal +- DotComParker ready to buy $500K SOL below $100 + +--- + +## Section 3: CRITICAL — CPI TODAY + +**January CPI Report drops at 8:30 AM ET (TODAY)** +- December CPI: 2.7% YoY +- Consensus expects: **2.5% YoY** (decline) +- Delayed by government shutdown — extra uncertainty +- Hot print = no rate cuts = crypto dumps further +- Cool print = relief rally potential +- Also: Delayed January jobs report this week +- THIS IS THE SINGLE HIGHEST IMPACT CATALYST TODAY + +**Other Macro This Week:** +- Fed Chair Powell testimony (if scheduled) +- Trump tariffs on 8 EU nations (10% rising to 25% by June) +- US shot down Iranian drone — geopolitical risk elevated +- Kevin Warsh Fed Chair nomination creating uncertainty + +--- + +## Section 4: DeFi Intelligence + +**Total DeFi TVL: ~$130-140B** (down from $176B highs late 2025) + +| Protocol | TVL | Notes | +|----------|-----|-------| +| Lido | ~$27.5B | v3 launch imminent | +| Aave | ~$27B | v4 expected Q1-Q2 2026 | +| EigenLayer | ~$13-18.5B | 68% of restaking market | +| Uniswap | ~$7.3B | #1 DEX by TVL | +| Fluid | ~$5.1B | Rising fast, DEX V2 in Q2 | + +**Exploits & Security (Feb 2026):** +- **CrossCurve** (~$3M) — Spoofed cross-chain messages, drained PortalV2 +- **Matcha Meta/SwapNet** ($13.5M) — Users with One-Time Approvals disabled were drained +- **Truebit** ($26.4M) — Free TRU minting bug +- **MakinaFi** ($4.1M) — DUSD/USDC CurveStable pool exploit +- **Trezor Social Engineering** ($282M) — IT support scam compromised root key +- DPRK remains #1 threat actor ($2.02B stolen in 2025) + +**Yield Environment:** +- Baseline: 3-month US Treasury 3.67% +- DeFi stablecoin yields: Aave 3-5%, Compound 2-4%, multiplifi 5% +- Best risk-adjusted: Fluid + USDC/USDT pools +- TVL manipulation warning from Morpho CEO — inflation loops via stables/lending + +**Protocol Launches:** +- Lido v3 (customizable ETH staking) — near launch +- Aave v4 — AI agents for DAO governance +- Fluid DEX V2 — Q2, expanding to Solana +- Jupiter launched stablecoin (90% backed by BlackRock BUIDL) +- SMARDEX — merged DEX + lending + perps, Feb 2026 launch +- **JUP unlock: 253.47M tokens on Feb 28** — watch for sell pressure + +--- + +## Section 5: Solana Trenches — Memecoin Alpha + +**Solana Memecoin Category MC: ~$6.08B** (down 61% from $93B Jan 2025 peak) + +**DexScreener Top Boosted + X Alpha (Today):** + +| Token | Signal | MC | Notes | +|-------|--------|-----|-------| +| $LIONTRUMP | +23,585% 24h | $2.9M | X viral today | +| $ZOO | +24,923% 24h | $2.9M | Fresh pump | +| $BallsDeep | +14,664% 24h | $1.8M | New launch | +| $MLM | +1,122% 24h | $417K | **Our scanner found this (Score 85)** | +| $CUPID | +739% 24h | $286K | **Our scanner found this (Score 50)** | +| $soluna | Multiple 82x, 20x calls | $901K | **Our scanner found this (Score 85)** | +| PIPPIN | +153% 7d | $444M | AI unicorn agent by Yohei Nakajima | + +**Scanner Validated: 3 of today's X alpha tokens ($MLM, $CUPID, $soluna) were independently found by our trending scanner.** Pipeline is working. + +**Major MC Tokens Status:** +- TRUMP: $3.29 (-95.6% from ATH). Whale transfer to BitGo custody — OTC sell signal +- BONK: Sells outnumber buys. -83% from ATH +- PENGU: -86% from peak. Volume surged 27% today +- FARTCOIN: $194M MC. 156K DEX txns/24h. Balanced +- WIF: -91% from $4.83 ATH +- WHITEWHALE: $71M MC, -23.8% 24h. Volatile +- VINE: $18M MC. Move is OVER +- BUTTCOIN: Appearing on top-24h X lists — aligns with our 3/7 wallet convergence + +**Pump.fun Stats:** +- ~20,000 tokens/day deploying (down from 37K peak) +- 98.6% show signs of fraud (Solidus Labs report) +- $SOLY (Soly Inu) launching Feb 12 ~3PM UTC — 228 likes, massive buildup + +--- + +## Section 6: JESTER Deep Dive Update + +**$JESTER** (6WdHhpRY7vL8SQ69bd89tAj3sk8jsjBrCLDUTZSNpump) + +| Metric | Feb 10 | Feb 11 | Change | +|--------|--------|--------|--------| +| MC | ~$90K | **$235,743** | **+161%** | +| Holders | 7K | 7K+ | Stable | +| Top 20 exits | 0 | 0 | **Diamond hands** | +| Accumulators | 10 | Active | Ongoing | + +**On-Chain (1h scan, 53 RPC calls):** +- 24 trades (13 buys, 11 sells) across 12 wallets +- Net JESTER flow: perfectly balanced (5.27M each way) +- SOL flow: mild sell pressure (4.15 SOL in vs 10.92 SOL out) +- Holder #1 (2Aj1...sDG2, 101.8M) still market-making, net +2.54M JESTER +- Holders #2-#5 ALL IDLE — diamond hands +- New funded whale: DNfuF1L6... with 120.3 SOL + +**X Intel:** +- Google Trends showing 4x popularity spike since Jan 21 +- Only 1 active shiller (@youkaichao) +- Indonesian CT picking it up +- JESTERGOON has more social momentum ($135K → $403K MC range) +- Jestermaxxing meme going viral in looksmaxxing communities + +**Assessment:** Structure remains extremely bullish (0 exits, 161% MC gain). Needs a real caller to break out. Monitor but don't chase — social momentum still anemic for $JESTER specifically. $JESTERGOON may capture more mindshare. + +--- + +## Section 7: Alpha Wallet Scanner Results + +**Today's Scan: 60 tokens scanned → 15 new alpha wallets discovered** + +### Top Alpha Wallets (Score 120+) + +| # | Wallet | From | PnL | Multiple | SOL | Score | +|---|--------|------|-----|----------|-----|-------| +| 27 | `Cqj2kGj9...Z9TW` | $SAFEMOON | $2,457 | 9,707x | 93.1 | **140** | +| 25 | `87rRdssF...AAxJ` | $GIRAFFES | $14,152 | 160x | 74.5 | **135** | +| 28 | `EXWGUMiu...pYzP` | $SAFEMOON | $2,005 | 11,495x | 10.0 | **130** | +| 26 | `8WXKcUjw...qhyq` | $GIRAFFES | $19,725 | 1.2Mx | 1.5 | **125** | +| 32 | `DM3LKCMn...hQP` | $ICF | $11,544 | 63,642x | 1.0 | **125** | +| 23 | `4qPaGk9s...g1u` | $Ferociter | $522 | 811x | 2.3 | **120** | + +### All New Wallets (Score 60+) + +| Wallet | Token | PnL | Multiple | SOL | Score | +|--------|-------|-----|----------|-----|-------| +| `3ABA...418G` | BUCKARU | $4,578 | 24,426x | 6.5 | 110 | +| `75tP...yX4` | #MLM | $4,826 | 15,850x | 1.9 | 110 | +| `H6Ki...3n33` | #MLM | $3,748 | 47,433x | 1.3 | 110 | +| `B5hh...EB5t` | Ferociter | $542 | 30,407x | 1.2 | 100 | +| `BC8y...9TW` | soluna | $15,665 | 5.1x | 106.1 | 90 | +| `5T22...mwEP` | BUCKARU | $3,617 | 9.4x | 61.9 | 70 | +| `2z24...eHeW` | GROKPEPE | $1,451 | 6.9x | 5.8 | 60 | + +**Total wallet registry: 32** (17 previous + 15 new today) +**Extended scan of 41 more tokens running in background** — more wallets expected. + +--- + +## Section 8: Risk Radar + +**HIGH RISK — TODAY:** +1. **CPI Report (8:30 AM ET TODAY)** — Delayed January data. Hot print = no rate cuts = dump. #1 catalyst. +2. **US-Iran escalation** — Drone shot down, explosions at Bandar Abbas. Risk-off if escalates. +3. **US-EU tariff war** — 10% tariffs on 8 EU nations (rising to 25% by June). BTC crashed from $80K to $60K flash low on this. +4. **Miner capitulation** — BTC 22% below production cost. 24K BTC sent to exchanges Feb 5. Hash Ribbon inverted. +5. **Fed Chair transition** — Kevin Warsh nomination creates uncertainty. + +**MEDIUM RISK:** +- JUP token unlock: 253.47M on Feb 28 — potential sell pressure +- Trump tariff expansion — 25% on steel/aluminum, 10% on all imports +- ETF structural outflows ($1.7B recent weeks) +- Delayed jobs report this week — another volatility catalyst + +**LOW RISK:** +- Consensus Hong Kong (ongoing — potential announcements) +- CrossCurve exploit ($3M) — contained +- Pump.fun fraud rate (98.6%) — memecoin rug risk elevated + +--- + +## Section 9: Contrarian & Regime Analysis + +**Regime: DEEP CAPITULATION** + +The market has crossed from "Extreme Fear" into historically rare territory: +- FGI hit **6** over the weekend — one of the lowest readings EVER (comparable to 2018 bear bottom, March 2020 COVID crash, FTX collapse) +- Stablecoin dominance at 10.3% = FTX-era levels +- $9 BILLION liquidated in one week +- BTC trading 22% below production cost — miners are literally losing money + +**Historical Parallels:** +| Event | FGI Low | BTC at Low | 6-Month Return | +|-------|---------|------------|----------------| +| 2018 Bear Bottom | 6 | $3,200 | +300% | +| COVID Crash (Mar 2020) | 8 | $3,850 | +950% | +| FTX Collapse (Nov 2022) | 6 | $15,600 | +100% | +| **NOW (Feb 2026)** | **6** | **$67,400** | **???** | + +**Contrarian Signal:** Every time FGI has gone this low, it has preceded a major rally within 3-6 months. BUT: +- Don't catch falling knives — CPI today could push lower +- Wait for: BTC weekly close > $72K, ETH holding $2K on weekly close +- Positive: ETF inflows turning (2 consecutive positive days), whale accumulation signals +- Negative: Miner selling + Fed uncertainty + tariff war + +**Smart Money Signals:** +- 625K SOL ($50.9M) withdrawn from Coinbase Institutional → accumulation +- ETF inflows positive 2 consecutive days despite FGI = 6 +- Our auto-discovered wallets are still actively buying memecoins +- JESTER top 20 holders: 0 exits despite market carnage + +--- + +## Section 10: Recommendations Update + +| # | Position | Entry | Current | Change | Action | +|---|----------|-------|---------|--------|--------| +| 1 | ETH | $2,080 | $2,025 | -2.6% | HOLD — $2,000 support critical | +| 2 | HYPE | $32.98 | ~$29 | ~-12% | REDUCE 50% — momentum lost | +| 3 | AAVE | — | — | — | EXITED at -27% (Session #3) | +| 4 | ONDO | $0.28 | ~$0.24 | ~-14% | EXIT — below invalidation zone | +| 5 | SOL | $87 | $83 | -4.7% | HOLD — approaching $80 support | + +**New Recs:** +- **WAIT FOR CPI**: Do NOT add positions until CPI data is out +- **If CPI cool (<2.5%)**: Consider adding ETH at $2,000, SOL at $80 +- **If CPI hot (>2.7%)**: Reduce all positions, prepare for $60K BTC test +- **WATCH $soluna**: Multiple X callers, our scanner found it at Score 85, alpha wallets accumulating +- **WATCH PIPPIN**: +153% 7d, AI narrative, $444M MC — momentum play +- **$BUTTCOIN**: Still held by 3/7 tracked wallets, appearing on X top-24h lists + +**Risk Allocation:** Reduce to **15%** deployed. Cash is king in capitulation. + +--- + +## Section 11: System Status + +**Active Automation:** + +| Schedule | Service | Status | +|----------|---------|--------| +| Every 5 min | auto_deploy.sh | VPS down — GitHub Actions backup | +| 8:00 AM CET | daily_morning_report.py | Active (GitHub Actions) | +| 14:00 CET | run_alpha_pipeline.sh | Active (GitHub Actions) | +| 02:00 CET | run_alpha_pipeline.sh | Active (GitHub Actions) | +| Background | alpha_wallet_scanner (extended) | RUNNING — 41 tokens remaining | +| Background | monitor_rex.py | Tracking, output to log | + +**Pipeline Results Today:** +- 60 unique CAs scanned via trending scanner +- 15 new alpha wallets discovered (top 10 tokens) +- 41 more tokens scanning in background +- 32 total wallets tracked +- 5 Grok X searches completed +- 3 scanner-found tokens validated by X callers ($MLM, $CUPID, $soluna) + +--- + +*Report generated: Feb 11, 2026 ~10:30 CET | Data sources: 5 Research Agents (web search), Grok X search (5 queries), DexScreener, GeckoTerminal, Helius RPC (3000+ calls), CoinGecko, DeFiLlama, alternative.me FGI* diff --git a/crypto_intel_2026-02-12.md b/crypto_intel_2026-02-12.md new file mode 100644 index 0000000..49cbab1 --- /dev/null +++ b/crypto_intel_2026-02-12.md @@ -0,0 +1,132 @@ +# Daily Intelligence Report — 2026-02-12 09:32 UTC + +## Executive Summary +5-agent parallel scan completed. 40 new trending tokens discovered, wallet activity shows active rotation by alpha wallets. Grok X API key expired (403). No new alpha wallets found in current trending batch (mostly dust holders). Key convergence signal on USDC mint across 2 alpha wallets. + +--- + +## Agent 1: Trending Token Scanner +**Status:** COMPLETE | 59 unique CAs found | 40 new tokens added | 10 queued for alpha scan + +### Top 10 New Trending Tokens (by score) + +| # | Token | MC | Liquidity | Score | Age | +|---|-------|-----|-----------|-------|-----| +| 1 | **$ApeLiquid** | $66K | $21K | 105 | 7.7h | +| 2 | **$SHUTDOWN** | $352K | $50K | 105 | 3.9h | +| 3 | **$COOPERINU** | $113K | $51K | 95 | 32.2h | +| 4 | **$BIG** | $332K | $54K | 95 | 29.0h | +| 5 | **$Pepstein** | $107K | $26K | 95 | 2.8h | +| 6 | **$GIGACHAD** | $332K | $41K | 85 | 24.9h | +| 7 | **$MooNutPeng** | $529K | $62K | 85 | 7.1h | +| 8 | **$HTC** | $5.03M | $270K | 80 | 15.3h | +| 9 | **$snowball** | $1.0M | $173K | 70 | 55.6d | +| 10 | **$DOG** | $990K | $108K | 70 | 6.8d | + +**Notable:** $ApeLiquid and $SHUTDOWN both scored 105 (highest). $SHUTDOWN at $352K MC with only 3.9h age = rapid growth. $HTC at $5M MC is the biggest discovery this scan. + +**Sources:** DexScreener (27 boosted + 24 profiles), GeckoTerminal (20 trending + 1 new pool). Grok X search FAILED (403). + +--- + +## Agent 2: Alpha Wallet Scanner +**Status:** IN PROGRESS (scanning 41 tokens from queue) + +Scanned: $Gentlemen, $POKEMON30, $PENG, $WATT, $SKYNET, $SHARK, $USRX, $Perpcoin, $WhiteGRFF, $VALENTINES, $BullishGir, $LOTUS, $Rock, $Bucky, $REX, $NYAN + more + +### 4 NEW ALPHA WALLETS DETECTED + +| Token | Wallet | PnL Multiple | Profit | SOL Balance | Score | +|-------|--------|-------------|--------|-------------|-------| +| **$SHARK** | `9yQeRiPjh2aTYjp4J8j7...` | 17.5x | $3,117 | 160 SOL | 90 | +| **$SHARK** | `Hh1VyWve6VhEpaYTNt4Q...` | 5.4x | $4,770 | 9.8 SOL | 80 | +| **$REX** | `3GVVGPtkY7GaBMgfA277...` | **770.3x** | $396 | 1 SOL | 120 | +| **$PENG** | `FeMemrFFc9rrYaBFL8UZ...` | 60.0x | $11 | 1 SOL | 120 | + +**Key findings:** +- **$REX 770x wallet** — massive PnL multiple from tiny cost basis, classic sniper pattern +- **$SHARK** has 2 independent alpha wallets = **CONVERGENCE signal** ($311K MC) +- Most other tokens still dominated by dust wallets (<1 SOL holders) +- Overall: ~85% of top 20 holders across all tokens are dust/abandoned wallets + +--- + +## Agent 3: Cross-Reference Analysis +**Status:** COMPLETE + +Cross-referenced top holders of $ApeLiquid against 5 other top trending tokens ($SHUTDOWN, $BIG, $Pepstein, $COOPERINU, $MooNutPeng). + +**Result: 0 wallet overlap** across 6 tokens (20 holders each = 120 wallets checked). + +**Interpretation:** No smart money convergence detected in today's trending batch. Each token has an independent holder base — no coordinated buying across tokens. + +--- + +## Agent 4: X Alpha Scanner (The Degen) +**Status:** COMPLETE — ALL CALLS FAILED (403 Forbidden) + +Attempted to scan 7 tracked callers: +- @AidenJackCrypto, @BioStone_chad, @WavexCaller (critical) +- @cfm_sol, @JMania402, @EricCryptoman, @ELCharpo45 (high) + +**ACTION REQUIRED:** Grok API key `xai-F0u...` is returning 403 Forbidden on all requests. Key needs to be refreshed/rotated at https://console.x.ai + +--- + +## Agent 5: Wallet Position Scanner +**Status:** COMPLETE | 10 top alpha wallets scanned + +### Active Wallet Movements (Last 48h) + +| Wallet | Action | Token | Amount | Time | +|--------|--------|-------|--------|------| +| Alpha #27 ($SAFEMOON) | **BUY** | $SAFEMOON | +23.7M | Feb 11, 22:36 | +| Alpha #26 ($GIRAFFES) | **BUY** | $BFS | +67K | Feb 12, 00:56 | +| Alpha #26 ($GIRAFFES) | SELL | $Guardian | -10.0M | Feb 12, 00:56 | +| Alpha #32 ($ICF) | SELL | USDC | -$776 | Feb 12, 00:03 | +| Alpha #32 ($ICF) | SELL | $ICF | -10.8M | Feb 11, 20:16 | +| Alpha #23 ($Ferociter) | **BUY** | $STARCRAFT | +984K | Feb 11, 04:21 | +| Alpha #23 ($Ferociter) | SELL | USDC | -$505 | Feb 11, 04:21 | +| Alpha #17 ($Maximoto) | BUY+SELL | USDC | +/-$2.5K | Feb 10 | +| Alpha #11 ($POKEMON30) | SELL x5 | $delusional | -154K total | Feb 12, 09:20-32 | + +### Key Signals + +**CONVERGENCE ALERT:** USDC (`EPjFWdd...`) bought by **2 wallets** (Alpha #23 + Alpha #17). Both taking profits into USDC = rotation/exit signal. + +**BEARISH:** Alpha #11 ($POKEMON30 wallet) is **actively dumping $delusional** — 5 sell txs in 12 minutes. Despite $delusional being +1301% in 24h, this wallet is exiting. + +**BULLISH:** +- Alpha #27 opened **new position** in $SAFEMOON (+23.7M tokens) +- Alpha #23 opened **new position** in $STARCRAFT (+984K tokens, MC $439K, +21.5% 24h) +- Alpha #26 bought $BFS ($5.3M MC, +63% 24h) + +### Watchlist Updates +| Token | MC | 24h | Signal | +|-------|-----|-----|--------| +| **$STARCRAFT** | $439K | +21.5% | Alpha #23 NEW BUY | +| **$BFS** | $5.3M | +63.1% | Alpha #26 BUY | +| **$delusional** | $472K | +1301% | Alpha #11 DUMPING (5 sells) | +| **$SAFEMOON** | $124K | -45.9% | Alpha #27 NEW BUY (contrarian?) | + +--- + +## System Health + +| Component | Status | +|-----------|--------| +| DexScreener API | WORKING | +| GeckoTerminal API | WORKING | +| Helius RPC | WORKING | +| Grok X Search | **BROKEN (403)** | +| Discord Webhook | WORKING | +| Trading | DISABLED (report-only) | + +--- + +## Action Items +1. **URGENT:** Rotate Grok API key — all X intelligence is offline +2. **MONITOR:** $STARCRAFT (Alpha #23 new buy, $439K MC) +3. **MONITOR:** $BFS (Alpha #26 buy, $5.3M MC, strong momentum) +4. **WATCH:** $delusional dump by Alpha #11 — could signal top despite +1301% +5. **INVESTIGATE:** Why current trending tokens have almost all dust holders (bot activity?) diff --git a/daily_morning_report.py b/daily_morning_report.py new file mode 100644 index 0000000..d05cd25 --- /dev/null +++ b/daily_morning_report.py @@ -0,0 +1,278 @@ +#!/usr/bin/env python3 +""" +Daily Morning Report — Summarizes top alpha signals. +Summarizes what the system would have bought (buy bot is OFF), +including wallet signals, X caller signals, and trending discoveries. + +Run via cron at 8 AM daily, or manually: + python3 daily_morning_report.py +""" + +import json +import os +import sys +import time +from datetime import datetime, timezone, timedelta +from urllib.request import Request, urlopen + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) + +# Load env +env_path = os.path.join(SCRIPT_DIR, '.env') +if os.path.exists(env_path): + with open(env_path) as f: + for line in f: + line = line.strip() + if '=' in line and not line.startswith('#'): + key, val = line.split('=', 1) + os.environ[key] = val + +# Signal files +WALLET_SIGNALS = os.path.join(SCRIPT_DIR, 'memory', 'wallet_signals.jsonl') +X_SIGNALS = os.path.join(SCRIPT_DIR, 'memory', 'x_signals.jsonl') +ULTRA_SIGNALS = os.path.join(SCRIPT_DIR, 'memory', 'ultra_signals.jsonl') +TRENDING_LOG = os.path.join(SCRIPT_DIR, 'memory', 'trending_scans.jsonl') +TOKENS_REGISTRY = os.path.join(SCRIPT_DIR, 'memory', 'tokens.json') +SMART_WALLETS = os.path.join(SCRIPT_DIR, 'memory', 'smart_wallets.json') +TRADES_LOG = os.path.join(SCRIPT_DIR, 'memory', 'trades_log.jsonl') +EARLY_BUYER_SCAN = os.path.join(SCRIPT_DIR, 'memory', 'early_buyer_scan.json') +WALLET_SCAN_RESULTS = os.path.join(SCRIPT_DIR, 'memory', 'wallet_scan_results.json') + + +def load_jsonl_since(filepath, hours=24): + """Load JSONL entries from last N hours.""" + cutoff = datetime.now(timezone.utc) - timedelta(hours=hours) + entries = [] + if not os.path.exists(filepath): + return entries + try: + with open(filepath) as f: + for line in f: + line = line.strip() + if not line: + continue + try: + entry = json.loads(line) + date_str = entry.get("date") or entry.get("timestamp") or "" + if date_str: + if isinstance(date_str, str): + date_str = date_str.replace('Z', '+00:00') + try: + if isinstance(date_str, (int, float)): + dt = datetime.fromtimestamp(date_str, tz=timezone.utc) + else: + dt = datetime.fromisoformat(date_str) + if dt.tzinfo is None: + dt = dt.replace(tzinfo=timezone.utc) + if dt > cutoff: + entries.append(entry) + except Exception: + entries.append(entry) # Include if can't parse date + else: + entries.append(entry) # Include entries with no date field + except json.JSONDecodeError: + continue + except Exception: + pass + return entries + + +def load_json(filepath): + """Load a JSON file.""" + if not os.path.exists(filepath): + return {} + try: + with open(filepath) as f: + return json.load(f) + except Exception: + return {} + + +def get_token_info(mint): + """Get token info from DexScreener.""" + try: + url = f"https://api.dexscreener.com/latest/dex/tokens/{mint}" + req = Request(url, headers={'Accept': 'application/json', 'User-Agent': 'Mozilla/5.0'}) + with urlopen(req, timeout=10) as resp: + data = json.loads(resp.read()) + pairs = data.get("pairs") or [] + if pairs: + p = pairs[0] + return { + "symbol": p.get("baseToken", {}).get("symbol", "UNKNOWN"), + "name": p.get("baseToken", {}).get("name", "Unknown"), + "mc": p.get("marketCap") or 0, + "price_change_24h": (p.get("priceChange") or {}).get("h24") or 0, + "vol_24h": (p.get("volume") or {}).get("h24") or 0, + } + except Exception: + pass + return None + + +def generate_report(): + """Generate the daily morning report.""" + now = datetime.now(timezone.utc) + report_lines = [] + report_lines.append(f"**Daily Alpha Report -- {now.strftime('%Y-%m-%d %H:%M UTC')}**") + report_lines.append("") + + # 1. Conviction signals (would-have-been-bought) + ultra_signals = load_jsonl_since(ULTRA_SIGNALS, hours=24) + trades = load_jsonl_since(TRADES_LOG, hours=24) + + simulated_buys = [t for t in trades if t.get("action") == "buy_simulated"] + actual_buys = [t for t in trades if t.get("action") == "buy"] + ultra_list = [s for s in ultra_signals if s.get("conviction") in ("ULTRA", "HIGH")] + + if simulated_buys or ultra_list: + report_lines.append("**Would-Have-Been-Bought (Trading OFF):**") + seen_mints = set() + + for trade in simulated_buys: + mint = trade.get("mint", "unknown") + if mint in seen_mints: + continue + seen_mints.add(mint) + info = get_token_info(mint) + if info: + change = info.get("price_change_24h", 0) or 0 + mc = info.get("mc", 0) or 0 + pnl_emoji = "+" if change > 0 else "" + report_lines.append( + f" - **${info['symbol']}** | MC: ${mc:,.0f} | " + f"24h: {pnl_emoji}{change:.1f}% | `{mint[:20]}...`" + ) + else: + report_lines.append(f" - `{mint[:24]}...` (no DexScreener data)") + + for sig in ultra_list: + mint = sig.get("mint") or (sig.get("addresses", [None])[0] if sig.get("addresses") else None) + if not mint or mint in seen_mints: + continue + seen_mints.add(mint) + ticker = sig.get("ticker", "?") + level = sig.get("conviction", "?") + reason = sig.get("reason", "") + report_lines.append(f" - **[{level}] ${ticker}** | {reason}") + + if not seen_mints: + report_lines.append(" No conviction signals in last 24h") + report_lines.append("") + else: + report_lines.append("**No conviction signals in last 24h**") + report_lines.append("") + + # 2. Wallet activity summary + wallet_signals = load_jsonl_since(WALLET_SIGNALS, hours=24) + wallet_buys = [s for s in wallet_signals if s.get("action") == "ALPHA_WALLET_BUY"] + + if wallet_buys: + report_lines.append(f"**Alpha Wallet Activity ({len(wallet_buys)} buys):**") + mint_wallets = {} + for s in wallet_buys: + mint = s.get("mint", "") + label = s.get("wallet_label", "unknown") + mint_wallets.setdefault(mint, []).append(label) + + for mint, wallets in sorted(mint_wallets.items(), key=lambda x: len(x[1]), reverse=True)[:8]: + info = get_token_info(mint) + if info: + report_lines.append( + f" - ${info['symbol']} ({len(wallets)} wallets) | MC: ${info.get('mc', 0):,.0f}" + ) + else: + report_lines.append(f" - `{mint[:20]}...` ({len(wallets)} wallets)") + report_lines.append("") + else: + report_lines.append("**No alpha wallet buys in last 24h**") + report_lines.append("") + + # 3. X caller signals + x_signals = load_jsonl_since(X_SIGNALS, hours=24) + caller_signals = [s for s in x_signals if s.get("action") == "X_ALPHA_CALL"] + + if caller_signals: + report_lines.append(f"**X Caller Activity ({len(caller_signals)} signals):**") + for s in caller_signals[:5]: + caller = s.get("caller", "unknown") + tickers = s.get("tickers", []) + report_lines.append(f" - {caller}: {', '.join(f'${t}' for t in tickers[:5])}") + report_lines.append("") + else: + report_lines.append("**No X caller signals in last 24h**") + report_lines.append("") + + # 4. Trending scanner results + trending = load_jsonl_since(TRENDING_LOG, hours=24) + if trending: + total_scanned = sum(e.get("tokens_scanned", 0) for e in trending) + report_lines.append(f"**Trending Scanner: {len(trending)} scans, {total_scanned} tokens checked**") + report_lines.append("") + + # 5. System status + smart_wallets = load_json(SMART_WALLETS) + tokens_reg = load_json(TOKENS_REGISTRY) + wallet_count = len([w for w in smart_wallets.get("wallets", []) if "active" in w.get("status", "")]) + token_count = tokens_reg.get("stats", {}).get("total_tokens", 0) + pending_scans = tokens_reg.get("stats", {}).get("pending_helius_scan", 0) + + report_lines.append("**System Status:**") + report_lines.append(f" - Wallets tracked: {wallet_count}") + report_lines.append(f" - Tokens in registry: {token_count}") + report_lines.append(f" - Pending Helius scans: {pending_scans}") + report_lines.append(f" - Trading: OFF (monitoring only)") + + # 6. Early buyer scan results + scan_results = load_json(EARLY_BUYER_SCAN) + if scan_results: + multi = scan_results.get("multi_token_wallets", []) + total_wallets = scan_results.get("total_unique_wallets", 0) + if multi: + report_lines.append(f" - Early buyer scan: {total_wallets} wallets, {len(multi)} multi-token") + + # 7. RPC Wallet Scan results (if recent) + wallet_scan = load_json(WALLET_SCAN_RESULTS) + if wallet_scan and wallet_scan.get("results"): + scan_date = wallet_scan.get("scan_date", "") + results = wallet_scan["results"] + report_lines.append("") + report_lines.append(f"**Wallet Scan ({len(results)} wallets, {scan_date[:10]}):**") + for r in results: + label = r.get("label", "?") + sol = r.get("sol_balance", 0) + hold_count = len(r.get("holdings", [])) + top = sorted(r.get("holdings", []), + key=lambda x: x.get("info", {}).get("mc", 0), reverse=True)[:2] + top_str = ", ".join( + f"${h.get('info',{}).get('symbol','?')} (${h.get('info',{}).get('mc',0):,.0f})" + for h in top if h.get("info", {}).get("mc", 0) > 0 + ) or "no priced tokens" + report_lines.append(f" - **{label}**: {sol:.1f} SOL | {hold_count} tok | {top_str}") + + shared = wallet_scan.get("shared", {}) + multi_wallet = {m: ws for m, ws in shared.items() if len(ws) >= 3} + if multi_wallet: + report_lines.append(" **Convergence (3+ wallets):**") + for mint, ws in sorted(multi_wallet.items(), key=lambda x: len(x[1]), reverse=True)[:5]: + # Find symbol from results + sym = mint[:12] + for r in results: + for h in r.get("holdings", []): + if h.get("mint") == mint and h.get("info", {}).get("symbol"): + sym = "$" + h["info"]["symbol"] + break + report_lines.append(f" {sym} — {len(ws)} wallets") + + return "\n".join(report_lines) + + +def main(): + print(f"[{datetime.now(timezone.utc).isoformat()}] Generating daily morning report...") + report = generate_report() + print(report) + print(f"\n[{datetime.now(timezone.utc).isoformat()}] Report generated.") + + +if __name__ == "__main__": + main() diff --git a/ftx2_bundle_analysis.py b/ftx2_bundle_analysis.py new file mode 100644 index 0000000..a26adcb --- /dev/null +++ b/ftx2_bundle_analysis.py @@ -0,0 +1,479 @@ +#!/usr/bin/env python3 +""" +FTX 2.0 ($FTX2.0) — Bundle / Cluster / Whale / Sniper Analysis +Token: ANVWi3AAkjXRnesAMtAQNRPcrhSnKKbQwsRVe7xpump +""" + +import json, time, sys +from urllib.request import Request, urlopen +from urllib.error import HTTPError, URLError +from collections import defaultdict +from datetime import datetime, timezone + +TOKEN_MINT = "ANVWi3AAkjXRnesAMtAQNRPcrhSnKKbQwsRVe7xpump" +TOKEN_NAME = "FTX2.0" +RPC = "https://mainnet.helius-rpc.com/?api-key=28d0e718-6052-4054-a8c8-c38c3897ac15" +RPC_DELAY = 0.4 +TOP_N = 20 +TOTAL_SUPPLY = 1_000_000_000 # pump.fun standard + +# Token created timestamp from DexScreener (Dec 10 2024 based on data, but pair timestamp 1770723138 = Feb 2026) +# We'll detect creation time from earliest tx +TOKEN_CREATION_TS = None + +def rpc_call(method, params, retries=3): + body = json.dumps({"jsonrpc":"2.0","id":1,"method":method,"params":params}).encode() + for attempt in range(retries): + try: + req = Request(RPC, data=body, headers={"Content-Type":"application/json"}) + resp = urlopen(req, timeout=30) + data = json.loads(resp.read()) + if "error" in data: + print(f" RPC error: {data['error']}") + return None + return data.get("result") + except Exception as e: + if attempt < retries - 1: + time.sleep(2 ** attempt) + else: + print(f" RPC failed after {retries} attempts: {e}") + return None + return None + +def short(addr): + if not addr or len(addr) <= 16: + return str(addr) + return f"{addr[:6]}...{addr[-4:]}" + +print("=" * 90) +print(f" {TOKEN_NAME} — BUNDLE / CLUSTER / WHALE / SNIPER ANALYSIS") +print(f" Mint: {TOKEN_MINT}") +print(f" Time: {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M UTC')}") +print("=" * 90) + +# ───────────────────────────────────────────── +# STEP 1: Get top holders +# ───────────────────────────────────────────── +print(f"\n[STEP 1] Fetching top {TOP_N} holders...") +result = rpc_call("getTokenLargestAccounts", [TOKEN_MINT]) +if not result or "value" not in result: + print("FATAL: Could not fetch largest accounts") + sys.exit(1) + +accounts = result["value"][:TOP_N] +print(f" Got {len(accounts)} token accounts") + +# Resolve owner wallets +holders = [] +for i, acc in enumerate(accounts): + token_account = acc["address"] + raw_amount = int(acc["amount"]) + decimals = acc["decimals"] + balance = raw_amount / (10 ** decimals) + pct_supply = (balance / TOTAL_SUPPLY) * 100 + + info = rpc_call("getAccountInfo", [token_account, {"encoding": "jsonParsed"}]) + time.sleep(RPC_DELAY) + + owner = "unknown" + if info and info.get("value"): + parsed = info["value"].get("data", {}) + if isinstance(parsed, dict) and "parsed" in parsed: + owner = parsed["parsed"].get("info", {}).get("owner", "unknown") + + holders.append({ + "rank": i + 1, + "wallet": owner, + "token_account": token_account, + "balance": balance, + "pct_supply": pct_supply, + }) + print(f" [{i+1:2d}] {short(owner):16s} | {balance:>14,.0f} {TOKEN_NAME} ({pct_supply:.2f}%)") + +total_top_holders = sum(h["balance"] for h in holders) +top_pct = (total_top_holders / TOTAL_SUPPLY) * 100 +print(f"\n Top {len(holders)} hold: {total_top_holders:,.0f} ({top_pct:.1f}% of supply)") + +# ───────────────────────────────────────────── +# STEP 2: Analyze each holder — first buy, SOL balance, funding source +# ───────────────────────────────────────────── +print(f"\n[STEP 2] Analyzing holders: first buy time, SOL balance, funding source...") + +for i, h in enumerate(holders): + wallet = h["wallet"] + if wallet == "unknown": + h.update({"sol_balance": 0, "first_buy_slot": None, "first_buy_time": None, + "funding_source": None, "buy_slots": [], "sniper_tag": ""}) + continue + + # SOL balance + bal = rpc_call("getBalance", [wallet]) + h["sol_balance"] = (bal["value"] / 1e9) if bal and "value" in bal else 0 + time.sleep(RPC_DELAY) + + # Get token account tx history (for first buy + slot detection) + token_sigs = rpc_call("getSignaturesForAddress", [h["token_account"], {"limit": 30}]) + time.sleep(RPC_DELAY) + + jester_slots = [] + if token_sigs: + for sig_info in token_sigs: + slot = sig_info.get("slot", 0) + bt = sig_info.get("blockTime", 0) + jester_slots.append({"slot": slot, "time": bt, "sig": sig_info["signature"]}) + jester_slots.sort(key=lambda x: x["time"] if x["time"] else 0) + + h["buy_slots"] = jester_slots + h["first_buy_slot"] = jester_slots[0]["slot"] if jester_slots else None + h["first_buy_time"] = jester_slots[0]["time"] if jester_slots else None + + # Get wallet sigs to find funding source + wallet_sigs = rpc_call("getSignaturesForAddress", [wallet, {"limit": 30}]) + time.sleep(RPC_DELAY) + + funding_source = None + if wallet_sigs: + oldest_sorted = sorted(wallet_sigs, key=lambda x: x.get("blockTime", 0) or 0) + # Check first few txs + for sig_info in oldest_sorted[:5]: + tx = rpc_call("getTransaction", [sig_info["signature"], + {"encoding": "jsonParsed", "maxSupportedTransactionVersion": 0}]) + time.sleep(RPC_DELAY) + if tx and tx.get("transaction"): + instructions = tx["transaction"].get("message", {}).get("instructions", []) + for inst in instructions: + if isinstance(inst, dict) and isinstance(inst.get("parsed"), dict): + ptype = inst["parsed"].get("type", "") + pinfo = inst["parsed"].get("info", {}) + if ptype == "transfer" and pinfo.get("destination") == wallet: + funding_source = pinfo.get("source") + break + # Also check inner instructions + if not funding_source: + meta = tx.get("meta", {}) + inner = meta.get("innerInstructions", []) + for ii in inner: + for inst in ii.get("instructions", []): + if isinstance(inst, dict) and isinstance(inst.get("parsed"), dict): + ptype = inst["parsed"].get("type", "") + pinfo = inst["parsed"].get("info", {}) + if ptype == "transfer" and pinfo.get("destination") == wallet: + funding_source = pinfo.get("source") + break + if funding_source: + break + if funding_source: + break + + h["funding_source"] = funding_source + + # Sniper tag (will set after we determine creation time) + h["sniper_tag"] = "" + + fund_str = short(funding_source) if funding_source else "?" + buy_time = "" + if h["first_buy_time"]: + dt = datetime.fromtimestamp(h["first_buy_time"], tz=timezone.utc) + buy_time = dt.strftime("%m-%d %H:%M:%S") + + print(f" [{h['rank']:2d}] {short(wallet):16s} | SOL: {h['sol_balance']:>7.2f} | 1st buy: {buy_time:>14s} | Funded: {fund_str}") + +# ───────────────────────────────────────────── +# STEP 3: Detect creation time from earliest holder buy +# ───────────────────────────────────────────── +all_times = [h["first_buy_time"] for h in holders if h.get("first_buy_time")] +if all_times: + TOKEN_CREATION_TS = min(all_times) + print(f"\n Estimated token creation: {datetime.fromtimestamp(TOKEN_CREATION_TS, tz=timezone.utc).strftime('%Y-%m-%d %H:%M:%S UTC')}") + +# Set sniper tags now +for h in holders: + if h.get("first_buy_time") and TOKEN_CREATION_TS: + age = h["first_buy_time"] - TOKEN_CREATION_TS + if age < 10: + h["sniper_tag"] = f"GENESIS ({age}s)" + elif age < 60: + h["sniper_tag"] = f"SNIPER ({age}s)" + elif age < 300: + h["sniper_tag"] = f"EARLY ({age//60}m{age%60}s)" + elif age < 3600: + h["sniper_tag"] = f"FAST ({age//60}m)" + else: + h["sniper_tag"] = "" + +# ───────────────────────────────────────────── +# STEP 3: BUNDLE DETECTION — wallets buying in same slot +# ───────────────────────────────────────────── +print(f"\n[STEP 3] BUNDLE DETECTION — checking for same-slot purchases among top holders...") + +slot_to_wallets = defaultdict(list) +for h in holders: + if h.get("buy_slots"): + for s in h["buy_slots"]: + slot_to_wallets[s["slot"]].append({ + "wallet": h["wallet"], + "rank": h["rank"], + "balance": h["balance"], + "pct": h["pct_supply"], + "sig": s["sig"] + }) + +bundles_found = [] +for slot, wallets in sorted(slot_to_wallets.items()): + # Only count if 2+ DIFFERENT wallets in same slot + unique_wallets = set(w["wallet"] for w in wallets) + if len(unique_wallets) >= 2: + bundles_found.append({"slot": slot, "wallets": wallets, "unique_count": len(unique_wallets)}) + +if bundles_found: + print(f"\n BUNDLES DETECTED: {len(bundles_found)} slots with 2+ holders transacting together!") + total_bundle_supply = 0 + bundle_wallets = set() + for b in bundles_found: + print(f"\n Slot {b['slot']} ({b['unique_count']} wallets):") + for w in b["wallets"]: + print(f" #{w['rank']:2d} {short(w['wallet']):16s} | {w['balance']:>12,.0f} ({w['pct']:.2f}%) | sig: {w['sig'][:24]}...") + if w["wallet"] not in bundle_wallets: + total_bundle_supply += w["balance"] + bundle_wallets.add(w["wallet"]) + bundle_pct = (total_bundle_supply / TOTAL_SUPPLY) * 100 + print(f"\n Total bundled wallets: {len(bundle_wallets)} controlling {total_bundle_supply:,.0f} ({bundle_pct:.2f}%)") +else: + print(" No same-slot bundles found among top holders.") + +# ───────────────────────────────────────────── +# STEP 4: CLUSTER DETECTION — wallets funded by same source +# ───────────────────────────────────────────── +print(f"\n[STEP 4] CLUSTER DETECTION — wallets funded by same source...") + +funder_to_wallets = defaultdict(list) +for h in holders: + if h.get("funding_source") and h["funding_source"] not in ("unknown", None): + funder_to_wallets[h["funding_source"]].append(h) + +clusters_found = [] +for funder, wallets in funder_to_wallets.items(): + if len(wallets) >= 2: + clusters_found.append({"funder": funder, "wallets": wallets}) + +if clusters_found: + print(f"\n CLUSTERS DETECTED: {len(clusters_found)} funding sources linked to 2+ holders!") + for c in clusters_found: + total_held = sum(w["balance"] for w in c["wallets"]) + cluster_pct = (total_held / TOTAL_SUPPLY) * 100 + print(f"\n Funder: {c['funder']}") + print(f" Combined: {total_held:,.0f} {TOKEN_NAME} ({cluster_pct:.2f}%)") + for w in c["wallets"]: + print(f" #{w['rank']:2d} {short(w['wallet']):16s} | {w['balance']:>12,.0f} ({w['pct_supply']:.2f}%) | SOL: {w['sol_balance']:.2f}") +else: + print(" No clusters found (no shared funding sources among top holders).") + +# Check if any holder directly funded another +print(f"\n Checking holder-to-holder funding links...") +holder_wallets_set = set(h["wallet"] for h in holders) +linked = [] +for h in holders: + if h.get("funding_source") and h["funding_source"] in holder_wallets_set: + funder_h = next((x for x in holders if x["wallet"] == h["funding_source"]), None) + if funder_h: + linked.append((funder_h, h)) + +if linked: + print(f" LINKED: {len(linked)} pairs where one holder funded another!") + for funder_h, funded_h in linked: + combined = funder_h["balance"] + funded_h["balance"] + pct = (combined / TOTAL_SUPPLY) * 100 + print(f" #{funder_h['rank']} {short(funder_h['wallet'])} -> #{funded_h['rank']} {short(funded_h['wallet'])} | Combined: {combined:,.0f} ({pct:.2f}%)") +else: + print(" No direct holder-to-holder funding links found.") + +# ───────────────────────────────────────────── +# STEP 5: WHALE ANALYSIS +# ───────────────────────────────────────────── +print(f"\n[STEP 5] WHALE ANALYSIS — concentration & distribution...") + +# Top 5 concentration +top5_balance = sum(h["balance"] for h in holders[:5]) +top5_pct = (top5_balance / TOTAL_SUPPLY) * 100 +top10_balance = sum(h["balance"] for h in holders[:10]) +top10_pct = (top10_balance / TOTAL_SUPPLY) * 100 + +print(f"\n Top 5 wallets: {top5_balance:>14,.0f} ({top5_pct:.2f}%)") +print(f" Top 10 wallets: {top10_balance:>14,.0f} ({top10_pct:.2f}%)") +print(f" Top 20 wallets: {total_top_holders:>14,.0f} ({top_pct:.2f}%)") + +# Whale threshold: >1% supply +whales = [h for h in holders if h["pct_supply"] >= 1.0] +print(f"\n Whales (>1% supply): {len(whales)}") +for w in whales: + tag = w.get("sniper_tag", "") + fund = short(w.get("funding_source")) if w.get("funding_source") else "?" + print(f" #{w['rank']:2d} {short(w['wallet']):16s} | {w['balance']:>12,.0f} ({w['pct_supply']:.2f}%) | SOL: {w['sol_balance']:>7.2f} | {tag:>15s} | Funded: {fund}") + +# ───────────────────────────────────────────── +# STEP 6: Check earliest mint transactions for absolute first buyers +# ───────────────────────────────────────────── +print(f"\n[STEP 6] Checking earliest mint transactions...") + +mint_sigs = rpc_call("getSignaturesForAddress", [TOKEN_MINT, {"limit": 50}]) +time.sleep(RPC_DELAY) + +early_buyers = [] +if mint_sigs: + mint_sigs_sorted = sorted(mint_sigs, key=lambda x: x.get("blockTime", 0) or 0) + + # Parse oldest 15 transactions + for sig_info in mint_sigs_sorted[:15]: + sig = sig_info["signature"] + bt = sig_info.get("blockTime", 0) + slot = sig_info.get("slot", 0) + + tx = rpc_call("getTransaction", [sig, {"encoding": "jsonParsed", "maxSupportedTransactionVersion": 0}]) + time.sleep(RPC_DELAY) + + if not tx: + continue + + # Find signer + acct_keys = tx.get("transaction", {}).get("message", {}).get("accountKeys", []) + signers = [] + for ak in acct_keys: + if isinstance(ak, dict) and ak.get("signer"): + signers.append(ak["pubkey"]) + + buyer = signers[0] if signers else "unknown" + is_top_holder = buyer in holder_wallets_set + + early_buyers.append({ + "sig": sig, "buyer": buyer, "slot": slot, + "time": bt, "is_top_holder": is_top_holder + }) + + # Group by slot for bundle detection + early_slot_map = defaultdict(list) + for eb in early_buyers: + early_slot_map[eb["slot"]].append(eb) + + print(f"\n {'#':>3} | {'Time':>19} | {'Slot':>12} | {'Buyer':>16} | {'Top20?':>6} | {'Bundle?':>8}") + print(" " + "-" * 80) + + for i, eb in enumerate(early_buyers): + dt_str = datetime.fromtimestamp(eb["time"], tz=timezone.utc).strftime("%m-%d %H:%M:%S") if eb["time"] else "?" + is_bundle = len(early_slot_map[eb["slot"]]) > 1 + unique_in_slot = len(set(x["buyer"] for x in early_slot_map[eb["slot"]])) + bundle_str = f"BDL({unique_in_slot})" if is_bundle and unique_in_slot > 1 else ("SAME-W" if is_bundle else "") + print(f" {i+1:3d} | {dt_str:>19s} | {eb['slot']:>12d} | {short(eb['buyer']):>16s} | {'YES' if eb['is_top_holder'] else 'no':>6s} | {bundle_str:>8s}") + + # Early bundle detection + early_bundles = [] + for slot, buyers in early_slot_map.items(): + unique_buyers = set(b["buyer"] for b in buyers) + if len(unique_buyers) >= 2: + early_bundles.append((slot, buyers, unique_buyers)) + + if early_bundles: + print(f"\n EARLY BUNDLE ALERT: {len(early_bundles)} slots with multiple DIFFERENT buyers!") + for slot, buyers, unique in early_bundles: + print(f" Slot {slot} ({len(unique)} unique wallets):") + for eb in buyers: + in_top = " [TOP HOLDER]" if eb["is_top_holder"] else "" + print(f" {short(eb['buyer'])}{in_top}") + +# ───────────────────────────────────────────── +# STEP 7: DEV WALLET CHECK +# ───────────────────────────────────────────── +print(f"\n[STEP 7] Checking for dev/deployer wallet among holders...") + +# The #1 holder is often bonding curve or dev +h1 = holders[0] +print(f" #1 holder: {h1['wallet']} ({h1['pct_supply']:.2f}%)") +if h1["pct_supply"] > 5: + print(f" WARNING: #1 holder has {h1['pct_supply']:.2f}% — potential dev/insider wallet") + +# Check if any wallet has very high SOL balance (whale signal) +high_sol = [h for h in holders if h.get("sol_balance", 0) > 5] +if high_sol: + print(f"\n HIGH SOL BALANCE wallets (>5 SOL):") + for h in high_sol: + print(f" #{h['rank']} {short(h['wallet'])} | SOL: {h['sol_balance']:.2f} | Tokens: {h['balance']:,.0f} ({h['pct_supply']:.2f}%)") + +# ───────────────────────────────────────────── +# FINAL SUMMARY +# ───────────────────────────────────────────── +print("\n" + "=" * 90) +print(" FINAL SUMMARY — RISK FLAGS") +print("=" * 90) + +snipers = [h for h in holders if "SNIPER" in h.get("sniper_tag", "") or "GENESIS" in h.get("sniper_tag", "")] +early = [h for h in holders if "EARLY" in h.get("sniper_tag", "")] + +sniper_bal = sum(h["balance"] for h in snipers) +sniper_pct = (sniper_bal / TOTAL_SUPPLY) * 100 +early_bal = sum(h["balance"] for h in early) +early_pct = (early_bal / TOTAL_SUPPLY) * 100 +cluster_bal = sum(sum(w["balance"] for w in c["wallets"]) for c in clusters_found) if clusters_found else 0 +cluster_pct = (cluster_bal / TOTAL_SUPPLY) * 100 + +print(f"\n SNIPERS (<60s): {len(snipers):3d} wallets | {sniper_bal:>12,.0f} ({sniper_pct:.2f}%)") +print(f" EARLY (<5min): {len(early):3d} wallets | {early_bal:>12,.0f} ({early_pct:.2f}%)") +print(f" BUNDLES (same slot): {len(bundles_found):3d} detected") +print(f" CLUSTERS (same funder): {len(clusters_found):3d} detected | {cluster_bal:>12,.0f} ({cluster_pct:.2f}%)") +print(f" LINKED HOLDERS: {len(linked):3d} pairs") +print(f" WHALES (>1%): {len(whales):3d} wallets | {sum(w['balance'] for w in whales):>12,.0f} ({sum(w['pct_supply'] for w in whales):.2f}%)") + +# Concentration +print(f"\n CONCENTRATION:") +print(f" Top 5: {top5_pct:.2f}%") +print(f" Top 10: {top10_pct:.2f}%") +print(f" Top 20: {top_pct:.2f}%") + +# Risk score +risk_score = 0 +risk_reasons = [] + +if snipers: + risk_score += 2 + risk_reasons.append(f"{len(snipers)} snipers") +if len(bundles_found) >= 2: + risk_score += 3 + risk_reasons.append(f"{len(bundles_found)} bundles") +elif len(bundles_found) == 1: + risk_score += 1 + risk_reasons.append("1 bundle") +if clusters_found: + risk_score += 2 + risk_reasons.append(f"{len(clusters_found)} clusters") +if linked: + risk_score += 1 + risk_reasons.append(f"{len(linked)} linked holders") +if sniper_pct > 10: + risk_score += 2 + risk_reasons.append(f"snipers hold {sniper_pct:.1f}%") +if top5_pct > 15: + risk_score += 1 + risk_reasons.append(f"top5 concentration {top5_pct:.1f}%") +if holders[0]["pct_supply"] > 10: + risk_score += 1 + risk_reasons.append(f"#1 holder has {holders[0]['pct_supply']:.1f}%") + +risk_label = "LOW" if risk_score <= 2 else "MEDIUM" if risk_score <= 5 else "HIGH" if risk_score <= 8 else "CRITICAL" +color = "🟢" if risk_score <= 2 else "🟡" if risk_score <= 5 else "🔴" + +print(f"\n INSIDER RISK SCORE: {risk_score}/10 — {risk_label}") +print(f" Reasons: {', '.join(risk_reasons) if risk_reasons else 'None detected'}") + +if snipers: + print(f"\n SNIPER WALLETS:") + for h in snipers: + print(f" #{h['rank']} {h['wallet']} | {h['balance']:,.0f} ({h['pct_supply']:.2f}%) | {h['sniper_tag']}") + +if clusters_found: + print(f"\n CLUSTER DETAILS:") + for c in clusters_found: + print(f" Funder: {c['funder']}") + for w in c["wallets"]: + print(f" #{w['rank']} {w['wallet']} | {w['balance']:,.0f} ({w['pct_supply']:.2f}%)") + +print(f"\n{'='*90}") +print(" ANALYSIS COMPLETE") +print(f"{'='*90}") diff --git a/holder_health_analysis.py b/holder_health_analysis.py new file mode 100644 index 0000000..71e0511 --- /dev/null +++ b/holder_health_analysis.py @@ -0,0 +1,640 @@ +#!/usr/bin/env python3 +""" +Deep Holder Health Analysis for Solana Token +Analyzes top 20 holders for clusters, bundlers, snipers, and unhealthy patterns. +""" + +import json +import os +import time +import sys +from urllib.request import Request, urlopen +from urllib.error import URLError, HTTPError +from collections import defaultdict +from datetime import datetime, timezone + +# Load env +from dotenv import load_dotenv +load_dotenv("/home/user/Cute-Panel/.env") + +RPC_URL = os.getenv("HELIUS_RPC_URL") +MINT = "HXvQAQwytoLngKWQtge3oJnLHsaLwTxPbX48DctLpump" +TOKEN_CREATION_TIME = 1770696318 # unix timestamp +RPC_DELAY = 0.3 +DECIMALS = 6 # pump.fun tokens are 6 decimals + +def rpc_call(method, params, retries=3): + """Make a Solana RPC call with retries.""" + payload = json.dumps({"jsonrpc": "2.0", "id": 1, "method": method, "params": params}) + for attempt in range(retries): + try: + req = Request(RPC_URL, data=payload.encode(), headers={"Content-Type": "application/json"}) + resp = urlopen(req, timeout=30) + data = json.loads(resp.read().decode()) + if "error" in data: + print(f" RPC error ({method}): {data['error']}") + if attempt < retries - 1: + time.sleep(1) + continue + return None + return data.get("result") + except Exception as e: + if attempt < retries - 1: + time.sleep(1) + continue + print(f" RPC exception ({method}): {e}") + return None + return None + +def lamports_to_sol(lamports): + return lamports / 1_000_000_000 + +def raw_to_tokens(raw): + return raw / (10 ** DECIMALS) + +# ═══════════════════════════════════════════════════════════════ +# PART 1: Top 20 Holders Snapshot +# ═══════════════════════════════════════════════════════════════ +print("=" * 100) +print(f" DEEP HOLDER HEALTH ANALYSIS") +print(f" Token Mint: {MINT}") +print(f" Token Creation: {datetime.fromtimestamp(TOKEN_CREATION_TIME, tz=timezone.utc).strftime('%Y-%m-%d %H:%M:%S UTC')}") +print(f" Analysis Time: {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M:%S UTC')}") +print("=" * 100) + +print("\n[PART 1] Fetching top 20 token holders...") + +# Step 1: Get largest token accounts +result = rpc_call("getTokenLargestAccounts", [MINT]) +time.sleep(RPC_DELAY) + +if not result or "value" not in result: + print("FATAL: Could not fetch largest token accounts.") + sys.exit(1) + +accounts = result["value"][:20] +print(f" Found {len(accounts)} largest token accounts") + +# Step 2: Resolve owners for each token account +holders = [] +total_top20_supply = 0 + +for i, acc in enumerate(accounts): + token_account = acc["address"] + raw_amount = int(acc["amount"]) + token_balance = raw_to_tokens(raw_amount) + total_top20_supply += token_balance + + # Get account info to find owner + info = rpc_call("getAccountInfo", [token_account, {"encoding": "jsonParsed"}]) + time.sleep(RPC_DELAY) + + owner = "UNKNOWN" + if info and info.get("value") and info["value"].get("data"): + try: + parsed = info["value"]["data"]["parsed"]["info"] + owner = parsed.get("owner", "UNKNOWN") + except (KeyError, TypeError): + pass + + holders.append({ + "rank": i + 1, + "token_account": token_account, + "owner": owner, + "token_balance": token_balance, + "raw_amount": raw_amount, + "sol_balance": 0, + "flags": [], + "health": "HEALTHY", + "earliest_mint_tx_time": None, + "buy_delay_seconds": None, + "tx_count_100": 0, + "funding_source": None, + "shared_counterparties": set(), + "counterparty_map": defaultdict(int), + }) + print(f" [{i+1}/20] Resolved owner: {owner[:8]}...{owner[-6:]}" if owner != "UNKNOWN" else f" [{i+1}/20] Owner: UNKNOWN") + +# Step 3: Get SOL balances +print("\n Fetching SOL balances...") +for h in holders: + if h["owner"] == "UNKNOWN": + continue + bal = rpc_call("getBalance", [h["owner"]]) + time.sleep(RPC_DELAY) + if bal and "value" in bal: + h["sol_balance"] = lamports_to_sol(bal["value"]) + +# Print holder table +print("\n" + "=" * 100) +print(" TOP 20 HOLDERS SNAPSHOT") +print("=" * 100) +print(f" {'#':<4} {'Wallet':<46} {'Tokens':>16} {'% Top20':>8} {'SOL':>10}") +print(" " + "-" * 96) +for h in holders: + pct = (h["token_balance"] / total_top20_supply * 100) if total_top20_supply > 0 else 0 + h["pct_top20"] = pct + wallet_display = h["owner"] if h["owner"] != "UNKNOWN" else "UNKNOWN" + print(f" {h['rank']:<4} {wallet_display:<46} {h['token_balance']:>16,.0f} {pct:>7.2f}% {h['sol_balance']:>9.3f}") + +print(f"\n Total top-20 supply: {total_top20_supply:,.0f} tokens") + +# ═══════════════════════════════════════════════════════════════ +# PART 2: Sniper / Bot Detection +# ═══════════════════════════════════════════════════════════════ +print("\n" + "=" * 100) +print(" [PART 2] SNIPER / BOT DETECTION") +print("=" * 100) + +holder_signatures = {} # owner -> list of sig info + +for h in holders: + owner = h["owner"] + if owner == "UNKNOWN": + continue + + print(f"\n Scanning wallet {h['rank']}: {owner[:8]}...{owner[-6:]}") + + # Get last 100 signatures + sigs = rpc_call("getSignaturesForAddress", [owner, {"limit": 100}]) + time.sleep(RPC_DELAY) + + if not sigs: + print(f" No signatures found") + continue + + h["tx_count_100"] = len(sigs) + holder_signatures[owner] = sigs + + # Find earliest tx involving this mint + # We check blockTime of all transactions and look for ones involving the mint + # To find mint-related txs, we need to check a few transactions + earliest_mint_time = None + checked = 0 + + # Sort sigs by blockTime ascending (oldest first) to find earliest + sorted_sigs = sorted(sigs, key=lambda s: s.get("blockTime") or float("inf")) + + for sig_info in sorted_sigs[:30]: # Check oldest 30 txs + sig = sig_info["signature"] + block_time = sig_info.get("blockTime") + if not block_time: + continue + + # Only check txs that happened within a reasonable window after token creation + if block_time > TOKEN_CREATION_TIME + 86400 * 7: # Within 7 days of creation + # Get the transaction to check if it involves our mint + tx = rpc_call("getTransaction", [sig, {"encoding": "jsonParsed", "maxSupportedTransactionVersion": 0}]) + time.sleep(RPC_DELAY) + checked += 1 + + if tx and tx.get("transaction"): + tx_json = json.dumps(tx) + if MINT in tx_json or MINT[:20] in tx_json: + if earliest_mint_time is None or block_time < earliest_mint_time: + earliest_mint_time = block_time + break # Found the earliest, stop + + if checked >= 8: # Limit how many full txs we fetch per wallet + break + + if earliest_mint_time: + delay = earliest_mint_time - TOKEN_CREATION_TIME + h["earliest_mint_tx_time"] = earliest_mint_time + h["buy_delay_seconds"] = delay + delay_str = f"{delay}s" if delay < 3600 else f"{delay/3600:.1f}h" + print(f" First mint tx: {delay_str} after creation (blockTime: {earliest_mint_time})") + + if delay <= 60: + h["flags"].append("SNIPER (<=60s)") + print(f" *** SNIPER DETECTED *** Bought within {delay}s of creation!") + elif delay <= 300: + h["flags"].append("EARLY_BOT (<=5min)") + print(f" ** EARLY BOT ** Bought within {delay}s of creation") + else: + print(f" Could not determine first mint transaction in sampled txs") + + # Check for dust wallet + if h["sol_balance"] < 0.01 and h["token_balance"] > 0: + h["flags"].append("DUST_WALLET") + print(f" DUST wallet: only {h['sol_balance']:.4f} SOL") + + # Check for high tx frequency (bot indicator) + if len(sigs) >= 100: + # Check time span of 100 txs + times = [s.get("blockTime") for s in sigs if s.get("blockTime")] + if len(times) >= 2: + span = max(times) - min(times) + if span > 0: + tx_per_hour = len(times) / (span / 3600) + if tx_per_hour > 20: + h["flags"].append(f"HIGH_FREQ ({tx_per_hour:.0f} tx/hr)") + print(f" High frequency: {tx_per_hour:.1f} tx/hr over {span/3600:.1f}h") + +# ═══════════════════════════════════════════════════════════════ +# PART 3: Cluster / Bundle Detection +# ═══════════════════════════════════════════════════════════════ +print("\n" + "=" * 100) +print(" [PART 3] CLUSTER / BUNDLE DETECTION") +print("=" * 100) + +owner_set = set(h["owner"] for h in holders if h["owner"] != "UNKNOWN") +holder_counterparties = defaultdict(lambda: defaultdict(int)) # owner -> {counterparty -> count} +holder_tx_accounts = defaultdict(set) # owner -> set of all account keys they interacted with + +for h in holders: + owner = h["owner"] + if owner == "UNKNOWN": + continue + + sigs = holder_signatures.get(owner, []) + if not sigs: + continue + + print(f"\n Analyzing tx graph for holder {h['rank']}: {owner[:8]}...{owner[-6:]}") + + # Get last 20 transactions detail + tx_checked = 0 + for sig_info in sigs[:20]: + sig = sig_info["signature"] + tx = rpc_call("getTransaction", [sig, {"encoding": "jsonParsed", "maxSupportedTransactionVersion": 0}]) + time.sleep(RPC_DELAY) + tx_checked += 1 + + if not tx or not tx.get("transaction"): + continue + + # Extract all account keys from the transaction + msg = tx["transaction"].get("message", {}) + account_keys = [] + + # Handle both legacy and versioned transaction formats + if "accountKeys" in msg: + for ak in msg["accountKeys"]: + if isinstance(ak, dict): + account_keys.append(ak.get("pubkey", "")) + else: + account_keys.append(ak) + + # Track all counterparties (excluding self and known programs) + known_programs = { + "11111111111111111111111111111111", # System Program + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", # Token Program + "ComputeBudget111111111111111111111111111111", + "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", # ATA Program + "SysvarRent111111111111111111111111111111111", + "Sysvar1nstructions1111111111111111111111111", + "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", + } + + for key in account_keys: + if key and key != owner and key not in known_programs and len(key) > 30: + holder_tx_accounts[owner].add(key) + holder_counterparties[owner][key] += 1 + + print(f" Checked {tx_checked} txs, found {len(holder_tx_accounts[owner])} unique counterparties") + +# Find shared counterparties between holders +print("\n Checking for shared counterparties between top holders...") +clusters = [] +cluster_connections = defaultdict(list) + +holder_list = [h for h in holders if h["owner"] != "UNKNOWN"] + +for i in range(len(holder_list)): + for j in range(i + 1, len(holder_list)): + o1 = holder_list[i]["owner"] + o2 = holder_list[j]["owner"] + shared = holder_tx_accounts[o1] & holder_tx_accounts[o2] + + # Remove the token's own accounts and other holders from shared + shared -= owner_set + # Remove the mint itself + shared.discard(MINT) + + # Filter to only meaningful shared accounts (appeared 2+ times with either) + meaningful_shared = set() + for s in shared: + if holder_counterparties[o1][s] >= 1 and holder_counterparties[o2][s] >= 1: + meaningful_shared.add(s) + + if len(meaningful_shared) >= 3: # 3+ shared counterparties = suspicious + cluster_connections[o1].append((o2, len(meaningful_shared))) + cluster_connections[o2].append((o1, len(meaningful_shared))) + print(f" CLUSTER SIGNAL: Holder {holder_list[i]['rank']} & Holder {holder_list[j]['rank']} share {len(meaningful_shared)} counterparties") + + # Check if they directly transacted + if o2 in holder_tx_accounts[o1] or o1 in holder_tx_accounts[o2]: + holder_list[i]["flags"].append(f"DIRECT_LINK->#{holder_list[j]['rank']}") + holder_list[j]["flags"].append(f"DIRECT_LINK->#{holder_list[i]['rank']}") + print(f" *** DIRECT TRANSACTION between these holders! ***") + +# Check for direct links between holders +print("\n Checking for direct SOL transfers between holders...") +for i in range(len(holder_list)): + for j in range(i + 1, len(holder_list)): + o1 = holder_list[i]["owner"] + o2 = holder_list[j]["owner"] + if o2 in holder_tx_accounts[o1]: + if not any(f"DIRECT_LINK->#{holder_list[j]['rank']}" in f for f in holder_list[i]["flags"]): + holder_list[i]["flags"].append(f"DIRECT_LINK->#{holder_list[j]['rank']}") + holder_list[j]["flags"].append(f"DIRECT_LINK->#{holder_list[i]['rank']}") + print(f" DIRECT LINK: Holder {holder_list[i]['rank']} <-> Holder {holder_list[j]['rank']}") + +# Build final clusters using union-find +def find_clusters(connections, all_owners): + parent = {o: o for o in all_owners} + def find(x): + while parent[x] != x: + parent[x] = parent[parent[x]] + x = parent[x] + return x + def union(a, b): + ra, rb = find(a), find(b) + if ra != rb: + parent[ra] = rb + + for o, conns in connections.items(): + for (o2, count) in conns: + if count >= 3: + union(o, o2) + + groups = defaultdict(list) + for o in all_owners: + r = find(o) + groups[r].append(o) + + return {k: v for k, v in groups.items() if len(v) > 1} + +detected_clusters = find_clusters(cluster_connections, [h["owner"] for h in holder_list]) + +for cluster_id, (root, members) in enumerate(detected_clusters.items()): + for h in holders: + if h["owner"] in members: + h["flags"].append(f"CLUSTER_{cluster_id+1}") + +# ═══════════════════════════════════════════════════════════════ +# PART 4: Funding Source Analysis +# ═══════════════════════════════════════════════════════════════ +print("\n" + "=" * 100) +print(" [PART 4] FUNDING SOURCE ANALYSIS") +print("=" * 100) + +funding_groups = defaultdict(list) # funder -> list of holders funded + +for h in holders: + owner = h["owner"] + if owner == "UNKNOWN": + continue + + sigs = holder_signatures.get(owner, []) + if not sigs: + continue + + # Look at the oldest transactions to find funding source + sorted_sigs = sorted(sigs, key=lambda s: s.get("blockTime") or float("inf")) + + print(f"\n Checking funding for holder {h['rank']}: {owner[:8]}...{owner[-6:]}") + + # Check oldest 5 transactions for incoming SOL transfer + for sig_info in sorted_sigs[:5]: + sig = sig_info["signature"] + tx = rpc_call("getTransaction", [sig, {"encoding": "jsonParsed", "maxSupportedTransactionVersion": 0}]) + time.sleep(RPC_DELAY) + + if not tx or not tx.get("transaction"): + continue + + msg = tx["transaction"].get("message", {}) + instructions = msg.get("instructions", []) + + for instr in instructions: + if isinstance(instr, dict): + parsed = instr.get("parsed") + if isinstance(parsed, dict): + itype = parsed.get("type", "") + info = parsed.get("info", {}) + + # Check for system transfer TO this wallet + if itype == "transfer" and info.get("destination") == owner: + source = info.get("source", "") + amount_lamports = info.get("lamports", 0) + if source and source != owner and amount_lamports > 0: + h["funding_source"] = source + funding_groups[source].append(h["rank"]) + print(f" Funded by: {source[:8]}...{source[-6:]} ({lamports_to_sol(amount_lamports):.3f} SOL)") + break + if h["funding_source"]: + break + if h["funding_source"]: + break + + if not h["funding_source"]: + print(f" Could not determine funding source from sampled txs") + +# Print funding groups +print("\n FUNDING SOURCE GROUPS:") +for funder, funded_ranks in funding_groups.items(): + if len(funded_ranks) >= 2: + print(f" *** SAME FUNDER: {funder[:8]}...{funder[-6:]} funded holders: {funded_ranks}") + for h in holders: + if h["rank"] in funded_ranks: + h["flags"].append(f"SAME_FUNDER({len(funded_ranks)} wallets)") + +# ═══════════════════════════════════════════════════════════════ +# PART 5: Health Scoring & Final Report +# ═══════════════════════════════════════════════════════════════ +print("\n" + "=" * 100) +print(" [PART 5] HOLDER HEALTH SCORING & FINAL REPORT") +print("=" * 100) + +for h in holders: + score = 0 # Start neutral + + # Positive signals + if h["sol_balance"] > 5: + score += 2 + elif h["sol_balance"] > 1: + score += 1 + + if h["buy_delay_seconds"] is not None and h["buy_delay_seconds"] > 300: + score += 2 # Bought after 5 min + elif h["buy_delay_seconds"] is not None and h["buy_delay_seconds"] > 60: + score += 1 + + # Negative signals + if any("SNIPER" in f for f in h["flags"]): + score -= 4 + if any("EARLY_BOT" in f for f in h["flags"]): + score -= 2 + if any("DUST_WALLET" in f for f in h["flags"]): + score -= 2 + if any("CLUSTER" in f for f in h["flags"]): + score -= 3 + if any("DIRECT_LINK" in f for f in h["flags"]): + score -= 2 + if any("SAME_FUNDER" in f for f in h["flags"]): + score -= 3 + if any("HIGH_FREQ" in f for f in h["flags"]): + score -= 1 + + if h["sol_balance"] < 0.01 and h["owner"] != "UNKNOWN": + score -= 2 + + # Determine health rating + if score >= 2: + h["health"] = "HEALTHY" + elif score >= 0: + h["health"] = "NEUTRAL" + elif score >= -2: + h["health"] = "SUSPICIOUS" + else: + h["health"] = "UNHEALTHY" + + h["health_score"] = score + +# ─────────── FINAL TABLE ─────────── +print("\n" + "=" * 120) +print(" COMPLETE HOLDER ANALYSIS TABLE") +print("=" * 120) +print(f" {'#':<3} {'Wallet':<46} {'Tokens':>14} {'%':>6} {'SOL':>8} {'Buy Delay':>10} {'Health':>11} {'Flags'}") +print(" " + "-" * 116) + +sniper_count = 0 +sniper_supply = 0 +early_bot_count = 0 +unhealthy_count = 0 +suspicious_count = 0 + +for h in holders: + delay_str = "?" + if h["buy_delay_seconds"] is not None: + d = h["buy_delay_seconds"] + if d < 60: + delay_str = f"{d}s" + elif d < 3600: + delay_str = f"{d//60}m{d%60}s" + else: + delay_str = f"{d/3600:.1f}h" + + health_icon = { + "HEALTHY": "[OK]", + "NEUTRAL": "[--]", + "SUSPICIOUS": "[??]", + "UNHEALTHY": "[!!]" + }.get(h["health"], "[??]") + + flags_str = ", ".join(h["flags"]) if h["flags"] else "-" + wallet_short = h["owner"][:20] + "..." + h["owner"][-6:] if len(h["owner"]) > 30 else h["owner"] + + print(f" {h['rank']:<3} {h['owner']:<46} {h['token_balance']:>14,.0f} {h['pct_top20']:>5.1f}% {h['sol_balance']:>7.3f} {delay_str:>10} {health_icon} {h['health']:<11} {flags_str}") + + if any("SNIPER" in f for f in h["flags"]): + sniper_count += 1 + sniper_supply += h["token_balance"] + if any("EARLY_BOT" in f for f in h["flags"]): + early_bot_count += 1 + if h["health"] == "UNHEALTHY": + unhealthy_count += 1 + if h["health"] == "SUSPICIOUS": + suspicious_count += 1 + +# ─────────── DETECTED CLUSTERS ─────────── +print("\n" + "=" * 100) +print(" DETECTED CLUSTERS") +print("=" * 100) + +if detected_clusters: + for cluster_id, (root, members) in enumerate(detected_clusters.items()): + print(f"\n CLUSTER {cluster_id + 1}:") + cluster_supply = 0 + for h in holders: + if h["owner"] in members: + print(f" - Holder #{h['rank']}: {h['owner'][:20]}...{h['owner'][-6:]} ({h['token_balance']:,.0f} tokens, {h['pct_top20']:.1f}%)") + cluster_supply += h["token_balance"] + pct = (cluster_supply / total_top20_supply * 100) if total_top20_supply > 0 else 0 + print(f" Combined supply: {cluster_supply:,.0f} tokens ({pct:.1f}% of top-20)") +else: + print(" No clusters detected from counterparty analysis (threshold: 3+ shared counterparties)") + +# Check for same-funder clusters +same_funder_clusters = {f: ranks for f, ranks in funding_groups.items() if len(ranks) >= 2} +if same_funder_clusters: + print("\n SAME-FUNDER CLUSTERS:") + for funder, ranks in same_funder_clusters.items(): + funder_supply = sum(h["token_balance"] for h in holders if h["rank"] in ranks) + pct = (funder_supply / total_top20_supply * 100) if total_top20_supply > 0 else 0 + print(f" Funder: {funder}") + for h in holders: + if h["rank"] in ranks: + print(f" - Holder #{h['rank']}: {h['owner'][:20]}...{h['owner'][-6:]} ({h['token_balance']:,.0f} tokens)") + print(f" Combined: {funder_supply:,.0f} tokens ({pct:.1f}% of top-20)") + +# ─────────── SUMMARY ─────────── +print("\n" + "=" * 100) +print(" FINAL SUMMARY") +print("=" * 100) + +sniper_pct = (sniper_supply / total_top20_supply * 100) if total_top20_supply > 0 else 0 + +print(f""" + Snipers (<=60s): {sniper_count} holders, {sniper_supply:,.0f} tokens ({sniper_pct:.1f}% of top-20) + Early Bots (<=5min): {early_bot_count} holders + Clusters detected: {len(detected_clusters)} counterparty clusters, {len(same_funder_clusters)} same-funder clusters + + Health Distribution: + HEALTHY: {sum(1 for h in holders if h['health'] == 'HEALTHY')}/20 + NEUTRAL: {sum(1 for h in holders if h['health'] == 'NEUTRAL')}/20 + SUSPICIOUS: {suspicious_count}/20 + UNHEALTHY: {unhealthy_count}/20 +""") + +# Overall token health +total_unhealthy_supply = sum(h["token_balance"] for h in holders if h["health"] in ("UNHEALTHY", "SUSPICIOUS")) +unhealthy_pct = (total_unhealthy_supply / total_top20_supply * 100) if total_top20_supply > 0 else 0 + +if unhealthy_pct > 50: + overall = "CRITICAL - Majority of top supply is unhealthy" +elif unhealthy_pct > 30: + overall = "POOR - Significant unhealthy concentration" +elif unhealthy_pct > 15: + overall = "MODERATE - Some concerning holders" +elif unhealthy_count <= 2 and sniper_count <= 1: + overall = "GOOD - Mostly organic holder base" +else: + overall = "FAIR - Mixed signals" + +print(f" OVERALL TOKEN HEALTH: {overall}") +print(f" Unhealthy+Suspicious supply: {total_unhealthy_supply:,.0f} tokens ({unhealthy_pct:.1f}% of top-20)") + +# Red flags +print("\n RED FLAGS:") +red_flags = [] +if sniper_count >= 3: + red_flags.append(f" - {sniper_count} snipers in top 20 (coordinated sniping likely)") +if sniper_pct > 20: + red_flags.append(f" - Snipers hold {sniper_pct:.1f}% of top-20 supply") +if len(detected_clusters) > 0: + red_flags.append(f" - {len(detected_clusters)} wallet cluster(s) detected (possible bundling/coordination)") +if len(same_funder_clusters) > 0: + for funder, ranks in same_funder_clusters.items(): + red_flags.append(f" - {len(ranks)} wallets funded by same source {funder[:12]}... (likely same entity)") +dust_wallets = sum(1 for h in holders if any("DUST" in f for f in h["flags"])) +if dust_wallets >= 3: + red_flags.append(f" - {dust_wallets} dust wallets in top 20 (value extraction pattern)") +direct_links = sum(1 for h in holders if any("DIRECT_LINK" in f for f in h["flags"])) +if direct_links > 0: + red_flags.append(f" - {direct_links} holders with direct transaction links to other holders") +top1_pct = holders[0]["pct_top20"] if holders else 0 +if top1_pct > 30: + red_flags.append(f" - Top holder controls {top1_pct:.1f}% of top-20 supply (concentration risk)") + +if red_flags: + for rf in red_flags: + print(rf) +else: + print(" No major red flags detected.") + +print("\n" + "=" * 100) +print(" Analysis complete.") +print("=" * 100) diff --git a/jester_3h_analysis.py b/jester_3h_analysis.py new file mode 100644 index 0000000..b1473ce --- /dev/null +++ b/jester_3h_analysis.py @@ -0,0 +1,562 @@ +#!/usr/bin/env python3 +"""JESTER — Full 3-hour on-chain analysis: holders, buys, sells, accumulators, whales.""" + +import json, time, urllib.request, os, sys +from collections import defaultdict +from datetime import datetime, timezone + +# ── Config ────────────────────────────────────────────────────────────── +RPC = "" +try: + with open("/home/user/Cute-Panel/.env") as f: + for line in f: + line = line.strip() + if line.startswith("HELIUS_RPC_URL="): + RPC = line.split("=", 1)[1].strip().strip('"').strip("'") +except: + pass + +if not RPC: + print("FATAL: No HELIUS_RPC_URL"); sys.exit(1) + +MINT = "6WdHhpRY7vL8SQ69bd89tAj3sk8jsjBrCLDUTZSNpump" +DELAY = 0.35 +THREE_HOURS = 10800 +NOW = int(time.time()) +CUTOFF = NOW - THREE_HOURS + +print("=" * 80) +print(" JESTER ($JESTER) — FULL 3-HOUR ON-CHAIN ANALYSIS") +print("=" * 80) +print(f" Mint: {MINT}") +print(f" Now: {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M:%S UTC')}") +print(f" Window: Last 3 hours (since {datetime.fromtimestamp(CUTOFF, tz=timezone.utc).strftime('%H:%M:%S UTC')})") +print("=" * 80) +print() + +# ── RPC helper ────────────────────────────────────────────────────────── +call_count = 0 + +def rpc(method, params): + global call_count + call_count += 1 + body = json.dumps({"jsonrpc": "2.0", "id": call_count, "method": method, "params": params}).encode() + req = urllib.request.Request(RPC, data=body, headers={"Content-Type": "application/json"}) + for attempt in range(3): + try: + with urllib.request.urlopen(req, timeout=30) as resp: + data = json.loads(resp.read()) + if "error" in data: + print(f" [RPC ERR] {method}: {data['error']}") + return None + return data.get("result") + except Exception as e: + if attempt < 2: + time.sleep(1) + else: + print(f" [RPC FAIL] {method}: {e}") + return None + return None + +def short(addr): + if not addr or len(addr) < 10: return str(addr) + return addr[:4] + "..." + addr[-4:] + +# ══════════════════════════════════════════════════════════════════════════ +# PART 1: TOP 20 HOLDERS — CURRENT SNAPSHOT +# ══════════════════════════════════════════════════════════════════════════ +print("[PART 1] Fetching top 20 holders...") +t0 = time.time() + +res = rpc("getTokenLargestAccounts", [MINT]) +time.sleep(DELAY) + +if not res or "value" not in res: + print("FATAL: Could not fetch largest accounts"); sys.exit(1) + +largest = res["value"][:20] +holders = [] + +for i, acct in enumerate(largest): + token_account = acct["address"] + raw_amount = int(acct["amount"]) + decimals = acct["decimals"] + balance = raw_amount / (10 ** decimals) + + info = rpc("getAccountInfo", [token_account, {"encoding": "jsonParsed"}]) + time.sleep(DELAY) + + owner = "unknown" + if info and info.get("value") and info["value"].get("data"): + try: + owner = info["value"]["data"]["parsed"]["info"]["owner"] + except (KeyError, TypeError): + pass + + sol_bal = 0.0 + if owner != "unknown": + bal = rpc("getBalance", [owner]) + time.sleep(DELAY) + if bal and "value" in bal: + sol_bal = bal["value"] / 1e9 + + holders.append({ + "rank": i + 1, "wallet": owner, "token_account": token_account, + "jester": balance, "sol": sol_bal, + }) + +t1 = time.time() +print(f" Done in {t1 - t0:.1f}s\n") + +# Print holder table +KNOWN_PROGRAMS = { + "5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1": "RAYDIUM", + "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8": "RAYDIUM_V4", + "39azUYFWPz3VHgKCf3VChUwbpURdCHRxjWVowf5jUJjg": "ORCA", +} + +print("=" * 80) +print(" TOP 20 JESTER HOLDERS") +print("=" * 80) +print(f"{'#':>3} | {'Wallet':>44} | {'JESTER':>18} | {'SOL':>10} | Tag") +print("-" * 92) + +for h in holders: + w = h["wallet"] + tag = KNOWN_PROGRAMS.get(w, "") + if not tag and h["sol"] > 50: + tag = "WHALE" + elif not tag and h["sol"] < 0.5 and w != "unknown": + tag = "DUST" + print(f"{h['rank']:>3} | {w:>44} | {h['jester']:>18,.2f} | {h['sol']:>10.4f} | {tag}") + +print() + +# ══════════════════════════════════════════════════════════════════════════ +# PART 2: MINT SIGNATURES — LAST 3 HOURS +# ══════════════════════════════════════════════════════════════════════════ +print("[PART 2] Fetching mint signatures (last 3h)...") +t2 = time.time() + +# Fetch up to 200 signatures in batches +all_sigs = [] +last_sig = None +for batch in range(2): # 2 batches of 100 = 200 max + params = {"limit": 100} + if last_sig: + params["before"] = last_sig + sigs = rpc("getSignaturesForAddress", [MINT, params]) + time.sleep(DELAY) + if not sigs: + break + all_sigs.extend(sigs) + # Check if we've gone past our 3h window + oldest_in_batch = min(s.get("blockTime", NOW) for s in sigs) + if oldest_in_batch < CUTOFF: + break + last_sig = sigs[-1]["signature"] + if len(sigs) < 100: + break + +# Filter to 3h window +recent_sigs = [s for s in all_sigs if s.get("blockTime") and s["blockTime"] > CUTOFF and not s.get("err")] +total_fetched = len(all_sigs) +recent_count = len(recent_sigs) + +print(f" Total fetched: {total_fetched}") +print(f" In 3h window: {recent_count}") +if recent_sigs: + oldest_ts = min(s["blockTime"] for s in recent_sigs) + newest_ts = max(s["blockTime"] for s in recent_sigs) + print(f" Time range: {datetime.fromtimestamp(oldest_ts, tz=timezone.utc).strftime('%H:%M:%S')} — {datetime.fromtimestamp(newest_ts, tz=timezone.utc).strftime('%H:%M:%S')} UTC") +print() + +# ══════════════════════════════════════════════════════════════════════════ +# PART 3: PARSE ALL RECENT TRADES +# ══════════════════════════════════════════════════════════════════════════ +print(f"[PART 3] Parsing {recent_count} transactions...") +t3 = time.time() + +trades = [] +known_wallets = set(h["wallet"] for h in holders if h["wallet"] != "unknown") +all_active_wallets = set() + +for idx, sig_info in enumerate(recent_sigs): + sig = sig_info["signature"] + block_time = sig_info["blockTime"] + ts_str = datetime.fromtimestamp(block_time, tz=timezone.utc).strftime('%H:%M:%S') + + tx = rpc("getTransaction", [sig, {"encoding": "jsonParsed", "maxSupportedTransactionVersion": 0}]) + time.sleep(DELAY) + + if not tx or not tx.get("meta"): + continue + + meta = tx["meta"] + + # Account keys for SOL balance + account_keys = [] + try: + msg = tx["transaction"]["message"] + if "accountKeys" in msg: + account_keys = [k if isinstance(k, str) else k.get("pubkey", "") for k in msg["accountKeys"]] + loaded = meta.get("loadedAddresses", {}) + if loaded: + account_keys += loaded.get("writable", []) + loaded.get("readonly", []) + except (KeyError, TypeError): + pass + + # Pre/post JESTER balances + pre_jester = {} + post_jester = {} + for b in (meta.get("preTokenBalances") or []): + if b.get("mint") == MINT and b.get("owner"): + try: + pre_jester[b["owner"]] = float(b["uiTokenAmount"]["uiAmount"] or 0) + except (KeyError, TypeError): + pre_jester[b["owner"]] = 0 + for b in (meta.get("postTokenBalances") or []): + if b.get("mint") == MINT and b.get("owner"): + try: + post_jester[b["owner"]] = float(b["uiTokenAmount"]["uiAmount"] or 0) + except (KeyError, TypeError): + post_jester[b["owner"]] = 0 + + all_owners = set(list(pre_jester.keys()) + list(post_jester.keys())) + + for owner in all_owners: + pre_val = pre_jester.get(owner, 0) + post_val = post_jester.get(owner, 0) + delta = post_val - pre_val + + if abs(delta) < 1: + continue + + all_active_wallets.add(owner) + + # SOL delta + sol_delta = 0.0 + if owner in account_keys: + aidx = account_keys.index(owner) + pre_bals = meta.get("preBalances") or [] + post_bals = meta.get("postBalances") or [] + if aidx < len(pre_bals) and aidx < len(post_bals): + sol_delta = (post_bals[aidx] - pre_bals[aidx]) / 1e9 + + trade_type = "BUY" if delta > 0 else "SELL" + trades.append({ + "wallet": owner, "type": trade_type, + "jester": abs(delta), "sol": abs(sol_delta), "sol_delta": sol_delta, + "timestamp": block_time, "time_str": ts_str, + "sig": sig[:20] + "...", "is_top20": owner in known_wallets, + "mins_ago": (NOW - block_time) / 60, + }) + + if (idx + 1) % 20 == 0: + print(f" Parsed {idx + 1}/{recent_count}...") + +t4 = time.time() +trades.sort(key=lambda t: t["timestamp"], reverse=True) +buys = [t for t in trades if t["type"] == "BUY"] +sells = [t for t in trades if t["type"] == "SELL"] +print(f" Done in {t4 - t3:.1f}s — {len(trades)} trades ({len(buys)} buys, {len(sells)} sells)\n") + +# ══════════════════════════════════════════════════════════════════════════ +# PART 4: LARGE TRADES (>500K JESTER) +# ══════════════════════════════════════════════════════════════════════════ +print("=" * 80) +print(" LARGE TRADES (>500K JESTER) — LAST 3 HOURS") +print("=" * 80) + +large_trades = [t for t in trades if t["jester"] > 500_000] +if large_trades: + print(f"\n {'Time':>8} | {'Wallet':>12} | {'Type':>4} | {'JESTER':>18} | {'SOL':>10} | {'Ago':>6} | Top20") + print(" " + "-" * 78) + for t in large_trades: + tag = "YES" if t["is_top20"] else "no" + print(f" {t['time_str']:>8} | {short(t['wallet']):>12} | {t['type']:>4} | {t['jester']:>18,.0f} | {t['sol']:>10.4f} | {t['mins_ago']:>5.0f}m | {tag:>5}") +else: + print("\n No large trades (>500K JESTER) in last 3 hours.") + +# ══════════════════════════════════════════════════════════════════════════ +# PART 5: NET BUY/SELL PRESSURE +# ══════════════════════════════════════════════════════════════════════════ +print() +print("=" * 80) +print(" NET BUY/SELL PRESSURE — LAST 3 HOURS") +print("=" * 80) + +total_bought = sum(t["jester"] for t in buys) +total_sold = sum(t["jester"] for t in sells) +total_sol_in = sum(t["sol"] for t in buys) +total_sol_out = sum(t["sol"] for t in sells) +num_buyers = len(set(t["wallet"] for t in buys)) +num_sellers = len(set(t["wallet"] for t in sells)) + +print(f"\n Total JESTER bought: {total_bought:>20,.0f} ({len(buys)} txs, {num_buyers} wallets)") +print(f" Total JESTER sold: {total_sold:>20,.0f} ({len(sells)} txs, {num_sellers} wallets)") +print(f" Net JESTER flow: {total_bought - total_sold:>+20,.0f}") +print(f" SOL spent buying: {total_sol_in:>20.4f}") +print(f" SOL received selling: {total_sol_out:>20.4f}") +print(f" Net SOL flow: {total_sol_in - total_sol_out:>+20.4f}") + +if total_bought > total_sold * 1.5: + verdict = "STRONG BUY PRESSURE" +elif total_bought > total_sold: + verdict = "MILD BUY PRESSURE" +elif total_sold > total_bought * 1.5: + verdict = "STRONG SELL PRESSURE" +elif total_sold > total_bought: + verdict = "MILD SELL PRESSURE" +else: + verdict = "NEUTRAL" +print(f"\n >>> VERDICT: {verdict} <<<") + +# ══════════════════════════════════════════════════════════════════════════ +# PART 6: WHALE WATCH (Top 5 Holders) +# ══════════════════════════════════════════════════════════════════════════ +print() +print("=" * 80) +print(" WHALE WATCH — TOP 5 HOLDERS ACTIVITY") +print("=" * 80) + +whale_moved = False +for h in holders[:5]: + w = h["wallet"] + whale_trades = [t for t in trades if t["wallet"] == w] + if whale_trades: + whale_moved = True + wb = sum(t["jester"] for t in whale_trades if t["type"] == "BUY") + ws = sum(t["jester"] for t in whale_trades if t["type"] == "SELL") + print(f"\n WHALE #{h['rank']} {short(w)} (holds {h['jester']:,.0f} JESTER, {h['sol']:.2f} SOL)") + print(f" Bought: {wb:,.0f} | Sold: {ws:,.0f} | Txs: {len(whale_trades)}") + for t in whale_trades[:5]: + print(f" -> {t['time_str']} {t['type']} {t['jester']:,.0f} JESTER ({t['sol']:.4f} SOL) [{t['mins_ago']:.0f}m ago]") + else: + print(f"\n Whale #{h['rank']} {short(w)} — IDLE (holds {h['jester']:,.0f} JESTER, {h['sol']:.2f} SOL)") + +if not whale_moved: + print("\n No whale (top 5) movement in last 3 hours.") + +# ══════════════════════════════════════════════════════════════════════════ +# PART 7: ACCUMULATORS & DUMPERS +# ══════════════════════════════════════════════════════════════════════════ +print() +print("=" * 80) +print(" ACCUMULATORS & DUMPERS — NET POSITION CHANGES (3H)") +print("=" * 80) + +wallet_net = defaultdict(lambda: {"bought": 0, "sold": 0, "buys": 0, "sells": 0, "sol_spent": 0, "sol_got": 0}) +for t in trades: + w = t["wallet"] + if t["type"] == "BUY": + wallet_net[w]["bought"] += t["jester"] + wallet_net[w]["buys"] += 1 + wallet_net[w]["sol_spent"] += t["sol"] + else: + wallet_net[w]["sold"] += t["jester"] + wallet_net[w]["sells"] += 1 + wallet_net[w]["sol_got"] += t["sol"] + +# Net accumulators +accumulators = [] +dumpers = [] +for w, data in wallet_net.items(): + net = data["bought"] - data["sold"] + data["net"] = net + data["wallet"] = w + data["is_top20"] = w in known_wallets + if net > 10_000: + accumulators.append(data) + elif net < -10_000: + dumpers.append(data) + +accumulators.sort(key=lambda x: x["net"], reverse=True) +dumpers.sort(key=lambda x: x["net"]) + +print(f"\n TOP ACCUMULATORS (net bought >10K JESTER):") +if accumulators: + print(f" {'Wallet':>12} | {'Net JESTER':>18} | {'Buys':>5} | {'Sells':>5} | {'SOL Spent':>10} | Top20") + print(" " + "-" * 72) + for d in accumulators[:15]: + tag = "YES" if d["is_top20"] else "no" + print(f" {short(d['wallet']):>12} | {d['net']:>+18,.0f} | {d['buys']:>5} | {d['sells']:>5} | {d['sol_spent']:>10.4f} | {tag:>5}") + # Print full wallet address for notable ones + if d["net"] > 500_000: + print(f" ^ Full: {d['wallet']}") +else: + print(" None") + +print(f"\n TOP DUMPERS (net sold >10K JESTER):") +if dumpers: + print(f" {'Wallet':>12} | {'Net JESTER':>18} | {'Buys':>5} | {'Sells':>5} | {'SOL Got':>10} | Top20") + print(" " + "-" * 72) + for d in dumpers[:15]: + tag = "YES" if d["is_top20"] else "no" + print(f" {short(d['wallet']):>12} | {d['net']:>+18,.0f} | {d['buys']:>5} | {d['sells']:>5} | {d['sol_got']:>10.4f} | {tag:>5}") + if abs(d["net"]) > 500_000: + print(f" ^ Full: {d['wallet']}") +else: + print(" None") + +# ══════════════════════════════════════════════════════════════════════════ +# PART 8: NEW WALLETS (not in top 20) with significant activity +# ══════════════════════════════════════════════════════════════════════════ +print() +print("=" * 80) +print(" NEW/NOTABLE WALLETS (NOT IN TOP 20)") +print("=" * 80) + +new_significant = [(w, d) for w, d in wallet_net.items() if w not in known_wallets and (d["bought"] > 100_000 or d["sold"] > 100_000)] +new_significant.sort(key=lambda x: x[1]["bought"] + x[1]["sold"], reverse=True) + +if new_significant: + print(f"\n {len(new_significant)} non-top-20 wallets with >100K JESTER activity:") + for w, d in new_significant[:15]: + net_str = f"+{d['net']:,.0f}" if d['net'] > 0 else f"{d['net']:,.0f}" + action = "ACCUMULATING" if d['net'] > 0 else "DUMPING" + print(f" {short(w):>12} | Bought: {d['bought']:>12,.0f} | Sold: {d['sold']:>12,.0f} | Net: {net_str:>14} | {action}") + print(f" Full: {w}") +else: + print("\n No new wallets with significant activity (>100K JESTER).") + +# ══════════════════════════════════════════════════════════════════════════ +# PART 9: HOURLY BREAKDOWN +# ══════════════════════════════════════════════════════════════════════════ +print() +print("=" * 80) +print(" HOURLY BREAKDOWN") +print("=" * 80) + +# Split into 3 one-hour buckets +hour_buckets = {0: {"buys": 0, "sells": 0, "vol_buy": 0, "vol_sell": 0, "label": "0-1h ago"}, + 1: {"buys": 0, "sells": 0, "vol_buy": 0, "vol_sell": 0, "label": "1-2h ago"}, + 2: {"buys": 0, "sells": 0, "vol_buy": 0, "vol_sell": 0, "label": "2-3h ago"}} + +for t in trades: + bucket = min(int(t["mins_ago"] / 60), 2) + if t["type"] == "BUY": + hour_buckets[bucket]["buys"] += 1 + hour_buckets[bucket]["vol_buy"] += t["jester"] + else: + hour_buckets[bucket]["sells"] += 1 + hour_buckets[bucket]["vol_sell"] += t["jester"] + +print(f"\n {'Period':>10} | {'Buys':>5} | {'Sells':>5} | {'JESTER Bought':>18} | {'JESTER Sold':>18} | Net") +print(" " + "-" * 85) +for b_idx in [2, 1, 0]: + b = hour_buckets[b_idx] + net = b["vol_buy"] - b["vol_sell"] + net_str = f"+{net:,.0f}" if net > 0 else f"{net:,.0f}" + print(f" {b['label']:>10} | {b['buys']:>5} | {b['sells']:>5} | {b['vol_buy']:>18,.0f} | {b['vol_sell']:>18,.0f} | {net_str:>14}") + +# ══════════════════════════════════════════════════════════════════════════ +# PART 10: ALPHA WALLET CHECK +# ══════════════════════════════════════════════════════════════════════════ +print() +print("=" * 80) +print(" ALPHA WALLET CHECK") +print("=" * 80) + +try: + with open("/home/user/Cute-Panel/memory/smart_wallets.json") as f: + sw = json.load(f) + alpha_wallets = [] + for w in sw.get("wallets", []): + if w.get("chain") == "solana" and w.get("address", "unknown") != "unknown": + alpha_wallets.append({"address": w["address"], "label": w.get("label", "")}) + + if alpha_wallets: + print(f"\n Checking {len(alpha_wallets)} alpha wallets for JESTER activity...") + alpha_in_trades = set() + for aw in alpha_wallets: + addr = aw["address"] + if addr in wallet_net: + d = wallet_net[addr] + alpha_in_trades.add(addr) + net_str = f"+{d['net']:,.0f}" if d['net'] > 0 else f"{d['net']:,.0f}" + print(f"\n *** ALPHA WALLET ACTIVE: {aw['label']}") + print(f" Wallet: {addr}") + print(f" Bought: {d['bought']:,.0f} | Sold: {d['sold']:,.0f} | Net: {net_str}") + + # Check if any alpha wallets are in top 20 + alpha_addrs = {aw["address"] for aw in alpha_wallets} + alpha_in_top20 = alpha_addrs & known_wallets + for addr in alpha_in_top20: + lbl = next((aw["label"] for aw in alpha_wallets if aw["address"] == addr), "") + h = next((h for h in holders if h["wallet"] == addr), None) + if h: + print(f"\n *** ALPHA IN TOP 20: #{h['rank']} {lbl}") + print(f" Wallet: {addr}") + print(f" Holds: {h['jester']:,.0f} JESTER | SOL: {h['sol']:.4f}") + + if not alpha_in_trades and not alpha_in_top20: + print("\n No alpha wallets active in JESTER (last 3h).") + # Still check holdings + print(" Checking holdings...") + for aw in alpha_wallets[:10]: # limit to 10 checks + result = rpc("getTokenAccountsByOwner", [ + aw["address"], {"mint": MINT}, {"encoding": "jsonParsed"} + ]) + time.sleep(DELAY) + if result and result.get("value"): + for acc in result["value"]: + try: + ui = float(acc["account"]["data"]["parsed"]["info"]["tokenAmount"]["uiAmount"] or 0) + if ui > 0: + print(f" HOLDS: {aw['label']} ({short(aw['address'])}) — {ui:,.0f} JESTER") + except: + pass + else: + print("\n No alpha wallets loaded.") +except Exception as e: + print(f"\n [SKIP] Could not load alpha wallets: {e}") + +# ══════════════════════════════════════════════════════════════════════════ +# EXECUTIVE SUMMARY +# ══════════════════════════════════════════════════════════════════════════ +print() +print("=" * 80) +print(" EXECUTIVE SUMMARY") +print("=" * 80) + +print(f""" + Token: JESTER ($JESTER) + Mint: {MINT} + + MARKET DATA (DexScreener): + MC ~$447K | Liq ~$69K | Price $0.000448 + 24h: +138% | 6h: +113% | 1h: -13% + 1h txns: 105 buys / 50 sells + + ON-CHAIN (Last 3 Hours): + Transactions parsed: {len(recent_sigs)} + Trades identified: {len(trades)} ({len(buys)} buys, {len(sells)} sells) + Unique wallets: {len(all_active_wallets)} + + VOLUME: + JESTER bought: {total_bought:>15,.0f} + JESTER sold: {total_sold:>15,.0f} + Net flow: {total_bought - total_sold:>+15,.0f} + + PRESSURE: {verdict} + + KEY ACTORS: + Accumulators: {len(accumulators)} wallets (net >10K JESTER) + Dumpers: {len(dumpers)} wallets (net >10K JESTER sold) + + WHALE STATUS:""") + +for h in holders[:5]: + w = h["wallet"] + wt = [t for t in trades if t["wallet"] == w] + status = "IDLE" if not wt else f"{sum(1 for t in wt if t['type']=='BUY')}B/{sum(1 for t in wt if t['type']=='SELL')}S" + print(f" #{h['rank']} {short(w)} | {h['jester']:>12,.0f} JESTER | {h['sol']:.2f} SOL | {status}") + +print(f""" + ANALYSIS: + Total RPC calls: {call_count} + Runtime: {time.time() - t0:.1f}s + Timestamp: {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M:%S UTC')} +""") +print("=" * 80) diff --git a/jester_3h_full.py b/jester_3h_full.py new file mode 100644 index 0000000..93ed22a --- /dev/null +++ b/jester_3h_full.py @@ -0,0 +1,623 @@ +#!/usr/bin/env python3 +"""JESTER — FULL 3-hour analysis. Paginates ALL signatures, samples trades per hour.""" + +import json, time, urllib.request, os, sys +from collections import defaultdict +from datetime import datetime, timezone + +# ── Config ────────────────────────────────────────────────────────────── +RPC = "" +try: + with open("/home/user/Cute-Panel/.env") as f: + for line in f: + line = line.strip() + if line.startswith("HELIUS_RPC_URL="): + RPC = line.split("=", 1)[1].strip().strip('"').strip("'") +except: + pass + +if not RPC: + print("FATAL: No HELIUS_RPC_URL"); sys.exit(1) + +MINT = "6WdHhpRY7vL8SQ69bd89tAj3sk8jsjBrCLDUTZSNpump" +DELAY = 0.3 +THREE_HOURS = 10800 +NOW = int(time.time()) +CUTOFF = NOW - THREE_HOURS + +print("=" * 80) +print(" JESTER ($JESTER) — FULL 3-HOUR ON-CHAIN ANALYSIS") +print("=" * 80) +print(f" Mint: {MINT}") +print(f" Now: {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M:%S UTC')}") +print(f" Cutoff: {datetime.fromtimestamp(CUTOFF, tz=timezone.utc).strftime('%H:%M:%S UTC')} (3h ago)") +print("=" * 80) +print() + +# ── RPC helper ────────────────────────────────────────────────────────── +call_count = 0 + +def rpc(method, params): + global call_count + call_count += 1 + body = json.dumps({"jsonrpc": "2.0", "id": call_count, "method": method, "params": params}).encode() + req = urllib.request.Request(RPC, data=body, headers={"Content-Type": "application/json"}) + for attempt in range(3): + try: + with urllib.request.urlopen(req, timeout=30) as resp: + data = json.loads(resp.read()) + if "error" in data: + print(f" [RPC ERR] {method}: {data['error']}") + return None + return data.get("result") + except Exception as e: + if attempt < 2: + time.sleep(1) + else: + print(f" [RPC FAIL] {method}: {e}") + return None + return None + +def short(addr): + if not addr or len(addr) < 10: return str(addr) + return addr[:4] + "..." + addr[-4:] + +# ══════════════════════════════════════════════════════════════════════════ +# PHASE 1: TOP 30 HOLDERS SNAPSHOT +# ══════════════════════════════════════════════════════════════════════════ +print("[PHASE 1] Top 20 holders snapshot...") +t0 = time.time() + +res = rpc("getTokenLargestAccounts", [MINT]) +time.sleep(DELAY) + +if not res or "value" not in res: + print("FATAL: Could not fetch largest accounts"); sys.exit(1) + +largest = res["value"][:30] +holders = [] + +for i, acct in enumerate(largest): + token_account = acct["address"] + raw_amount = int(acct["amount"]) + decimals = acct["decimals"] + balance = raw_amount / (10 ** decimals) + + info = rpc("getAccountInfo", [token_account, {"encoding": "jsonParsed"}]) + time.sleep(DELAY) + + owner = "unknown" + if info and info.get("value") and info["value"].get("data"): + try: + owner = info["value"]["data"]["parsed"]["info"]["owner"] + except (KeyError, TypeError): + pass + + sol_bal = 0.0 + if owner != "unknown": + bal = rpc("getBalance", [owner]) + time.sleep(DELAY) + if bal and "value" in bal: + sol_bal = bal["value"] / 1e9 + + holders.append({ + "rank": i + 1, "wallet": owner, "token_account": token_account, + "jester": balance, "sol": sol_bal, + }) + +known_wallets = set(h["wallet"] for h in holders if h["wallet"] != "unknown") + +print(f" Resolved {len(holders)} holders in {time.time()-t0:.0f}s\n") + +# Print table +print("=" * 80) +print(" TOP 30 JESTER HOLDERS") +print("=" * 80) +print(f"{'#':>3} | {'Wallet':>44} | {'JESTER':>16} | {'SOL':>10} | Tag") +print("-" * 90) +for h in holders: + w = h["wallet"] + tag = "" + if w == "2Aj1MJG6GLWfU8YEyyTcGsehxDo3MboVAx3XNLeEsDG2": + tag = "POOL" + elif h["sol"] > 50: + tag = "WHALE" + elif h["sol"] < 0.5 and w != "unknown": + tag = "dust" + print(f"{h['rank']:>3} | {w:>44} | {h['jester']:>16,.0f} | {h['sol']:>10.4f} | {tag}") +print() + +# ══════════════════════════════════════════════════════════════════════════ +# PHASE 2: PAGINATE ALL MINT SIGNATURES (full 3h) +# ══════════════════════════════════════════════════════════════════════════ +print("[PHASE 2] Paginating ALL mint signatures for 3-hour window...") +t1 = time.time() + +all_sigs = [] +last_sig = None +batch_num = 0 +reached_cutoff = False + +while not reached_cutoff: + batch_num += 1 + params = {"limit": 1000} + if last_sig: + params["before"] = last_sig + + sigs = rpc("getSignaturesForAddress", [MINT, params]) + time.sleep(DELAY) + + if not sigs or len(sigs) == 0: + print(f" Batch {batch_num}: no more signatures") + break + + all_sigs.extend(sigs) + last_sig = sigs[-1]["signature"] + + # Check oldest timestamp in this batch + oldest_in_batch = min(s.get("blockTime", NOW) for s in sigs if s.get("blockTime")) + newest_in_batch = max(s.get("blockTime", 0) for s in sigs if s.get("blockTime")) + + oldest_str = datetime.fromtimestamp(oldest_in_batch, tz=timezone.utc).strftime('%H:%M:%S') + newest_str = datetime.fromtimestamp(newest_in_batch, tz=timezone.utc).strftime('%H:%M:%S') + print(f" Batch {batch_num}: +{len(sigs)} sigs (total: {len(all_sigs)}) | range: {oldest_str}-{newest_str} UTC") + + if oldest_in_batch <= CUTOFF: + reached_cutoff = True + + if len(sigs) < 1000: + break + + # Safety: cap at 5000 sigs total + if len(all_sigs) >= 5000: + print(f" Safety cap reached (5000 sigs)") + break + +# Filter to 3h window, remove errored +recent_sigs = [s for s in all_sigs if s.get("blockTime") and s["blockTime"] > CUTOFF and not s.get("err")] +failed_sigs = [s for s in all_sigs if s.get("blockTime") and s["blockTime"] > CUTOFF and s.get("err")] + +print(f"\n Total fetched: {len(all_sigs)}") +print(f" In 3h window: {len(recent_sigs)} successful + {len(failed_sigs)} failed") + +if recent_sigs: + oldest_ts = min(s["blockTime"] for s in recent_sigs) + newest_ts = max(s["blockTime"] for s in recent_sigs) + span_min = (newest_ts - oldest_ts) / 60 + print(f" Time span: {datetime.fromtimestamp(oldest_ts, tz=timezone.utc).strftime('%H:%M:%S')} — {datetime.fromtimestamp(newest_ts, tz=timezone.utc).strftime('%H:%M:%S')} UTC ({span_min:.0f} min)") + +print(f" Fetch time: {time.time()-t1:.0f}s") +print() + +# ══════════════════════════════════════════════════════════════════════════ +# PHASE 3: HOURLY STATS (from signature metadata — no parsing needed) +# ══════════════════════════════════════════════════════════════════════════ +print("=" * 80) +print(" HOURLY TRANSACTION COUNTS (from signature metadata)") +print("=" * 80) + +hour_buckets = defaultdict(lambda: {"count": 0, "failed": 0}) + +for s in all_sigs: + bt = s.get("blockTime", 0) + if bt <= CUTOFF: + continue + mins_ago = (NOW - bt) / 60 + bucket = min(int(mins_ago / 60), 2) + hour_buckets[bucket]["count"] += 1 + if s.get("err"): + hour_buckets[bucket]["failed"] += 1 + +print(f"\n {'Period':>10} | {'Total Txs':>10} | {'Failed':>7} | {'Success':>8} | Txs/min") +print(" " + "-" * 60) +for b_idx in [2, 1, 0]: + b = hour_buckets[b_idx] + label = f"{b_idx*60}-{(b_idx+1)*60}m ago" + success = b["count"] - b["failed"] + tpm = success / 60 if success > 0 else 0 + print(f" {label:>10} | {b['count']:>10} | {b['failed']:>7} | {success:>8} | {tpm:>6.1f}") + +total_3h = sum(b["count"] for b in hour_buckets.values()) +total_success = sum(b["count"] - b["failed"] for b in hour_buckets.values()) +print(f" {'TOTAL 3H':>10} | {total_3h:>10} | {sum(b['failed'] for b in hour_buckets.values()):>7} | {total_success:>8} | {total_success/180:.1f}") +print() + +# ══════════════════════════════════════════════════════════════════════════ +# PHASE 4: SAMPLE-PARSE TRADES (30 per hour = 90 max) +# ══════════════════════════════════════════════════════════════════════════ +# Group sigs by hour bucket +sigs_by_hour = defaultdict(list) +for s in recent_sigs: + bt = s["blockTime"] + mins_ago = (NOW - bt) / 60 + bucket = min(int(mins_ago / 60), 2) + sigs_by_hour[bucket].append(s) + +SAMPLES_PER_HOUR = 40 # parse 40 from each hour + +print(f"[PHASE 4] Sample-parsing trades ({SAMPLES_PER_HOUR}/hour)...") +t2 = time.time() + +trades = [] +all_active_wallets = set() + +for hour_idx in [0, 1, 2]: + bucket_sigs = sigs_by_hour.get(hour_idx, []) + if not bucket_sigs: + print(f" Hour {hour_idx} (={hour_idx*60}-{(hour_idx+1)*60}m ago): 0 sigs, skip") + continue + + # Even sample across the hour + sample_count = min(SAMPLES_PER_HOUR, len(bucket_sigs)) + step = max(1, len(bucket_sigs) // sample_count) + sampled = bucket_sigs[::step][:sample_count] + + print(f" Hour {hour_idx} (={hour_idx*60}-{(hour_idx+1)*60}m ago): {len(bucket_sigs)} sigs, parsing {len(sampled)} samples...") + + for sig_info in sampled: + sig = sig_info["signature"] + block_time = sig_info["blockTime"] + ts_str = datetime.fromtimestamp(block_time, tz=timezone.utc).strftime('%H:%M:%S') + + tx = rpc("getTransaction", [sig, {"encoding": "jsonParsed", "maxSupportedTransactionVersion": 0}]) + time.sleep(DELAY) + + if not tx or not tx.get("meta"): + continue + + meta = tx["meta"] + + # Account keys + account_keys = [] + try: + msg = tx["transaction"]["message"] + if "accountKeys" in msg: + account_keys = [k if isinstance(k, str) else k.get("pubkey", "") for k in msg["accountKeys"]] + loaded = meta.get("loadedAddresses", {}) + if loaded: + account_keys += loaded.get("writable", []) + loaded.get("readonly", []) + except (KeyError, TypeError): + pass + + # Pre/post JESTER balances + pre_j = {} + post_j = {} + for b in (meta.get("preTokenBalances") or []): + if b.get("mint") == MINT and b.get("owner"): + try: pre_j[b["owner"]] = float(b["uiTokenAmount"]["uiAmount"] or 0) + except: pre_j[b["owner"]] = 0 + for b in (meta.get("postTokenBalances") or []): + if b.get("mint") == MINT and b.get("owner"): + try: post_j[b["owner"]] = float(b["uiTokenAmount"]["uiAmount"] or 0) + except: post_j[b["owner"]] = 0 + + for owner in set(list(pre_j.keys()) + list(post_j.keys())): + pre_val = pre_j.get(owner, 0) + post_val = post_j.get(owner, 0) + delta = post_val - pre_val + if abs(delta) < 1: + continue + + all_active_wallets.add(owner) + + sol_delta = 0.0 + if owner in account_keys: + aidx = account_keys.index(owner) + pre_b = meta.get("preBalances") or [] + post_b = meta.get("postBalances") or [] + if aidx < len(pre_b) and aidx < len(post_b): + sol_delta = (post_b[aidx] - pre_b[aidx]) / 1e9 + + trades.append({ + "wallet": owner, "type": "BUY" if delta > 0 else "SELL", + "jester": abs(delta), "sol": abs(sol_delta), "sol_delta": sol_delta, + "timestamp": block_time, "time_str": ts_str, + "sig": sig[:16] + "...", "is_top30": owner in known_wallets, + "mins_ago": (NOW - block_time) / 60, "hour_bucket": hour_idx, + }) + +trades.sort(key=lambda t: t["timestamp"], reverse=True) +buys = [t for t in trades if t["type"] == "BUY"] +sells = [t for t in trades if t["type"] == "SELL"] +print(f"\n Parsed {len(trades)} trades ({len(buys)} buys, {len(sells)} sells) in {time.time()-t2:.0f}s\n") + +# ══════════════════════════════════════════════════════════════════════════ +# PHASE 5: HOURLY BUY/SELL BREAKDOWN +# ══════════════════════════════════════════════════════════════════════════ +print("=" * 80) +print(" HOURLY BUY/SELL BREAKDOWN (sampled)") +print("=" * 80) + +# We need to scale the sampled data to estimate full volume +print(f"\n {'Period':>10} | {'Buys':>5} | {'Sells':>5} | {'JESTER Bought':>18} | {'JESTER Sold':>18} | {'SOL In':>10} | {'SOL Out':>10}") +print(" " + "-" * 100) + +for b_idx in [2, 1, 0]: + label = f"{b_idx*60}-{(b_idx+1)*60}m ago" + b_trades = [t for t in trades if t["hour_bucket"] == b_idx] + b_buys = [t for t in b_trades if t["type"] == "BUY"] + b_sells = [t for t in b_trades if t["type"] == "SELL"] + b_bought = sum(t["jester"] for t in b_buys) + b_sold = sum(t["jester"] for t in b_sells) + b_sol_in = sum(t["sol"] for t in b_buys) + b_sol_out = sum(t["sol"] for t in b_sells) + + # Scale factor: total sigs in hour / sampled count + total_in_hour = len(sigs_by_hour.get(b_idx, [])) + sampled_in_hour = len(set(t["sig"] for t in b_trades)) # unique txs parsed + scale = total_in_hour / sampled_in_hour if sampled_in_hour > 0 else 1 + + print(f" {label:>10} | {len(b_buys):>5} | {len(b_sells):>5} | {b_bought:>18,.0f} | {b_sold:>18,.0f} | {b_sol_in:>10.2f} | {b_sol_out:>10.2f}") + if scale > 1.5: + print(f" {'':>10} (sampled {sampled_in_hour}/{total_in_hour} txs, ~{scale:.1f}x scale for estimates)") + +# Totals +total_bought = sum(t["jester"] for t in buys) +total_sold = sum(t["jester"] for t in sells) +total_sol_in = sum(t["sol"] for t in buys) +total_sol_out = sum(t["sol"] for t in sells) + +print(f"\n SAMPLED TOTALS:") +print(f" JESTER bought: {total_bought:>18,.0f} ({len(buys)} txs)") +print(f" JESTER sold: {total_sold:>18,.0f} ({len(sells)} txs)") +print(f" Net flow: {total_bought - total_sold:>+18,.0f}") +print(f" SOL in: {total_sol_in:>18.4f}") +print(f" SOL out: {total_sol_out:>18.4f}") +print(f" Net SOL: {total_sol_in - total_sol_out:>+18.4f}") + +# Extrapolate to full 3h +total_sampled_txs = len(set(t["sig"] for t in trades)) +total_3h_txs = len(recent_sigs) +ext_scale = total_3h_txs / total_sampled_txs if total_sampled_txs > 0 else 1 + +print(f"\n ESTIMATED FULL 3H (extrapolated x{ext_scale:.1f}):") +print(f" JESTER bought: {total_bought * ext_scale:>18,.0f}") +print(f" JESTER sold: {total_sold * ext_scale:>18,.0f}") +print(f" SOL in: {total_sol_in * ext_scale:>18.2f}") +print(f" SOL out: {total_sol_out * ext_scale:>18.2f}") + +if total_sol_out > total_sol_in * 1.2: + verdict = "SELL PRESSURE (more SOL extracted)" +elif total_sol_in > total_sol_out * 1.2: + verdict = "BUY PRESSURE (more SOL deposited)" +elif total_bought > total_sold * 1.1: + verdict = "MILD BUY PRESSURE" +elif total_sold > total_bought * 1.1: + verdict = "MILD SELL PRESSURE" +else: + verdict = "BALANCED / NEUTRAL" +print(f"\n >>> VERDICT: {verdict} <<<") +print() + +# ══════════════════════════════════════════════════════════════════════════ +# PHASE 6: LARGE TRADES (>500K JESTER) +# ══════════════════════════════════════════════════════════════════════════ +print("=" * 80) +print(" LARGE TRADES (>500K JESTER) — from sampled data") +print("=" * 80) + +large = [t for t in trades if t["jester"] > 500_000] +if large: + print(f"\n {'Time':>8} | {'Wallet':>12} | {'Type':>4} | {'JESTER':>16} | {'SOL':>10} | {'Ago':>6} | Top30") + print(" " + "-" * 75) + for t in sorted(large, key=lambda x: x["jester"], reverse=True): + tag = "YES" if t["is_top30"] else "no" + print(f" {t['time_str']:>8} | {short(t['wallet']):>12} | {t['type']:>4} | {t['jester']:>16,.0f} | {t['sol']:>10.4f} | {t['mins_ago']:>5.0f}m | {tag:>5}") +else: + print("\n None found in sampled transactions.") +print() + +# ══════════════════════════════════════════════════════════════════════════ +# PHASE 7: WHALE WATCH (top 5) +# ══════════════════════════════════════════════════════════════════════════ +print("=" * 80) +print(" WHALE WATCH — TOP 5 HOLDERS") +print("=" * 80) + +for h in holders[:5]: + w = h["wallet"] + wt = [t for t in trades if t["wallet"] == w] + if wt: + wb = sum(t["jester"] for t in wt if t["type"] == "BUY") + ws = sum(t["jester"] for t in wt if t["type"] == "SELL") + print(f"\n #{h['rank']} {short(w)} (holds {h['jester']:,.0f} JESTER, {h['sol']:.2f} SOL)") + print(f" Bought: {wb:,.0f} | Sold: {ws:,.0f} | Txs: {len(wt)}") + for t in wt[:8]: + print(f" -> {t['time_str']} {t['type']} {t['jester']:,.0f} ({t['sol']:.4f} SOL) [{t['mins_ago']:.0f}m ago]") + else: + print(f"\n #{h['rank']} {short(w)} — IDLE (holds {h['jester']:,.0f} JESTER, {h['sol']:.2f} SOL)") +print() + +# ══════════════════════════════════════════════════════════════════════════ +# PHASE 8: TOP 20 HOLDER ACTIVITY (check each wallet's last 3h sigs) +# ══════════════════════════════════════════════════════════════════════════ +print("=" * 80) +print(" TOP 30 HOLDER — INDIVIDUAL 3H ACTIVITY CHECK") +print("=" * 80) +print(" (Checking each holder's recent signatures directly...)\n") + +holder_activity = {} + +for h in holders: + w = h["wallet"] + if w == "unknown" or w == "2Aj1MJG6GLWfU8YEyyTcGsehxDo3MboVAx3XNLeEsDG2": + holder_activity[w] = {"jester_buys": 0, "jester_sells": 0, "total_txs_3h": 0, "other_active": False} + continue + + sigs_res = rpc("getSignaturesForAddress", [w, {"limit": 30}]) + time.sleep(DELAY) + + if not sigs_res: + holder_activity[w] = {"jester_buys": 0, "jester_sells": 0, "total_txs_3h": 0, "other_active": False} + continue + + recent = [s for s in sigs_res if s.get("blockTime") and s["blockTime"] > CUTOFF and not s.get("err")] + activity = {"jester_buys": 0, "jester_sells": 0, "total_txs_3h": len(recent), "other_active": False, "details": []} + + # Parse up to 10 recent txs to check for JESTER activity + for sig_info in recent[:10]: + sig = sig_info["signature"] + tx = rpc("getTransaction", [sig, {"encoding": "jsonParsed", "maxSupportedTransactionVersion": 0}]) + time.sleep(DELAY) + if not tx or not tx.get("meta"): + continue + meta = tx["meta"] + + pre_amt = 0 + post_amt = 0 + found = False + for b in (meta.get("preTokenBalances") or []): + if b.get("mint") == MINT and b.get("owner") == w: + try: pre_amt = float(b["uiTokenAmount"]["uiAmount"] or 0) + except: pass + found = True + for b in (meta.get("postTokenBalances") or []): + if b.get("mint") == MINT and b.get("owner") == w: + try: post_amt = float(b["uiTokenAmount"]["uiAmount"] or 0) + except: pass + found = True + + if found: + delta = post_amt - pre_amt + if delta > 100: + activity["jester_buys"] += 1 + activity["details"].append(f"BUY +{delta:,.0f}") + elif delta < -100: + activity["jester_sells"] += 1 + activity["details"].append(f"SELL {delta:,.0f}") + else: + # Active on other tokens + activity["other_active"] = True + + holder_activity[w] = activity + + status_parts = [] + if activity["jester_buys"]: status_parts.append(f"{activity['jester_buys']}B") + if activity["jester_sells"]: status_parts.append(f"{activity['jester_sells']}S") + if activity["other_active"] and not status_parts: status_parts.append("OTHER") + status = "/".join(status_parts) if status_parts else "IDLE" + + if activity["total_txs_3h"] > 0: + print(f" #{h['rank']:>2} {short(w):>12} | {h['jester']:>14,.0f} JESTER | {h['sol']:>8.2f} SOL | {activity['total_txs_3h']} txs | {status}") + for d in activity["details"][:3]: + print(f" -> {d}") + else: + print(f" #{h['rank']:>2} {short(w):>12} | {h['jester']:>14,.0f} JESTER | {h['sol']:>8.2f} SOL | IDLE") + +print() + +# ══════════════════════════════════════════════════════════════════════════ +# PHASE 9: ACCUMULATORS & DUMPERS +# ══════════════════════════════════════════════════════════════════════════ +print("=" * 80) +print(" ACCUMULATORS & DUMPERS (from sampled trades)") +print("=" * 80) + +wallet_net = defaultdict(lambda: {"bought": 0, "sold": 0, "buys": 0, "sells": 0, "sol_spent": 0, "sol_got": 0}) +for t in trades: + if t["wallet"] == "2Aj1MJG6GLWfU8YEyyTcGsehxDo3MboVAx3XNLeEsDG2": + continue # skip pool + w = t["wallet"] + if t["type"] == "BUY": + wallet_net[w]["bought"] += t["jester"] + wallet_net[w]["buys"] += 1 + wallet_net[w]["sol_spent"] += t["sol"] + else: + wallet_net[w]["sold"] += t["jester"] + wallet_net[w]["sells"] += 1 + wallet_net[w]["sol_got"] += t["sol"] + +accumulators = [] +dumpers = [] +for w, d in wallet_net.items(): + d["net"] = d["bought"] - d["sold"] + d["wallet"] = w + d["is_top30"] = w in known_wallets + if d["net"] > 10_000: + accumulators.append(d) + elif d["net"] < -10_000: + dumpers.append(d) + +accumulators.sort(key=lambda x: x["net"], reverse=True) +dumpers.sort(key=lambda x: x["net"]) + +print(f"\n TOP ACCUMULATORS (net >10K JESTER):") +if accumulators: + for d in accumulators[:15]: + tag = " [TOP30]" if d["is_top30"] else "" + print(f" {short(d['wallet']):>12}{tag} | net +{d['net']:>12,.0f} | {d['buys']}B/{d['sells']}S | {d['sol_spent']:.2f} SOL spent") + if d["net"] > 200_000: + print(f" Full: {d['wallet']}") +else: + print(" None") + +print(f"\n TOP DUMPERS (net <-10K JESTER):") +if dumpers: + for d in dumpers[:15]: + tag = " [TOP30]" if d["is_top30"] else "" + print(f" {short(d['wallet']):>12}{tag} | net {d['net']:>12,.0f} | {d['buys']}B/{d['sells']}S | {d['sol_got']:.2f} SOL received") + if abs(d["net"]) > 200_000: + print(f" Full: {d['wallet']}") +else: + print(" None") + +print() + +# ══════════════════════════════════════════════════════════════════════════ +# EXECUTIVE SUMMARY +# ══════════════════════════════════════════════════════════════════════════ +print("=" * 80) +print(" EXECUTIVE SUMMARY — JESTER 3-HOUR ANALYSIS") +print("=" * 80) + +# Count holder statuses +idle_count = sum(1 for w, a in holder_activity.items() if a["total_txs_3h"] == 0 and w != "unknown") +buying_count = sum(1 for a in holder_activity.values() if a["jester_buys"] > 0) +selling_count = sum(1 for a in holder_activity.values() if a["jester_sells"] > 0) + +print(f""" + Token: JESTER ($JESTER) + Window: Full 3 hours ({datetime.fromtimestamp(CUTOFF, tz=timezone.utc).strftime('%H:%M')} — {datetime.now(timezone.utc).strftime('%H:%M')} UTC) + + TRANSACTION VOLUME (full 3h, from signature pagination): + Total mint txs: {len(recent_sigs):,} + Failed txs: {len(failed_sigs):,} + Avg txs/min: {len(recent_sigs)/180:.1f} + + TRADE ANALYSIS (from {len(set(t['sig'] for t in trades))} sampled txs → {len(trades)} trades): + Buys: {len(buys)} ({total_bought:,.0f} JESTER, {total_sol_in:.2f} SOL) + Sells: {len(sells)} ({total_sold:,.0f} JESTER, {total_sol_out:.2f} SOL) + Net: {total_bought - total_sold:+,.0f} JESTER / {total_sol_in - total_sol_out:+.2f} SOL + + PRESSURE: {verdict} + + TOP 30 HOLDERS (3h activity): + IDLE: {idle_count} + BUYING JESTER: {buying_count} + SELLING JESTER: {selling_count} + + ACCUMULATORS: {len(accumulators)} wallets + DUMPERS: {len(dumpers)} wallets + + WHALE STATUS (top 5):""") +for h in holders[:5]: + w = h["wallet"] + a = holder_activity.get(w, {}) + if w == "2Aj1MJG6GLWfU8YEyyTcGsehxDo3MboVAx3XNLeEsDG2": + status = "POOL (AMM)" + elif a.get("total_txs_3h", 0) > 0: + parts = [] + if a.get("jester_buys"): parts.append(f"{a['jester_buys']}B") + if a.get("jester_sells"): parts.append(f"{a['jester_sells']}S") + if a.get("other_active") and not parts: parts.append("OTHER TOKENS") + status = "/".join(parts) if parts else f"ACTIVE ({a['total_txs_3h']} txs)" + else: + status = "IDLE" + print(f" #{h['rank']} {short(w)} | {h['jester']:>12,.0f} | {h['sol']:.2f} SOL | {status}") + +print(f""" + RPC calls: {call_count} + Runtime: {time.time()-t0:.0f}s + Timestamp: {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M:%S UTC')} +""") +print("=" * 80) diff --git a/jester_analysis.py b/jester_analysis.py new file mode 100644 index 0000000..bbb75df --- /dev/null +++ b/jester_analysis.py @@ -0,0 +1,428 @@ +#!/usr/bin/env python3 +"""JESTER token on-chain analysis — last 2 hours of activity.""" + +import json, time, urllib.request, os, sys +from collections import defaultdict +from datetime import datetime, timezone + +# ── Config ────────────────────────────────────────────────────────────────── +RPC = os.getenv("HELIUS_RPC_URL", "").strip() +if not RPC: + # Manual load .env + try: + with open("/home/user/Cute-Panel/.env") as f: + for line in f: + line = line.strip() + if line.startswith("HELIUS_RPC_URL="): + RPC = line.split("=", 1)[1].strip().strip('"').strip("'") + except: + pass + +MINT = "6WdHhpRY7vL8SQ69bd89tAj3sk8jsjBrCLDUTZSNpump" +DELAY = 0.5 +TWO_HOURS = 7200 +NOW = int(time.time()) +CUTOFF = NOW - TWO_HOURS + +print(f"=== JESTER ON-CHAIN ANALYSIS ===") +print(f"Mint: {MINT}") +print(f"Time: {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M:%S UTC')}") +print(f"Cutoff: {datetime.fromtimestamp(CUTOFF, tz=timezone.utc).strftime('%Y-%m-%d %H:%M:%S UTC')} (2h ago)") +print(f"RPC: {RPC[:50]}...") +print() + +# ── RPC helper ────────────────────────────────────────────────────────────── +call_count = 0 + +def rpc(method, params): + global call_count + call_count += 1 + body = json.dumps({"jsonrpc": "2.0", "id": call_count, "method": method, "params": params}).encode() + req = urllib.request.Request(RPC, data=body, headers={"Content-Type": "application/json"}) + for attempt in range(3): + try: + with urllib.request.urlopen(req, timeout=30) as resp: + data = json.loads(resp.read()) + if "error" in data: + print(f" RPC error ({method}): {data['error']}") + return None + return data.get("result") + except Exception as e: + if attempt < 2: + time.sleep(1) + else: + print(f" RPC fail ({method}): {e}") + return None + return None + +def short(addr): + return addr[:4] + "..." + addr[-4:] if addr and len(addr) > 10 else str(addr) + +# ══════════════════════════════════════════════════════════════════════════════ +# PART 1: Current holder snapshot +# ══════════════════════════════════════════════════════════════════════════════ +print("=" * 70) +print("PART 1: TOP 20 HOLDERS — CURRENT SNAPSHOT") +print("=" * 70) + +res = rpc("getTokenLargestAccounts", [MINT]) +time.sleep(DELAY) + +if not res or "value" not in res: + print("FATAL: Could not get largest accounts") + sys.exit(1) + +largest = res["value"][:20] +print(f"Got {len(largest)} largest token accounts\n") + +holders = [] # list of dicts + +for i, acct in enumerate(largest): + token_account = acct["address"] + raw_amount = int(acct["amount"]) + decimals = acct["decimals"] + balance = raw_amount / (10 ** decimals) + + # Resolve owner + info = rpc("getAccountInfo", [token_account, {"encoding": "jsonParsed"}]) + time.sleep(DELAY) + + owner = "unknown" + if info and info.get("value") and info["value"].get("data"): + try: + parsed = info["value"]["data"]["parsed"]["info"] + owner = parsed.get("owner", "unknown") + except (KeyError, TypeError): + pass + + # Get SOL balance + sol_bal = 0.0 + if owner != "unknown": + bal = rpc("getBalance", [owner]) + time.sleep(DELAY) + if bal and "value" in bal: + sol_bal = bal["value"] / 1e9 + + holders.append({ + "rank": i + 1, + "wallet": owner, + "token_account": token_account, + "jester_balance": balance, + "sol_balance": sol_bal, + }) + print(f" [{i+1:2d}] {short(owner):12s} JESTER: {balance:>18,.2f} SOL: {sol_bal:>10.4f}") + +print() + +# ══════════════════════════════════════════════════════════════════════════════ +# PART 2: Recent activity per holder (last 2 hours) +# ══════════════════════════════════════════════════════════════════════════════ +print("=" * 70) +print("PART 2: HOLDER ACTIVITY — LAST 2 HOURS") +print("=" * 70) + +holder_activity = {} + +for h in holders: + wallet = h["wallet"] + if wallet == "unknown": + continue + + sigs_res = rpc("getSignaturesForAddress", [wallet, {"limit": 50}]) + time.sleep(DELAY) + + if not sigs_res: + holder_activity[wallet] = {"buys": 0, "sells": 0, "sol_delta": 0, "other_tokens": set(), "tx_count": 0, "details": []} + continue + + recent_sigs = [s for s in sigs_res if s.get("blockTime") and s["blockTime"] > CUTOFF and not s.get("err")] + activity = {"buys": 0, "sells": 0, "sol_delta": 0.0, "other_tokens": set(), "tx_count": len(recent_sigs), "details": []} + + for sig_info in recent_sigs: + sig = sig_info["signature"] + tx = rpc("getTransaction", [sig, {"encoding": "jsonParsed", "maxSupportedTransactionVersion": 0}]) + time.sleep(DELAY) + + if not tx: + continue + + meta = tx.get("meta") + if not meta: + continue + + # Check pre/post token balances for JESTER + pre_balances = {b.get("owner", ""): b for b in (meta.get("preTokenBalances") or []) if b.get("mint") == MINT} + post_balances = {b.get("owner", ""): b for b in (meta.get("postTokenBalances") or []) if b.get("mint") == MINT} + + pre_amt = 0 + post_amt = 0 + if wallet in pre_balances: + try: + pre_amt = float(pre_balances[wallet]["uiTokenAmount"]["uiAmount"] or 0) + except (KeyError, TypeError): + pass + if wallet in post_balances: + try: + post_amt = float(post_balances[wallet]["uiTokenAmount"]["uiAmount"] or 0) + except (KeyError, TypeError): + pass + + jester_delta = post_amt - pre_amt + if jester_delta > 0: + activity["buys"] += 1 + activity["details"].append(f"BUY +{jester_delta:,.0f} JESTER") + elif jester_delta < 0: + activity["sells"] += 1 + activity["details"].append(f"SELL {jester_delta:,.0f} JESTER") + + # SOL delta + account_keys = [] + try: + msg = tx["transaction"]["message"] + if "accountKeys" in msg: + account_keys = [k if isinstance(k, str) else k.get("pubkey", "") for k in msg["accountKeys"]] + except (KeyError, TypeError): + pass + + if wallet in account_keys: + idx = account_keys.index(wallet) + pre_sol = (meta.get("preBalances") or [])[idx] if idx < len(meta.get("preBalances") or []) else 0 + post_sol = (meta.get("postBalances") or [])[idx] if idx < len(meta.get("postBalances") or []) else 0 + sol_change = (post_sol - pre_sol) / 1e9 + activity["sol_delta"] += sol_change + + # Other tokens + all_mints = set() + for b in (meta.get("preTokenBalances") or []) + (meta.get("postTokenBalances") or []): + m = b.get("mint", "") + if m and m != MINT: + all_mints.add(m) + activity["other_tokens"].update(all_mints) + + holder_activity[wallet] = activity + if recent_sigs: + print(f" #{h['rank']:2d} {short(wallet)} — {len(recent_sigs)} recent txs, {activity['buys']} buys, {activity['sells']} sells") + +# Print activity summary +buyers = [] +sellers = [] +inactive = [] + +for h in holders: + w = h["wallet"] + if w == "unknown": + inactive.append(h) + continue + act = holder_activity.get(w, {}) + tx_count = act.get("tx_count", 0) + if act.get("buys", 0) > 0: + buyers.append((h, act)) + elif act.get("sells", 0) > 0: + sellers.append((h, act)) + elif tx_count > 0: + buyers.append((h, act)) + else: + inactive.append(h) + +print(f"\n--- BUYERS (accumulated JESTER in last 2h) ---") +if buyers: + for h, act in buyers: + print(f" #{h['rank']:2d} {short(h['wallet']):12s} | {act['buys']} buys, {act['sells']} sells | SOL delta: {act['sol_delta']:+.4f} | Txs: {act['tx_count']}") + for d in act.get("details", []): + print(f" -> {d}") +else: + print(" None") + +print(f"\n--- SELLERS (reduced JESTER in last 2h) ---") +if sellers: + for h, act in sellers: + print(f" #{h['rank']:2d} {short(h['wallet']):12s} | {act['buys']} buys, {act['sells']} sells | SOL delta: {act['sol_delta']:+.4f} | Txs: {act['tx_count']}") + for d in act.get("details", []): + print(f" -> {d}") +else: + print(" None") + +print(f"\n--- INACTIVE (no txs in last 2h) ---") +if inactive: + for h in inactive: + print(f" #{h['rank']:2d} {short(h['wallet']):12s} | JESTER: {h['jester_balance']:>15,.2f} | SOL: {h['sol_balance']:.4f}") +else: + print(" None") + +# Other tokens traded +all_other_tokens = set() +for act in holder_activity.values(): + all_other_tokens.update(act.get("other_tokens", set())) + +if all_other_tokens: + print(f"\n--- OTHER TOKENS TOUCHED BY ACTIVE HOLDERS ({len(all_other_tokens)} tokens) ---") + for mint in sorted(all_other_tokens): + wallets_touching = [short(w) for w, a in holder_activity.items() if mint in a.get("other_tokens", set())] + print(f" {short(mint)} ({mint}) — by: {', '.join(wallets_touching)}") + +print() + +# ══════════════════════════════════════════════════════════════════════════════ +# PART 3: Token-level activity (mint signatures) +# ══════════════════════════════════════════════════════════════════════════════ +print("=" * 70) +print("PART 3: JESTER MINT — LAST 2 HOURS ACTIVITY") +print("=" * 70) + +mint_sigs = rpc("getSignaturesForAddress", [MINT, {"limit": 100}]) +time.sleep(DELAY) + +if not mint_sigs: + print("No signatures found for mint") +else: + recent_mint_sigs = [s for s in mint_sigs if s.get("blockTime") and s["blockTime"] > CUTOFF and not s.get("err")] + total_mint_sigs = len(mint_sigs) + recent_count = len(recent_mint_sigs) + + print(f"Total signatures fetched: {total_mint_sigs}") + print(f"Signatures in last 2h: {recent_count}") + + if recent_mint_sigs: + oldest_recent = min(s["blockTime"] for s in recent_mint_sigs) + newest_recent = max(s["blockTime"] for s in recent_mint_sigs) + print(f"Time range: {datetime.fromtimestamp(oldest_recent, tz=timezone.utc).strftime('%H:%M:%S')} - {datetime.fromtimestamp(newest_recent, tz=timezone.utc).strftime('%H:%M:%S')} UTC") + + # Analyze a sample of recent transactions for new wallets + known_wallets = set(h["wallet"] for h in holders if h["wallet"] != "unknown") + new_wallets = set() + large_transfers = [] + unique_wallets_in_period = set() + + sample_count = min(20, recent_count) + print(f"\nAnalyzing {sample_count} of {recent_count} recent transactions...") + + for sig_info in recent_mint_sigs[:sample_count]: + sig = sig_info["signature"] + tx = rpc("getTransaction", [sig, {"encoding": "jsonParsed", "maxSupportedTransactionVersion": 0}]) + time.sleep(DELAY) + + if not tx or not tx.get("meta"): + continue + + meta = tx["meta"] + for bal_list in [meta.get("preTokenBalances") or [], meta.get("postTokenBalances") or []]: + for b in bal_list: + if b.get("mint") == MINT: + owner = b.get("owner", "") + if owner: + unique_wallets_in_period.add(owner) + if owner not in known_wallets: + new_wallets.add(owner) + + # Check for large transfers + pre_map = {} + post_map = {} + for b in (meta.get("preTokenBalances") or []): + if b.get("mint") == MINT: + try: + pre_map[b["owner"]] = float(b["uiTokenAmount"]["uiAmount"] or 0) + except (KeyError, TypeError): + pass + for b in (meta.get("postTokenBalances") or []): + if b.get("mint") == MINT: + try: + post_map[b["owner"]] = float(b["uiTokenAmount"]["uiAmount"] or 0) + except (KeyError, TypeError): + pass + + for owner in set(list(pre_map.keys()) + list(post_map.keys())): + pre_v = pre_map.get(owner, 0) + post_v = post_map.get(owner, 0) + delta = post_v - pre_v + if abs(delta) > 1_000_000: + ts = datetime.fromtimestamp(sig_info["blockTime"], tz=timezone.utc).strftime('%H:%M:%S') + large_transfers.append({ + "wallet": owner, + "delta": delta, + "time": ts, + "sig": sig[:16] + "...", + "is_known": owner in known_wallets, + }) + + print(f"\nUnique wallets active in period: {len(unique_wallets_in_period)}") + print(f"Known top-20 wallets active: {len(unique_wallets_in_period & known_wallets)}") + print(f"NEW wallets detected: {len(new_wallets)}") + + if new_wallets: + print(f"\n--- NEW WALLETS (not in top 20) ---") + for nw in sorted(new_wallets): + bal = rpc("getBalance", [nw]) + time.sleep(DELAY) + sol = bal["value"] / 1e9 if bal and "value" in bal else 0 + print(f" {short(nw)} ({nw}) SOL: {sol:.4f}") + + if large_transfers: + print(f"\n--- LARGE TRANSFERS (>1M JESTER) ---") + for lt in large_transfers: + direction = "BOUGHT" if lt["delta"] > 0 else "SOLD" + known_tag = " [TOP 20]" if lt["is_known"] else " [NEW]" + print(f" {lt['time']} | {short(lt['wallet'])}{known_tag} | {direction} {abs(lt['delta']):>15,.0f} JESTER | sig: {lt['sig']}") + else: + print("\nNo large transfers (>1M JESTER) detected in sampled transactions.") + +print() + +# ══════════════════════════════════════════════════════════════════════════════ +# PART 4: Summary report +# ══════════════════════════════════════════════════════════════════════════════ +print("=" * 70) +print("PART 4: SUMMARY REPORT") +print("=" * 70) + +print("\n--- TOP 20 HOLDERS TABLE ---") +print(f"{'Rank':>4} | {'Wallet':>12} | {'JESTER Balance':>20} | {'SOL':>10} | {'2h Activity':>15}") +print("-" * 75) +for h in holders: + w = h["wallet"] + act = holder_activity.get(w, {}) + if act.get("buys", 0) > 0 and act.get("sells", 0) > 0: + status = f"B:{act['buys']} S:{act['sells']}" + elif act.get("buys", 0) > 0: + status = f"BUYING ({act['buys']})" + elif act.get("sells", 0) > 0: + status = f"SELLING ({act['sells']})" + elif act.get("tx_count", 0) > 0: + status = f"ACTIVE ({act['tx_count']}tx)" + else: + status = "IDLE" + print(f"{h['rank']:>4} | {short(h['wallet']):>12} | {h['jester_balance']:>20,.2f} | {h['sol_balance']:>10.4f} | {status:>15}") + +# Net pressure +total_buys = sum(a.get("buys", 0) for a in holder_activity.values()) +total_sells = sum(a.get("sells", 0) for a in holder_activity.values()) +total_sol_delta = sum(a.get("sol_delta", 0) for a in holder_activity.values()) + +print(f"\n--- NET PRESSURE (Top 20 holders, last 2h) ---") +print(f" Total buy transactions: {total_buys}") +print(f" Total sell transactions: {total_sells}") +print(f" Net SOL flow: {total_sol_delta:+.4f} SOL") +if total_buys > total_sells: + print(f" VERDICT: NET BUY PRESSURE ({total_buys} buys vs {total_sells} sells)") +elif total_sells > total_buys: + print(f" VERDICT: NET SELL PRESSURE ({total_sells} sells vs {total_buys} buys)") +else: + print(f" VERDICT: NEUTRAL (equal buys and sells)") + +# Whale movements +print(f"\n--- WHALE WATCH ---") +top5 = holders[:5] +whale_moved = False +for h in top5: + w = h["wallet"] + act = holder_activity.get(w, {}) + if act.get("tx_count", 0) > 0: + whale_moved = True + print(f" WHALE #{h['rank']} {short(w)} — {act.get('buys',0)} buys, {act.get('sells',0)} sells, SOL delta: {act.get('sol_delta',0):+.4f}") + for d in act.get("details", []): + print(f" -> {d}") +if not whale_moved: + print(" No whale (top 5) movement in last 2 hours.") + +print(f"\n--- ANALYSIS COMPLETE ---") +print(f"Total RPC calls: {call_count}") +print(f"Timestamp: {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M:%S UTC')}") diff --git a/jester_bundle_analysis.py b/jester_bundle_analysis.py new file mode 100644 index 0000000..6386306 --- /dev/null +++ b/jester_bundle_analysis.py @@ -0,0 +1,416 @@ +#!/usr/bin/env python3 +""" +JESTER (Jestermaxxing) — Bundle / Cluster / Sniper / Insider Analysis +Checks top holders for: +1. SNIPERS: Bought within first minutes of launch +2. BUNDLES: Multiple wallets buying in same slot/block +3. CLUSTERS: Wallets funded by the same SOL source +4. INSIDERS: Dev-linked wallets, pre-migration holders +""" + +import json, time, sys +from urllib.request import Request, urlopen +from urllib.error import HTTPError, URLError +from collections import defaultdict +from datetime import datetime, timezone + +JESTER_MINT = "6WdHhpRY7vL8SQ69bd89tAj3sk8jsjBrCLDUTZSNpump" +RPC = "https://mainnet.helius-rpc.com/?api-key=28d0e718-6052-4054-a8c8-c38c3897ac15" +RPC_DELAY = 0.5 +TOP_N = 30 # top holders to analyze + +# Token created ~Feb 16 2025 (from DexScreener creation timestamp 1765915973) +TOKEN_CREATION_TS = 1765915973 + +def rpc_call(method, params, retries=3): + body = json.dumps({"jsonrpc":"2.0","id":1,"method":method,"params":params}).encode() + for attempt in range(retries): + try: + req = Request(RPC, data=body, headers={"Content-Type":"application/json"}) + resp = urlopen(req, timeout=30) + data = json.loads(resp.read()) + if "error" in data: + print(f" RPC error: {data['error']}") + return None + return data.get("result") + except Exception as e: + if attempt < retries - 1: + time.sleep(2 ** attempt) + else: + print(f" RPC failed after {retries} attempts: {e}") + return None + return None + +def short(addr): + return f"{addr[:8]}...{addr[-6:]}" if len(addr) > 16 else addr + +print("=" * 80) +print(" JESTER (Jestermaxxing) — BUNDLE / CLUSTER / SNIPER / INSIDER ANALYSIS") +print(f" Mint: {JESTER_MINT}") +print(f" Time: {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M UTC')}") +print("=" * 80) + +# ───────────────────────────────────────────── +# STEP 1: Get top holders via getTokenLargestAccounts +# ───────────────────────────────────────────── +print(f"\n[STEP 1] Fetching top {TOP_N} JESTER holders...") +result = rpc_call("getTokenLargestAccounts", [JESTER_MINT]) +if not result or "value" not in result: + print("FATAL: Could not fetch largest accounts") + sys.exit(1) + +accounts = result["value"][:TOP_N] +print(f" Got {len(accounts)} token accounts") + +# Resolve owner for each token account +holders = [] +for i, acc in enumerate(accounts): + token_account = acc["address"] + raw_amount = int(acc["amount"]) + decimals = acc["decimals"] + balance = raw_amount / (10 ** decimals) + + # Get account info to find owner + info = rpc_call("getAccountInfo", [token_account, {"encoding": "jsonParsed"}]) + time.sleep(RPC_DELAY) + + owner = "unknown" + if info and info.get("value"): + parsed = info["value"].get("data", {}) + if isinstance(parsed, dict) and "parsed" in parsed: + owner = parsed["parsed"].get("info", {}).get("owner", "unknown") + + holders.append({ + "rank": i + 1, + "wallet": owner, + "token_account": token_account, + "balance": balance, + "raw_amount": raw_amount, + }) + print(f" [{i+1:2d}] {short(owner):20s} | {balance:>18,.2f} JESTER") + +total_scanned = sum(h["balance"] for h in holders) +print(f"\n Total in top {len(holders)}: {total_scanned:,.2f} JESTER") + +# ───────────────────────────────────────────── +# STEP 2: For each holder, find their FIRST JESTER buy tx +# Also get SOL balance and funding source +# ───────────────────────────────────────────── +print(f"\n[STEP 2] Analyzing each holder: first buy, SOL balance, funding source...") + +for i, h in enumerate(holders): + wallet = h["wallet"] + if wallet == "unknown": + h["sol_balance"] = 0 + h["first_buy_slot"] = None + h["first_buy_time"] = None + h["funding_source"] = "unknown" + h["buy_slots"] = [] + continue + + # SOL balance + bal = rpc_call("getBalance", [wallet]) + h["sol_balance"] = (bal["value"] / 1e9) if bal and "value" in bal else 0 + time.sleep(RPC_DELAY) + + # Get recent signatures for this wallet (up to 50) + sigs_result = rpc_call("getSignaturesForAddress", [wallet, {"limit": 50}]) + time.sleep(RPC_DELAY) + + if not sigs_result: + h["first_buy_slot"] = None + h["first_buy_time"] = None + h["funding_source"] = "unknown" + h["buy_slots"] = [] + continue + + # Find JESTER-related txs by checking each + jester_slots = [] + first_jester_slot = None + first_jester_time = None + funding_source = None + + # Also get oldest sigs to find funding source + oldest_sigs = rpc_call("getSignaturesForAddress", [wallet, {"limit": 10, "before": None}]) + time.sleep(RPC_DELAY) + + # Check the token account's transaction history instead for accuracy + token_sigs = rpc_call("getSignaturesForAddress", [h["token_account"], {"limit": 20}]) + time.sleep(RPC_DELAY) + + if token_sigs: + for sig_info in token_sigs: + slot = sig_info.get("slot", 0) + bt = sig_info.get("blockTime", 0) + jester_slots.append({"slot": slot, "time": bt, "sig": sig_info["signature"]}) + + # Sort by time ascending + jester_slots.sort(key=lambda x: x["time"] if x["time"] else 0) + if jester_slots: + first_jester_slot = jester_slots[0]["slot"] + first_jester_time = jester_slots[0]["time"] + + # Try to find who funded this wallet (first SOL transfer in) + # Check the first few wallet transactions + if sigs_result: + # Get the oldest available tx + oldest_sigs_sorted = sorted(sigs_result, key=lambda x: x.get("blockTime", 0) or 0) + if oldest_sigs_sorted: + oldest_sig = oldest_sigs_sorted[0]["signature"] + tx = rpc_call("getTransaction", [oldest_sig, {"encoding": "jsonParsed", "maxSupportedTransactionVersion": 0}]) + time.sleep(RPC_DELAY) + + if tx and tx.get("transaction"): + instructions = tx["transaction"].get("message", {}).get("instructions", []) + for inst in instructions: + if isinstance(inst, dict) and isinstance(inst.get("parsed"), dict): + ptype = inst["parsed"].get("type", "") + pinfo = inst["parsed"].get("info", {}) + if ptype == "transfer" and pinfo.get("destination") == wallet: + funding_source = pinfo.get("source") + break + + h["first_buy_slot"] = first_jester_slot + h["first_buy_time"] = first_jester_time + h["funding_source"] = funding_source + h["buy_slots"] = jester_slots + + time_str = "" + if first_jester_time: + dt = datetime.fromtimestamp(first_jester_time, tz=timezone.utc) + time_str = dt.strftime("%Y-%m-%d %H:%M") + age_from_creation = first_jester_time - TOKEN_CREATION_TS + if age_from_creation < 60: + h["sniper_tag"] = f"SNIPER ({age_from_creation}s)" + elif age_from_creation < 300: + h["sniper_tag"] = f"EARLY ({age_from_creation//60}m{age_from_creation%60}s)" + elif age_from_creation < 3600: + h["sniper_tag"] = f"FAST ({age_from_creation//60}m)" + else: + h["sniper_tag"] = "" + else: + h["sniper_tag"] = "" + + fund_str = short(funding_source) if funding_source else "unknown" + print(f" [{h['rank']:2d}] {short(wallet):20s} | SOL: {h['sol_balance']:>8.2f} | First buy: {time_str} | {h['sniper_tag']:15s} | Funded by: {fund_str}") + +# ───────────────────────────────────────────── +# STEP 3: BUNDLE DETECTION — wallets buying in same slot +# ───────────────────────────────────────────── +print(f"\n[STEP 3] BUNDLE DETECTION — checking for same-slot purchases...") + +slot_to_wallets = defaultdict(list) +for h in holders: + if h.get("buy_slots"): + for s in h["buy_slots"]: + slot_to_wallets[s["slot"]].append({ + "wallet": h["wallet"], + "rank": h["rank"], + "balance": h["balance"], + "sig": s["sig"] + }) + +bundles_found = [] +for slot, wallets in sorted(slot_to_wallets.items()): + if len(wallets) >= 2: + bundles_found.append({"slot": slot, "wallets": wallets}) + +if bundles_found: + print(f"\n BUNDLES DETECTED: {len(bundles_found)} slots with 2+ holders transacting together") + for b in bundles_found: + print(f"\n Slot {b['slot']}:") + for w in b["wallets"]: + print(f" #{w['rank']:2d} {short(w['wallet']):20s} | {w['balance']:>15,.2f} JESTER | sig: {w['sig'][:20]}...") +else: + print(" No same-slot bundles found among top holders.") + +# ───────────────────────────────────────────── +# STEP 4: CLUSTER DETECTION — wallets funded by same source +# ───────────────────────────────────────────── +print(f"\n[STEP 4] CLUSTER DETECTION — wallets funded by same source...") + +funder_to_wallets = defaultdict(list) +for h in holders: + if h.get("funding_source") and h["funding_source"] != "unknown": + funder_to_wallets[h["funding_source"]].append(h) + +clusters_found = [] +for funder, wallets in funder_to_wallets.items(): + if len(wallets) >= 2: + clusters_found.append({"funder": funder, "wallets": wallets}) + +if clusters_found: + print(f"\n CLUSTERS DETECTED: {len(clusters_found)} funding sources linked to 2+ holders") + for c in clusters_found: + total_held = sum(w["balance"] for w in c["wallets"]) + print(f"\n Funder: {c['funder']}") + print(f" Total JESTER controlled: {total_held:,.2f}") + for w in c["wallets"]: + print(f" #{w['rank']:2d} {short(w['wallet']):20s} | {w['balance']:>15,.2f} JESTER | SOL: {w['sol_balance']:.2f}") +else: + print(" No clusters found (no shared funding sources among top holders).") + +# Also check if any holder IS a funder of another holder +print(f"\n Checking if any holder directly funded another holder...") +holder_wallets = set(h["wallet"] for h in holders) +linked = [] +for h in holders: + if h.get("funding_source") and h["funding_source"] in holder_wallets: + funder_h = next((x for x in holders if x["wallet"] == h["funding_source"]), None) + if funder_h: + linked.append((funder_h, h)) + +if linked: + print(f" LINKED HOLDERS: {len(linked)} pairs where one holder funded another") + for funder_h, funded_h in linked: + print(f" #{funder_h['rank']} {short(funder_h['wallet'])} -> #{funded_h['rank']} {short(funded_h['wallet'])} | Combined: {funder_h['balance'] + funded_h['balance']:,.2f} JESTER") +else: + print(" No direct holder-to-holder funding links found.") + +# ───────────────────────────────────────────── +# STEP 5: SNIPER SUMMARY +# ───────────────────────────────────────────── +print(f"\n[STEP 5] SNIPER ANALYSIS — who bought first?") + +timed_holders = [h for h in holders if h.get("first_buy_time")] +timed_holders.sort(key=lambda x: x["first_buy_time"]) + +print(f"\n {'Rank':>4} | {'Wallet':>20} | {'First Buy':>19} | {'Age from Launch':>15} | {'Balance':>18} | {'Tag':>15}") +print(" " + "-" * 105) + +for h in timed_holders[:20]: + dt = datetime.fromtimestamp(h["first_buy_time"], tz=timezone.utc) + age = h["first_buy_time"] - TOKEN_CREATION_TS + if age < 0: + age_str = f"-{abs(age)//60}m (PRE!)" + elif age < 3600: + age_str = f"+{age//60}m{age%60}s" + elif age < 86400: + age_str = f"+{age//3600}h{(age%3600)//60}m" + else: + age_str = f"+{age//86400}d{(age%86400)//3600}h" + + print(f" #{h['rank']:3d} | {short(h['wallet']):20s} | {dt.strftime('%Y-%m-%d %H:%M'):>19s} | {age_str:>15s} | {h['balance']:>15,.2f} | {h.get('sniper_tag',''):>15s}") + +# ───────────────────────────────────────────── +# STEP 6: Look at earliest mint signatures for absolute first buyers +# ───────────────────────────────────────────── +print(f"\n[STEP 6] Checking EARLIEST mint transactions (first buyers ever)...") + +# Get the last (oldest) signatures for the mint +mint_sigs = rpc_call("getSignaturesForAddress", [JESTER_MINT, {"limit": 50}]) +time.sleep(RPC_DELAY) + +if mint_sigs: + # These come newest-first, reverse for oldest-first + mint_sigs_sorted = sorted(mint_sigs, key=lambda x: x.get("blockTime", 0) or 0) + + # Parse the oldest 20 transactions + early_buyers = [] + seen_sigs = set() + + print(f" Parsing {min(20, len(mint_sigs_sorted))} earliest mint transactions...") + + for sig_info in mint_sigs_sorted[:20]: + sig = sig_info["signature"] + if sig in seen_sigs: + continue + seen_sigs.add(sig) + + bt = sig_info.get("blockTime", 0) + slot = sig_info.get("slot", 0) + + tx = rpc_call("getTransaction", [sig, {"encoding": "jsonParsed", "maxSupportedTransactionVersion": 0}]) + time.sleep(RPC_DELAY) + + if not tx: + continue + + # Find the signer (buyer) + signers = [] + acct_keys = tx.get("transaction", {}).get("message", {}).get("accountKeys", []) + for ak in acct_keys: + if isinstance(ak, dict) and ak.get("signer"): + signers.append(ak["pubkey"]) + elif isinstance(ak, str): + signers.append(ak) + + buyer = signers[0] if signers else "unknown" + + early_buyers.append({ + "sig": sig, + "buyer": buyer, + "slot": slot, + "time": bt, + "is_top_holder": buyer in holder_wallets + }) + + # Group early buyers by slot to detect bundles + early_slot_map = defaultdict(list) + for eb in early_buyers: + early_slot_map[eb["slot"]].append(eb) + + print(f"\n EARLIEST BUYERS:") + print(f" {'#':>3} | {'Time':>19} | {'Slot':>12} | {'Buyer':>20} | {'Top Holder?':>10} | {'Bundle?':>8}") + print(" " + "-" * 85) + + for i, eb in enumerate(early_buyers): + dt_str = datetime.fromtimestamp(eb["time"], tz=timezone.utc).strftime("%Y-%m-%d %H:%M:%S") if eb["time"] else "?" + is_bundle = len(early_slot_map[eb["slot"]]) > 1 + print(f" {i+1:3d} | {dt_str:>19s} | {eb['slot']:>12d} | {short(eb['buyer']):>20s} | {'YES' if eb['is_top_holder'] else 'no':>10s} | {'BUNDLE' if is_bundle else '':>8s}") + + # Detect early bundles + early_bundles = [(slot, buyers) for slot, buyers in early_slot_map.items() if len(buyers) >= 2] + if early_bundles: + print(f"\n EARLY BUNDLE ALERT: {len(early_bundles)} slots with multiple buys!") + for slot, buyers in early_bundles: + print(f" Slot {slot}:") + for eb in buyers: + print(f" {short(eb['buyer'])} | sig: {eb['sig'][:30]}...") + +# ───────────────────────────────────────────── +# STEP 7: SUMMARY & RISK FLAGS +# ───────────────────────────────────────────── +print("\n" + "=" * 80) +print(" FINAL SUMMARY — RISK FLAGS") +print("=" * 80) + +snipers = [h for h in holders if h.get("sniper_tag") and "SNIPER" in h.get("sniper_tag", "")] +early = [h for h in holders if h.get("sniper_tag") and "EARLY" in h.get("sniper_tag", "")] + +sniper_pct = sum(h["balance"] for h in snipers) / total_scanned * 100 if snipers else 0 +early_pct = sum(h["balance"] for h in early) / total_scanned * 100 if early else 0 +cluster_pct = sum(sum(w["balance"] for w in c["wallets"]) for c in clusters_found) / total_scanned * 100 if clusters_found else 0 + +print(f"\n SNIPERS (<60s): {len(snipers):3d} wallets | {sniper_pct:6.2f}% of top holder supply") +print(f" EARLY BUYERS (<5min): {len(early):3d} wallets | {early_pct:6.2f}% of top holder supply") +print(f" BUNDLES (same slot): {len(bundles_found):3d} detected") +print(f" CLUSTERS (same funder): {len(clusters_found):3d} detected | {cluster_pct:6.2f}% of top holder supply") +print(f" LINKED HOLDERS: {len(linked):3d} pairs") + +# Overall risk +risk_score = 0 +if snipers: risk_score += 2 +if len(bundles_found) >= 2: risk_score += 3 +if clusters_found: risk_score += 2 +if linked: risk_score += 1 +if sniper_pct > 20: risk_score += 2 + +risk_label = "LOW" if risk_score <= 2 else "MEDIUM" if risk_score <= 5 else "HIGH" +print(f"\n INSIDER RISK SCORE: {risk_score}/10 — {risk_label}") + +if snipers: + print(f"\n SNIPER WALLETS:") + for h in snipers: + print(f" #{h['rank']} {h['wallet']} | {h['balance']:,.2f} JESTER | {h['sniper_tag']}") + +if clusters_found: + print(f"\n CLUSTER WALLETS:") + for c in clusters_found: + print(f" Funder: {c['funder']}") + for w in c["wallets"]: + print(f" #{w['rank']} {w['wallet']} | {w['balance']:,.2f} JESTER") + +print(f"\n{'='*80}") +print(" ANALYSIS COMPLETE") +print(f"{'='*80}") diff --git a/jester_live_check.py b/jester_live_check.py new file mode 100644 index 0000000..5743f26 --- /dev/null +++ b/jester_live_check.py @@ -0,0 +1,429 @@ +#!/usr/bin/env python3 +"""JESTER token LIVE on-chain check — last 1 hour of activity.""" + +import json, time, urllib.request, os, sys +from collections import defaultdict +from datetime import datetime, timezone + +# ── Config ────────────────────────────────────────────────────────────────── +RPC = "" +try: + with open("/home/user/Cute-Panel/.env") as f: + for line in f: + line = line.strip() + if line.startswith("HELIUS_RPC_URL="): + RPC = line.split("=", 1)[1].strip().strip('"').strip("'") +except: + pass + +if not RPC: + print("FATAL: No HELIUS_RPC_URL found"); sys.exit(1) + +MINT = "6WdHhpRY7vL8SQ69bd89tAj3sk8jsjBrCLDUTZSNpump" +DELAY = 0.3 +ONE_HOUR = 3600 +NOW = int(time.time()) +CUTOFF = NOW - ONE_HOUR + +print("=" * 78) +print(" JESTER ($JESTER) — LIVE ON-CHAIN CHECK") +print("=" * 78) +print(f" Mint: {MINT}") +print(f" Now: {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M:%S UTC')}") +print(f" Window: Last 1 hour (since {datetime.fromtimestamp(CUTOFF, tz=timezone.utc).strftime('%H:%M:%S UTC')})") +print(f" RPC: Helius mainnet") +print("=" * 78) +print() + +# ── RPC helper ────────────────────────────────────────────────────────────── +call_count = 0 + +def rpc(method, params): + global call_count + call_count += 1 + body = json.dumps({"jsonrpc": "2.0", "id": call_count, "method": method, "params": params}).encode() + req = urllib.request.Request(RPC, data=body, headers={"Content-Type": "application/json"}) + for attempt in range(3): + try: + with urllib.request.urlopen(req, timeout=30) as resp: + data = json.loads(resp.read()) + if "error" in data: + print(f" [RPC ERROR] {method}: {data['error']}") + return None + return data.get("result") + except Exception as e: + if attempt < 2: + time.sleep(0.5) + else: + print(f" [RPC FAIL] {method}: {e}") + return None + return None + +def short(addr): + if not addr or len(addr) < 10: + return str(addr) + return addr[:4] + "..." + addr[-4:] + +# ══════════════════════════════════════════════════════════════════════════════ +# STEP 1: Get top 20 holders +# ══════════════════════════════════════════════════════════════════════════════ +print("[STEP 1] Fetching top 20 holders...") +t0 = time.time() + +res = rpc("getTokenLargestAccounts", [MINT]) +time.sleep(DELAY) + +if not res or "value" not in res: + print("FATAL: Could not fetch largest accounts"); sys.exit(1) + +largest = res["value"][:20] +total_supply_raw = sum(int(a["amount"]) for a in largest) # approx from top 20 + +holders = [] +for i, acct in enumerate(largest): + token_account = acct["address"] + raw_amount = int(acct["amount"]) + decimals = acct["decimals"] + balance = raw_amount / (10 ** decimals) + + # Resolve owner + info = rpc("getAccountInfo", [token_account, {"encoding": "jsonParsed"}]) + time.sleep(DELAY) + + owner = "unknown" + if info and info.get("value") and info["value"].get("data"): + try: + owner = info["value"]["data"]["parsed"]["info"]["owner"] + except (KeyError, TypeError): + pass + + # SOL balance + sol_bal = 0.0 + if owner != "unknown": + bal = rpc("getBalance", [owner]) + time.sleep(DELAY) + if bal and "value" in bal: + sol_bal = bal["value"] / 1e9 + + holders.append({ + "rank": i + 1, + "wallet": owner, + "token_account": token_account, + "jester": balance, + "sol": sol_bal, + "raw": raw_amount, + }) + +t1 = time.time() +print(f" Done in {t1 - t0:.1f}s ({len(holders)} holders resolved)\n") + +# Print holder table +print("=" * 78) +print(" TOP 20 JESTER HOLDERS — CURRENT SNAPSHOT") +print("=" * 78) +print(f"{'#':>3} | {'Wallet':>44} | {'JESTER':>18} | {'SOL':>10}") +print("-" * 78) +for h in holders: + w = h["wallet"] + tag = "" + # Check for known program addresses + if w in ("5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1",): + tag = " [RAYDIUM]" + elif w == "unknown": + tag = " [UNKNOWN]" + print(f"{h['rank']:>3} | {w:>44}{tag} | {h['jester']:>18,.2f} | {h['sol']:>10.4f}") +print() + +# ══════════════════════════════════════════════════════════════════════════════ +# STEP 2: Get last 100 signatures for the MINT address +# ══════════════════════════════════════════════════════════════════════════════ +print("[STEP 2] Fetching last 100 signatures for the JESTER mint...") +t2 = time.time() + +mint_sigs = rpc("getSignaturesForAddress", [MINT, {"limit": 100}]) +time.sleep(DELAY) + +if not mint_sigs: + print(" No signatures found for mint address!") + mint_sigs = [] + +total_fetched = len(mint_sigs) +recent_sigs = [s for s in mint_sigs if s.get("blockTime") and s["blockTime"] > CUTOFF and not s.get("err")] +failed_sigs = [s for s in mint_sigs if s.get("err")] + +print(f" Total fetched: {total_fetched}") +print(f" In last 1h: {len(recent_sigs)}") +print(f" Failed txs: {len(failed_sigs)}") + +if recent_sigs: + oldest = min(s["blockTime"] for s in recent_sigs) + newest = max(s["blockTime"] for s in recent_sigs) + print(f" Time range: {datetime.fromtimestamp(oldest, tz=timezone.utc).strftime('%H:%M:%S')} — {datetime.fromtimestamp(newest, tz=timezone.utc).strftime('%H:%M:%S')} UTC") + +if total_fetched > 0 and not recent_sigs: + # Check how old the most recent tx is + most_recent_time = max(s.get("blockTime", 0) for s in mint_sigs) + if most_recent_time: + age_min = (NOW - most_recent_time) / 60 + print(f" NOTE: Most recent mint tx is {age_min:.0f} minutes old") + +print() + +# ══════════════════════════════════════════════════════════════════════════════ +# STEP 3: Parse each recent transaction +# ══════════════════════════════════════════════════════════════════════════════ +print(f"[STEP 3] Parsing {len(recent_sigs)} recent transactions...") +t3 = time.time() + +trades = [] # list of {wallet, type, jester_amount, sol_amount, timestamp, sig} +all_active_wallets = set() +known_wallets = set(h["wallet"] for h in holders if h["wallet"] != "unknown") + +for idx, sig_info in enumerate(recent_sigs): + sig = sig_info["signature"] + block_time = sig_info["blockTime"] + ts_str = datetime.fromtimestamp(block_time, tz=timezone.utc).strftime('%H:%M:%S') + + tx = rpc("getTransaction", [sig, {"encoding": "jsonParsed", "maxSupportedTransactionVersion": 0}]) + time.sleep(DELAY) + + if not tx or not tx.get("meta"): + continue + + meta = tx["meta"] + + # Build account keys list for SOL balance lookup + account_keys = [] + try: + msg = tx["transaction"]["message"] + if "accountKeys" in msg: + account_keys = [k if isinstance(k, str) else k.get("pubkey", "") for k in msg["accountKeys"]] + # Also include loaded addresses (for v0 txs) + loaded = meta.get("loadedAddresses", {}) + if loaded: + account_keys += loaded.get("writable", []) + loaded.get("readonly", []) + except (KeyError, TypeError): + pass + + # Pre/post JESTER balances per owner + pre_jester = {} + post_jester = {} + for b in (meta.get("preTokenBalances") or []): + if b.get("mint") == MINT and b.get("owner"): + try: + pre_jester[b["owner"]] = float(b["uiTokenAmount"]["uiAmount"] or 0) + except (KeyError, TypeError): + pre_jester[b["owner"]] = 0 + for b in (meta.get("postTokenBalances") or []): + if b.get("mint") == MINT and b.get("owner"): + try: + post_jester[b["owner"]] = float(b["uiTokenAmount"]["uiAmount"] or 0) + except (KeyError, TypeError): + post_jester[b["owner"]] = 0 + + # Compute deltas for each wallet involved + all_owners = set(list(pre_jester.keys()) + list(post_jester.keys())) + + for owner in all_owners: + pre_val = pre_jester.get(owner, 0) + post_val = post_jester.get(owner, 0) + delta = post_val - pre_val + + if abs(delta) < 1: # skip dust + continue + + all_active_wallets.add(owner) + + # Calculate SOL delta for this wallet + sol_delta = 0.0 + if owner in account_keys: + aidx = account_keys.index(owner) + pre_bals = meta.get("preBalances") or [] + post_bals = meta.get("postBalances") or [] + if aidx < len(pre_bals) and aidx < len(post_bals): + sol_delta = (post_bals[aidx] - pre_bals[aidx]) / 1e9 + + trade_type = "BUY" if delta > 0 else "SELL" + trades.append({ + "wallet": owner, + "type": trade_type, + "jester": abs(delta), + "sol": abs(sol_delta), + "sol_delta": sol_delta, + "timestamp": block_time, + "time_str": ts_str, + "sig": sig[:20] + "...", + "is_top20": owner in known_wallets, + "mins_ago": (NOW - block_time) / 60, + }) + + if (idx + 1) % 10 == 0: + print(f" Parsed {idx + 1}/{len(recent_sigs)}...") + +t4 = time.time() +print(f" Done in {t4 - t3:.1f}s — {len(trades)} trades identified\n") + +# ══════════════════════════════════════════════════════════════════════════════ +# STEP 4: Print all trades +# ══════════════════════════════════════════════════════════════════════════════ +print("=" * 78) +print(" ALL BUYS/SELLS IN LAST 1 HOUR") +print("=" * 78) + +if not trades: + print(" No trades detected in the last hour.") +else: + # Sort by timestamp descending (most recent first) + trades.sort(key=lambda t: t["timestamp"], reverse=True) + + buys = [t for t in trades if t["type"] == "BUY"] + sells = [t for t in trades if t["type"] == "SELL"] + + print(f"\n --- BUYS ({len(buys)}) ---") + if buys: + print(f" {'Time':>8} | {'Wallet':>12} | {'JESTER Amount':>18} | {'SOL Cost':>12} | {'Ago':>6} | {'Top20':>5}") + print(" " + "-" * 72) + for t in buys: + tag = "YES" if t["is_top20"] else "no" + print(f" {t['time_str']:>8} | {short(t['wallet']):>12} | {t['jester']:>18,.2f} | {t['sol']:>12.4f} | {t['mins_ago']:>5.1f}m | {tag:>5}") + else: + print(" None") + + print(f"\n --- SELLS ({len(sells)}) ---") + if sells: + print(f" {'Time':>8} | {'Wallet':>12} | {'JESTER Amount':>18} | {'SOL Received':>12} | {'Ago':>6} | {'Top20':>5}") + print(" " + "-" * 72) + for t in sells: + tag = "YES" if t["is_top20"] else "no" + print(f" {t['time_str']:>8} | {short(t['wallet']):>12} | {t['jester']:>18,.2f} | {t['sol']:>12.4f} | {t['mins_ago']:>5.1f}m | {tag:>5}") + else: + print(" None") + +# ══════════════════════════════════════════════════════════════════════════════ +# STEP 5: Net buy/sell pressure +# ══════════════════════════════════════════════════════════════════════════════ +print() +print("=" * 78) +print(" NET BUY/SELL PRESSURE (Last 1 Hour)") +print("=" * 78) + +total_bought = sum(t["jester"] for t in trades if t["type"] == "BUY") +total_sold = sum(t["jester"] for t in trades if t["type"] == "SELL") +total_sol_in = sum(t["sol"] for t in trades if t["type"] == "BUY") +total_sol_out = sum(t["sol"] for t in trades if t["type"] == "SELL") +num_buyers = len(set(t["wallet"] for t in trades if t["type"] == "BUY")) +num_sellers = len(set(t["wallet"] for t in trades if t["type"] == "SELL")) + +print(f" Total JESTER bought: {total_bought:>20,.2f} ({len(buys)} txs, {num_buyers} wallets)") +print(f" Total JESTER sold: {total_sold:>20,.2f} ({len(sells)} txs, {num_sellers} wallets)") +print(f" Net JESTER flow: {total_bought - total_sold:>+20,.2f}") +print(f" SOL spent buying: {total_sol_in:>20.4f}") +print(f" SOL received selling: {total_sol_out:>20.4f}") +print() + +if total_bought > total_sold * 1.2: + print(" >>> VERDICT: STRONG BUY PRESSURE <<<") +elif total_bought > total_sold: + print(" >>> VERDICT: MILD BUY PRESSURE <<<") +elif total_sold > total_bought * 1.2: + print(" >>> VERDICT: STRONG SELL PRESSURE <<<") +elif total_sold > total_bought: + print(" >>> VERDICT: MILD SELL PRESSURE <<<") +else: + print(" >>> VERDICT: NEUTRAL / BALANCED <<<") + +# ══════════════════════════════════════════════════════════════════════════════ +# STEP 6: Whale movements (top 5 holder activity) +# ══════════════════════════════════════════════════════════════════════════════ +print() +print("=" * 78) +print(" WHALE WATCH (Top 5 Holders)") +print("=" * 78) + +whale_moved = False +for h in holders[:5]: + w = h["wallet"] + whale_trades = [t for t in trades if t["wallet"] == w] + if whale_trades: + whale_moved = True + whale_bought = sum(t["jester"] for t in whale_trades if t["type"] == "BUY") + whale_sold = sum(t["jester"] for t in whale_trades if t["type"] == "SELL") + print(f" WHALE #{h['rank']} {short(w)} (holds {h['jester']:,.0f} JESTER, {h['sol']:.2f} SOL)") + print(f" Bought: {whale_bought:,.2f} | Sold: {whale_sold:,.2f} | Txs: {len(whale_trades)}") + for t in whale_trades: + print(f" -> {t['time_str']} {t['type']} {t['jester']:,.2f} JESTER ({t['sol']:.4f} SOL)") + else: + print(f" Whale #{h['rank']} {short(w)} — IDLE (holds {h['jester']:,.0f} JESTER)") + +if not whale_moved: + print("\n No whale (top 5) movement in the last hour.") + +# ══════════════════════════════════════════════════════════════════════════════ +# STEP 7: New large holders / position changes +# ══════════════════════════════════════════════════════════════════════════════ +print() +print("=" * 78) +print(" NEW/NOTABLE WALLETS & POSITION CHANGES") +print("=" * 78) + +# Identify wallets that traded but are NOT in top 20 +new_large_wallets = set() +for t in trades: + if not t["is_top20"] and t["jester"] > 100_000: + new_large_wallets.add(t["wallet"]) + +if new_large_wallets: + print(f"\n Non-top-20 wallets with large trades (>100K JESTER):") + for w in new_large_wallets: + w_trades = [t for t in trades if t["wallet"] == w] + w_bought = sum(t["jester"] for t in w_trades if t["type"] == "BUY") + w_sold = sum(t["jester"] for t in w_trades if t["type"] == "SELL") + print(f" {short(w)} ({w})") + print(f" Bought: {w_bought:,.2f} | Sold: {w_sold:,.2f}") +else: + print(" No new large wallets detected (>100K JESTER trades).") + +# Check for wallets that might be accumulating +print(f"\n Active wallet summary:") +wallet_net = defaultdict(float) +for t in trades: + if t["type"] == "BUY": + wallet_net[t["wallet"]] += t["jester"] + else: + wallet_net[t["wallet"]] -= t["jester"] + +accumulators = [(w, v) for w, v in wallet_net.items() if v > 10_000] +dumpers = [(w, v) for w, v in wallet_net.items() if v < -10_000] + +accumulators.sort(key=lambda x: x[1], reverse=True) +dumpers.sort(key=lambda x: x[1]) + +if accumulators: + print(f"\n TOP ACCUMULATORS (net >10K JESTER):") + for w, net in accumulators[:10]: + tag = " [TOP 20]" if w in known_wallets else "" + print(f" {short(w)}{tag}: net +{net:,.2f} JESTER") + +if dumpers: + print(f"\n TOP DUMPERS (net <-10K JESTER):") + for w, net in dumpers[:10]: + tag = " [TOP 20]" if w in known_wallets else "" + print(f" {short(w)}{tag}: net {net:,.2f} JESTER") + +# ══════════════════════════════════════════════════════════════════════════════ +# FINAL SUMMARY +# ══════════════════════════════════════════════════════════════════════════════ +print() +print("=" * 78) +print(" EXECUTIVE SUMMARY") +print("=" * 78) +print(f" Time: {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M:%S UTC')}") +print(f" Trades (1h): {len(trades)} ({len(buys)} buys, {len(sells)} sells)") +print(f" Unique wallets: {len(all_active_wallets)}") +print(f" JESTER bought: {total_bought:,.2f}") +print(f" JESTER sold: {total_sold:,.2f}") +print(f" Net: {total_bought - total_sold:+,.2f} JESTER") +print(f" Whale activity: {'YES' if whale_moved else 'NO'}") +print(f" RPC calls made: {call_count}") +print(f" Total runtime: {time.time() - t0:.1f}s") +print("=" * 78) diff --git a/jester_resolve_wallets.py b/jester_resolve_wallets.py new file mode 100644 index 0000000..f9db3b0 --- /dev/null +++ b/jester_resolve_wallets.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +"""Resolve token accounts to owner wallets for JESTER top holders.""" +import json, time +from urllib.request import Request, urlopen + +JESTER_MINT = "6WdHhpRY7vL8SQ69bd89tAj3sk8jsjBrCLDUTZSNpump" +RPC = "https://mainnet.helius-rpc.com/?api-key=28d0e718-6052-4054-a8c8-c38c3897ac15" + +def rpc_call(method, params): + body = json.dumps({"jsonrpc":"2.0","id":1,"method":method,"params":params}).encode() + for attempt in range(3): + try: + req = Request(RPC, data=body, headers={"Content-Type":"application/json"}) + resp = urlopen(req, timeout=30) + data = json.loads(resp.read()) + return data.get("result") + except Exception as e: + if attempt < 2: time.sleep(2**attempt) + else: print(f" FAIL: {e}") + return None + +# Get top holders +result = rpc_call("getTokenLargestAccounts", [JESTER_MINT]) +accounts = result["value"][:20] + +print(f"{'Rank':>4} | {'Token Account':>44} | {'Owner Wallet':>44} | {'Balance':>20}") +print("-" * 120) + +for i, acc in enumerate(accounts): + token_acc = acc["address"] + balance = int(acc["amount"]) / (10 ** acc["decimals"]) + + info = rpc_call("getAccountInfo", [token_acc, {"encoding": "jsonParsed"}]) + time.sleep(0.5) + + owner = "unknown" + if info and info.get("value"): + parsed = info["value"].get("data", {}) + if isinstance(parsed, dict) and "parsed" in parsed: + owner = parsed["parsed"].get("info", {}).get("owner", "unknown") + + print(f"#{i+1:3d} | {token_acc} | {owner} | {balance:>18,.2f}") + +# Also print the early bundle wallets (already have full addresses from step 6) +print("\n\nEARLY BUNDLE WALLETS (from mint tx parsing):") +# These were already displayed — just need to re-fetch them +print("\nSlot 399518483 bundle:") +for sig in ["2SZNpqcNbqobb3pF1eeM3RtyukxXJp", "582rRfhsg6xBzPUVJf7bni4S9XqwJA"]: + print(f" (sig fragment: {sig}...)") +print("Slot 399520939 bundle (3 wallets):") +print("Slot 399523063 bundle (2 wallets):") + +# Re-fetch mint sigs to get full wallet addrs +print("\nRe-fetching earliest mint transactions for FULL wallet addresses...") +mint_sigs = rpc_call("getSignaturesForAddress", [JESTER_MINT, {"limit": 50}]) +time.sleep(0.5) + +if mint_sigs: + mint_sigs.sort(key=lambda x: x.get("blockTime", 0) or 0) + for sig_info in mint_sigs[:25]: + sig = sig_info["signature"] + bt = sig_info.get("blockTime", 0) + slot = sig_info.get("slot", 0) + + tx = rpc_call("getTransaction", [sig, {"encoding": "jsonParsed", "maxSupportedTransactionVersion": 0}]) + time.sleep(0.5) + + if not tx: continue + + signers = [] + acct_keys = tx.get("transaction", {}).get("message", {}).get("accountKeys", []) + for ak in acct_keys: + if isinstance(ak, dict) and ak.get("signer"): + signers.append(ak["pubkey"]) + + buyer = signers[0] if signers else "unknown" + from datetime import datetime, timezone + dt_str = datetime.fromtimestamp(bt, tz=timezone.utc).strftime("%H:%M:%S") if bt else "?" + + print(f" {dt_str} | Slot {slot} | {buyer}") diff --git a/memory/alpha_scans.jsonl b/memory/alpha_scans.jsonl new file mode 100644 index 0000000..95ae5c7 --- /dev/null +++ b/memory/alpha_scans.jsonl @@ -0,0 +1,12 @@ +{"timestamp": "2026-02-09T17:07:33.373403+00:00", "tokens_scanned": 1, "alpha_wallets_found": 2, "new_wallets_added": 2, "top_wallets": [{"wallet": "GjPSeaLm72QgTqzo38Wb", "score": 110, "symbol": "$POKEMON30"}, {"wallet": "Fj2uMrBaHkMcadrrTXeT", "score": 65, "symbol": "$POKEMON30"}]} +{"timestamp": "2026-02-09T17:09:09.296935+00:00", "tokens_scanned": 1, "alpha_wallets_found": 4, "new_wallets_added": 4, "top_wallets": [{"wallet": "EqQZvQDWr1cp96PejiFk", "score": 95, "symbol": "ROCK"}, {"wallet": "Ci8oK32uRq1itnBRzVSw", "score": 60, "symbol": "ROCK"}, {"wallet": "3AGkLzoHJ6pz3qARi2vc", "score": 60, "symbol": "ROCK"}, {"wallet": "FnRQiKnfcudnBLk5KmsS", "score": 40, "symbol": "ROCK"}]} +{"timestamp": "2026-02-09T17:11:07.357549+00:00", "tokens_scanned": 1, "alpha_wallets_found": 1, "new_wallets_added": 1, "top_wallets": [{"wallet": "ND8nFkaHP9kwQXnhb3EL", "score": 115, "symbol": "Maximoto"}]} +{"timestamp": "2026-02-11T09:43:00.483627+00:00", "tokens_scanned": 10, "alpha_wallets_found": 15, "new_wallets_added": 15, "top_wallets": [{"wallet": "Cqj2kGj9Wap4ghLuJkJ3", "score": 140, "symbol": "SAFEMOON"}, {"wallet": "87rRdssFiTJKY4MGARa4", "score": 135, "symbol": "GIRAFFES"}, {"wallet": "EXWGUMiuxxTB1TL1ZguY", "score": 130, "symbol": "SAFEMOON"}, {"wallet": "8WXKcUjwMU5TxiEN4mjw", "score": 125, "symbol": "GIRAFFES"}, {"wallet": "DM3LKCMnZEmjnW57WVeW", "score": 125, "symbol": "ICF"}]} +{"timestamp": "2026-02-11T12:19:45.081358+00:00", "tokens_scanned": 1, "alpha_wallets_found": 1, "new_wallets_added": 1, "top_wallets": [{"wallet": "24DCWvhrk4xwH6eCQ2UK", "score": 80, "symbol": "Rex"}]} +{"timestamp": "2026-02-11T17:08:23.575462+00:00", "tokens_scanned": 1, "alpha_wallets_found": 1, "new_wallets_added": 1, "top_wallets": [{"wallet": "7TQfNAr4R5wh3G7Pjksn", "score": 135, "symbol": "JESTER"}]} +{"timestamp": "2026-02-11T17:59:29.166850+00:00", "tokens_scanned": 1, "alpha_wallets_found": 1, "new_wallets_added": 1, "top_wallets": [{"wallet": "6QDnPbwbJuph4LdRDBj6", "score": 65, "symbol": "CARDS"}]} +{"timestamp": "2026-02-11T17:59:30.213691+00:00", "tokens_scanned": 1, "alpha_wallets_found": 1, "new_wallets_added": 1, "top_wallets": [{"wallet": "3pdX233Gg1QaAhpzBQpd", "score": 125, "symbol": "BLOWFISH"}]} +{"timestamp": "2026-02-11T17:59:25.850086+00:00", "tokens_scanned": 1, "alpha_wallets_found": 1, "new_wallets_added": 1, "top_wallets": [{"wallet": "74R4zxxwNJEcgnjUYvXb", "score": 75, "symbol": "PsyopAnime"}]} +{"timestamp": "2026-02-13T14:32:47.158549+00:00", "tokens_scanned": 1, "alpha_wallets_found": 6, "new_wallets_added": 6, "top_wallets": [{"wallet": "BEWjNZivbn4x2cLYFDjd", "score": 80, "symbol": "NAMECOIN"}, {"wallet": "GuQNDopfv7PWGGyminzN", "score": 65, "symbol": "NAMECOIN"}, {"wallet": "p4jsxPV5DKoJA2hroCyV", "score": 65, "symbol": "NAMECOIN"}, {"wallet": "7Y5fKQkErwDfDmP3m5Dk", "score": 65, "symbol": "NAMECOIN"}, {"wallet": "9Er4cUFH6myj7vowBFR3", "score": 60, "symbol": "NAMECOIN"}]} +{"timestamp": "2026-02-13T18:04:49.910610+00:00", "tokens_scanned": 10, "alpha_wallets_found": 26, "new_wallets_added": 24, "top_wallets": [{"wallet": "8WXKcUjwMU5TxiEN4mjw", "score": 110, "symbol": "LIZARD"}, {"wallet": "4fUFnzvRaMJqoowoKaHx", "score": 110, "symbol": "hoodrat"}, {"wallet": "CECN4BW4DKnbyddkd9Fh", "score": 110, "symbol": "Buttfish"}, {"wallet": "7gDx5mDysjbqBWHQR3uv", "score": 110, "symbol": "RATHBUN"}, {"wallet": "6r8YXQ8KXmF9JTMh7u5n", "score": 100, "symbol": "MoonLiquid"}]} +{"timestamp": "2026-02-13T18:22:16.903509+00:00", "tokens_scanned": 1, "alpha_wallets_found": 3, "new_wallets_added": 3, "top_wallets": [{"wallet": "CUwrDw7YHtGqyW6rcZSz", "score": 90, "symbol": "FTX2.0"}, {"wallet": "13BdMrG2uLNMBaitN54D", "score": 80, "symbol": "FTX2.0"}, {"wallet": "7L19GXJ4ZA6MnyQ89Fko", "score": 45, "symbol": "FTX2.0"}]} diff --git a/memory/alpha_wallets_scan.json b/memory/alpha_wallets_scan.json new file mode 100644 index 0000000..12ef55f --- /dev/null +++ b/memory/alpha_wallets_scan.json @@ -0,0 +1,1175 @@ +{ + "scan_date": "2026-02-08T16:18:28.810863", + "tokens_scanned": 8, + "total_early_buyers": 103, + "repeat_winners_count": 10, + "repeat_winners": [ + { + "wallet": "62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV", + "token_count": 4, + "tokens": [ + { + "token": "SOLPRISM", + "mint": "8fZjyDPme2aYmujuxJjKAk3hAGHCgggrHUJFv9roC8cN", + "slot": 398601629, + "blockTime": 1770443462, + "sol_spent": 0 + }, + { + "token": "COPPERINU", + "mint": "61Wj56QgGyyB966T7YsMzEAKRLcMvJpDbPzjkrCZc4Bi", + "slot": 398888980, + "blockTime": 1770556057, + "sol_spent": 0 + }, + { + "token": "BLOWFISH", + "mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "slot": 398898961, + "blockTime": 1770559966, + "sol_spent": 0 + }, + { + "token": "BUTTCOIN", + "mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "slot": 391850890, + "blockTime": 1767764044, + "sol_spent": 0 + } + ], + "total_sol_spent": 0 + }, + { + "wallet": "7hTckgnGnLQR6sdH7YkqFTAA7VwTfYFaZ6EhEsU3saCX", + "token_count": 3, + "tokens": [ + { + "token": "SOLPRISM", + "mint": "8fZjyDPme2aYmujuxJjKAk3hAGHCgggrHUJFv9roC8cN", + "slot": 398601661, + "blockTime": 1770443474, + "sol_spent": 0 + }, + { + "token": "OPAL", + "mint": "2PzS5SYYWjUFvzXNFaMmRkpjkxGX6R5v8DnKYtdcpump", + "slot": 398888260, + "blockTime": 1770555775, + "sol_spent": 0 + }, + { + "token": "TESTICLE", + "mint": "4TyZGqRLG3VcHTGMcLBoPUmqYitMVojXinAmkL8xpump", + "slot": 398893055, + "blockTime": 1770557651, + "sol_spent": 0 + } + ], + "total_sol_spent": 0 + }, + { + "wallet": "HFqp6ErWHY6Uzhj8rFyjYuDya2mXUpYEk8VW75K9PSiY", + "token_count": 3, + "tokens": [ + { + "token": "OPAL", + "mint": "2PzS5SYYWjUFvzXNFaMmRkpjkxGX6R5v8DnKYtdcpump", + "slot": 398888260, + "blockTime": 1770555775, + "sol_spent": 0 + }, + { + "token": "BLOWFISH", + "mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "slot": 398899259, + "blockTime": 1770560084, + "sol_spent": 0 + }, + { + "token": "BUTTCOIN", + "mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "slot": 391885801, + "blockTime": 1767777935, + "sol_spent": 0 + } + ], + "total_sol_spent": 0 + }, + { + "wallet": "GpMZbSM2GgvTKHJirzeGfMFoaZ8UR2X7F4v8vHTvxFbL", + "token_count": 2, + "tokens": [ + { + "token": "SOLPRISM", + "mint": "8fZjyDPme2aYmujuxJjKAk3hAGHCgggrHUJFv9roC8cN", + "slot": 398601629, + "blockTime": 1770443462, + "sol_spent": 0 + }, + { + "token": "BUTTCOIN", + "mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "slot": 391849401, + "blockTime": 1767763454, + "sol_spent": 0 + } + ], + "total_sol_spent": 0 + }, + { + "wallet": "65ZHSArs5XxPseKQbB1B4r16vDxMWnCxHMzogDAqiDUc", + "token_count": 2, + "tokens": [ + { + "token": "SOLPRISM", + "mint": "8fZjyDPme2aYmujuxJjKAk3hAGHCgggrHUJFv9roC8cN", + "slot": 398602027, + "blockTime": 1770443617, + "sol_spent": 0 + }, + { + "token": "BUTTCOIN", + "mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "slot": 391850500, + "blockTime": 1767763891, + "sol_spent": 0 + } + ], + "total_sol_spent": 0 + }, + { + "wallet": "8psNvWTrdNTiVRNzAgsou9kETXNJm2SXZyaKuJraVRtf", + "token_count": 2, + "tokens": [ + { + "token": "SOLPRISM", + "mint": "8fZjyDPme2aYmujuxJjKAk3hAGHCgggrHUJFv9roC8cN", + "slot": 398602031, + "blockTime": 1770443618, + "sol_spent": 0 + }, + { + "token": "BUTTCOIN", + "mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "slot": 391850500, + "blockTime": 1767763891, + "sol_spent": 0 + } + ], + "total_sol_spent": 0 + }, + { + "wallet": "G5UZAVbAf46s7cKWoyKu8kYTip9DGTpbLZ2qa9Aq69dP", + "token_count": 2, + "tokens": [ + { + "token": "OPAL", + "mint": "2PzS5SYYWjUFvzXNFaMmRkpjkxGX6R5v8DnKYtdcpump", + "slot": 398888260, + "blockTime": 1770555775, + "sol_spent": 0 + }, + { + "token": "BLOWFISH", + "mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "slot": 398899206, + "blockTime": 1770560063, + "sol_spent": 0 + } + ], + "total_sol_spent": 0 + }, + { + "wallet": "GP8StUXNYSZjPikyRsvkTbvRV1GBxMErb59cpeCJnDf1", + "token_count": 2, + "tokens": [ + { + "token": "BLOWFISH", + "mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "slot": 398898654, + "blockTime": 1770559847, + "sol_spent": 0 + }, + { + "token": "BUTTCOIN", + "mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "slot": 391885608, + "blockTime": 1767777859, + "sol_spent": 0 + } + ], + "total_sol_spent": 0 + }, + { + "wallet": "HLnpSz9h2S4hiLQ43rnSD9XkcUThA7B8hQMKmDaiTLcC", + "token_count": 2, + "tokens": [ + { + "token": "BLOWFISH", + "mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "slot": 398898654, + "blockTime": 1770559847, + "sol_spent": 0 + }, + { + "token": "BUTTCOIN", + "mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "slot": 391849401, + "blockTime": 1767763454, + "sol_spent": 0 + } + ], + "total_sol_spent": 0 + }, + { + "wallet": "DSN3j1ykL3obAVNv7ZX49VsFCPe4LqzxHnmtLiPwY6xg", + "token_count": 2, + "tokens": [ + { + "token": "BLOWFISH", + "mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "slot": 398898832, + "blockTime": 1770559916, + "sol_spent": 0 + }, + { + "token": "BUTTCOIN", + "mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "slot": 391885777, + "blockTime": 1767777925, + "sol_spent": 0 + } + ], + "total_sol_spent": 0 + } + ], + "all_early_buyers": [ + { + "wallet": "Hv4Hkx5dgZtJMDwhoywhE6Wkh6dtbh6EFSpNYUT4VK5t", + "slot": 398601629, + "blockTime": 1770443462, + "tokens": 22380.881126000022, + "sol_spent": 0, + "token_mint": "8fZjyDPme2aYmujuxJjKAk3hAGHCgggrHUJFv9roC8cN", + "token_ticker": "SOLPRISM" + }, + { + "wallet": "62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV", + "slot": 398601629, + "blockTime": 1770443462, + "tokens": 3.0709000157003175e-05, + "sol_spent": 0, + "token_mint": "8fZjyDPme2aYmujuxJjKAk3hAGHCgggrHUJFv9roC8cN", + "token_ticker": "SOLPRISM" + }, + { + "wallet": "7xPpioyKQjw2LAZZrK7acS78euAMm9ESVgAGZwS9UD11", + "slot": 398601629, + "blockTime": 1770443462, + "tokens": 0.00046063499999604574, + "sol_spent": 0, + "token_mint": "8fZjyDPme2aYmujuxJjKAk3hAGHCgggrHUJFv9roC8cN", + "token_ticker": "SOLPRISM" + }, + { + "wallet": "FBZSQpAYGQJpmRT8L33QnGwv6bCaTx6XCjmTPVCw3gdZ", + "slot": 398601629, + "blockTime": 1770443462, + "tokens": 7599.351055011153, + "sol_spent": 0, + "token_mint": "8fZjyDPme2aYmujuxJjKAk3hAGHCgggrHUJFv9roC8cN", + "token_ticker": "SOLPRISM" + }, + { + "wallet": "GpMZbSM2GgvTKHJirzeGfMFoaZ8UR2X7F4v8vHTvxFbL", + "slot": 398601629, + "blockTime": 1770443462, + "tokens": 0.060803764000013416, + "sol_spent": 0, + "token_mint": "8fZjyDPme2aYmujuxJjKAk3hAGHCgggrHUJFv9roC8cN", + "token_ticker": "SOLPRISM" + }, + { + "wallet": "4pebXP6kE1mAxN6EVQgBWpVoF4nTbhGH581xZonrFJrG", + "slot": 398601661, + "blockTime": 1770443474, + "tokens": 4560.587590000003, + "sol_spent": 0, + "token_mint": "8fZjyDPme2aYmujuxJjKAk3hAGHCgggrHUJFv9roC8cN", + "token_ticker": "SOLPRISM" + }, + { + "wallet": "7hTckgnGnLQR6sdH7YkqFTAA7VwTfYFaZ6EhEsU3saCX", + "slot": 398601661, + "blockTime": 1770443474, + "tokens": 6.2599999637313886e-06, + "sol_spent": 0, + "token_mint": "8fZjyDPme2aYmujuxJjKAk3hAGHCgggrHUJFv9roC8cN", + "token_ticker": "SOLPRISM" + }, + { + "wallet": "rqjrEZELGJvZPdqGPqe9AXN399KStE61BDgPgznAha7", + "slot": 398602027, + "blockTime": 1770443617, + "tokens": 7.924118, + "sol_spent": 0, + "token_mint": "8fZjyDPme2aYmujuxJjKAk3hAGHCgggrHUJFv9roC8cN", + "token_ticker": "SOLPRISM" + }, + { + "wallet": "65ZHSArs5XxPseKQbB1B4r16vDxMWnCxHMzogDAqiDUc", + "slot": 398602027, + "blockTime": 1770443617, + "tokens": 0.09067049000077532, + "sol_spent": 0, + "token_mint": "8fZjyDPme2aYmujuxJjKAk3hAGHCgggrHUJFv9roC8cN", + "token_ticker": "SOLPRISM" + }, + { + "wallet": "FkEB6uvyzuoaGpgs4yRtFtxC4WJxhejNFbUkj5R6wR32", + "slot": 398602027, + "blockTime": 1770443617, + "tokens": 7.960278999998991, + "sol_spent": 0, + "token_mint": "8fZjyDPme2aYmujuxJjKAk3hAGHCgggrHUJFv9roC8cN", + "token_ticker": "SOLPRISM" + }, + { + "wallet": "8Xn4YW9vTrW3MXkLdT2vbxd3ykcpMQK5iy9RuD146H6y", + "slot": 398602027, + "blockTime": 1770443617, + "tokens": 0.03981900000007954, + "sol_spent": 0, + "token_mint": "8fZjyDPme2aYmujuxJjKAk3hAGHCgggrHUJFv9roC8cN", + "token_ticker": "SOLPRISM" + }, + { + "wallet": "BeRWhwYYd5DmYkFjR3XMomjX4mSCnC4yCMyS77YCkuT1", + "slot": 398602031, + "blockTime": 1770443618, + "tokens": 641.789684, + "sol_spent": 0, + "token_mint": "8fZjyDPme2aYmujuxJjKAk3hAGHCgggrHUJFv9roC8cN", + "token_ticker": "SOLPRISM" + }, + { + "wallet": "8psNvWTrdNTiVRNzAgsou9kETXNJm2SXZyaKuJraVRtf", + "slot": 398602031, + "blockTime": 1770443618, + "tokens": 39.15685999999914, + "sol_spent": 0, + "token_mint": "8fZjyDPme2aYmujuxJjKAk3hAGHCgggrHUJFv9roC8cN", + "token_ticker": "SOLPRISM" + }, + { + "wallet": "5dhYayH9qvzNyCPoh2hKN8TJqumoGsWdyZ9UfPLXBfD9", + "slot": 398602031, + "blockTime": 1770443618, + "tokens": 0.01212812300002497, + "sol_spent": 0, + "token_mint": "8fZjyDPme2aYmujuxJjKAk3hAGHCgggrHUJFv9roC8cN", + "token_ticker": "SOLPRISM" + }, + { + "wallet": "3D2dsUZ3ZDMP7waDWVxtoLWzD2mR8CAxJoXxnCzwE6g1", + "slot": 398602031, + "blockTime": 1770443618, + "tokens": 1.0637729999999976, + "sol_spent": 0, + "token_mint": "8fZjyDPme2aYmujuxJjKAk3hAGHCgggrHUJFv9roC8cN", + "token_ticker": "SOLPRISM" + }, + { + "wallet": "HFqp6ErWHY6Uzhj8rFyjYuDya2mXUpYEk8VW75K9PSiY", + "slot": 398888260, + "blockTime": 1770555775, + "tokens": 300.0, + "sol_spent": 0, + "token_mint": "2PzS5SYYWjUFvzXNFaMmRkpjkxGX6R5v8DnKYtdcpump", + "token_ticker": "OPAL" + }, + { + "wallet": "8Ud1ydXep6nbffvMPhMkHmgrtyeymxAW1D8gocus18jf", + "slot": 398888260, + "blockTime": 1770555775, + "tokens": 0.00025589399999992324, + "sol_spent": 0, + "token_mint": "2PzS5SYYWjUFvzXNFaMmRkpjkxGX6R5v8DnKYtdcpump", + "token_ticker": "OPAL" + }, + { + "wallet": "G5UZAVbAf46s7cKWoyKu8kYTip9DGTpbLZ2qa9Aq69dP", + "slot": 398888260, + "blockTime": 1770555775, + "tokens": 4.176100003405736e-05, + "sol_spent": 0, + "token_mint": "2PzS5SYYWjUFvzXNFaMmRkpjkxGX6R5v8DnKYtdcpump", + "token_ticker": "OPAL" + }, + { + "wallet": "DN51XoPx6fPPfME5KJZSn4iCqDKos1i9uUwZc3Wm1xzn", + "slot": 398888260, + "blockTime": 1770555775, + "tokens": 4224.203690999999, + "sol_spent": 0, + "token_mint": "2PzS5SYYWjUFvzXNFaMmRkpjkxGX6R5v8DnKYtdcpump", + "token_ticker": "OPAL" + }, + { + "wallet": "3BcPVDWvxYrRMgRQuTsx991Z8Xp2SzuymTZ6MYBL1tDk", + "slot": 398888260, + "blockTime": 1770555775, + "tokens": 0.0005011299999999608, + "sol_spent": 0, + "token_mint": "2PzS5SYYWjUFvzXNFaMmRkpjkxGX6R5v8DnKYtdcpump", + "token_ticker": "OPAL" + }, + { + "wallet": "7onHnHZHgLxD7hMRm3XbQCfRiUNV7ardnNCgKkNcLLAb", + "slot": 398888260, + "blockTime": 1770555775, + "tokens": 299700.0, + "sol_spent": 0, + "token_mint": "2PzS5SYYWjUFvzXNFaMmRkpjkxGX6R5v8DnKYtdcpump", + "token_ticker": "OPAL" + }, + { + "wallet": "7hTckgnGnLQR6sdH7YkqFTAA7VwTfYFaZ6EhEsU3saCX", + "slot": 398888260, + "blockTime": 1770555775, + "tokens": 0.0007932690000416187, + "sol_spent": 0, + "token_mint": "2PzS5SYYWjUFvzXNFaMmRkpjkxGX6R5v8DnKYtdcpump", + "token_ticker": "OPAL" + }, + { + "wallet": "Co81s1dCCYkxvMQRdoapkpiRzKg83SpSStXv6rq95pmF", + "slot": 398888260, + "blockTime": 1770555775, + "tokens": 0.08368856300000971, + "sol_spent": 0, + "token_mint": "2PzS5SYYWjUFvzXNFaMmRkpjkxGX6R5v8DnKYtdcpump", + "token_ticker": "OPAL" + }, + { + "wallet": "Agp9XKejuAtvtWB6KPXefkK64Y7v9tCS9fEXDNJ6wpKG", + "slot": 398888980, + "blockTime": 1770556057, + "tokens": 2547.178366, + "sol_spent": 0.198349263, + "token_mint": "61Wj56QgGyyB966T7YsMzEAKRLcMvJpDbPzjkrCZc4Bi", + "token_ticker": "COPPERINU" + }, + { + "wallet": "3iUT1oAAUSqKeHAjkumZJbptihy2yN7AwFij2CrsUZVC", + "slot": 398888980, + "blockTime": 1770556057, + "tokens": 0.19649322999975993, + "sol_spent": 0, + "token_mint": "61Wj56QgGyyB966T7YsMzEAKRLcMvJpDbPzjkrCZc4Bi", + "token_ticker": "COPPERINU" + }, + { + "wallet": "7VtfL8fvgNfhz17qKRMjzQEXgbdpnHHHQRh54R9jP2RJ", + "slot": 398888980, + "blockTime": 1770556057, + "tokens": 9.805100000903622e-05, + "sol_spent": 0, + "token_mint": "61Wj56QgGyyB966T7YsMzEAKRLcMvJpDbPzjkrCZc4Bi", + "token_ticker": "COPPERINU" + }, + { + "wallet": "8GmVAeQBe9VkhXn15RaQyphLD9LN4WmkmEXvvhXBXvtS", + "slot": 398888980, + "blockTime": 1770556057, + "tokens": 0.0003529819999990025, + "sol_spent": 0, + "token_mint": "61Wj56QgGyyB966T7YsMzEAKRLcMvJpDbPzjkrCZc4Bi", + "token_ticker": "COPPERINU" + }, + { + "wallet": "CatyeC3LgBxub7HcpW2n7cZZZ66CUKdcZ8DzHucHrSiP", + "slot": 398888980, + "blockTime": 1770556057, + "tokens": 0.0009690740000678488, + "sol_spent": 0, + "token_mint": "61Wj56QgGyyB966T7YsMzEAKRLcMvJpDbPzjkrCZc4Bi", + "token_ticker": "COPPERINU" + }, + { + "wallet": "HTvjzsfX3yU6BUodCjZ5vZkUrAxMDTrBs3CJaq43ashR", + "slot": 398888980, + "blockTime": 1770556057, + "tokens": 25.33070299999963, + "sol_spent": 0, + "token_mint": "61Wj56QgGyyB966T7YsMzEAKRLcMvJpDbPzjkrCZc4Bi", + "token_ticker": "COPPERINU" + }, + { + "wallet": "62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV", + "slot": 398888980, + "blockTime": 1770556057, + "tokens": 0.0001430070001333661, + "sol_spent": 0, + "token_mint": "61Wj56QgGyyB966T7YsMzEAKRLcMvJpDbPzjkrCZc4Bi", + "token_ticker": "COPPERINU" + }, + { + "wallet": "2QnYfsAmmFhfzwEJAxfZ61MaUpT1rKyGdVsLrKCfyFsq", + "slot": 398888980, + "blockTime": 1770556057, + "tokens": 3715.9276519999985, + "sol_spent": 0, + "token_mint": "61Wj56QgGyyB966T7YsMzEAKRLcMvJpDbPzjkrCZc4Bi", + "token_ticker": "COPPERINU" + }, + { + "wallet": "6wwKE6k9s26XaU8Az9nGh9hS6TAmVw7umkGQERxJbEQ7", + "slot": 398893055, + "blockTime": 1770557651, + "tokens": 763.209407, + "sol_spent": 0.050025, + "token_mint": "4TyZGqRLG3VcHTGMcLBoPUmqYitMVojXinAmkL8xpump", + "token_ticker": "TESTICLE" + }, + { + "wallet": "E616WShkSjxnyToCExYLhNWxyYraFqs1RTQz1gZ9ZDUk", + "slot": 398893055, + "blockTime": 1770557651, + "tokens": 0.049362061000010726, + "sol_spent": 0, + "token_mint": "4TyZGqRLG3VcHTGMcLBoPUmqYitMVojXinAmkL8xpump", + "token_ticker": "TESTICLE" + }, + { + "wallet": "G3anQALkM7FkDWv6TbXEee4pW8TrZN1BW1NERDhxDfNC", + "slot": 398893055, + "blockTime": 1770557651, + "tokens": 0.00011330700000122818, + "sol_spent": 0, + "token_mint": "4TyZGqRLG3VcHTGMcLBoPUmqYitMVojXinAmkL8xpump", + "token_ticker": "TESTICLE" + }, + { + "wallet": "7hTckgnGnLQR6sdH7YkqFTAA7VwTfYFaZ6EhEsU3saCX", + "slot": 398893055, + "blockTime": 1770557651, + "tokens": 2.4631999849589192e-05, + "sol_spent": 0, + "token_mint": "4TyZGqRLG3VcHTGMcLBoPUmqYitMVojXinAmkL8xpump", + "token_ticker": "TESTICLE" + }, + { + "wallet": "GP8StUXNYSZjPikyRsvkTbvRV1GBxMErb59cpeCJnDf1", + "slot": 398898654, + "blockTime": 1770559847, + "tokens": 1.5429999999483357e-05, + "sol_spent": 0, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "HLnpSz9h2S4hiLQ43rnSD9XkcUThA7B8hQMKmDaiTLcC", + "slot": 398898654, + "blockTime": 1770559847, + "tokens": 826.2252099961042, + "sol_spent": 0, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "9s3zLabBFGFwf7HNckPdEucYnCtNikvf8CnHWUYYwYCv", + "slot": 398898754, + "blockTime": 1770559886, + "tokens": 1107.093505, + "sol_spent": 0, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "69yhtoJR4JYPPABZcSNkzuqbaFbwHsCkja1sP1Q2aVT5", + "slot": 398898794, + "blockTime": 1770559901, + "tokens": 0.0018589999999960582, + "sol_spent": 0, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "8ekCy2jHHUbW2yeNGFWYJT9Hm9FW7SvZcZK66dSZCDiF", + "slot": 398898794, + "blockTime": 1770559901, + "tokens": 0.0061398599991662195, + "sol_spent": 0, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "4UFscW8wSKQecPQFwcChoEdKByUSRA1dFAXuBWVLfsmu", + "slot": 398898794, + "blockTime": 1770559901, + "tokens": 0.014901469999998085, + "sol_spent": 0, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "6LDKXn2hqEtdW1r9jH2ykv5j4y3n4EPt1ZHDn5iVZgck", + "slot": 398898794, + "blockTime": 1770559901, + "tokens": 1.851000000030467e-05, + "sol_spent": 0, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "HFLPtHFSBA5rj83pyHENFSZ7hRVdCJErng6ebCjUARhk", + "slot": 398898829, + "blockTime": 1770559915, + "tokens": 74.323906, + "sol_spent": 0, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "DSN3j1ykL3obAVNv7ZX49VsFCPe4LqzxHnmtLiPwY6xg", + "slot": 398898832, + "blockTime": 1770559916, + "tokens": 1.3880000011567972e-06, + "sol_spent": 0, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "64LxMqM7ZJnpA5PK65CPz1qhGe3wYfkEtSXq2qvL22zA", + "slot": 398898918, + "blockTime": 1770559949, + "tokens": 41433.281414, + "sol_spent": 0.812772806, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "UwYvNFte7ub4rh2hE9rNmPg7u4aHjrMdD3YVavtvhXK", + "slot": 398898918, + "blockTime": 1770559949, + "tokens": 0.6043342259999918, + "sol_spent": 0, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "8VALoXS8gfwbHKFWvDYsXU3aNJdZuxeRD92tGAb8M1RU", + "slot": 398898922, + "blockTime": 1770559951, + "tokens": 513.643168, + "sol_spent": 0.010035405, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "F4ByVRDvx4bvCg4BNwg3X47p8pi8F9HDYjyv7TFEQs6q", + "slot": 398898961, + "blockTime": 1770559966, + "tokens": 0.006149667000000081, + "sol_spent": 0, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "7Z8K4RawuitwBFt3Nj4UXY5LtUBAmJEuxU4tgQgM8Eqt", + "slot": 398898961, + "blockTime": 1770559966, + "tokens": 32739.275929, + "sol_spent": 0, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV", + "slot": 398898961, + "blockTime": 1770559966, + "tokens": 0.00032366699997510295, + "sol_spent": 0, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "3VbpE4uCmN3j6LnUJzGqUjFDkxxyMpxUtUQjTBCdsjfy", + "slot": 398898961, + "blockTime": 1770559966, + "tokens": 521844.5592029989, + "sol_spent": 0, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "BBBjyqYUWDTgK1NUBUCYK58oVCiF8r6TaqEhW6St9WHd", + "slot": 398899046, + "blockTime": 1770559998, + "tokens": 7482.080412, + "sol_spent": 0.145817858, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "45ruCyfdRkWpRNGEqWzjCiXRHkZs8WXCLQ67Pnpye7Hp", + "slot": 398899046, + "blockTime": 1770559998, + "tokens": 0.00029162299999999086, + "sol_spent": 0, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "ATdxaHo1dfeaq54cRu8LFadvpizf5F29pzzprsRfVZuD", + "slot": 398899169, + "blockTime": 1770560048, + "tokens": 101897.171603, + "sol_spent": 2.02403928, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "7HeD6sLLqAnKVRuSfc1Ko3BSPMNKWgGTiWLKXJF31vKM", + "slot": 398899169, + "blockTime": 1770560048, + "tokens": 0.0016005689999999961, + "sol_spent": 0, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "3hE53e3cLVaLBS9bWA37c3Hf2dLx5RMyebZ6jnnVamoK", + "slot": 398899169, + "blockTime": 1770560048, + "tokens": 102517.986483, + "sol_spent": 2.02403928, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "2BJHgDfho4u2Dxtx16a5YTu4hghjw7jq5ySWo8k4FA2S", + "slot": 398899206, + "blockTime": 1770560063, + "tokens": 8897.126405000003, + "sol_spent": 0, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "3CgvbiM3op4vjrrjH2zcrQUwsqh5veNVRjFCB9N6sRoD", + "slot": 398899206, + "blockTime": 1770560063, + "tokens": 8.906032000000778, + "sol_spent": 0, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "7gR5xfQauGY1qwpa262DxQ54i1Bfgb1S71Ge2vDa55hp", + "slot": 398899206, + "blockTime": 1770560063, + "tokens": 0.001400422999999984, + "sol_spent": 0, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "G5UZAVbAf46s7cKWoyKu8kYTip9DGTpbLZ2qa9Aq69dP", + "slot": 398899206, + "blockTime": 1770560063, + "tokens": 8.752700000513869e-05, + "sol_spent": 0, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "3qQNMCYocEqaf5dN3onBbGsXJ2PhGtn3227o3w6UtLS9", + "slot": 398899206, + "blockTime": 1770560063, + "tokens": 50000.0, + "sol_spent": 0, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "8r3XSZDoYtLJgEgy7WWeUffmzVM4keeNSNjVzA1cqQju", + "slot": 398899255, + "blockTime": 1770560082, + "tokens": 87154.865049, + "sol_spent": 0, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "GMCJvYGf5Ex2ARiMquaBDqU6iKM8uiEQkB8jCnoNfHpC", + "slot": 398899255, + "blockTime": 1770560082, + "tokens": 149.84999999997672, + "sol_spent": 0, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "HFqp6ErWHY6Uzhj8rFyjYuDya2mXUpYEk8VW75K9PSiY", + "slot": 398899259, + "blockTime": 1770560084, + "tokens": 9.999999999621423e-06, + "sol_spent": 0, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "2j2zrqPhFFgFaA6i63EYYzVBXrG5YWZFnCh1g8cgF7M8", + "slot": 398899286, + "blockTime": 1770560094, + "tokens": 228.14385399999992, + "sol_spent": 0, + "token_mint": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "token_ticker": "BLOWFISH" + }, + { + "wallet": "6mcV9oCQhnLza5jxnMs4twbdSaddo2RgxXsTqFJCV2pL", + "slot": 391849401, + "blockTime": 1767763454, + "tokens": 319.9966466203332, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "5Rt8gwgR4EgKsKpUJpspsQJVA21sUqM2dvQenEtQYoFs", + "slot": 391849401, + "blockTime": 1767763454, + "tokens": 1163.6423919999506, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "8NpbamdDtWWJktEK6Br9xgV4BHRFZcijhuioNNoQA65G", + "slot": 391849401, + "blockTime": 1767763454, + "tokens": 0.5821120000000519, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "HydraXoSz7oE3774DoWQQaofKb31Kbn2cbcqG4ShKy85", + "slot": 391849401, + "blockTime": 1767763454, + "tokens": 2.1624999988034688e-05, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "HLnpSz9h2S4hiLQ43rnSD9XkcUThA7B8hQMKmDaiTLcC", + "slot": 391849401, + "blockTime": 1767763454, + "tokens": 28.077886999992188, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "EhYYCPPhsqjwDzH9N6jUWWqfMUrv3yLPQfwgi548oRnr", + "slot": 391849401, + "blockTime": 1767763454, + "tokens": 81.88687500000015, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "GpMZbSM2GgvTKHJirzeGfMFoaZ8UR2X7F4v8vHTvxFbL", + "slot": 391849401, + "blockTime": 1767763454, + "tokens": 0.1288499999999999, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "HuTshmtwcQkWBLzgW3m4uwcmik7Lmz4YFpYcTqMJpXiP", + "slot": 391849401, + "blockTime": 1767763454, + "tokens": 2.2310000531433616e-06, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "HK5DeNa58vsFnVw3GMKUHd3SRBFoedaiqov9PQhVczHZ", + "slot": 391849401, + "blockTime": 1767763454, + "tokens": 0.7397169999999278, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "5ZRUGrsGby6hJ9XweGtjtSfvBhE5LteZW3YuxeCm7W4x", + "slot": 391850477, + "blockTime": 1767763882, + "tokens": 3.906881, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "8psNvWTrdNTiVRNzAgsou9kETXNJm2SXZyaKuJraVRtf", + "slot": 391850500, + "blockTime": 1767763891, + "tokens": 13.558941000000004, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "65ZHSArs5XxPseKQbB1B4r16vDxMWnCxHMzogDAqiDUc", + "slot": 391850500, + "blockTime": 1767763891, + "tokens": 0.09756844200092019, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "EzrFPWa7xMFL1XhzmYQkjNnAGDjQai1JZEUHJTrLmPJQ", + "slot": 391850500, + "blockTime": 1767763891, + "tokens": 2.3817579999999907, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "6EcioYG5g5svhRS3dL28JKp7VytCf86WPe9dNWVY95oJ", + "slot": 391850500, + "blockTime": 1767763891, + "tokens": 13.556329000013648, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "DuUk2a8rMY9bM3Y7cCLj93Rnx9CEksgX4X42v5rvUKvM", + "slot": 391850890, + "blockTime": 1767764044, + "tokens": 17723.324317, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV", + "slot": 391850890, + "blockTime": 1767764044, + "tokens": 2.120999999988271e-05, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "5b8rXMLHsZyrukgFP5HCNf6yej3AtTyTPqCGgHWZtFS1", + "slot": 391850890, + "blockTime": 1767764044, + "tokens": 0.04250475200001347, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "2qHN1fKAGCHM1F9dmHNVXbx9tnoZTRikn8HoYAa7xpEb", + "slot": 391850890, + "blockTime": 1767764044, + "tokens": 0.00038178000000055334, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "CnXEaMDgdyLUD1XbLVn84CoPkPYsJhjwZ8gjEM4EVDyT", + "slot": 391852230, + "blockTime": 1767764577, + "tokens": 704.9433620000054, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "SHARKRdGLNYRZrhotqvZi3XAtT62CRGCFxmg5LJgSHC", + "slot": 391852230, + "blockTime": 1767764577, + "tokens": 2.0348999999697526e-05, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "6Dnn1d4PQLAb3FZeSeBYsRPmtxfxBdygEjGFSM2eXiv3", + "slot": 391853882, + "blockTime": 1767765232, + "tokens": 161.985109, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "FMVHP1xw6ZHB9zLGyrJeeAvEzCBgouH8bPzdkYqq2C5W", + "slot": 391853882, + "blockTime": 1767765232, + "tokens": 2.4667780000000903, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "EEUNhHsRoUVgJUFpkupmdF4v7uLUw1zhYLp7u9s8zFqG", + "slot": 391853882, + "blockTime": 1767765232, + "tokens": 164.38512000000628, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "4moFKtX9z19N9DmsMQavTtrAKY9UbeFdLyaxxRANxDz2", + "slot": 391865100, + "blockTime": 1767769711, + "tokens": 2.012651, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "HSijg5XQVbo6CLfkMM8Jzk2qjaNn6DL9CEnQvZzkK24d", + "slot": 391867164, + "blockTime": 1767770536, + "tokens": 82007.61807900004, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "AvGeFw71N5sNfV97mZ1uNrHg4yfufRicCJUrS9j2ehTX", + "slot": 391867164, + "blockTime": 1767770536, + "tokens": 38.06657200001064, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "6wkyFncKnETKA3bxna7D2c6pbBWUQjfAyNGsnpREa6Bn", + "slot": 391871745, + "blockTime": 1767772363, + "tokens": 2621.395988, + "sol_spent": 0.010657678, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "5Mf2mw12MRg4W9g8yiR5WoXgzpeCMMYJBiX4XxHSuk6P", + "slot": 391872556, + "blockTime": 1767772687, + "tokens": 32488.68971, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "7H3bQRRCPjUyDt2i6wqLyWhjLQWUWPfHQjC2guRkb8Vu", + "slot": 391879312, + "blockTime": 1767775373, + "tokens": 1076657.428366, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "9yj3zvLS3fDMqi1F8zhkaWfq8TZpZWHe6cz1Sgt7djXf", + "slot": 391879312, + "blockTime": 1767775373, + "tokens": 4.25, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "FksffEqnBRixYGR791Qw2MgdU7zNCpHVFYBL4Fa4qVuH", + "slot": 391879312, + "blockTime": 1767775373, + "tokens": 495.75, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "VzurNCf8yjJp1RmTuHU32wT1XbeGoJXJEqQAgYhEj32", + "slot": 391881576, + "blockTime": 1767776267, + "tokens": 6676.960380000062, + "sol_spent": 0.022005793, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "7iWnBRRhBCiNXXPhqiGzvvBkKrvFSWqqmxRyu9VyYBxE", + "slot": 391881576, + "blockTime": 1767776267, + "tokens": 2.200000000129876e-05, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "2Zx3RBXZqKTZbS7sZR7tibA5VN2FqJTnpfv7fQ5hRdkL", + "slot": 391885608, + "blockTime": 1767777859, + "tokens": 334082.4496239999, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "GP8StUXNYSZjPikyRsvkTbvRV1GBxMErb59cpeCJnDf1", + "slot": 391885608, + "blockTime": 1767777859, + "tokens": 334.4168659999996, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "DSN3j1ykL3obAVNv7ZX49VsFCPe4LqzxHnmtLiPwY6xg", + "slot": 391885777, + "blockTime": 1767777925, + "tokens": 100.03458099999989, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "HFqp6ErWHY6Uzhj8rFyjYuDya2mXUpYEk8VW75K9PSiY", + "slot": 391885801, + "blockTime": 1767777935, + "tokens": 99.90108099999998, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + }, + { + "wallet": "HU23r7UoZbqTUuh3vA7emAGztFtqwTeVips789vqxxBw", + "slot": 391885821, + "blockTime": 1767777942, + "tokens": 99.76784800000314, + "sol_spent": 0, + "token_mint": "FasH397CeZLNYWkd3wWK9vrmjd1z93n3b59DssRXpump", + "token_ticker": "BUTTCOIN" + } + ] +} \ No newline at end of file diff --git a/memory/cross_reference_results.json b/memory/cross_reference_results.json new file mode 100644 index 0000000..c9ef9ff --- /dev/null +++ b/memory/cross_reference_results.json @@ -0,0 +1,9 @@ +{ + "timestamp": "2026-02-12T09:34:13.044938+00:00", + "target": { + "mint": "7Gc9WkXewLGBzNDbz9nWZ4PuvEUhy38sAFk1MXoqpump", + "name": "ApeLiquid" + }, + "compared_against": 5, + "multi_token_wallets": {} +} \ No newline at end of file diff --git a/memory/early_buyer_scan.json b/memory/early_buyer_scan.json new file mode 100644 index 0000000..db2363f --- /dev/null +++ b/memory/early_buyer_scan.json @@ -0,0 +1,31 @@ +{ + "scan_date": "2026-02-09T07:11:37.250546+00:00", + "scan_method": "rpc_only", + "tokens_scanned": [ + { + "mint": "HBQB6j9RkAroc3wotE94dyFBx2SntfnVNrKLiJSBpump", + "info": { + "name": "BadBunny", + "symbol": "BadBunny", + "mc": 177855, + "liq": 43060.58, + "dex": "pumpswap", + "price_change_24h": 379 + } + }, + { + "mint": "2NGBAfNMXBU85gjqYutA39b6BCBG5i5MZ4Jvjtdcpump", + "info": { + "name": "ShitCoin", + "symbol": "SHT", + "mc": 602662, + "liq": 73708.25, + "dex": "pumpswap", + "price_change_24h": -36.14 + } + } + ], + "multi_token_wallets": [], + "top_wallets": [], + "total_unique_wallets": 0 +} \ No newline at end of file diff --git a/memory/early_callers.json b/memory/early_callers.json new file mode 100644 index 0000000..ef85287 --- /dev/null +++ b/memory/early_callers.json @@ -0,0 +1,156 @@ +{ + "description": "X/Twitter accounts that were consistently early to winning tokens. Track these for future alpha signals.", + "last_updated": "2026-02-08", + "callers": [ + { + "handle": "@AidenJackCrypto", + "reliability_score": 9, + "early_calls": [ + {"token": "$LUMEN", "chain": "Base", "date": "2026-02-04", "mc_at_call": "130K", "peak_mc": "5.2M+", "multiple": "40x", "context": "Called at 130K MC via Telegram group. First trader call on $LUMEN."}, + {"token": "$JUNO", "chain": "Base", "date": "2026-02-07", "mc_at_call": "286K", "peak_mc": "1.8M+", "multiple": "6x+", "context": "First trader call ~09:24 GMT Feb 7. Called at 286K MC."} + ], + "notes": "HIGHEST PRIORITY. Early to BOTH $LUMEN and $JUNO. Base chain AI/agent token specialist. Runs Telegram alpha group.", + "follow_priority": "critical" + }, + { + "handle": "@BioStone_chad", + "reliability_score": 8, + "early_calls": [ + {"token": "$LUMEN", "chain": "Base", "date": "2026-02-04", "mc_at_call": "92K", "peak_mc": "5.6M+", "multiple": "60x+", "context": "Called channel at 92K MC. Dip-bought at 1.5M."}, + {"token": "$JUNO", "chain": "Base", "date": "2026-02-07", "mc_at_call": "1.2M", "peak_mc": "2.1M+", "multiple": "2x", "context": "Bought at 1.2M, called dip buy opportunity."} + ], + "notes": "HIGH PRIORITY. Early to BOTH $LUMEN (92K!) and $JUNO. Base chain focus. Channel caller.", + "follow_priority": "critical" + }, + { + "handle": "@WavexCaller", + "reliability_score": 8, + "early_calls": [ + {"token": "$BadBunny", "chain": "Solana", "date": "2026-02-08", "mc_at_call": "26K", "peak_mc": "2M+", "multiple": "54x+", "context": "Called at 26K MC."}, + {"token": "$LIQUID", "chain": "Solana", "date": "2026-02-08", "mc_at_call": "279K", "peak_mc": "3M+", "multiple": "11x", "context": "Called at 279K MC."}, + {"token": "$sims", "chain": "Solana", "date": "2026-02-08", "mc_at_call": "34K", "peak_mc": "86K+", "multiple": "6.38x", "context": "Called at 34K MC. PnL screenshots shared."}, + {"token": "$SHT", "chain": "Solana", "date": "2026-02-08", "mc_at_call": "122K", "peak_mc": "802K+", "multiple": "17x", "context": "Called at 122K MC ShitCoin."}, + {"token": "$BigTrout", "chain": "Solana", "date": "2026-02-05", "mc_at_call": "101K", "peak_mc": "5.4M+", "multiple": "53x", "context": "Called at 101K MC. 48-53x PnL claimed."}, + {"token": "$REKT", "chain": "Solana", "date": "2026-02-08", "mc_at_call": "121K", "peak_mc": "94K", "multiple": "4x", "context": "Called at 121K MC. Trending on DexScreener."}, + {"token": "$Sinclair", "chain": "Solana", "date": "2026-02-08", "mc_at_call": "100K", "peak_mc": "1.2M+", "multiple": "12x", "context": "Called at 100K MC. Baby Sinclair meme."} + ], + "notes": "VERIFIED: Posts CAs during early pump (2-5x within 5min of launch), NOT pre-pump. Real-time tracker, not pre-pump sniper. TG group t.me/WaveXCalls may call earlier. 7 tokens tracked. Coordinated with @0zutta.", + "follow_priority": "critical", + "verification_status": "verified_early_pump", + "verification_date": "2026-02-08", + "verification_notes": "$BadBunny: posted at 14:36 GMT, 5min in at 2.6x with CA. $BigTrout: posted at 22:42 GMT, 5min in at 2.5x with CA. $SHT: posted at 01:54 GMT, 3h in at 2.1x with CA." + }, + { + "handle": "@cfm_sol", + "reliability_score": 7, + "early_calls": [ + {"token": "$LUMEN", "chain": "Base", "date": "2026-02-04", "mc_at_call": "1M", "peak_mc": "5M+", "multiple": "5x", "context": "Called at 1M MC with detailed narrative breakdown on Albert Wenger/USV backing."} + ], + "notes": "Good narrative researcher. Called $LUMEN with detailed thesis on VC backing.", + "follow_priority": "high" + }, + { + "handle": "@JMania402", + "reliability_score": 7, + "early_calls": [ + {"token": "$LUMEN", "chain": "Base", "date": "2026-02-04", "mc_at_call": "1M", "peak_mc": "5.5M+", "multiple": "5.5x", "context": "Called at 1M, multiple threads on dips/reversals through Feb 8."} + ], + "notes": "Repeat updater — posts multiple times per token including dip analysis.", + "follow_priority": "high" + }, + { + "handle": "@EricCryptoman", + "reliability_score": 7, + "early_calls": [ + {"token": "$JUNO", "chain": "Base", "date": "2026-02-07", "mc_at_call": "sub-1M", "peak_mc": "2M+", "multiple": "2x+", "context": "Called at sub-1M MC. High-impact post (189 likes, 40K+ views)."} + ], + "notes": "High-engagement account. $JUNO call got massive visibility. Pairs related tokens.", + "follow_priority": "high" + }, + { + "handle": "@0zutta", + "reliability_score": 4, + "early_calls": [ + {"token": "$Goyim", "chain": "Solana", "date": "2026-02-01", "mc_at_call": "35.6K", "peak_mc": "1.2M+", "multiple": "18x", "context": "Called at 35.6K MC."}, + {"token": "$BlackSwan", "chain": "Solana", "date": "2026-02-06", "mc_at_call": "280K", "peak_mc": "844K+", "multiple": "3x", "context": "Called at 280.5K MC."}, + {"token": "$sims", "chain": "Solana", "date": "2026-02-08", "mc_at_call": "34.3K", "peak_mc": "86K+", "multiple": "5.94x", "context": "Called at 34.3K MC."}, + {"token": "$SHT", "chain": "Solana", "date": "2026-02-08", "mc_at_call": "122.4K", "peak_mc": "802K+", "multiple": "17x", "context": "Called at 122.4K MC."}, + {"token": "$BigTrout", "chain": "Solana", "date": "2026-02-04", "mc_at_call": "100.5K", "peak_mc": "5.4M+", "multiple": "51x+", "context": "Called at 100.5K MC on launch day."}, + {"token": "$REKT", "chain": "Solana", "date": "2026-02-08", "mc_at_call": "121K", "peak_mc": "94K", "multiple": "4x", "context": "Called at 121K MC. Same timing as @WavexCaller."}, + {"token": "$Sinclair", "chain": "Solana", "date": "2026-02-08", "mc_at_call": "100K", "peak_mc": "1.2M+", "multiple": "6x", "context": "Called at 100K MC. Same timing as @WavexCaller."} + ], + "notes": "PARTIALLY DEBUNKED: $Goyim posts referenced WRONG CA (different token). $BigTrout posted 44min after @WavexCaller (coordination). No pre-pump calls verified. Likely reposts @WavexCaller calls. No wallet/PnL proof ever shared.", + "follow_priority": "low", + "verification_status": "partially_debunked", + "verification_date": "2026-02-08", + "verification_notes": "$Goyim: referenced CA GJBSNoz...pump, NOT our tracked 9S8edq...pump. $BigTrout: first post 22:42 GMT, 44min after @WavexCaller, after initial pump. No wallet/PnL transparency." + }, + { + "handle": "@ELCharpo45", + "reliability_score": 7, + "early_calls": [ + {"token": "$JESTERGOON", "chain": "Solana", "date": "2026-02-07", "mc_at_call": "15K", "peak_mc": "393K+", "multiple": "15.8x", "context": "Called at 15K MC — one of the earliest public calls. Pre-graduation from pump.fun."} + ], + "notes": "Very early JESTERGOON caller at 15K MC (pre-graduation). Need more data points.", + "follow_priority": "high" + }, + { + "handle": "@Peter1015160", + "reliability_score": 2, + "early_calls": [ + {"token": "$Goyim", "chain": "Solana", "date": "2026-02-01", "mc_at_call": "2.4K", "peak_mc": "1.2M+", "multiple": "146x", "context": "Called at 2.4K MC — bonding curve phase."}, + {"token": "$SHT", "chain": "Solana", "date": "2026-02-08", "mc_at_call": "13K", "peak_mc": "802K+", "multiple": "84.6x", "context": "Called at 13K MC. Another insanely early entry."} + ], + "notes": "FULLY DEBUNKED: All 'early calls' are retroactive brags posted AFTER pump. Claims private TG calls at 2.4K/13K MC but zero public evidence. Selling TG access via fake track record.", + "follow_priority": "ignore", + "verification_status": "debunked", + "verification_date": "2026-02-08", + "verification_notes": "$Goyim: only post Feb 1, 21:22 GMT says 'Called at 2.4K, watched it run to 351K' — retroactive. $SHT: only post Feb 8, 09:52 GMT says '84.6x from 13K to 1.1M' — retroactive. No wallet/PnL proof. No public early CA posts found." + }, + { + "handle": "@TheWhiteWhaleX", + "reliability_score": 6, + "early_calls": [ + {"token": "$JESTERGOON", "chain": "Solana", "date": "2026-02-07", "mc_at_call": "30K", "peak_mc": "393K+", "multiple": "4.7x", "context": "Called at 30K MC, early pre-graduation call."} + ], + "notes": "Early JESTERGOON caller. Need more data points to assess consistency.", + "follow_priority": "medium" + }, + { + "handle": "@0xWiz7", + "reliability_score": 6, + "early_calls": [ + {"token": "$LUMEN", "chain": "Base", "date": "2026-02-04", "mc_at_call": "1M", "peak_mc": "5M+", "multiple": "5x", "context": "Called at 1M MC with CA and project details."} + ], + "notes": "Early $LUMEN caller. Need more data points.", + "follow_priority": "medium" + }, + { + "handle": "@tomosman", + "reliability_score": null, + "early_calls": [ + {"token": "$JUNO", "chain": "Base", "date": "2026-02-07", "mc_at_call": "launch", "peak_mc": "2M+", "multiple": "N/A (creator)", "context": "Creator of $JUNO / Juno Agent. Followed by Jeff Bezos, pmarca."} + ], + "notes": "CREATOR not caller. Watch his future launches — followed by Bezos/pmarca signals legitimacy.", + "follow_priority": "watch_launches" + }, + { + "handle": "@albertwenger", + "reliability_score": null, + "early_calls": [ + {"token": "$LUMEN", "chain": "Base", "date": "2026-02-04", "mc_at_call": "N/A (creator)", "peak_mc": "5M+", "multiple": "N/A (creator)", "context": "Creator/initiator of $LUMEN. USV partner."} + ], + "notes": "CREATOR not caller. USV venture capitalist. Watch for future agent token launches.", + "follow_priority": "watch_launches" + } + ], + "patterns_discovered": [ + {"pattern": "Same accounts early to multiple Base AI tokens", "evidence": "@AidenJackCrypto and @BioStone_chad were both early to $LUMEN AND $JUNO within 3 days", "implication": "These accounts are plugged into Base AI agent meta.", "confidence": "high"}, + {"pattern": "VC/elite-follow creators spawn tradeable tokens", "evidence": "@albertwenger (USV) created $LUMEN, @tomosman (followed by Bezos) created $JUNO. Both pumped 10x+.", "implication": "Monitor accounts followed by elite VCs/tech founders for new token launches.", "confidence": "high"}, + {"pattern": "Base AI agent tokens emerging as narrative", "evidence": "$LUMEN, $JUNO, $CLAW, $KELLYCLAUDE all on Base.", "implication": "Base chain AI agent tokens = current hot narrative.", "confidence": "high"}, + {"pattern": "Repeat Solana PF callers across unrelated tokens", "evidence": "@WavexCaller VERIFIED early to BadBunny (26K, 5min in) AND BigTrout (101K, 5min in). Posts CAs during early pump with real-time tracking.", "implication": "Track @WavexCaller next calls — but note they post DURING pump not BEFORE. Real alpha may be in TG group.", "confidence": "high"}, + {"pattern": "DEBUNKED: Bonding curve snipers call at sub-10K MC", "evidence": "@Peter1015160 DEBUNKED — all posts retroactive brags after pump. No public CA at 2.4K or 13K. @ELCharpo45 still unverified.", "implication": "Do NOT trust claimed low-MC calls without timestamp verification. Many accounts fake early calls to sell TG access.", "confidence": "debunked"}, + {"pattern": "Coordinated caller networks inflate apparent consensus", "evidence": "@0zutta posts same tokens as @WavexCaller 44min later. Referenced WRONG CA for $Goyim. No independent early calls verified.", "implication": "Cross-referencing multiple callers on same token may be misleading if they are coordinated/reposting. Verify independently.", "confidence": "high"} + ], + "tracking_instructions": "Each daily session should: 1) Check latest posts from all 'critical' and 'high' priority callers, 2) If they mention a new token, immediately flag it as alpha signal, 3) Cross-reference new calls against other early callers (if 2+ early callers mention same token = high conviction), 4) Update reliability_score based on outcomes" +} diff --git a/memory/intelligence_log.jsonl b/memory/intelligence_log.jsonl new file mode 100644 index 0000000..b66f75a --- /dev/null +++ b/memory/intelligence_log.jsonl @@ -0,0 +1,31 @@ +{"date":"2026-02-08","category":"market_structure","signal":"BTC capitulation event - dropped from $73K to $60K on Feb 5, record $3.2B realized loss. Fear & Greed at 7. Weekly RSI sub-30 for first time since mid-2022.","source":"web","confidence":"high","status":"developing","follow_up":"Monitor daily ETF flows for reversal signal. Check if BTC holds $60K support on retest.","related_tokens":["BTC","ETH"],"tags":["capitulation","bottom_signal","macro"]} +{"date":"2026-02-08","category":"market_structure","signal":"BTC ETF sustained outflows - $6.18B over 3 months. Only IBIT still receiving inflows. Institutional demand reversed per CryptoQuant.","source":"web","confidence":"high","status":"developing","follow_up":"Daily ETF flow check. IBIT inflow reversal would be extremely bearish.","related_tokens":["BTC"],"tags":["etf","institutional","flows"]} +{"date":"2026-02-08","category":"defi","signal":"DeFi TVL only dropped 12% (to ~$105B) despite 30-50% token price crashes. 1.6M ETH added to DeFi in past week. Better collateralized than 2025.","source":"web","confidence":"high","status":"confirmed","follow_up":"Track if ETH DeFi deposits continue growing. Sign of maturation.","related_tokens":["ETH","AAVE","LIDO"],"tags":["defi","resilience","tvl"]} +{"date":"2026-02-08","category":"protocol","signal":"HYPE slashed Feb unlock by 90% (1.2M to 140K tokens). Token rallied 50% while market dropped 5%. TVL $1.5B, 337% growth, $4M+/month fees.","source":"web","confidence":"high","status":"confirmed","follow_up":"Monitor HIP-4 prediction market launch. Watch March 6 $309M unlock - will they reduce again?","related_tokens":["HYPE"],"tags":["unlock","bullish","revenue"]} +{"date":"2026-02-08","category":"protocol","signal":"ONDO token down 80% despite tokenized equity volume up 2,695%. $1.94B unlock on Jan 18 crushed price. MetaMask integration Feb 3 gives access to 200+ tokenized stocks.","source":"web","confidence":"high","status":"developing","follow_up":"Monitor ONDO at $0.20-$0.32 demand floor. Track MetaMask integration adoption metrics.","related_tokens":["ONDO"],"tags":["rwa","unlock","paradox"]} +{"date":"2026-02-08","category":"protocol","signal":"Aave V4 launching 2026. Revenue sharing announced Jan 2. SEC investigation closed Dec 2025. $28B TVL, #1 DeFi protocol.","source":"web","confidence":"high","status":"confirmed","follow_up":"Track V4 launch date. Monitor revenue sharing implementation timeline.","related_tokens":["AAVE"],"tags":["defi","revenue","regulatory"]} +{"date":"2026-02-08","category":"ecosystem","signal":"Solana transitioning from memecoins to micropayments. Alpenglow upgrade (150ms finality) targeting H1 2026. Firedancer production rollout. SOL ETFs live.","source":"web","confidence":"high","status":"developing","follow_up":"Track Alpenglow mainnet deployment date. Monitor stablecoin supply growth on Solana.","related_tokens":["SOL","JUP"],"tags":["solana","infrastructure","narrative_shift"]} +{"date":"2026-02-08","category":"risk","signal":"$400M stolen in crypto hacks in January 2026. CrossCurve $3M bridge exploit. Truebit $26.5M hack. Same attacker hit Truebit and Sparkle.","source":"web","confidence":"high","status":"confirmed","follow_up":"Monitor for new exploits. Bridge risk remains elevated.","related_tokens":[],"tags":["security","exploit","risk"]} +{"date":"2026-02-08","category":"unlock","signal":"$732M in February token unlocks. HYPE $306M (slashed 90%), ZRO $44M+, JUP $44M+ (cliff Feb 28), MOVE Feb 9, BERA 41.7% of circulating.","source":"web","confidence":"high","status":"developing","follow_up":"Track JUP price around Feb 28 cliff. Monitor BERA post-unlock selling.","related_tokens":["HYPE","JUP","ZRO","MOVE","BERA"],"tags":["unlocks","sell_pressure"]} +{"date":"2026-02-08","category":"alpha","signal":"Lighter exchange running points program - largest decentralized perps DEX by 30-day volume. Token airdrop highly likely in 2026.","source":"web","confidence":"medium","status":"new","follow_up":"Track Lighter volume growth. Monitor for token announcement.","related_tokens":[],"tags":["airdrop","farming","perps"]} +{"date":"2026-02-08","category":"alpha","signal":"OpenSea SEA token launching Q1 2026. 50% to community, majority via airdrop claim.","source":"web","confidence":"high","status":"developing","follow_up":"Monitor for claim date announcement. Check eligibility criteria.","related_tokens":["SEA"],"tags":["airdrop","nft"]} +{"date":"2026-02-08","category":"alpha","signal":"Monad testnet live. $244M raised from Paradigm + DragonFly. EVM L1 with 10K TPS. Among most anticipated launches.","source":"web","confidence":"high","status":"developing","follow_up":"Track testnet activity and mainnet timeline. Farm testnet for airdrop.","related_tokens":[],"tags":["airdrop","l1","farming"]} +{"date":"2026-02-08","category":"smart_money","signal":"Trend Research deposited $1.8B ETH on Aave, borrowed $958M stablecoins. Massive leveraged ETH long.","source":"web","confidence":"high","status":"developing","follow_up":"Monitor Aave health factor. If ETH drops to $1,500, this position may face liquidation.","related_tokens":["ETH","AAVE"],"tags":["whale","leverage","institutional"]} +{"date":"2026-02-08","category":"vc","signal":"$1.4B in crypto VC funding in January 2026. Focus on stablecoin infrastructure, institutional rails, on-chain credit. Key deals: $250M interop/stablecoin Series C, LMAX $150M, Mesh $75M.","source":"web","confidence":"high","status":"confirmed","follow_up":"Track which funded protocols launch tokens. Stablecoin infra is the VC thesis.","related_tokens":[],"tags":["vc","funding","stablecoins"]} +{"date":"2026-02-08","category":"contrarian","signal":"BTC weekly RSI sub-30 has historically preceded major bottoms within 3-6 months. 44% of BTC supply underwater similar to 2015/2019/2022 bottoms. But ETF outflows haven't reversed.","source":"web","confidence":"medium","status":"developing","follow_up":"Track if RSI signal leads to bottom formation within expected timeframe. Key contrarian question: is this a structural shift or cyclical bottom?","related_tokens":["BTC"],"tags":["contrarian","bottom","cycle"]} +{"date":"2026-02-08","category":"market_structure","signal":"BTC ETF inflows flipped positive +$330M on Feb 7, breaking sustained outflow streak. First meaningful positive flow since capitulation.","source":"grok_x_search","confidence":"high","status":"new","follow_up":"CRITICAL: If inflows sustain 2-3 more days, confirms regime change. Monitor daily.","related_tokens":["BTC"],"tags":["etf","flows","regime_change"]} +{"date":"2026-02-08","category":"market_structure","signal":"BTC funding rates flipped negative (-0.0034% to -0.006%). Shorts paying longs. Classic bottom signal post-deleveraging.","source":"grok_x_search","confidence":"high","status":"confirmed","follow_up":"Monitor for funding normalization as sign of stabilization.","related_tokens":["BTC"],"tags":["funding","bottom_signal"]} +{"date":"2026-02-08","category":"market_structure","signal":"BTC OI crashed 23% during $60K dip, now stabilizing ~$82B. Deleveraging largely complete.","source":"grok_x_search","confidence":"high","status":"confirmed","follow_up":"Watch for OI rebuild as sign of new positioning.","related_tokens":["BTC"],"tags":["open_interest","deleveraging"]} +{"date":"2026-02-08","category":"market_structure","signal":"Stablecoin supply expanding: $267M USDC minted on ETH, $1B USDT minted on TRON (week total $3B+). Fresh dry powder.","source":"grok_x_search","confidence":"high","status":"confirmed","follow_up":"Track if stablecoin mints convert to spot buys.","related_tokens":["USDC","USDT"],"tags":["stablecoins","liquidity"]} +{"date":"2026-02-08","category":"smart_money","signal":"Hyperliquid top whales unanimously short BTC. 0x4e31 shorting 3x $3.53M at $70.7K entry. 0x94d3 $5.11M short +$4.8M unrealized PnL.","source":"grok_x_search","confidence":"high","status":"developing","follow_up":"If these whales close shorts = strong bullish signal. Monitor daily.","related_tokens":["BTC","HYPE"],"tags":["hyperliquid","shorts","positioning"]} +{"date":"2026-02-08","category":"smart_money","signal":"Trump insider whale dumped 6,599 BTC (~$500M). Political dimension to sell-off.","source":"grok_x_search","confidence":"medium","status":"new","follow_up":"Verify via Arkham. Track wallet for further movements.","related_tokens":["BTC"],"tags":["whale","political","dump"]} +{"date":"2026-02-08","category":"risk","signal":"Binance ETH/USDT manipulation: $100 pumps/dumps 40x in seconds, liquidating $1.3B longs ($7B total). X users calling it market manipulation.","source":"grok_x_search","confidence":"medium","status":"new","follow_up":"Monitor for regulatory response. Self-custody critical.","related_tokens":["ETH"],"tags":["manipulation","exchange","risk"]} +{"date":"2026-02-08","category":"defi","signal":"Perp DEX volumes hit second-highest on record. Hyperliquid captured >30% market share, 5 straight weeks growth.","source":"grok_x_search","confidence":"high","status":"confirmed","follow_up":"Track if perp volumes sustain. Leverage demand outpacing spot.","related_tokens":["HYPE"],"tags":["perps","volume","defi"]} +{"date":"2026-02-08","category":"alpha","signal":"Jupiter JUPUARY 2026 confirmed: snapshot Jan 30, 200M airdrop + 200M to stakers. Sellers get 3x penalty.","source":"grok_x_search","confidence":"high","status":"confirmed","follow_up":"Check eligibility. Track JUP price around distribution.","related_tokens":["JUP"],"tags":["airdrop","solana"]} +{"date":"2026-02-08","category":"vc","signal":"Week 1 Feb VC: $252M - Anchorage Digital $100M (Tether-led), TRM Labs $70M ($1B val), Konnex $15M. Compliance/custody/infra focus.","source":"grok_x_search","confidence":"high","status":"confirmed","follow_up":"Track Anchorage, TRM for token launches. VCs betting infra while retail panics.","related_tokens":[],"tags":["vc","infra","compliance"]} +{"date":"2026-02-08","category":"alpha","signal":"Decibel (Aptos perp DEX) Season 0 pre-deposit live Feb 10 UTC. Min 50 USDC, time-weighted points for TGE airdrop.","source":"grok_x_search","confidence":"medium","status":"new","follow_up":"Deposit on Feb 10. Track volume and TVL growth.","related_tokens":[],"tags":["airdrop","perps","aptos"]} +{"date":"2026-02-08","category":"risk","signal":"Massive Solana phishing wave: fake airdrop sites ($TULSA, $BFS, BlackSwan, $HYB, $USOR). GameFi phishing using bot-flagged screen tricks.","source":"grok_x_search","confidence":"high","status":"confirmed","follow_up":"Warn against connecting to unknown airdrop claim sites.","related_tokens":["SOL"],"tags":["phishing","scam","security"]} +{"date":"2026-02-08","category":"risk","signal":"HYPE pre-unlock pump pattern flagged on X. Team/insiders may pump before unlock to maximize exit value. Watch March 6.","source":"grok_x_search","confidence":"medium","status":"new","follow_up":"Monitor HYPE price action in late Feb. If pump accelerates before March 6, reduce position.","related_tokens":["HYPE"],"tags":["risk","unlock","manipulation"]} +{"date":"2026-02-08","category":"alpha","signal":"$LUMEN (Base AI agent token) launched Feb 4 by Albert Wenger (USV partner). CA: 0xa9FEE7b2F54781A14c85A1B8815345AefbE1EB07. Sub-200K to 5M+ MC. AI agent experiment funded by Bankr fee redirection. Organic discovery in Base trenches.","source":"grok_x_search","confidence":"high","status":"confirmed","follow_up":"Track @albertwenger for experiment updates. Monitor early callers (@AidenJackCrypto, @BioStone_chad) for next calls.","related_tokens":["LUMEN"],"tags":["base","ai_agent","alpha","early_caller"]} +{"date":"2026-02-08","category":"alpha","signal":"$JUNO (Base AI bot token) launched Feb 7 by @tomosman (followed by Bezos, pmarca). CA: 0x4E6c9f48f73E54EE5F3AB7e2992B2d733D0d0b07. AI agent hunting zero-human companies. +2354% in hours. Same early callers as $LUMEN.","source":"grok_x_search","confidence":"high","status":"confirmed","follow_up":"Track @tomosman and @JunoAgent for updates. Monitor same early callers — they spotted both tokens.","related_tokens":["JUNO"],"tags":["base","ai_agent","alpha","early_caller"]} +{"date":"2026-02-08","category":"pattern","signal":"EARLY CALLER CONVERGENCE: @AidenJackCrypto and @BioStone_chad were early to BOTH $LUMEN (Feb 4) and $JUNO (Feb 7). Base AI agent token meta emerging. Same callers finding multiple winners = high-signal accounts.","source":"analysis","confidence":"high","status":"new","follow_up":"CRITICAL: Check these accounts daily for new calls. If they mention a new token, treat as highest-priority alpha signal.","related_tokens":["LUMEN","JUNO"],"tags":["early_caller","pattern","meta"]} diff --git a/memory/jester_scan_latest.json b/memory/jester_scan_latest.json new file mode 100644 index 0000000..2e21832 --- /dev/null +++ b/memory/jester_scan_latest.json @@ -0,0 +1,112 @@ +{ + "timestamp": "2026-02-11T19:20:25Z", + "market": { + "mc": 280620, + "price": 0.0002806, + "change_24h": 48.32, + "liq": 51983, + "vol_24h": 78939 + }, + "holders": [ + { + "rank": 1, + "wallet": "2Aj1MJG6GLWfU8YEyyTcGsehxDo3MboVAx3XNLeEsDG2", + "amount": 92142719.82 + }, + { + "rank": 2, + "wallet": "DZeaVStjUv6Arnv9RZqTetqD8APNcgDiSMCEt6sYg7xY", + "amount": 36600689.44 + }, + { + "rank": 3, + "wallet": "5gvNhHuiFf2XUhKcgHX82paL93WTVnYjDLLtCmamVGZA", + "amount": 34829873.18 + }, + { + "rank": 4, + "wallet": "H5jMAEnAPj9ALTZ5mgmMAFhDzn7p29Fe24uEpHdZApgh", + "amount": 29010768.4 + }, + { + "rank": 5, + "wallet": "2f9WiMPTx3VBA7xgfn9iFtvfnVHzj7ha5qJPL4q771Fh", + "amount": 26681933.6 + }, + { + "rank": 6, + "wallet": "EwTNPYTuwxMzrvL19nzBsSLXdAoEmVBKkisN87csKgtt", + "amount": 23544015.38 + }, + { + "rank": 7, + "wallet": "97FAmxHrqx5uD4UHFfD2vh8Nh8tgFRNSvsQnzJVpDYpc", + "amount": 22819167.47 + }, + { + "rank": 8, + "wallet": "14KbXMEiDZ6jW4Q5fYyHkMn8HhAuF6rjdXQXrbaD9nZe", + "amount": 22541550.11 + }, + { + "rank": 9, + "wallet": "AmNQzpASgNwvfFgPKbftF46hFgDJ1qgyF9YhPt9XAE1u", + "amount": 20962185.56 + }, + { + "rank": 10, + "wallet": "7TQfNAr4R5wh3G7PjksnHhKmKjHYDHNa7jaKTntrmXXk", + "amount": 19552495.76 + }, + { + "rank": 11, + "wallet": "HUfVt5m9gEntmdU2yTdE7d3RUmtnWj7nHmCNS7bF4Z6K", + "amount": 18899891.42 + }, + { + "rank": 12, + "wallet": "F8v6SMMsjtLjS7C27d4paQrF6kaR8fZ7yVmNg3iuTXqR", + "amount": 17935068.13 + }, + { + "rank": 13, + "wallet": "737MTiBdXAqBCxVcAY81xNKkhmZBnECLzeGegyYV3BB", + "amount": 17279740.55 + }, + { + "rank": 14, + "wallet": "APRCU9UbhM7xYn2LNETJHtnwfo94GmnAupQdRiWp2Cm7", + "amount": 14614461.71 + }, + { + "rank": 15, + "wallet": "fNrJmJ1aQMx1vgnGwJcLWkUCBrDy7GF7ZpVqiXuRFrJ", + "amount": 13501348.55 + }, + { + "rank": 16, + "wallet": "G5CQNa8YpaBaPJQLQKc33AxfJmBG3p5yrRNZ2utZeK95", + "amount": 12312994.12 + }, + { + "rank": 17, + "wallet": "7cbguGjrcMTR7Y3ZzMk4xu96nisRS5trExgPTUD63WVe", + "amount": 12000000.0 + }, + { + "rank": 18, + "wallet": "C3nLTNMK6Ao1s3J1CQhv8GbT3NoMmifWoi9PGEcYd9hP", + "amount": 11765260.19 + }, + { + "rank": 19, + "wallet": "Ej6ZmCWs2pY4H2YrrNg6hazXkjdgcb8f1QEgEf5z1Meg", + "amount": 11376112.39 + }, + { + "rank": 20, + "wallet": "DNfuF1L62WWyW3pNakVkyGGFzVVhj4Yr52jSmdTyeBHm", + "amount": 11110189.99 + } + ] +} \ No newline at end of file diff --git a/memory/patterns.json b/memory/patterns.json new file mode 100644 index 0000000..10e329c --- /dev/null +++ b/memory/patterns.json @@ -0,0 +1,82 @@ +{ + "recurring_signals": [ + { + "pattern": "Token unlock reduction = immediate price pump", + "occurrences": 1, + "reliability": "high", + "example": "HYPE slashed Feb unlock 90%, rallied 50% while market dropped 5%", + "date_first_seen": "2026-02-08" + }, + { + "pattern": "Weekly RSI sub-30 precedes major bottoms within 3-6 months", + "occurrences": 4, + "reliability": "high", + "example": "2015, 2019, 2022 cycles all saw this. Now triggered again Feb 2026.", + "date_first_seen": "2026-02-08" + }, + { + "pattern": "DeFi TVL resilience during price crashes signals sector maturation", + "occurrences": 1, + "reliability": "medium", + "example": "TVL dropped 12% while prices dropped 30-50% in Jan-Feb 2026", + "date_first_seen": "2026-02-08" + }, + { + "pattern": "Massive token unlocks crush price regardless of fundamentals", + "occurrences": 2, + "reliability": "high", + "example": "ONDO $1.94B unlock sent token down 80%. BERA 41.7% circulating unlock.", + "date_first_seen": "2026-02-08" + } + ], + "market_regime_history": [ + { + "date": "2026-02-08", + "regime": "extreme_fear_capitulation", + "btc_price": 69542, + "fear_greed": 7, + "btc_dominance": 58.7, + "notes": "Record realized losses, weekly RSI sub-30, 52% drawdown from ATH. ETF outflows sustained." + } + ], + "source_reliability": { + "web_search": "primary_source_session_1", + "grok": "unavailable", + "defillama": "high_reliability", + "coinglass": "high_reliability", + "coindesk": "high_reliability", + "coingecko": "high_reliability" + }, + "narrative_lifecycle": [ + { + "narrative": "DeFi Real Yield", + "stage": "growing", + "started": "2025", + "tokens": ["AAVE", "HYPE", "LIDO"], + "notes": "Revenue-generating protocols outperforming in bear market" + }, + { + "narrative": "RWA Tokenization", + "stage": "infrastructure_building", + "started": "2024", + "tokens": ["ONDO"], + "notes": "Institutional adoption strong but token economics lagging (unlock pressure)" + }, + { + "narrative": "Memecoin Casino", + "stage": "declining", + "started": "2023", + "tokens": ["Various Solana memes"], + "notes": "Standard Chartered sees shift to micropayments. Bear market killing memecoin liquidity." + }, + { + "narrative": "Capitulation Bottom", + "stage": "forming", + "started": "2026-02", + "tokens": ["BTC", "ETH"], + "notes": "On-chain metrics at historical bottom levels. Need ETF flow reversal for confirmation." + } + ], + "ev_calibration_patterns": [], + "current_regime": "extreme_fear_capitulation" +} diff --git a/memory/positions.json b/memory/positions.json new file mode 100644 index 0000000..55a9746 --- /dev/null +++ b/memory/positions.json @@ -0,0 +1,11 @@ +{ + "positions": [], + "stats": { + "total_buys": 0, + "total_sells": 0, + "total_sol_spent": 0, + "total_sol_received": 0, + "buys_today": 0, + "last_buy_date": "" + } +} diff --git a/memory/realtime_alerts.jsonl b/memory/realtime_alerts.jsonl new file mode 100644 index 0000000..4e309a7 --- /dev/null +++ b/memory/realtime_alerts.jsonl @@ -0,0 +1,5 @@ +{"timestamp": "2026-02-11T10:17:13.444591+00:00", "symbol": "NIGGACULT", "ca": "348dLzNEF3bRQR4Wjwzuz7oE2mdy3hSvdPz4nDNEpump", "mc": 54826, "score": 90, "reasons": ["MC sweet spot ($50K-$500K)", "Extreme vol/MC 5.4x", "New (16h)", "Buy pressure 1.4x"], "alpha_wallets": []} +{"timestamp": "2026-02-11T10:17:13.444591+00:00", "symbol": "BUCKARU", "ca": "E2HNWS5L6gwmtC9SZPpRq6Yp3V5gzotFrL3dAEP2pump", "mc": 319501, "score": 90, "reasons": ["MC sweet spot ($50K-$500K)", "Strong liq $50,864", "Extreme vol/MC 13.4x", "New (15h)"], "alpha_wallets": []} +{"timestamp": "2026-02-11T10:17:13.444591+00:00", "symbol": "MOON", "ca": "25TBJCRN7m7EDcWcnKAZkLbTUiN9mUBnEBD6FBNUpump", "mc": 29149.08, "score": 75, "reasons": ["LOW LIQUIDITY", "Extreme vol/MC 2.3x", "$1h vol $68,363", "FRESH (0.8h old)", "Buy pressure 1.6x", "1h pump +1093%"], "alpha_wallets": []} +{"timestamp": "2026-02-11T10:17:13.444591+00:00", "symbol": "USRX", "ca": "USRX8A1BNVzPSWt9tXA1ZjeMWWnpsWktdhueCBDZAjS", "mc": 7102631, "score": 60, "reasons": ["Strong liq $246,254", "New (20h)", "Strong buy pressure 2.8x"], "alpha_wallets": []} +{"timestamp": "2026-02-11T10:17:13.444591+00:00", "symbol": "Rex", "ca": "HXvQAQwytoLngKWQtge3oJnLHsaLwTxPbX48DctLpump", "mc": 67342, "score": 85, "reasons": ["MC sweet spot ($50K-$500K)", "Extreme vol/MC 6.4x", "Buy pressure 1.5x"], "alpha_wallets": []} diff --git a/memory/realtime_seen.json b/memory/realtime_seen.json new file mode 100644 index 0000000..767cd23 --- /dev/null +++ b/memory/realtime_seen.json @@ -0,0 +1 @@ +{"cas": ["44YYJxxJA4RCFzJdgjUAtk5zvExiRViC7y1LYjgvpump", "BAfCyAUQhSeYUebeD9kbDSixsSoBmNy78M3KaEaF6rwJ", "348dLzNEF3bRQR4Wjwzuz7oE2mdy3hSvdPz4nDNEpump", "3FnCLcwzTEBmruDx8dkqYHbhxdXctW6Gg4Na2HU6pump", "2NGBAfNMXBU85gjqYutA39b6BCBG5i5MZ4Jvjtdcpump", "9YyTiaTzHkpxTPNEf8dSaENJLHABb9qsXHFTEqRLpump", "E2HNWS5L6gwmtC9SZPpRq6Yp3V5gzotFrL3dAEP2pump", "DMY5rohghiwGbxFDtBHLP8bM4zTXNu2UdgMovLARpump", "25TBJCRN7m7EDcWcnKAZkLbTUiN9mUBnEBD6FBNUpump", "KVzR8KHCQBj115EjeYTiBPtPGPgq8BhyjH6wGY3pump", "57KoEZXm2mJwFqbB7fvcgZmmjc9mivFmKhXA45H3pump", "USRX8A1BNVzPSWt9tXA1ZjeMWWnpsWktdhueCBDZAjS", "Gi7yTkdFrJ1qA6eVSAcYuTjwmA63R7KY6nNMHFKGpump", "HXvQAQwytoLngKWQtge3oJnLHsaLwTxPbX48DctLpump", "B4GmoKt2AHWxRgaVWHTL2Rj9v7Wuz7hQWsfNRsfbpump"], "last_run": "2026-02-11T10:17:28.220727+00:00", "count": 15} \ No newline at end of file diff --git a/memory/recommendations.jsonl b/memory/recommendations.jsonl new file mode 100644 index 0000000..072337f --- /dev/null +++ b/memory/recommendations.jsonl @@ -0,0 +1,7 @@ +{"date":"2026-02-08","ticker":"HYPE","action":"buy","price":32.98,"mcap":"8.1B","category":"conviction","thesis":"Real revenue protocol ($4M+/mo fees), 337% TVL growth, 90% unlock reduction, $644M buyback, HIP-4 prediction markets","target":48,"invalidation":24,"timeframe":"1-3 months","status":"open","current_price":32.98,"pnl":0,"close_date":null,"close_reason":null,"source_signal":"unlock_reduction_rally","ev":{"bull":{"prob":0.25,"return":0.80},"base":{"prob":0.50,"return":0.20},"bear":{"prob":0.25,"return":-0.30},"total":0.225}} +{"date":"2026-02-08","ticker":"ETH","action":"buy","price":2080,"mcap":"250B","category":"conviction","thesis":"DeFi TVL growing in ETH terms, L2 consolidation around ETH ecosystem, weekly RSI sub-30 historically precedes bottoms, institutional leverage long","target":3200,"invalidation":1800,"timeframe":"1-3 months","status":"open","current_price":2080,"pnl":0,"close_date":null,"close_reason":null,"source_signal":"capitulation_oversold","ev":{"bull":{"prob":0.25,"return":0.80},"base":{"prob":0.45,"return":0.25},"bear":{"prob":0.30,"return":-0.25},"total":0.2375}} +{"date":"2026-02-08","ticker":"AAVE","action":"buy","price":150,"mcap":"2.2B","category":"conviction","thesis":"#1 DeFi by TVL ($28B), SEC cleared, revenue sharing, V4 cross-chain coming, bear markets drive lending demand","target":250,"invalidation":100,"timeframe":"1-3 months","status":"open","current_price":150,"pnl":0,"close_date":null,"close_reason":null,"source_signal":"defi_resilience","ev":{"bull":{"prob":0.20,"return":1.00},"base":{"prob":0.50,"return":0.30},"bear":{"prob":0.30,"return":-0.35},"total":0.245}} +{"date":"2026-02-08","ticker":"ONDO","action":"buy","price":0.28,"mcap":"440M","category":"narrative","thesis":"RWA tokenization narrative, MetaMask integration, tokenized equity volume up 2695%, but crushed by $1.94B unlock. Demand floor test.","target":1.40,"invalidation":0.18,"timeframe":"3-6 months","status":"open","current_price":0.28,"pnl":0,"close_date":null,"close_reason":null,"source_signal":"rwa_paradox","ev":{"bull":{"prob":0.20,"return":4.00},"base":{"prob":0.40,"return":0.50},"bear":{"prob":0.40,"return":-0.50},"total":0.80}} +{"date":"2026-02-08","ticker":"SOL","action":"buy","price":87,"mcap":"40B","category":"narrative","thesis":"Infrastructure evolution from memecoins to micropayments, Alpenglow + Firedancer upgrades, ETFs approved, $17B stablecoins","target":200,"invalidation":60,"timeframe":"3-6 months","status":"open","current_price":87,"pnl":0,"close_date":null,"close_reason":null,"source_signal":"infrastructure_narrative","ev":{"bull":{"prob":0.25,"return":1.30},"base":{"prob":0.40,"return":0.40},"bear":{"prob":0.35,"return":-0.40},"total":0.345}} +{"date":"2026-02-08","ticker":"BERA","action":"sell","price":null,"mcap":null,"category":"sell","thesis":"41.7% circulating supply unlocked Feb 6, Nova Digital reclaim right, thin liquidity bear market","target":null,"invalidation":null,"timeframe":"immediate","status":"open","current_price":null,"pnl":0,"close_date":null,"close_reason":null,"source_signal":"massive_unlock","ev":{"bull":{"prob":0.15,"return":0.60},"base":{"prob":0.35,"return":-0.10},"bear":{"prob":0.50,"return":-0.50},"total":-0.195}} +{"date":"2026-02-08","ticker":"BTC","action":"short","price":"73000-75000","mcap":"1.37T","category":"short","thesis":"Dead-cat bounce in capitulation. ETF outflows continue. 44% supply underwater = supply overhang. Resistance at $73-75K.","target":65000,"invalidation":78000,"timeframe":"1-2 weeks","status":"pending_entry","current_price":69542,"pnl":0,"close_date":null,"close_reason":null,"source_signal":"capitulation_structure","ev":{"bull":{"prob":0.25,"return":-0.15},"base":{"prob":0.45,"return":0.12},"bear":{"prob":0.30,"return":0.25},"total":0.0915}} diff --git a/memory/rex_snapshots.jsonl b/memory/rex_snapshots.jsonl new file mode 100644 index 0000000..94460db --- /dev/null +++ b/memory/rex_snapshots.jsonl @@ -0,0 +1,5 @@ +{"timestamp": "2026-02-10T21:46:39.762519+00:00", "mc": 0, "price": 0, "liq": 0, "buys_10m": 21, "sells_10m": 20, "net_sol": 0.98, "top_holder_count": 20, "whale_count": 3} +{"timestamp": "2026-02-10T21:48:09.580320+00:00", "mc": 119103, "price": 0.0001192, "liq": 27969.83, "buys_10m": 22, "sells_10m": 20, "net_sol": 4.33, "top_holder_count": 20, "whale_count": 3} +{"timestamp": "2026-02-10T21:53:33.059207+00:00", "mc": 98085, "price": 9.821e-05, "liq": 25413.75, "buys_10m": 21, "sells_10m": 18, "net_sol": 6.9, "top_holder_count": 20, "whale_count": 4} +{"timestamp": "2026-02-10T22:04:40.381983+00:00", "mc": 94787, "price": 9.491e-05, "liq": 25039.35, "buys_10m": 21, "sells_10m": 19, "net_sol": 0.47, "top_holder_count": 20, "whale_count": 4} +{"ts": "2026-02-10T22:30:09.066782+00:00", "mc": 59601, "p5m": -4.25, "net_sol": 4.82} diff --git a/memory/scan_60min_results.json b/memory/scan_60min_results.json new file mode 100644 index 0000000..e8aa6f5 --- /dev/null +++ b/memory/scan_60min_results.json @@ -0,0 +1,289 @@ +{ + "scan_time": "2026-02-13T18:05:40.198030+00:00", + "window": "60min", + "total_buys": 9, + "total_sells": 9, + "unique_tokens": [ + "6KmwvVo8gDUVAnoAftMuyUTojfx6xtgm2xkHp2ixpump", + "E7AaqmGaPsYxBzWERpgigt75nNs99eZEBUjKYA3cpump", + "A2ehHT8Qp5XJHDWCvBMkV9yEGMzBoXPfND1zk8C5oUCB", + "BsXmXxfwQWks6WHtfmo5q3Ji4mQieEx2WNWmUUe1pump", + "5kFDCdsSftKu8qC8Gh4bMTMLx4ECmhDNbqZNPMiVxCVm", + "HrCWtgFcbqZw5kmhZRZ9xxhBrdtsosPAFAKEfy1e4atJ", + "EmjXxFScJhpUBczUH9dw2B8XV2nMzHVjahLnm6Njpump", + "8yYWqAQAaeAnCYJTTX39shexffHwSBrBuFu7KD6Apump", + "C4anfPXVaP9QTHP81cKbcAyhfXiN2Pzdu5JaoWCYpump", + "HUszYim5uyfkDYHQsWtNwVTeegZrjgW16b938CLCAERx", + "HTfw9uFBoUzdSEfJkRz9KZNvg9XN9nBjrEMUfYaUpump", + "7Rni7A9Sa8qut96FBEP5D3pbkkRnwMgRNqHS3hEFpump", + "58Ghft9TvGNuBiDzy9cFD2Px9rz5cDVZ1XoMFk1xpump", + "3oEHLDg8VokqBM37u7ohkbKUKcdPE8sT8Btgrxovpump", + "4kGz1KaqsHLsqKRC8cYV7hWzM8x2kYGu465mpNs2pump" + ], + "accumulators": [ + { + "address": "24DCWvhrk4xwH6eCQ2UK8rWM1KXb1k93D4ebGfZ9RWXT", + "label": "Alpha #33 (from $Rex)", + "buy_count": 3, + "sell_count": 2, + "tokens": [ + "C4anfPXVaP9QTHP81cKbcAyhfXiN2Pzdu5JaoWCYpump", + "HUszYim5uyfkDYHQsWtNwVTeegZrjgW16b938CLCAERx", + "HTfw9uFBoUzdSEfJkRz9KZNvg9XN9nBjrEMUfYaUpump" + ] + }, + { + "address": "AowTUid5daQr9EqwazF7hDm3jBTQSisv6LaHGhQL8k92", + "label": "hellkatai Alpha #4 - BUTTCOIN Winner", + "buy_count": 2, + "sell_count": 2, + "tokens": [ + "5kFDCdsSftKu8qC8Gh4bMTMLx4ECmhDNbqZNPMiVxCVm", + "EmjXxFScJhpUBczUH9dw2B8XV2nMzHVjahLnm6Njpump", + "HrCWtgFcbqZw5kmhZRZ9xxhBrdtsosPAFAKEfy1e4atJ", + "8yYWqAQAaeAnCYJTTX39shexffHwSBrBuFu7KD6Apump" + ] + }, + { + "address": "GjPSeaLm72QgTqzo38WbVajxnmRfZ6YQx8q5C3nEpq4p", + "label": "Alpha #11 (from $$POKEMON30)", + "buy_count": 1, + "sell_count": 1, + "tokens": [ + "E7AaqmGaPsYxBzWERpgigt75nNs99eZEBUjKYA3cpump", + "6KmwvVo8gDUVAnoAftMuyUTojfx6xtgm2xkHp2ixpump" + ] + }, + { + "address": "H6KiqN3wwirFumem4ZqxbF3hhHNTjpyps3q7TTLX3n33", + "label": "Alpha #21 (from $#MLM)", + "buy_count": 1, + "sell_count": 1, + "tokens": [ + "BsXmXxfwQWks6WHtfmo5q3Ji4mQieEx2WNWmUUe1pump", + "A2ehHT8Qp5XJHDWCvBMkV9yEGMzBoXPfND1zk8C5oUCB" + ] + }, + { + "address": "BEWjNZivbn4x2cLYFDjdiFV43UBupzGTx7YwxZYFB3tr", + "label": "Alpha #38 (from $NAMECOIN)", + "buy_count": 1, + "sell_count": 2, + "tokens": [ + "58Ghft9TvGNuBiDzy9cFD2Px9rz5cDVZ1XoMFk1xpump", + "7Rni7A9Sa8qut96FBEP5D3pbkkRnwMgRNqHS3hEFpump" + ] + }, + { + "address": "p4jsxPV5DKoJA2hroCyVv521VFDCm6qgxmRRHJFnH61", + "label": "Alpha #40 (from $NAMECOIN)", + "buy_count": 1, + "sell_count": 0, + "tokens": [ + "3oEHLDg8VokqBM37u7ohkbKUKcdPE8sT8Btgrxovpump" + ] + } + ], + "convergence": [], + "new_positions": [ + { + "label": "Alpha #11 (from $$POKEMON30)", + "mint": "6KmwvVo8gDUVAnoAftMuyUTojfx6xtgm2xkHp2ixpump", + "amount": 1245989.398555, + "time": "17:59 UTC" + }, + { + "label": "hellkatai Alpha #4 - BUTTCOIN Winner", + "mint": "HrCWtgFcbqZw5kmhZRZ9xxhBrdtsosPAFAKEfy1e4atJ", + "amount": 12442988.294063, + "time": "18:00 UTC" + }, + { + "label": "hellkatai Alpha #4 - BUTTCOIN Winner", + "mint": "8yYWqAQAaeAnCYJTTX39shexffHwSBrBuFu7KD6Apump", + "amount": 10391838.100887, + "time": "17:50 UTC" + }, + { + "label": "Alpha #33 (from $Rex)", + "mint": "C4anfPXVaP9QTHP81cKbcAyhfXiN2Pzdu5JaoWCYpump", + "amount": 6220657.673035, + "time": "17:51 UTC" + }, + { + "label": "Alpha #33 (from $Rex)", + "mint": "HUszYim5uyfkDYHQsWtNwVTeegZrjgW16b938CLCAERx", + "amount": 5092005.212073, + "time": "17:48 UTC" + }, + { + "label": "Alpha #33 (from $Rex)", + "mint": "HTfw9uFBoUzdSEfJkRz9KZNvg9XN9nBjrEMUfYaUpump", + "amount": 11691379.633386, + "time": "17:48 UTC" + }, + { + "label": "Alpha #40 (from $NAMECOIN)", + "mint": "3oEHLDg8VokqBM37u7ohkbKUKcdPE8sT8Btgrxovpump", + "amount": 8244446.347733, + "time": "17:56 UTC" + } + ], + "full_exits": [ + { + "label": "Alpha #11 (from $$POKEMON30)", + "mint": "E7AaqmGaPsYxBzWERpgigt75nNs99eZEBUjKYA3cpump", + "amount": 4448221.93391, + "time": "17:45 UTC" + }, + { + "label": "hellkatai Alpha #4 - BUTTCOIN Winner", + "mint": "5kFDCdsSftKu8qC8Gh4bMTMLx4ECmhDNbqZNPMiVxCVm", + "amount": 11739396.17432, + "time": "18:04 UTC" + }, + { + "label": "hellkatai Alpha #4 - BUTTCOIN Winner", + "mint": "EmjXxFScJhpUBczUH9dw2B8XV2nMzHVjahLnm6Njpump", + "amount": 12093622.751079, + "time": "17:52 UTC" + }, + { + "label": "Alpha #33 (from $Rex)", + "mint": "HUszYim5uyfkDYHQsWtNwVTeegZrjgW16b938CLCAERx", + "amount": 5092005.212073, + "time": "17:50 UTC" + }, + { + "label": "Alpha #33 (from $Rex)", + "mint": "HTfw9uFBoUzdSEfJkRz9KZNvg9XN9nBjrEMUfYaUpump", + "amount": 11691379.633386, + "time": "17:48 UTC" + }, + { + "label": "Alpha #38 (from $NAMECOIN)", + "mint": "7Rni7A9Sa8qut96FBEP5D3pbkkRnwMgRNqHS3hEFpump", + "amount": 10047296.771921, + "time": "17:46 UTC" + }, + { + "label": "Alpha #38 (from $NAMECOIN)", + "mint": "58Ghft9TvGNuBiDzy9cFD2Px9rz5cDVZ1XoMFk1xpump", + "amount": 4980235.062774, + "time": "17:46 UTC" + }, + { + "label": "Alpha #42 (from $NAMECOIN)", + "mint": "4kGz1KaqsHLsqKRC8cYV7hWzM8x2kYGu465mpNs2pump", + "amount": 28944112.438935, + "time": "17:41 UTC" + } + ], + "whale_moves": [ + { + "label": "Alpha #42 (from $NAMECOIN)", + "action": "SELL", + "mint": "4kGz1KaqsHLsqKRC8cYV7hWzM8x2kYGu465mpNs2pump", + "change": -28944112.438935, + "time": "17:41 UTC" + }, + { + "label": "hellkatai Alpha #4 - BUTTCOIN Winner", + "action": "BUY", + "mint": "HrCWtgFcbqZw5kmhZRZ9xxhBrdtsosPAFAKEfy1e4atJ", + "change": 12442988.294063, + "time": "18:00 UTC" + }, + { + "label": "hellkatai Alpha #4 - BUTTCOIN Winner", + "action": "SELL", + "mint": "EmjXxFScJhpUBczUH9dw2B8XV2nMzHVjahLnm6Njpump", + "change": -12093622.751079, + "time": "17:52 UTC" + }, + { + "label": "hellkatai Alpha #4 - BUTTCOIN Winner", + "action": "SELL", + "mint": "5kFDCdsSftKu8qC8Gh4bMTMLx4ECmhDNbqZNPMiVxCVm", + "change": -11739396.17432, + "time": "18:04 UTC" + }, + { + "label": "Alpha #33 (from $Rex)", + "action": "BUY", + "mint": "HTfw9uFBoUzdSEfJkRz9KZNvg9XN9nBjrEMUfYaUpump", + "change": 11691379.633386, + "time": "17:48 UTC" + }, + { + "label": "Alpha #33 (from $Rex)", + "action": "SELL", + "mint": "HTfw9uFBoUzdSEfJkRz9KZNvg9XN9nBjrEMUfYaUpump", + "change": -11691379.633386, + "time": "17:48 UTC" + }, + { + "label": "hellkatai Alpha #4 - BUTTCOIN Winner", + "action": "BUY", + "mint": "8yYWqAQAaeAnCYJTTX39shexffHwSBrBuFu7KD6Apump", + "change": 10391838.100887, + "time": "17:50 UTC" + }, + { + "label": "Alpha #38 (from $NAMECOIN)", + "action": "SELL", + "mint": "7Rni7A9Sa8qut96FBEP5D3pbkkRnwMgRNqHS3hEFpump", + "change": -10047296.771921, + "time": "17:46 UTC" + }, + { + "label": "Alpha #40 (from $NAMECOIN)", + "action": "BUY", + "mint": "3oEHLDg8VokqBM37u7ohkbKUKcdPE8sT8Btgrxovpump", + "change": 8244446.347733, + "time": "17:56 UTC" + }, + { + "label": "Alpha #33 (from $Rex)", + "action": "BUY", + "mint": "C4anfPXVaP9QTHP81cKbcAyhfXiN2Pzdu5JaoWCYpump", + "change": 6220657.673035, + "time": "17:51 UTC" + }, + { + "label": "Alpha #33 (from $Rex)", + "action": "BUY", + "mint": "HUszYim5uyfkDYHQsWtNwVTeegZrjgW16b938CLCAERx", + "change": 5092005.212073, + "time": "17:48 UTC" + }, + { + "label": "Alpha #33 (from $Rex)", + "action": "SELL", + "mint": "HUszYim5uyfkDYHQsWtNwVTeegZrjgW16b938CLCAERx", + "change": -5092005.212073, + "time": "17:50 UTC" + }, + { + "label": "Alpha #38 (from $NAMECOIN)", + "action": "SELL", + "mint": "58Ghft9TvGNuBiDzy9cFD2Px9rz5cDVZ1XoMFk1xpump", + "change": -4980235.062774, + "time": "17:46 UTC" + }, + { + "label": "Alpha #11 (from $$POKEMON30)", + "action": "SELL", + "mint": "E7AaqmGaPsYxBzWERpgigt75nNs99eZEBUjKYA3cpump", + "change": -4448221.93391, + "time": "17:45 UTC" + }, + { + "label": "Alpha #21 (from $#MLM)", + "action": "BUY", + "mint": "A2ehHT8Qp5XJHDWCvBMkV9yEGMzBoXPfND1zk8C5oUCB", + "change": 2006686.2328190003, + "time": "17:44 UTC" + } + ] +} \ No newline at end of file diff --git a/memory/scan_queue.json b/memory/scan_queue.json new file mode 100644 index 0000000..095a49f --- /dev/null +++ b/memory/scan_queue.json @@ -0,0 +1,65 @@ +{ + "queued_at": "2026-02-13T18:03:40.121207+00:00", + "tokens": [ + { + "ca": "5T17aqgJ8cM39SNuVBu2LK2cq5MWUpZxcQnnuwNjpump", + "symbol": "LIZARD", + "mc": 221997, + "score": 105 + }, + { + "ca": "63p6ir6gGQ59ZCDN2iRGUkCrZyJvu2xaacRYBfKopump", + "symbol": "MoonLiquid", + "mc": 118366, + "score": 105 + }, + { + "ca": "58ExX8TFqiDqUpr1ZGiAhhiUsKfT14gwTFykLoVCpump", + "symbol": "hoodrat", + "mc": 457305, + "score": 95 + }, + { + "ca": "3g3YFfUZLspiKpVmv9mDkaDcKh168CLArcqShR64pump", + "symbol": "hopecoin", + "mc": 91436, + "score": 90 + }, + { + "ca": "58Ghft9TvGNuBiDzy9cFD2Px9rz5cDVZ1XoMFk1xpump", + "symbol": "Buttfish", + "mc": 216220, + "score": 90 + }, + { + "ca": "EFt9JrrGyLWLU6Wc4oxfTjDKryENPrjbGgZ2V6x8pump", + "symbol": "helicator", + "mc": 62724, + "score": 85 + }, + { + "ca": "V6e9AvFGp1hqE7HZBkTar8t1C7JorqZxaa5iS6kpump", + "symbol": "DEW", + "mc": 68204, + "score": 85 + }, + { + "ca": "9ekm6h4pxZcNbdyMw5fWkEnqAStjQCSzZ3TEfZ7tpump", + "symbol": "TOLY", + "mc": 128753, + "score": 85 + }, + { + "ca": "72Ed2QEAbZkbRqJ5vhciuyhGbDqpkh1BE98cuMeepump", + "symbol": "YETI", + "mc": 15782, + "score": 85 + }, + { + "ca": "Bq9D4BbhVR4kL1qSdsYpQ5JM59q2LzUYzv7zFA1epump", + "symbol": "RATHBUN", + "mc": 207877, + "score": 85 + } + ] +} \ No newline at end of file diff --git a/memory/scan_queue_extended.json b/memory/scan_queue_extended.json new file mode 100644 index 0000000..5b4ca31 --- /dev/null +++ b/memory/scan_queue_extended.json @@ -0,0 +1,425 @@ +{ + "queued_at": "2026-02-11T10:00:00", + "tokens": [ + { + "ca": "5TATk16oMrt4vsMR8WwQ9AtiPeosdJhXFkp2UhGJpump", + "symbol": "Gentlemen", + "mc": 354704, + "score": 95 + }, + { + "ca": "E2HNWS5L6gwmtC9SZPpRq6Yp3V5gzotFrL3dAEP2pump", + "symbol": "BUCKARU", + "mc": 313960, + "score": 95 + }, + { + "ca": "B1RB6i7gvxYoyx8Us1eFrJxr7DZv3RzLmBHdfPwDpump", + "symbol": "$POKEMON30", + "mc": 159170, + "score": 85 + }, + { + "ca": "8QJGmTnGhJAfGmkGrscYzrYKacaUCMYTTQQ2Wb3apump", + "symbol": "Maximoto", + "mc": 73929, + "score": 85 + }, + { + "ca": "9MCaWcXJRhCBxaYmqPwmdfqY9qxVwo427wYJu2MjWoyC", + "symbol": "$PENG", + "mc": 69992, + "score": 85 + }, + { + "ca": "8ckfBhNvEDA62udk4YGNbSYcd5wvmQDjhY6kAYsgpump", + "symbol": "#MLM", + "mc": 146047, + "score": 85 + }, + { + "ca": "3mHw8CJffDZpY8F6KmGVF3LwwejCkMHG2o2pV5ZVpump", + "symbol": "GROKPEPE", + "mc": 100209, + "score": 85 + }, + { + "ca": "7SYuU1Z6EKfpYQQ9VeTXfLW5ofhigdn8Y7iQsqoepump", + "symbol": "Ferociter", + "mc": 51870, + "score": 85 + }, + { + "ca": "GbqbsRyBHVPHEv7xLEsikXmdpPPiApLTJesDBbL5pump", + "symbol": "GIRAFFES", + "mc": 1748404, + "score": 85 + }, + { + "ca": "G9YU3K1MiPTv7Krui5omkPBPP21GChPPE3c9izRKbonk", + "symbol": "SAFEMOON", + "mc": 223160, + "score": 85 + }, + { + "ca": "2qT8JVotQ2C1gKbqpuqNatkpSBWxiKHbXkCyTqH9pump", + "symbol": "soluna", + "mc": 901809, + "score": 85 + }, + { + "ca": "CvTMSEB9RzHPhB1CgE7PAkszomozDv3JJNz28sDbpump", + "symbol": "HAL", + "mc": 94434, + "score": 85 + }, + { + "ca": "5TcwTnpmvBv6CZAjzceGCAoR3KubRvtoz86TZoePpump", + "symbol": "WATT", + "mc": 66430, + "score": 80 + }, + { + "ca": "88UweYzEAGVFAdjFwjhyPtSHhQf8SwSy85hh5vu4V2Hj", + "symbol": "SKYNET", + "mc": 6567, + "score": 75 + }, + { + "ca": "CMRpNWSaSnyfoMDYhAWdPNXXrwXwPhz3CVEdZmToX9jR", + "symbol": "CMR", + "mc": 2431440, + "score": 75 + }, + { + "ca": "F6QoH8WfU67V7xP7fnTHGpkR6xdegLUcPGjSLsGQmMD4", + "symbol": "ICF", + "mc": 1077116, + "score": 75 + }, + { + "ca": "63Z3Q7JX3SBGDiiwqqnPTVvHcuUk6ixkzsYQbKzhpump", + "symbol": "SHARK", + "mc": 443816, + "score": 70 + }, + { + "ca": "USRX8A1BNVzPSWt9tXA1ZjeMWWnpsWktdhueCBDZAjS", + "symbol": "USRX", + "mc": 7098953, + "score": 70 + }, + { + "ca": "NeT4mWkYNuqBVy9XV2rhRMW59GwqTZLioYM5sktperp", + "symbol": "Perpcoin", + "mc": 22011, + "score": 65 + }, + { + "ca": "6Ky1ndumnWVGQBbxauh3mgoVj7Ytr7YmFea1K8Zcpump", + "symbol": "WhiteGRFF", + "mc": 148297, + "score": 65 + }, + { + "ca": "F7FjenqxEcs8aEXnP4MHbstZKNwiEs6FHnWhYH2Xpump", + "symbol": "VALENTINES", + "mc": 24274, + "score": 65 + }, + { + "ca": "DUohwmGsB53vZ4LVntYh3GHXnpzJjH3RgiC4phkypump", + "symbol": "BullishGir", + "mc": 153697, + "score": 65 + }, + { + "ca": "Dwwsv9JyCw3Zxufe7E4YQFX4q9Nf12YzTiPwQHaxpump", + "symbol": "LOTUS", + "mc": 10498084, + "score": 60 + }, + { + "ca": "5fN3pcZiyLJVY7NvzkHTLHRyjETG3NRrQXEaPFoRn2D2", + "symbol": "Rock", + "mc": 14874, + "score": 55 + }, + { + "ca": "HuorCKdoLVYbodCaNLiZBDPKfHAQUb4CUzSBf23Bpump", + "symbol": "Bucky", + "mc": 36468, + "score": 55 + }, + { + "ca": "7soqpgjvvF1cMn2xVHnGbSZezCdTjMoqHotLEH2Wpump", + "symbol": "REX", + "mc": 22212, + "score": 55 + }, + { + "ca": "9yrjW2ZhxB1t738E3ATFYyyXUBPJUL266hZFzJEYndgL", + "symbol": "NYAN", + "mc": 25561, + "score": 50 + }, + { + "ca": "9G2ASTJycfKzbMvpUy8EzCtG5cjF274Sx3vW6Rurpump", + "symbol": "BAPE", + "mc": 35553.46, + "score": 50 + }, + { + "ca": "6csbmriS9a6GiRi4gZA4nzmRwrstpyA3HXXzo9Q2pump", + "symbol": "Poopcoin", + "mc": 3618, + "score": 50 + }, + { + "ca": "3d9ZqLpKGvXrE7YKcCRhwMzzVBAcbcp1LYhW1tCWpump", + "symbol": "SEAHAWKS", + "mc": 6375, + "score": 50 + }, + { + "ca": "BgNuhimT99WmuKSa7F5znCcsDoXQ6MsX4MWxz8LUnRTs", + "symbol": "Elephants", + "mc": 1304, + "score": 50 + }, + { + "ca": "wQXEwMUkWqXtxGJ6TRuKq9kTUnNoydwq2EG5gk7HBp5", + "symbol": "LIGHTNING", + "mc": 3229, + "score": 50 + }, + { + "ca": "KVzR8KHCQBj115EjeYTiBPtPGPgq8BhyjH6wGY3pump", + "symbol": "CUPID", + "mc": 34152.36, + "score": 50 + }, + { + "ca": "2CwYrUEkfxNKTdBFTrvZaP6kgR5jKGKYmmk9eaNxpump", + "symbol": "BADBUNNY", + "mc": 2605, + "score": 45 + }, + { + "ca": "8TVr3U85V3Uazkxd5DJbmzdUWaxhQdEGNNGJ7eNTpump", + "symbol": "TULSA", + "mc": 562260, + "score": 45 + }, + { + "ca": "5XUmwpwHscJsUfTRA7somtUCtfmUVi1Hz7YGH3H8pump", + "symbol": "Animals", + "mc": 2348819, + "score": 45 + }, + { + "ca": "7Y2TPeq3hqw21LRTCi4wBWoivDngCpNNJsN1hzhZpump", + "symbol": "SACHI", + "mc": 1550603, + "score": 40 + }, + { + "ca": "Cm6fNnMk7NfzStP9CZpsQA2v3jjzbcYGAxdJySmHpump", + "symbol": "Buttcoin", + "mc": 37186246, + "score": 40 + }, + { + "ca": "86WM5NBUtRWTHULKrspS1TdzVFAcZ9buXsGRAiFDpump", + "symbol": "ICEBEAR", + "mc": 35629, + "score": 40 + }, + { + "ca": "HG8qtpKpSQ8uPrCBDbWohnT9sh8s5S7oBYzvBwVFpump", + "symbol": "MILK", + "mc": 35487.72, + "score": 40 + }, + { + "ca": "57KoEZXm2mJwFqbB7fvcgZmmjc9mivFmKhXA45H3pump", + "symbol": "Preguntale", + "mc": 34505.72, + "score": 40 + }, + { + "ca": "2k8yZaJjf61unHriuqdmvbxe7CUhEYML5kVJDbcotKjU", + "symbol": "BFS", + "mc": 1418092, + "score": 35 + }, + { + "ca": "HDYtwNnQ948isoVGZywWpt4nEFLRukmj2VXqfoDJpump", + "symbol": "UNDERDOG", + "mc": 6632, + "score": 35 + }, + { + "ca": "3ToKnopDeSUAy8fc1bX6rUK25UMCA24Xwe1WXqZspump", + "symbol": "BIT", + "mc": 43763, + "score": 35 + }, + { + "ca": "DDtXARjuwSPRE16Q9yPCTH7s2ZgCM5SoBbsd5kiApump", + "symbol": "DOGGO", + "mc": 8052, + "score": 35 + }, + { + "ca": "DvH9A3dSv2n6s6WArARtXm988kiaS8m47jWa6kTjpump", + "symbol": "BOB", + "mc": 2864, + "score": 30 + }, + { + "ca": "AZjDNg2WhoZUnhtyfWTXxTbc3Pq6bg1XfUrAAbvCpump", + "symbol": "KidRock", + "mc": 7312, + "score": 30 + }, + { + "ca": "Z4KACzcxkRzT7htPqnNsNLtH7zoDDzDFQR5sMJ3perp", + "symbol": "PERPTRADE", + "mc": 3142.46, + "score": 30 + }, + { + "ca": "61Wj56QgGyyB966T7YsMzEAKRLcMvJpDbPzjkrCZc4Bi", + "symbol": "COPPERINU", + "mc": 7906852, + "score": 25 + }, + { + "ca": "8Jx8AAHj86wbQgUTjGuj6GTTL5Ps3cqxKRTvpaJApump", + "symbol": "PENGUIN", + "mc": 27052981, + "score": 25 + }, + { + "ca": "Dfh5DzRgSvvCFDoYc2ciTkMrbDfRKybA4SoFbPmApump", + "symbol": "pippin", + "mc": 267206029, + "score": 25 + }, + { + "ca": "8J69rbLTzWWgUJziFY8jeu5tDwEPBwUz4pKBMr5rpump", + "symbol": "WOJAK", + "mc": 12340653, + "score": 25 + }, + { + "ca": "a3W4qutoEJA4232T2gwZUfgYJTetr96pU4SJMwppump", + "symbol": "WhiteWhale", + "mc": 90749024, + "score": 20 + }, + { + "ca": "2cCbvJChfXcUf3fiQFZqJXT1zQybrAgtqjjinaxNBAGS", + "symbol": "SURVIVAL", + "mc": 14653.79, + "score": 20 + }, + { + "ca": "FYCyBpzbFfP3gVFVaCBRtjoWg1LzZUtH7DsD2MjVpump", + "symbol": ".gif", + "mc": 8856.49, + "score": 20 + }, + { + "ca": "FqzojLo6YRgNZfaBgaPyv26L4fcL2t2dT3mE225gFWjh", + "symbol": "The", + "mc": 196946973, + "score": 20 + }, + { + "ca": "25TBJCRN7m7EDcWcnKAZkLbTUiN9mUBnEBD6FBNUpump", + "symbol": "MOON", + "mc": 10673.11, + "score": 20 + }, + { + "ca": "USoRyaQjch6E18nCdDvWoRgTo6osQs9MUd8JXEsspWR", + "symbol": "USOR", + "mc": 5578526, + "score": 10 + }, + { + "ca": "2Gavi27q6jrF3bhLb4fJg9nVuydPorxmLEvVVAp7pump", + "symbol": "WHITEMICHI", + "mc": 33264.86, + "score": 10 + }, + { + "ca": "63XiXdPhsBhg5zZU2trnxuh2J7emXc55CVtn9nvzpump", + "symbol": "NPC", + "mc": 2318.31, + "score": 10 + }, + { + "ca": "CW3dAZC1RHTTXZeEcmvYGLt2tziXHMv9crLDd5uDpump", + "symbol": "TiktokCoin", + "mc": 3493.77, + "score": 10 + }, + { + "ca": "2LjA87GjNGnCLgYC5PvduVhKRTRDK7N74zExPeS3dMQP", + "symbol": "Roadrunner", + "mc": 3587.57, + "score": 10 + }, + { + "ca": "9YyTiaTzHkpxTPNEf8dSaENJLHABb9qsXHFTEqRLpump", + "symbol": "nuralineAI", + "mc": 5309, + "score": 10 + }, + { + "ca": "75wdZ1M297ngMifL8YFvk1kaumuDWwLpAQ8tdNwDUtEj", + "symbol": "C-13", + "mc": 36689, + "score": 5 + }, + { + "ca": "8gG5C5cVuDnpCyqDFTc6LH6L6oAWNgDkyCp4XnHqpump", + "symbol": "Horse", + "mc": 1450, + "score": 5 + }, + { + "ca": "SABfuDo2cGJNumfHCyBYAPxfs8Fnmi5NzDmYS3rpump", + "symbol": "G", + "mc": 4047.21, + "score": 5 + }, + { + "ca": "3a2Hw79jCGcUwgsL5qec78EU4Y8LRkLkUP39HTCopump", + "symbol": "RUBY", + "mc": 16042, + "score": 5 + }, + { + "ca": "2NGBAfNMXBU85gjqYutA39b6BCBG5i5MZ4Jvjtdcpump", + "symbol": "SHT", + "mc": 802000, + "score": 0 + }, + { + "ca": "EKwF2HD6X4rHHr4322EJeK9QBGkqhpHZQSanSUmWkecG", + "symbol": "BigTrout", + "mc": 2100000, + "score": 0 + }, + { + "ca": "8opvqaWysX1oYbXuTL8PHaoaTiXD69VFYAX4smPebonk", + "symbol": "UNKNOWN", + "mc": 0, + "score": 0 + } + ] +} \ No newline at end of file diff --git a/memory/session_state.json b/memory/session_state.json new file mode 100644 index 0000000..f6fa03c --- /dev/null +++ b/memory/session_state.json @@ -0,0 +1,103 @@ +{ + "last_run": "2026-02-08T18:00:00Z", + "session_number": 1.5, + "session_version": "v2_full_social_with_early_callers", + "grok_api_status": "ACTIVE - grok-4-1-fast with x_search via Responses API", + "grok_model": "grok-4-1-fast", + "grok_endpoint": "https://api.x.ai/v1/responses", + "grok_tools": [{"type": "x_search"}], + "x_search_calls_today": 64, + "early_caller_tracking": "ACTIVE - see memory/early_callers.json", + "open_investigations": [ + { + "topic": "ETF inflow reversal signal", + "findings": "+$330M on Feb 7 breaks sustained outflow streak. CRITICAL.", + "next_steps": "Check Feb 8-9 flows. 3 consecutive positive days = regime change confirmed." + }, + { + "topic": "Hyperliquid whale shorts", + "findings": "0x4e31 and 0x94d3 both max short BTC.", + "next_steps": "Monitor positions daily. Closing = squeeze incoming." + }, + { + "topic": "HYPE March 6 unlock", + "findings": "$309M unlock. X flags pre-unlock pump pattern.", + "next_steps": "Watch for unlock reduction announcement. If no announcement + pump = caution." + }, + { + "topic": "Trend Research Aave position", + "findings": "$1.8B ETH collateral, dumped $44M at loss per X.", + "next_steps": "Find wallet on Arkham. Monitor health factor." + }, + { + "topic": "Trump insider whale BTC dump", + "findings": "6,599 BTC (~$500M) dumped.", + "next_steps": "Verify via Arkham." + }, + { + "topic": "ONDO floor test", + "findings": "Testing $0.20-$0.32. Team/VCs dumping per X.", + "next_steps": "Monitor for selling exhaustion." + }, + { + "topic": "Decibel Aptos perp DEX", + "findings": "Pre-deposit opens Feb 10.", + "next_steps": "Deposit 50 USDC on Feb 10." + }, + { + "topic": "White Whale identity", + "findings": "$50M+ profit, momentum trader.", + "next_steps": "Check Hypurrscan for wallet address." + }, + { + "topic": "Base AI agent token meta", + "findings": "$LUMEN (USV/Albert Wenger, Feb 4) and $JUNO (@tomosman/Bezos-followed, Feb 7) both 10x+ on Base. Same early callers found both.", + "next_steps": "Track @AidenJackCrypto and @BioStone_chad daily for next Base AI agent call. Check for $CLAW, $KELLYCLAUDE updates." + }, + { + "topic": "Early caller network", + "findings": "@AidenJackCrypto and @BioStone_chad early to BOTH $LUMEN and $JUNO. @EricCryptoman, @cfm_sol, @JMania402 also early.", + "next_steps": "Check all critical/high priority callers each session. If 2+ callers mention same new token = immediate alpha signal." + } + ], + "questions_for_next_session": [ + "Did BTC ETF inflows sustain on Feb 8-9?", + "Did Hyperliquid whale shorts close?", + "MOVE unlock impact on Feb 9?", + "BTC holding $69K or retracing?", + "New exploits/hacks?", + "ONDO above $0.20?", + "SEA token date?", + "JUP airdrop claim details?", + "What are @AidenJackCrypto and @BioStone_chad calling now?", + "Any new Base AI agent token launches?", + "$LUMEN and $JUNO current MC and status?" + ], + "contrarian_challenges": [ + { + "challenge": "ETF inflow may be one-day noise", + "status": "partially_resolved", + "resolution_criteria": "3 consecutive positive days" + }, + { + "challenge": "Hyperliquid whales short may be right (dead cat bounce)", + "status": "unresolved", + "resolution_criteria": "BTC >$75K = wrong, BTC <$60K = right" + }, + { + "challenge": "HYPE pre-unlock pump manipulation", + "status": "unresolved", + "resolution_criteria": "March unlock reduction announcement = bullish" + }, + { + "challenge": "RWA narrative overblown (sub-5% yields vs T-bills)", + "status": "unresolved", + "resolution_criteria": "ONDO holds $0.20 + RWA TVL grows = valid" + }, + { + "challenge": "Base AI agent token meta may be short-lived hype", + "status": "unresolved", + "resolution_criteria": "If $LUMEN/$JUNO hold MC >2M for 2+ weeks AND new launches follow = sustainable meta" + } + ] +} diff --git a/memory/smart_wallets.json b/memory/smart_wallets.json new file mode 100644 index 0000000..b47a8cb --- /dev/null +++ b/memory/smart_wallets.json @@ -0,0 +1,1711 @@ +{ + "wallets": [ + { + "address": "unknown", + "chain": "ethereum", + "label": "Trend Research", + "category": "fund_wallet", + "first_spotted": "2026-02-08", + "reason": "Deposited $1.8B ETH on Aave, borrowed $958M stablecoins. Massive leveraged ETH long.", + "reliability_score": null, + "notable_trades": [ + { + "date": "2026-02", + "action": "Deposited $1.8B ETH on Aave, borrowed $958M", + "outcome": "pending" + } + ], + "current_holdings": "Long ETH via Aave leverage", + "last_checked": "2026-02-08", + "status": "active", + "notes": "Need to identify exact on-chain address via Arkham. Monitor Aave health factor." + }, + { + "address": "unknown", + "chain": "hyperliquid", + "label": "White Whale", + "category": "smart_trader", + "first_spotted": "2026-02-08", + "reason": "Top Hyperliquid trader, $50M+ profit in 30 days. Momentum-following strategy.", + "reliability_score": null, + "notable_trades": [ + { + "date": "2026-02", + "action": "$50M+ profit on Hyperliquid 30-day leaderboard", + "outcome": "profitable" + } + ], + "current_holdings": "Unknown - need to identify positions", + "last_checked": "2026-02-08", + "status": "active", + "notes": "Need to identify on-chain wallet address via Hypurrscan. Track positions as directional signal." + }, + { + "address": "unknown", + "chain": "hyperliquid", + "label": "James Wynn", + "category": "smart_trader", + "first_spotted": "2026-02-08", + "reason": "High-profile Hyperliquid trader mentioned alongside top performers.", + "reliability_score": null, + "notable_trades": [], + "current_holdings": "Unknown", + "last_checked": "2026-02-08", + "status": "active", + "notes": "Identify wallet and track positions." + }, + { + "address": "gasTzr94Pmp4Gf8vknQnqxeYxdgwFjbgdJa4msYRpnB", + "chain": "solana", + "label": "PISS Top Trader", + "category": "early_buyer", + "first_spotted": "2026-02-08", + "reason": "Top trader on $PISS (PissCoin) with $70K+ verified profit. Found via X alpha intelligence.", + "reliability_score": 7, + "notable_trades": [ + { + "date": "2025-10", + "action": "Early buy $PISS \u2014 $70K+ profit", + "outcome": "highly_profitable" + } + ], + "current_holdings": "Unknown \u2014 needs on-chain scan via Helius", + "last_checked": "2026-02-08", + "status": "active", + "notes": "First REAL alpha wallet with verified profitable trade. Discovered from X post sharing PnL. Run scan_early_buyers.py on VPS to find more wallets from same tokens." + }, + { + "address": "62nvXUcG8bKp1BFqJfFr5Rz223QrLrHdSE4oupDAGsvF", + "chain": "solana", + "label": "hellkatai Alpha #1", + "category": "smart_trader", + "first_spotted": "2026-02-08", + "reason": "+$51.4K PnL (30D), 6/8 smart-money criteria per @hellkatai. Found via X alpha scan.", + "reliability_score": 6, + "notable_trades": [ + { + "date": "2026-02", + "action": "+$51.4K PnL in 30 days", + "outcome": "profitable" + } + ], + "current_holdings": "Unknown \u2014 needs on-chain scan via Helius", + "last_checked": "2026-02-08", + "status": "active, needs_verification", + "notes": "Found from @hellkatai cielo.finance tracker. Needs on-chain verification via Helius on VPS." + }, + { + "address": "3nak6DM3bAkc27wQ71WH5mfXUVN9vhLfYWENTea2fbEE", + "chain": "solana", + "label": "hellkatai Alpha #2 - AI Meme Trader", + "category": "smart_trader", + "first_spotted": "2026-02-08", + "reason": "+$81K PnL (30D), specializes in AI memes ($COMPUTA, $APEX). Found via X.", + "reliability_score": 6, + "notable_trades": [ + { + "date": "2026-02", + "action": "+$81K PnL in 30 days, AI meme focus ($COMPUTA, $APEX)", + "outcome": "profitable" + } + ], + "current_holdings": "Unknown \u2014 needs on-chain scan via Helius", + "last_checked": "2026-02-08", + "status": "active, needs_verification", + "notes": "AI meme specialist. Found from @hellkatai. Needs on-chain verification." + }, + { + "address": "GUBz6J9ojFoVEKHEhgHgv4FfsePY7UE2Hj5sMnvdwhMq", + "chain": "solana", + "label": "hellkatai Alpha #3 - Non-Sniper", + "category": "smart_trader", + "first_spotted": "2026-02-08", + "reason": "+$72K PnL (30D), 66% win rate, non-sniper (human trading pattern). Found via X.", + "reliability_score": 7, + "notable_trades": [ + { + "date": "2026-02", + "action": "+$72K PnL in 30 days, 66% win rate", + "outcome": "profitable" + } + ], + "current_holdings": "Unknown \u2014 needs on-chain scan via Helius", + "last_checked": "2026-02-08", + "status": "active, needs_verification", + "notes": "Non-sniper with consistent win rate. Found from @hellkatai. Needs on-chain verification." + }, + { + "address": "AowTUid5daQr9EqwazF7hDm3jBTQSisv6LaHGhQL8k92", + "chain": "solana", + "label": "hellkatai Alpha #4 - BUTTCOIN Winner", + "category": "early_buyer", + "first_spotted": "2026-02-08", + "reason": "+$50.5K PnL, 125,000% ROI on $BUTTCOIN. Found via X.", + "reliability_score": 6, + "notable_trades": [ + { + "date": "2026-02", + "action": "+$50.5K PnL, 125,000% ROI on $BUTTCOIN", + "outcome": "highly_profitable" + } + ], + "current_holdings": "Unknown \u2014 needs on-chain scan via Helius", + "last_checked": "2026-02-08", + "status": "active, needs_verification", + "notes": "Extreme ROI on $BUTTCOIN. Found from @hellkatai. Needs on-chain verification." + }, + { + "address": "3q1wAx4qSjADADkC1oYLmBxu5fW1bA1cLGUDmv2oEGSi", + "chain": "solana", + "label": "hellkatai Alpha #5 - Sniper", + "category": "early_buyer", + "first_spotted": "2026-02-08", + "reason": "+$97.9K PnL (30D), sniper style, holds $BIGTROUT. Found via X.", + "reliability_score": 6, + "notable_trades": [ + { + "date": "2026-02", + "action": "+$97.9K PnL in 30 days, sniper style, holds $BIGTROUT", + "outcome": "profitable" + } + ], + "current_holdings": "Unknown \u2014 needs on-chain scan via Helius", + "last_checked": "2026-02-08", + "status": "active, needs_verification", + "notes": "Sniper style trader. Holds $BIGTROUT which overlaps with our tracked tokens. Found from @hellkatai." + }, + { + "address": "DP7G43VPwR5Ab5rcjrCnvJ8UgvRXRHTWscMjRD1eSdGC", + "chain": "solana", + "label": "hellkatai Alpha #6 - TOP PERFORMER", + "category": "smart_trader", + "first_spotted": "2026-02-08", + "reason": "+$240K PnL (30D), $160K current balance. Highest PnL of all discovered wallets. Found via X.", + "reliability_score": 7, + "notable_trades": [ + { + "date": "2026-02", + "action": "+$240K PnL in 30 days, $160K current balance", + "outcome": "highly_profitable" + } + ], + "current_holdings": "Unknown \u2014 needs on-chain scan via Helius", + "last_checked": "2026-02-08", + "status": "active, needs_verification", + "notes": "HIGHEST PnL wallet discovered. Priority for on-chain verification and monitoring. Found from @hellkatai." + }, + { + "address": "GjPSeaLm72QgTqzo38WbVajxnmRfZ6YQx8q5C3nEpq4p", + "chain": "solana", + "label": "Alpha #11 (from $$POKEMON30)", + "source": "alpha_scanner:$POKEMON30", + "alpha_score": 110, + "sol_balance": 2.330019124, + "token_count": 0, + "discovered_via": "B1RB6i7gvxYoyx8Us1eFrJxr7DZv3RzLmBHdfPwDpump", + "discovered_at": "2026-02-09T17:07:33.482120+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 1, + "sell_count": 0, + "cost_sol": 0.252, + "cost_usd": 21.42, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 1466.83, + "total_pnl_usd": 1445.41, + "profit_multiple": 68.48, + "still_holding": true, + "earliest_buy_time": 1770655363 + } + }, + { + "address": "Fj2uMrBaHkMcadrrTXeT5WSKfS6TCZyMUN1sSnoxQawv", + "chain": "solana", + "label": "Alpha #12 (from $$POKEMON30)", + "source": "alpha_scanner:$POKEMON30", + "alpha_score": 65, + "sol_balance": 16.114938037, + "token_count": 0, + "discovered_via": "B1RB6i7gvxYoyx8Us1eFrJxr7DZv3RzLmBHdfPwDpump", + "discovered_at": "2026-02-09T17:07:33.482120+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 2, + "sell_count": 0, + "cost_sol": 1.5006, + "cost_usd": 127.55, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 1244.07, + "total_pnl_usd": 1116.52, + "profit_multiple": 9.75, + "still_holding": true, + "earliest_buy_time": 1770640310 + } + }, + { + "address": "EqQZvQDWr1cp96PejiFkJo4UCkmti7nfLZjPuAw9Hz6K", + "chain": "solana", + "label": "Alpha #13 (from $ROCK)", + "source": "alpha_scanner:ROCK", + "alpha_score": 95, + "sol_balance": 12.345240223, + "token_count": 0, + "discovered_via": "HjgwHz7QRjdT7DckZL2sJVKZ9iJm6K3oUmHu3bFapump", + "discovered_at": "2026-02-09T17:09:09.389720+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 2, + "sell_count": 1, + "cost_sol": 1.0288, + "cost_usd": 87.45, + "realized_sol": 0.9719, + "realized_usd": 82.61, + "unrealized_usd": 2394.82, + "total_pnl_usd": 2389.98, + "profit_multiple": 28.33, + "still_holding": true, + "earliest_buy_time": 1770652582 + } + }, + { + "address": "Ci8oK32uRq1itnBRzVSwbyBNqJANhbsjuQe3qB5FfKxu", + "chain": "solana", + "label": "Alpha #14 (from $ROCK)", + "source": "alpha_scanner:ROCK", + "alpha_score": 60, + "sol_balance": 4.056918373, + "token_count": 0, + "discovered_via": "HjgwHz7QRjdT7DckZL2sJVKZ9iJm6K3oUmHu3bFapump", + "discovered_at": "2026-02-09T17:09:09.389720+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 2, + "sell_count": 0, + "cost_sol": 6.0109, + "cost_usd": 510.93, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 4647.68, + "total_pnl_usd": 4136.75, + "profit_multiple": 9.1, + "still_holding": true, + "earliest_buy_time": 1770655633 + } + }, + { + "address": "3AGkLzoHJ6pz3qARi2vc7gDGyVNDaPj9dwBcCj2qMY16", + "chain": "solana", + "label": "Alpha #15 (from $ROCK)", + "source": "alpha_scanner:ROCK", + "alpha_score": 60, + "sol_balance": 8.432769508, + "token_count": 0, + "discovered_via": "HjgwHz7QRjdT7DckZL2sJVKZ9iJm6K3oUmHu3bFapump", + "discovered_at": "2026-02-09T17:09:09.389720+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 3, + "sell_count": 4, + "cost_sol": 4.2012, + "cost_usd": 357.1, + "realized_sol": 8.6348, + "realized_usd": 733.96, + "unrealized_usd": 2562.76, + "total_pnl_usd": 2939.62, + "profit_multiple": 9.23, + "still_holding": true, + "earliest_buy_time": 1770655481 + } + }, + { + "address": "FnRQiKnfcudnBLk5KmsSCWFgKvgfpaZd9guz31ghLRkF", + "chain": "solana", + "label": "Alpha #16 (from $ROCK)", + "source": "alpha_scanner:ROCK", + "alpha_score": 90, + "sol_balance": 64.737845319, + "token_count": 0, + "discovered_via": "HjgwHz7QRjdT7DckZL2sJVKZ9iJm6K3oUmHu3bFapump", + "discovered_at": "2026-02-09T17:09:09.389720+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 3, + "sell_count": 0, + "cost_sol": 0.0, + "cost_usd": 0.0, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 6820.0, + "total_pnl_usd": 6820.0, + "profit_multiple": 0, + "still_holding": true, + "earliest_buy_time": 1770640987 + }, + "last_scan": "2026-02-13T18:10:55.934601+00:00" + }, + { + "address": "ND8nFkaHP9kwQXnhb3ELMEWqgHUu6ww2pzYcg7UfGCe", + "chain": "solana", + "label": "Alpha #17 (from $Maximoto)", + "source": "alpha_scanner:Maximoto", + "alpha_score": 115, + "sol_balance": 14.977989965, + "token_count": 0, + "discovered_via": "8QJGmTnGhJAfGmkGrscYzrYKacaUCMYTTQQ2Wb3apump", + "discovered_at": "2026-02-09T17:11:07.450746+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 1, + "sell_count": 0, + "cost_sol": 0.2001, + "cost_usd": 17.01, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 1301.05, + "total_pnl_usd": 1284.05, + "profit_multiple": 76.51, + "still_holding": true, + "earliest_buy_time": 1770654445 + } + }, + { + "address": "3ABA191xHH2eVAdBXu8wv2W1kfUWvZoNYbF7Yhkn418G", + "chain": "solana", + "label": "Alpha #18 (from $BUCKARU)", + "source": "alpha_scanner:BUCKARU", + "alpha_score": 110, + "sol_balance": 6.487483724, + "token_count": 0, + "discovered_via": "E2HNWS5L6gwmtC9SZPpRq6Yp3V5gzotFrL3dAEP2pump", + "discovered_at": "2026-02-11T09:43:00.590852+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 2, + "sell_count": 0, + "cost_sol": 0.0022, + "cost_usd": 0.19, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 4578.38, + "total_pnl_usd": 4578.19, + "profit_multiple": 24425.68, + "still_holding": true, + "earliest_buy_time": 1770768365 + } + }, + { + "address": "5T229oePmJGE5Cefys8jE9Jq8C7qfGNNWy3RVA7SmwEP", + "chain": "solana", + "label": "Alpha #19 (from $BUCKARU)", + "source": "alpha_scanner:BUCKARU", + "alpha_score": 70, + "sol_balance": 61.929826401, + "token_count": 0, + "discovered_via": "E2HNWS5L6gwmtC9SZPpRq6Yp3V5gzotFrL3dAEP2pump", + "discovered_at": "2026-02-11T09:43:00.590852+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 1, + "sell_count": 0, + "cost_sol": 5.0485, + "cost_usd": 429.12, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 4045.98, + "total_pnl_usd": 3616.86, + "profit_multiple": 9.43, + "still_holding": true, + "earliest_buy_time": 1770794877 + } + }, + { + "address": "75tPJxmQDz612FCQ4eRnP5mL7YnQqg3DtsqXbyZogyX4", + "chain": "solana", + "label": "Alpha #20 (from $#MLM)", + "source": "alpha_scanner:#MLM", + "alpha_score": 110, + "sol_balance": 1.928756902, + "token_count": 0, + "discovered_via": "8ckfBhNvEDA62udk4YGNbSYcd5wvmQDjhY6kAYsgpump", + "discovered_at": "2026-02-11T09:45:08.118997+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 4, + "sell_count": 0, + "cost_sol": 0.0036, + "cost_usd": 0.3, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 4826.02, + "total_pnl_usd": 4825.71, + "profit_multiple": 15849.69, + "still_holding": true, + "earliest_buy_time": 1770773778 + } + }, + { + "address": "H6KiqN3wwirFumem4ZqxbF3hhHNTjpyps3q7TTLX3n33", + "chain": "solana", + "label": "Alpha #21 (from $#MLM)", + "source": "alpha_scanner:#MLM", + "alpha_score": 110, + "sol_balance": 1.299250714, + "token_count": 0, + "discovered_via": "8ckfBhNvEDA62udk4YGNbSYcd5wvmQDjhY6kAYsgpump", + "discovered_at": "2026-02-11T09:45:08.118997+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 1, + "sell_count": 1, + "cost_sol": 0.0009, + "cost_usd": 0.08, + "realized_sol": 20.4843, + "realized_usd": 1741.17, + "unrealized_usd": 2007.01, + "total_pnl_usd": 3748.09, + "profit_multiple": 47432.86, + "still_holding": true, + "earliest_buy_time": 1770786015 + } + }, + { + "address": "2z24tiA9QR4PA1nBUK8Wpvo5viDAxVZpAeprKQqeyHeW", + "chain": "solana", + "label": "Alpha #22 (from $GROKPEPE)", + "source": "alpha_scanner:GROKPEPE", + "alpha_score": 60, + "sol_balance": 5.847135915, + "token_count": 0, + "discovered_via": "3mHw8CJffDZpY8F6KmGVF3LwwejCkMHG2o2pV5ZVpump", + "discovered_at": "2026-02-11T09:46:52.935291+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 3, + "sell_count": 2, + "cost_sol": 2.9003, + "cost_usd": 246.52, + "realized_sol": 5.8471, + "realized_usd": 497.01, + "unrealized_usd": 1200.16, + "total_pnl_usd": 1450.65, + "profit_multiple": 6.88, + "still_holding": true, + "earliest_buy_time": 1770763097 + } + }, + { + "address": "4qPaGk9s8wpFhxVzncAQAt7dhGkp2byeG7qxU3AuKg1u", + "chain": "solana", + "label": "Alpha #23 (from $Ferociter)", + "source": "alpha_scanner:Ferociter", + "alpha_score": 120, + "sol_balance": 2.305192537, + "token_count": 0, + "discovered_via": "7SYuU1Z6EKfpYQQ9VeTXfLW5ofhigdn8Y7iQsqoepump", + "discovered_at": "2026-02-11T09:48:06.987359+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 1, + "sell_count": 0, + "cost_sol": 0.0076, + "cost_usd": 0.64, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 522.89, + "total_pnl_usd": 522.25, + "profit_multiple": 811.02, + "still_holding": true, + "earliest_buy_time": 1770700074 + } + }, + { + "address": "B5hhu1W6E3qgqgd5WYGiBPdg4zShUyFXLoH3KA2NEB5t", + "chain": "solana", + "label": "Alpha #24 (from $Ferociter)", + "source": "alpha_scanner:Ferociter", + "alpha_score": 100, + "sol_balance": 1.195165604, + "token_count": 0, + "discovered_via": "7SYuU1Z6EKfpYQQ9VeTXfLW5ofhigdn8Y7iQsqoepump", + "discovered_at": "2026-02-11T09:48:06.987359+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 1, + "sell_count": 0, + "cost_sol": 0.0002, + "cost_usd": 0.02, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 542.17, + "total_pnl_usd": 542.16, + "profit_multiple": 30406.99, + "still_holding": true, + "earliest_buy_time": 1770717681 + } + }, + { + "address": "87rRdssFiTJKY4MGARa4G5vQ31hmR7MxSmhzeaJ5AAxJ", + "chain": "solana", + "label": "Alpha #25 (from $GIRAFFES)", + "source": "alpha_scanner:GIRAFFES", + "alpha_score": 135, + "sol_balance": 74.517244456, + "token_count": 0, + "discovered_via": "GbqbsRyBHVPHEv7xLEsikXmdpPPiApLTJesDBbL5pump", + "discovered_at": "2026-02-11T09:49:30.348790+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 2, + "sell_count": 0, + "cost_sol": 1.0422, + "cost_usd": 88.59, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 14240.61, + "total_pnl_usd": 14152.02, + "profit_multiple": 160.75, + "still_holding": true, + "earliest_buy_time": 1770800044 + } + }, + { + "address": "8WXKcUjwMU5TxiEN4mjw52iP4uPKx8VpXGozqMadqhyq", + "chain": "solana", + "label": "Alpha #26 (from $GIRAFFES)", + "source": "alpha_scanner:GIRAFFES", + "alpha_score": 125, + "sol_balance": 1.470610327, + "token_count": 0, + "discovered_via": "GbqbsRyBHVPHEv7xLEsikXmdpPPiApLTJesDBbL5pump", + "discovered_at": "2026-02-11T09:49:30.348790+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 2, + "sell_count": 0, + "cost_sol": 0.0002, + "cost_usd": 0.02, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 19724.62, + "total_pnl_usd": 19724.61, + "profit_multiple": 1195472.55, + "still_holding": true, + "earliest_buy_time": 1770772171 + } + }, + { + "address": "Cqj2kGj9Wap4ghLuJkJ3HC1ZC2Brd2dVi7HweXLPH1b1", + "chain": "solana", + "label": "Alpha #27 (from $SAFEMOON)", + "source": "alpha_scanner:SAFEMOON", + "alpha_score": 140, + "sol_balance": 93.149115636, + "token_count": 0, + "discovered_via": "G9YU3K1MiPTv7Krui5omkPBPP21GChPPE3c9izRKbonk", + "discovered_at": "2026-02-11T09:50:43.878768+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 1, + "sell_count": 0, + "cost_sol": 0.003, + "cost_usd": 0.25, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 2457.56, + "total_pnl_usd": 2457.31, + "profit_multiple": 9707.4, + "still_holding": true, + "earliest_buy_time": 1770692839 + } + }, + { + "address": "EXWGUMiuxxTB1TL1ZguYkDSyo4DwVfpDDZE3aox1pYzP", + "chain": "solana", + "label": "Alpha #28 (from $SAFEMOON)", + "source": "alpha_scanner:SAFEMOON", + "alpha_score": 130, + "sol_balance": 9.997291914, + "token_count": 0, + "discovered_via": "G9YU3K1MiPTv7Krui5omkPBPP21GChPPE3c9izRKbonk", + "discovered_at": "2026-02-11T09:50:43.878768+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 1, + "sell_count": 0, + "cost_sol": 0.0021, + "cost_usd": 0.17, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 2004.98, + "total_pnl_usd": 2004.8, + "profit_multiple": 11495.34, + "still_holding": true, + "earliest_buy_time": 1770709377 + } + }, + { + "address": "BC8yiFFQWFEKrEEj75zYsuK3ZDCfv6QEeMRif9oZZ9TW", + "chain": "solana", + "label": "Alpha #29 (from $soluna)", + "source": "alpha_scanner:soluna", + "alpha_score": 90, + "sol_balance": 106.0528855, + "token_count": 0, + "discovered_via": "2qT8JVotQ2C1gKbqpuqNatkpSBWxiKHbXkCyTqH9pump", + "discovered_at": "2026-02-11T09:52:17.847791+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 3, + "sell_count": 0, + "cost_sol": 45.0022, + "cost_usd": 3825.19, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 19490.13, + "total_pnl_usd": 15664.95, + "profit_multiple": 5.1, + "still_holding": true, + "earliest_buy_time": 1770770333 + } + }, + { + "address": "4QodqLUiQ57XF3W2X6AjYhKW2NGUuVdreGLQJkbWkVa2", + "chain": "solana", + "label": "Alpha #30 (from $soluna)", + "source": "alpha_scanner:soluna", + "alpha_score": 40, + "sol_balance": 90.36258218, + "token_count": 0, + "discovered_via": "2qT8JVotQ2C1gKbqpuqNatkpSBWxiKHbXkCyTqH9pump", + "discovered_at": "2026-02-11T09:52:17.847791+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 2, + "sell_count": 0, + "cost_sol": 0.0, + "cost_usd": 0.0, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 8177.93, + "total_pnl_usd": 8177.93, + "profit_multiple": 0, + "still_holding": true, + "earliest_buy_time": 1770799050 + } + }, + { + "address": "CjHKLXKPCC8rf6sdYznkmMxsMEDoLgJsawsWaheAqTRa", + "chain": "solana", + "label": "Alpha #31 (from $HAL)", + "source": "alpha_scanner:HAL", + "alpha_score": 40, + "sol_balance": 77.005721586, + "token_count": 0, + "discovered_via": "CvTMSEB9RzHPhB1CgE7PAkszomozDv3JJNz28sDbpump", + "discovered_at": "2026-02-11T09:53:21.928669+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 6, + "sell_count": 0, + "cost_sol": 7.0869, + "cost_usd": 602.38, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 2112.38, + "total_pnl_usd": 1509.99, + "profit_multiple": 3.51, + "still_holding": true, + "earliest_buy_time": 1770741727 + } + }, + { + "address": "DM3LKCMnZEmjnW57WVeWodRbur9ivBytjo2dkHKEfhQP", + "chain": "solana", + "label": "Alpha #32 (from $ICF)", + "source": "alpha_scanner:ICF", + "alpha_score": 125, + "sol_balance": 1.021190683, + "token_count": 0, + "discovered_via": "F6QoH8WfU67V7xP7fnTHGpkR6xdegLUcPGjSLsGQmMD4", + "discovered_at": "2026-02-11T09:55:40.829532+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 11, + "sell_count": 1, + "cost_sol": 0.0021, + "cost_usd": 0.18, + "realized_sol": 0.0, + "realized_usd": 0.0, + "unrealized_usd": 11544.02, + "total_pnl_usd": 11543.84, + "profit_multiple": 63641.92, + "still_holding": true, + "earliest_buy_time": 1770763861 + } + }, + { + "address": "24DCWvhrk4xwH6eCQ2UK8rWM1KXb1k93D4ebGfZ9RWXT", + "chain": "solana", + "label": "Alpha #33 (from $Rex)", + "source": "alpha_scanner:Rex", + "alpha_score": 80, + "sol_balance": 16.470336395, + "token_count": 0, + "discovered_via": "HXvQAQwytoLngKWQtge3oJnLHsaLwTxPbX48DctLpump", + "discovered_at": "2026-02-11T12:19:45.207601+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 1, + "sell_count": 0, + "cost_sol": 1.0191, + "cost_usd": 86.62, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 1537.37, + "total_pnl_usd": 1450.75, + "profit_multiple": 17.75, + "still_holding": true, + "earliest_buy_time": 1770798872 + } + }, + { + "address": "7TQfNAr4R5wh3G7PjksnHhKmKjHYDHNa7jaKTntrmXXk", + "chain": "solana", + "label": "Alpha #34 (from $JESTER)", + "source": "alpha_scanner:JESTER", + "alpha_score": 135, + "sol_balance": 11.004215083, + "token_count": 0, + "discovered_via": "6WdHhpRY7vL8SQ69bd89tAj3sk8jsjBrCLDUTZSNpump", + "discovered_at": "2026-02-11T17:08:23.733314+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 1, + "sell_count": 0, + "cost_sol": 1.0, + "cost_usd": 85.0, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 5748.43, + "total_pnl_usd": 5663.43, + "profit_multiple": 67.63, + "still_holding": true, + "earliest_buy_time": 1770680931 + } + }, + { + "address": "6QDnPbwbJuph4LdRDBj6ZGhVvw5fFx2dL2uBeDXCHWH", + "chain": "solana", + "label": "Alpha #35 (from $CARDS)", + "source": "alpha_scanner:CARDS", + "alpha_score": 65, + "sol_balance": 11.009940002, + "token_count": 0, + "discovered_via": "CARDSccUMFKoPRZxt5vt3ksUbxEFEcnZ3H2pd3dKxYjp", + "discovered_at": "2026-02-11T17:59:29.242629+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 4, + "sell_count": 0, + "cost_sol": 441.946, + "cost_usd": 37565.41, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 154323.04, + "total_pnl_usd": 116757.63, + "profit_multiple": 4.11, + "still_holding": true, + "earliest_buy_time": 1760801178 + } + }, + { + "address": "3pdX233Gg1QaAhpzBQpd2h6prY8V1s2C9V1Hwh2viZnG", + "chain": "solana", + "label": "Alpha #36 (from $BLOWFISH)", + "source": "alpha_scanner:BLOWFISH", + "alpha_score": 125, + "sol_balance": 600.140229054, + "token_count": 0, + "discovered_via": "CFB4Ff7W87uN9Gf2DSj63L7prZycJvzQeg1MbGxwBcqC", + "discovered_at": "2026-02-11T17:59:30.344696+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 8, + "sell_count": 0, + "cost_sol": 0.0055, + "cost_usd": 0.47, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 9077.11, + "total_pnl_usd": 9076.64, + "profit_multiple": 19348.44, + "still_holding": true, + "earliest_buy_time": 1770772477 + } + }, + { + "address": "74R4zxxwNJEcgnjUYvXbSN3j8e2Xm8nXN9fPDcSxhcQF", + "chain": "solana", + "label": "Alpha #37 (from $PsyopAnime)", + "source": "alpha_scanner:PsyopAnime", + "alpha_score": 75, + "sol_balance": 1.001372843, + "token_count": 0, + "discovered_via": "2nP9yKQNSGQy851iyawDvBkzkK2R2aqKArQCKc2gpump", + "discovered_at": "2026-02-11T17:59:26.008402+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 2, + "sell_count": 1, + "cost_sol": 75.7109, + "cost_usd": 6435.43, + "realized_sol": 79.4116, + "realized_usd": 6749.99, + "unrealized_usd": 37775.01, + "total_pnl_usd": 38089.57, + "profit_multiple": 6.92, + "still_holding": true, + "earliest_buy_time": 1770800684 + } + }, + { + "address": "BEWjNZivbn4x2cLYFDjdiFV43UBupzGTx7YwxZYFB3tr", + "chain": "solana", + "label": "Alpha #38 (from $NAMECOIN)", + "source": "alpha_scanner:NAMECOIN", + "alpha_score": 80, + "sol_balance": 12.908217173, + "token_count": 0, + "discovered_via": "bZyeJwx2ZTNRq9HSpCBdXFdDXrpiLW5AEiZad2ipump", + "discovered_at": "2026-02-13T14:32:47.351110+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 1, + "sell_count": 0, + "cost_sol": 1.02, + "cost_usd": 86.7, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 1490.67, + "total_pnl_usd": 1403.97, + "profit_multiple": 17.19, + "still_holding": true, + "earliest_buy_time": 1770990986 + } + }, + { + "address": "GuQNDopfv7PWGGyminzNRnjPMs7Ss6ZRQBHjzE88oXVc", + "chain": "solana", + "label": "Alpha #39 (from $NAMECOIN)", + "source": "alpha_scanner:NAMECOIN", + "alpha_score": 65, + "sol_balance": 21.226617249, + "token_count": 0, + "discovered_via": "bZyeJwx2ZTNRq9HSpCBdXFdDXrpiLW5AEiZad2ipump", + "discovered_at": "2026-02-13T14:32:47.351110+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 1, + "sell_count": 0, + "cost_sol": 5.1146, + "cost_usd": 434.74, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 2547.18, + "total_pnl_usd": 2112.44, + "profit_multiple": 5.86, + "still_holding": true, + "earliest_buy_time": 1770987782 + } + }, + { + "address": "p4jsxPV5DKoJA2hroCyVv521VFDCm6qgxmRRHJFnH61", + "chain": "solana", + "label": "Alpha #40 (from $NAMECOIN)", + "source": "alpha_scanner:NAMECOIN", + "alpha_score": 65, + "sol_balance": 13.21982535, + "token_count": 0, + "discovered_via": "bZyeJwx2ZTNRq9HSpCBdXFdDXrpiLW5AEiZad2ipump", + "discovered_at": "2026-02-13T14:32:47.351110+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 4, + "sell_count": 2, + "cost_sol": 5.072, + "cost_usd": 431.12, + "realized_sol": 4.9457, + "realized_usd": 420.39, + "unrealized_usd": 1896.19, + "total_pnl_usd": 1885.46, + "profit_multiple": 5.37, + "still_holding": true, + "earliest_buy_time": 1770989999 + } + }, + { + "address": "7Y5fKQkErwDfDmP3m5DkhUbvFo4ahMVnTz3QSpwcs12", + "chain": "solana", + "label": "Alpha #41 (from $NAMECOIN)", + "source": "alpha_scanner:NAMECOIN", + "alpha_score": 65, + "sol_balance": 37.65418289, + "token_count": 0, + "discovered_via": "bZyeJwx2ZTNRq9HSpCBdXFdDXrpiLW5AEiZad2ipump", + "discovered_at": "2026-02-13T14:32:47.351110+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 1, + "sell_count": 3, + "cost_sol": 10.0004, + "cost_usd": 850.04, + "realized_sol": 50.695, + "realized_usd": 4309.08, + "unrealized_usd": 1741.0, + "total_pnl_usd": 5200.04, + "profit_multiple": 7.12, + "still_holding": true, + "earliest_buy_time": 1770983679 + } + }, + { + "address": "9Er4cUFH6myj7vowBFR3YeV3xJuXSMKqnBVygpjm2g5o", + "chain": "solana", + "label": "Alpha #42 (from $NAMECOIN)", + "source": "alpha_scanner:NAMECOIN", + "alpha_score": 60, + "sol_balance": 5.374852976, + "token_count": 0, + "discovered_via": "bZyeJwx2ZTNRq9HSpCBdXFdDXrpiLW5AEiZad2ipump", + "discovered_at": "2026-02-13T14:32:47.351110+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 1, + "sell_count": 0, + "cost_sol": 3.0425, + "cost_usd": 258.62, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 1707.39, + "total_pnl_usd": 1448.77, + "profit_multiple": 6.6, + "still_holding": true, + "earliest_buy_time": 1770987731 + } + }, + { + "address": "6Q3iMkRrGrWtHY2VXHf3b8g7VQEn8JpE4ZPDPYZnJrSZ", + "chain": "solana", + "label": "Alpha #43 (from $NAMECOIN)", + "source": "alpha_scanner:NAMECOIN", + "alpha_score": 40, + "sol_balance": 88.653303516, + "token_count": 0, + "discovered_via": "bZyeJwx2ZTNRq9HSpCBdXFdDXrpiLW5AEiZad2ipump", + "discovered_at": "2026-02-13T14:32:47.351110+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 2, + "sell_count": 0, + "cost_sol": 8.2922, + "cost_usd": 704.84, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 2034.87, + "total_pnl_usd": 1330.04, + "profit_multiple": 2.89, + "still_holding": true, + "earliest_buy_time": 1770980072 + } + }, + { + "address": "6SMNVye8DWgFMrk2Uvm6zowCTSAL4QD4nb9SbchtNcLR", + "chain": "solana", + "label": "Alpha #44 (from $LIZARD)", + "source": "alpha_scanner:LIZARD", + "alpha_score": 95, + "sol_balance": 14.687290241, + "token_count": 0, + "discovered_via": "5T17aqgJ8cM39SNuVBu2LK2cq5MWUpZxcQnnuwNjpump", + "discovered_at": "2026-02-13T18:04:50.043289+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 2, + "sell_count": 0, + "cost_sol": 2.0059, + "cost_usd": 170.5, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 5743.74, + "total_pnl_usd": 5573.24, + "profit_multiple": 33.69, + "still_holding": true, + "earliest_buy_time": 1771004428 + } + }, + { + "address": "6BkLdVcsk9TwowQg8ZWYqH1TgTUFyJrf1xr3vSXo4pHX", + "chain": "solana", + "label": "Alpha #45 (from $LIZARD)", + "source": "alpha_scanner:LIZARD", + "alpha_score": 95, + "sol_balance": 41.118106653, + "token_count": 0, + "discovered_via": "5T17aqgJ8cM39SNuVBu2LK2cq5MWUpZxcQnnuwNjpump", + "discovered_at": "2026-02-13T18:04:50.043289+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 1, + "sell_count": 4, + "cost_sol": 1.004, + "cost_usd": 85.34, + "realized_sol": 3.9597, + "realized_usd": 336.57, + "unrealized_usd": 3800.11, + "total_pnl_usd": 4051.34, + "profit_multiple": 48.47, + "still_holding": true, + "earliest_buy_time": 1771004627 + } + }, + { + "address": "B9oKseVKRntTvfADyaUoH7oVmoyVbBfUf4NKyQc4KK2D", + "chain": "solana", + "label": "Alpha #46 (from $LIZARD)", + "source": "alpha_scanner:LIZARD", + "alpha_score": 65, + "sol_balance": 17.052968507, + "token_count": 0, + "discovered_via": "5T17aqgJ8cM39SNuVBu2LK2cq5MWUpZxcQnnuwNjpump", + "discovered_at": "2026-02-13T18:04:50.043289+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 3, + "sell_count": 0, + "cost_sol": 3.63, + "cost_usd": 308.55, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 2707.42, + "total_pnl_usd": 2398.87, + "profit_multiple": 8.77, + "still_holding": true, + "earliest_buy_time": 1771003280 + } + }, + { + "address": "6r8YXQ8KXmF9JTMh7u5nHQiirW8WqvKiJubFBj2jYHPt", + "chain": "solana", + "label": "Alpha #47 (from $MoonLiquid)", + "source": "alpha_scanner:MoonLiquid", + "alpha_score": 100, + "sol_balance": 2.364247237, + "token_count": 0, + "discovered_via": "63p6ir6gGQ59ZCDN2iRGUkCrZyJvu2xaacRYBfKopump", + "discovered_at": "2026-02-13T18:07:21.600885+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 1, + "sell_count": 4, + "cost_sol": 0.0858, + "cost_usd": 7.29, + "realized_sol": 0.3853, + "realized_usd": 32.75, + "unrealized_usd": 384.33, + "total_pnl_usd": 409.78, + "profit_multiple": 57.19, + "still_holding": true, + "earliest_buy_time": 1770997864 + } + }, + { + "address": "FMueRHVUsxAgDtsMwAYj972rLNzFkdC4xF22chZEG2zP", + "chain": "solana", + "label": "Alpha #48 (from $MoonLiquid)", + "source": "alpha_scanner:MoonLiquid", + "alpha_score": 65, + "sol_balance": 2.423902911, + "token_count": 0, + "discovered_via": "63p6ir6gGQ59ZCDN2iRGUkCrZyJvu2xaacRYBfKopump", + "discovered_at": "2026-02-13T18:07:21.600885+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 4, + "sell_count": 4, + "cost_sol": 0.6031, + "cost_usd": 51.27, + "realized_sol": 1.4694, + "realized_usd": 124.9, + "unrealized_usd": 447.12, + "total_pnl_usd": 520.75, + "profit_multiple": 11.16, + "still_holding": true, + "earliest_buy_time": 1771003652 + } + }, + { + "address": "H5Y7cBhZcQSB1X2VZ6ZNtjs1hr5LyU5bhdpJhtzx5uf1", + "chain": "solana", + "label": "Alpha #49 (from $MoonLiquid)", + "source": "alpha_scanner:MoonLiquid", + "alpha_score": 65, + "sol_balance": 1.996647386, + "token_count": 0, + "discovered_via": "63p6ir6gGQ59ZCDN2iRGUkCrZyJvu2xaacRYBfKopump", + "discovered_at": "2026-02-13T18:07:21.600885+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 4, + "sell_count": 4, + "cost_sol": 0.5406, + "cost_usd": 45.95, + "realized_sol": 0.7618, + "realized_usd": 64.75, + "unrealized_usd": 432.77, + "total_pnl_usd": 451.58, + "profit_multiple": 10.83, + "still_holding": true, + "earliest_buy_time": 1771003206 + } + }, + { + "address": "6sisAr73CdtU3CiSYwPsuQNKrUjnrzWHVDfs8dQCaAeK", + "chain": "solana", + "label": "Alpha #50 (from $MoonLiquid)", + "source": "alpha_scanner:MoonLiquid", + "alpha_score": 65, + "sol_balance": 2.714422976, + "token_count": 0, + "discovered_via": "63p6ir6gGQ59ZCDN2iRGUkCrZyJvu2xaacRYBfKopump", + "discovered_at": "2026-02-13T18:07:21.600885+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 4, + "sell_count": 8, + "cost_sol": 0.6118, + "cost_usd": 52.0, + "realized_sol": 1.7971, + "realized_usd": 152.75, + "unrealized_usd": 386.73, + "total_pnl_usd": 487.48, + "profit_multiple": 10.37, + "still_holding": true, + "earliest_buy_time": 1771004190 + } + }, + { + "address": "F85VkJ5gnR4iaYMc9orfjTXUvfbVxwFQoQfW3yYskDJi", + "chain": "solana", + "label": "Alpha #51 (from $MoonLiquid)", + "source": "alpha_scanner:MoonLiquid", + "alpha_score": 65, + "sol_balance": 4.605090624, + "token_count": 0, + "discovered_via": "63p6ir6gGQ59ZCDN2iRGUkCrZyJvu2xaacRYBfKopump", + "discovered_at": "2026-02-13T18:07:21.600885+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 4, + "sell_count": 8, + "cost_sol": 0.527, + "cost_usd": 44.8, + "realized_sol": 1.7901, + "realized_usd": 152.16, + "unrealized_usd": 386.71, + "total_pnl_usd": 494.06, + "profit_multiple": 12.03, + "still_holding": true, + "earliest_buy_time": 1771004235 + } + }, + { + "address": "31q4Z7jSnETrMq7xAnCENfLKfYT37cGjt65UizBDjraE", + "chain": "solana", + "label": "Alpha #52 (from $MoonLiquid)", + "source": "alpha_scanner:MoonLiquid", + "alpha_score": 50, + "sol_balance": 2.360882184, + "token_count": 0, + "discovered_via": "63p6ir6gGQ59ZCDN2iRGUkCrZyJvu2xaacRYBfKopump", + "discovered_at": "2026-02-13T18:07:21.600885+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 4, + "sell_count": 0, + "cost_sol": 0.6791, + "cost_usd": 57.72, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 479.34, + "total_pnl_usd": 421.61, + "profit_multiple": 8.3, + "still_holding": true, + "earliest_buy_time": 1771003502 + } + }, + { + "address": "FBSAJw1xT18aie43mu24BENkCaXGUAd32MXjjVQtBdDg", + "chain": "solana", + "label": "Alpha #53 (from $MoonLiquid)", + "source": "alpha_scanner:MoonLiquid", + "alpha_score": 50, + "sol_balance": 2.304757047, + "token_count": 0, + "discovered_via": "63p6ir6gGQ59ZCDN2iRGUkCrZyJvu2xaacRYBfKopump", + "discovered_at": "2026-02-13T18:07:21.600885+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 4, + "sell_count": 4, + "cost_sol": 0.6501, + "cost_usd": 55.26, + "realized_sol": 0.6421, + "realized_usd": 54.58, + "unrealized_usd": 425.03, + "total_pnl_usd": 424.35, + "profit_multiple": 8.68, + "still_holding": true, + "earliest_buy_time": 1771000926 + } + }, + { + "address": "Dn8WybAQsjFC39HD2Jj16etFALP99Uqt6u73yJXM36U9", + "chain": "solana", + "label": "Alpha #54 (from $MoonLiquid)", + "source": "alpha_scanner:MoonLiquid", + "alpha_score": 50, + "sol_balance": 2.283345722, + "token_count": 0, + "discovered_via": "63p6ir6gGQ59ZCDN2iRGUkCrZyJvu2xaacRYBfKopump", + "discovered_at": "2026-02-13T18:07:21.600885+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 4, + "sell_count": 4, + "cost_sol": 0.6922, + "cost_usd": 58.84, + "realized_sol": 0.4634, + "realized_usd": 39.39, + "unrealized_usd": 423.35, + "total_pnl_usd": 403.9, + "profit_multiple": 7.86, + "still_holding": true, + "earliest_buy_time": 1771003772 + } + }, + { + "address": "9vF5Dd6xHneaWhEnDuuzNEfbUw2dPiayYZ6QuWeL6Eok", + "chain": "solana", + "label": "Alpha #55 (from $MoonLiquid)", + "source": "alpha_scanner:MoonLiquid", + "alpha_score": 50, + "sol_balance": 1.947575462, + "token_count": 0, + "discovered_via": "63p6ir6gGQ59ZCDN2iRGUkCrZyJvu2xaacRYBfKopump", + "discovered_at": "2026-02-13T18:07:21.600885+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 4, + "sell_count": 0, + "cost_sol": 0.5414, + "cost_usd": 46.02, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 398.75, + "total_pnl_usd": 352.73, + "profit_multiple": 8.67, + "still_holding": true, + "earliest_buy_time": 1771004371 + } + }, + { + "address": "EUW1V7fguJEfTGCNBcssfsyy6sXVvNFZ9SsMosLz6Z8y", + "chain": "solana", + "label": "Alpha #56 (from $MoonLiquid)", + "source": "alpha_scanner:MoonLiquid", + "alpha_score": 50, + "sol_balance": 2.713933119, + "token_count": 0, + "discovered_via": "63p6ir6gGQ59ZCDN2iRGUkCrZyJvu2xaacRYBfKopump", + "discovered_at": "2026-02-13T18:07:21.600885+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 4, + "sell_count": 4, + "cost_sol": 0.6215, + "cost_usd": 52.83, + "realized_sol": 0.5603, + "realized_usd": 47.63, + "unrealized_usd": 397.38, + "total_pnl_usd": 392.18, + "profit_multiple": 8.42, + "still_holding": true, + "earliest_buy_time": 1771003670 + } + }, + { + "address": "4fUFnzvRaMJqoowoKaHxViQ3jZS1jbKCyyhJLtcKDNBp", + "chain": "solana", + "label": "Alpha #57 (from $hoodrat)", + "source": "alpha_scanner:hoodrat", + "alpha_score": 110, + "sol_balance": 1.216685247, + "token_count": 0, + "discovered_via": "58ExX8TFqiDqUpr1ZGiAhhiUsKfT14gwTFykLoVCpump", + "discovered_at": "2026-02-13T18:10:55.934601+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 1, + "sell_count": 0, + "cost_sol": 0.0055, + "cost_usd": 0.47, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 4682.16, + "total_pnl_usd": 4681.69, + "profit_multiple": 10002.99, + "still_holding": true, + "earliest_buy_time": 1771006193 + } + }, + { + "address": "CECN4BW4DKnbyddkd9FhWVR5dotzKhQr5p7DUPhQ55Du", + "chain": "solana", + "label": "Alpha #58 (from $Buttfish)", + "source": "alpha_scanner:Buttfish", + "alpha_score": 110, + "sol_balance": 5.531061037, + "token_count": 0, + "discovered_via": "58Ghft9TvGNuBiDzy9cFD2Px9rz5cDVZ1XoMFk1xpump", + "discovered_at": "2026-02-13T18:13:43.018300+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 5, + "sell_count": 0, + "cost_sol": 0.105, + "cost_usd": 8.93, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 5204.0, + "total_pnl_usd": 5195.07, + "profit_multiple": 582.94, + "still_holding": true, + "earliest_buy_time": 1771003072 + } + }, + { + "address": "9z8EbPzyTML4BDXWm7bhZ5NsLRYrTfhaxjmE9m4zanrf", + "chain": "solana", + "label": "Alpha #59 (from $helicator)", + "source": "alpha_scanner:helicator", + "alpha_score": 75, + "sol_balance": 2.695890514, + "token_count": 0, + "discovered_via": "EFt9JrrGyLWLU6Wc4oxfTjDKryENPrjbGgZ2V6x8pump", + "discovered_at": "2026-02-13T18:15:16.746047+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 4, + "sell_count": 0, + "cost_sol": 1.0701, + "cost_usd": 90.96, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 1197.65, + "total_pnl_usd": 1106.69, + "profit_multiple": 13.17, + "still_holding": true, + "earliest_buy_time": 1770973988 + } + }, + { + "address": "5MigbXPuoCBzzDXBHMxRKudWmby4BVDQckZLAB6ti1RF", + "chain": "solana", + "label": "Alpha #60 (from $helicator)", + "source": "alpha_scanner:helicator", + "alpha_score": 55, + "sol_balance": 30.315980907, + "token_count": 0, + "discovered_via": "EFt9JrrGyLWLU6Wc4oxfTjDKryENPrjbGgZ2V6x8pump", + "discovered_at": "2026-02-13T18:15:16.746047+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 1, + "sell_count": 0, + "cost_sol": 2.0502, + "cost_usd": 174.26, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 1003.96, + "total_pnl_usd": 829.7, + "profit_multiple": 5.76, + "still_holding": true, + "earliest_buy_time": 1770998275 + } + }, + { + "address": "B51uzzSTAtm7ay5NX73iMY1Ta2nj1DXnpPzkWzMztr7x", + "chain": "solana", + "label": "Alpha #61 (from $DEW)", + "source": "alpha_scanner:DEW", + "alpha_score": 90, + "sol_balance": 6.137278025, + "token_count": 0, + "discovered_via": "V6e9AvFGp1hqE7HZBkTar8t1C7JorqZxaa5iS6kpump", + "discovered_at": "2026-02-13T18:17:21.527415+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 6, + "sell_count": 1, + "cost_sol": 0.6271, + "cost_usd": 53.3, + "realized_sol": 0.6056, + "realized_usd": 51.48, + "unrealized_usd": 2382.58, + "total_pnl_usd": 2380.75, + "profit_multiple": 45.66, + "still_holding": true, + "earliest_buy_time": 1770987766 + } + }, + { + "address": "Bkj9GyvUA83cLMk7tvNysXCr5FV6p7MTQaw8XytwBq7b", + "chain": "solana", + "label": "Alpha #62 (from $DEW)", + "source": "alpha_scanner:DEW", + "alpha_score": 50, + "sol_balance": 2.514157263, + "token_count": 0, + "discovered_via": "V6e9AvFGp1hqE7HZBkTar8t1C7JorqZxaa5iS6kpump", + "discovered_at": "2026-02-13T18:17:21.527415+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 2, + "sell_count": 4, + "cost_sol": 1.8163, + "cost_usd": 154.39, + "realized_sol": 0.8926, + "realized_usd": 75.87, + "unrealized_usd": 785.17, + "total_pnl_usd": 706.66, + "profit_multiple": 5.58, + "still_holding": true, + "earliest_buy_time": 1770982990 + } + }, + { + "address": "BRPnPAAy9S9QqbVax9jbcSbQeAWbjQYZ8W9J3Dvt2Cm3", + "chain": "solana", + "label": "Alpha #63 (from $TOLY)", + "source": "alpha_scanner:TOLY", + "alpha_score": 95, + "sol_balance": 38.888931398, + "token_count": 0, + "discovered_via": "9ekm6h4pxZcNbdyMw5fWkEnqAStjQCSzZ3TEfZ7tpump", + "discovered_at": "2026-02-13T18:19:07.446072+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 1, + "sell_count": 0, + "cost_sol": 0.523, + "cost_usd": 44.46, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 1855.56, + "total_pnl_usd": 1811.1, + "profit_multiple": 41.74, + "still_holding": true, + "earliest_buy_time": 1771004874 + } + }, + { + "address": "6Z5udwZJfVe9ikA8ob3bDbyhtWwQ2DBZG4PWxNdzp3UN", + "chain": "solana", + "label": "Alpha #64 (from $TOLY)", + "source": "alpha_scanner:TOLY", + "alpha_score": 65, + "sol_balance": 11.7221562, + "token_count": 0, + "discovered_via": "9ekm6h4pxZcNbdyMw5fWkEnqAStjQCSzZ3TEfZ7tpump", + "discovered_at": "2026-02-13T18:19:07.446072+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 2, + "sell_count": 0, + "cost_sol": 2.0003, + "cost_usd": 170.02, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 1301.96, + "total_pnl_usd": 1131.94, + "profit_multiple": 7.66, + "still_holding": true, + "earliest_buy_time": 1770940415 + } + }, + { + "address": "7gDx5mDysjbqBWHQR3uvn1N7gRq3LKkGgBUJ2vYCuRhF", + "chain": "solana", + "label": "Alpha #65 (from $RATHBUN)", + "source": "alpha_scanner:RATHBUN", + "alpha_score": 110, + "sol_balance": 4.696299022, + "token_count": 0, + "discovered_via": "Bq9D4BbhVR4kL1qSdsYpQ5JM59q2LzUYzv7zFA1epump", + "discovered_at": "2026-02-13T18:21:18.361254+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 3, + "sell_count": 0, + "cost_sol": 0.0026, + "cost_usd": 0.22, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 2460.77, + "total_pnl_usd": 2460.55, + "profit_multiple": 11113.23, + "still_holding": true, + "earliest_buy_time": 1770975093 + } + }, + { + "address": "3qN41pdkpLtBFi8FouKf3Z4gcR14F7E4z5GGrV3Joekj", + "chain": "solana", + "label": "Alpha #66 (from $RATHBUN)", + "source": "alpha_scanner:RATHBUN", + "alpha_score": 95, + "sol_balance": 22.533570379, + "token_count": 0, + "discovered_via": "Bq9D4BbhVR4kL1qSdsYpQ5JM59q2LzUYzv7zFA1epump", + "discovered_at": "2026-02-13T18:21:18.361254+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 1, + "sell_count": 0, + "cost_sol": 1.002, + "cost_usd": 85.17, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 3046.76, + "total_pnl_usd": 2961.59, + "profit_multiple": 35.77, + "still_holding": true, + "earliest_buy_time": 1771006673 + } + }, + { + "address": "DB6MHMubYqrV5wgxUpaoZV8pCjz7jFgfYfNdVEouauDN", + "chain": "solana", + "label": "Alpha #67 (from $RATHBUN)", + "source": "alpha_scanner:RATHBUN", + "alpha_score": 85, + "sol_balance": 50.99999597, + "token_count": 0, + "discovered_via": "Bq9D4BbhVR4kL1qSdsYpQ5JM59q2LzUYzv7zFA1epump", + "discovered_at": "2026-02-13T18:21:18.361254+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 1, + "sell_count": 0, + "cost_sol": 5.054, + "cost_usd": 429.59, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 6911.53, + "total_pnl_usd": 6481.94, + "profit_multiple": 16.09, + "still_holding": true, + "earliest_buy_time": 1771005297 + } + }, + { + "address": "CUwrDw7YHtGqyW6rcZSzxLGLZtprxpG3fzkAfkbmPjeQ", + "chain": "solana", + "label": "Alpha #68 (from $FTX2.0)", + "source": "alpha_scanner:FTX2.0", + "alpha_score": 90, + "sol_balance": 1.402832235, + "token_count": 0, + "discovered_via": "ANVWi3AAkjXRnesAMtAQNRPcrhSnKKbQwsRVe7xpump", + "discovered_at": "2026-02-13T18:22:17.058188+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 2, + "sell_count": 0, + "cost_sol": 2.0487, + "cost_usd": 174.14, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 4308.21, + "total_pnl_usd": 4134.08, + "profit_multiple": 24.74, + "still_holding": true, + "earliest_buy_time": 1771000516 + } + }, + { + "address": "13BdMrG2uLNMBaitN54DD3g7UKMwN1TVQTHXZzWuTRwP", + "chain": "solana", + "label": "Alpha #69 (from $FTX2.0)", + "source": "alpha_scanner:FTX2.0", + "alpha_score": 80, + "sol_balance": 22.794577835, + "token_count": 0, + "discovered_via": "ANVWi3AAkjXRnesAMtAQNRPcrhSnKKbQwsRVe7xpump", + "discovered_at": "2026-02-13T18:22:17.058188+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 1, + "sell_count": 1, + "cost_sol": 3.5, + "cost_usd": 297.5, + "realized_sol": 5.9695, + "realized_usd": 507.41, + "unrealized_usd": 3613.74, + "total_pnl_usd": 3823.65, + "profit_multiple": 13.85, + "still_holding": true, + "earliest_buy_time": 1771001410 + } + }, + { + "address": "7L19GXJ4ZA6MnyQ89FkonjVoRHkziAgRvh5Adv2LNg4H", + "chain": "solana", + "label": "Alpha #70 (from $FTX2.0)", + "source": "alpha_scanner:FTX2.0", + "alpha_score": 45, + "sol_balance": 155.761556489, + "token_count": 0, + "discovered_via": "ANVWi3AAkjXRnesAMtAQNRPcrhSnKKbQwsRVe7xpump", + "discovered_at": "2026-02-13T18:22:17.058188+00:00", + "status": "active, auto_discovered", + "pnl_data": { + "buy_count": 3, + "sell_count": 0, + "cost_sol": 17.0003, + "cost_usd": 1445.03, + "realized_sol": 0, + "realized_usd": 0.0, + "unrealized_usd": 6539.03, + "total_pnl_usd": 5094.01, + "profit_multiple": 4.53, + "still_holding": true, + "earliest_buy_time": 1770989707 + } + } + ], + "last_updated": "2026-02-08T22:00:00Z", + "removed": "22 Solana distributor bot wallets removed (all had sol_spent=0, reliability 2-4). Need real alpha wallets with verified profitable trades.", + "discovery_queue": [ + "Run scan_early_buyers.py on VPS for all 6 tokens (Helius works there)", + "Identify White Whale on-chain wallet via Hypurrscan", + "Identify Trend Research exact Ethereum address via Arkham", + "Cross-reference early buyer wallets from scan_early_buyers.py across tokens", + "Scan gasTzr94Pmp4Gf8vknQnqxeYxdgwFjbgdJa4msYRpnB for other token buys", + "Verify all 6 @hellkatai wallets on-chain via Helius on VPS", + "Cross-reference hellkatai wallets with our 9 tracked tokens", + "Monitor DP7G43VPwR5Ab5rcjrCnvJ8UgvRXRHTWscMjRD1eSdGC (top performer) daily" + ] +} \ No newline at end of file diff --git a/memory/tokens.json b/memory/tokens.json new file mode 100644 index 0000000..baea9d8 --- /dev/null +++ b/memory/tokens.json @@ -0,0 +1,2792 @@ +{ + "description": "Master registry of ALL token contract addresses scanned or tracked. Updated automatically by scanners.", + "last_updated": "2026-02-09", + "tokens": [ + { + "ca": "HBQB6j9RkAroc3wotE94dyFBx2SntfnVNrKLiJSBpump", + "symbol": "BadBunny", + "name": "BadBunny", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 2000000, + "source": "user_provided", + "date_added": "2026-02-08", + "scan_status": "completed", + "callers": [ + "@WavexCaller" + ], + "notes": "+5321% at discovery", + "last_scanned": "2026-02-09", + "source_count": 1, + "last_seen": "2026-02-09T17:06:48.774359+00:00" + }, + { + "ca": "9gPMDSwfwtByWSgBxGCpFJE3q91ap58e3VFMprshpump", + "symbol": "JESTERGOON", + "name": "JesterGoon", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 394000, + "source": "user_provided", + "date_added": "2026-02-08", + "scan_status": "completed", + "callers": [ + "@ELCharpo45", + "@TheWhiteWhaleX" + ], + "notes": "+801% at discovery", + "last_scanned": "2026-02-09" + }, + { + "ca": "9S8edqWxoWz5LYLnxWUmWBJnePg35WfdYQp7HQkUpump", + "symbol": "Goyim", + "name": "Goyim", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 1200000, + "source": "user_provided", + "date_added": "2026-02-08", + "scan_status": "completed", + "callers": [ + "@WavexCaller", + "@Peter1015160" + ], + "notes": "-18% at discovery. @0zutta referenced WRONG CA for this token.", + "last_scanned": "2026-02-09", + "source_count": 1, + "last_seen": "2026-02-09T17:06:48.774359+00:00" + }, + { + "ca": "4YxQxZLkfwmhbw5W9HaDpUYX5zo1J8ycqBSJWjRF6Mby", + "symbol": "PISS", + "name": "PissCoin", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 97000, + "source": "user_provided", + "date_added": "2026-02-08", + "scan_status": "completed", + "callers": [], + "notes": "+13306%. Wallet gasTzr94... found with $70K+ profit on this token.", + "last_scanned": "2026-02-09" + }, + { + "ca": "71mfKdePwyWXtiF1mqu2aaCdMKnKuN664z2vEM2Xpump", + "symbol": "LIQUID", + "name": "Liquid", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 1700000, + "source": "user_provided", + "date_added": "2026-02-08", + "scan_status": "completed", + "callers": [ + "@WavexCaller" + ], + "notes": "+4376% at discovery", + "last_scanned": "2026-02-09", + "source_count": 1, + "last_seen": "2026-02-12T09:32:24.185743+00:00" + }, + { + "ca": "FzLMPzqz9Ybn26qRzPKDKwsLV6Kpvugh31jF7T7npump", + "symbol": "BlackSwan", + "name": "BlackSwan", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 187000, + "source": "user_provided", + "date_added": "2026-02-08", + "scan_status": "completed", + "callers": [ + "@0zutta" + ], + "notes": "-77% at discovery", + "last_scanned": "2026-02-09" + }, + { + "ca": "9XR4tUgg3yLMRV4D9cx5RZqoDg6AGNxPsAP9ZFnspump", + "symbol": "sims", + "name": "Sims", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 86000, + "source": "user_provided", + "date_added": "2026-02-08", + "scan_status": "completed", + "callers": [ + "@WavexCaller", + "@0zutta" + ], + "notes": "+137% at discovery", + "last_scanned": "2026-02-09" + }, + { + "ca": "2NGBAfNMXBU85gjqYutA39b6BCBG5i5MZ4Jvjtdcpump", + "symbol": "SHT", + "name": "ShitCoin", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 802000, + "source": "user_provided", + "date_added": "2026-02-08", + "scan_status": "completed", + "callers": [ + "@WavexCaller", + "@0zutta", + "@Peter1015160" + ], + "notes": "+2057% at discovery", + "last_scanned": "2026-02-09", + "source_count": 1, + "last_seen": "2026-02-11T09:42:05.273350+00:00" + }, + { + "ca": "EKwF2HD6X4rHHr4322EJeK9QBGkqhpHZQSanSUmWkecG", + "symbol": "BigTrout", + "name": "BigTrout", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 2100000, + "source": "user_provided", + "date_added": "2026-02-08", + "scan_status": "completed", + "callers": [ + "@WavexCaller", + "@0zutta" + ], + "notes": "-33% at discovery. Wallet 3q1wAx4q... holds this token.", + "last_scanned": "2026-02-09", + "source_count": 1, + "last_seen": "2026-02-13T18:03:40.121207+00:00" + }, + { + "ca": "8UDpkzHn1zdsJG3vZGn7GGpA3xhsqRYT1SEni1nmpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "14uHdFLjwUrDoTmuYkprYar4uwK5YQDPVKVagbHtpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "HYdBgwSvEWHJKsagcwhKNNKThe91qYPk1aDvZjqzpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "8opvqaWysX1oYbXuTL8PHaoaTiXD69VFYAX4smPebonk", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "raydium", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted", + "source_count": 2, + "last_seen": "2026-02-13T18:03:40.121207+00:00" + }, + { + "ca": "6sQFHSpofBoerhKm5QmcoMbrHi5V3hLCUiQes4Upump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "ECgC6Avhwai9rHUQH3CgZ8TX29qXD4rAReF8tvFVpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "BAuqzCH4gm2LrdUoWR33VabbGhoBK5iP7iugvqPDpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "GDmSzyg3F3CqgusT4CcxhjaKKfaucN98L4EUePeqpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "CV38eqqRKfhvqZ5yyuwuNFGTfof1wYvNguJXt2mZDRMj", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "raydium", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "9ANxaLYH4cFzWKoMnwK4CSwPGHE39h97dk9S6dYkpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "6GTBQj1w2AH7xTLrCGijFTHFyjBUZL1Zq2jX1AdSpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "89q6aHpZ1fXhuwpnrBgqmCvuAX4GaCrRPQNp5xVHpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted", + "source_count": 1, + "last_seen": "2026-02-09T17:06:48.774359+00:00" + }, + { + "ca": "7k74YrjdUY6EaATMUXQ57HjUURm8V9SFYksfa6prpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "ARv3GX3PkKMkQXSxvTSwKnRMwrVNvQtm5YfTrkkppump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "8MdkXe5G77xaMheVQxLqAYV8e2m2Dfc5ZbuXup2epump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "CgghGMyu1cnSxP1GnZ5aurLrTbCQvH6vjABgZHMApump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "Hmb4JjcBSvLdbtxiTk9sLFp5AmirofEu5vQpEzsDpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "GP77ba3oTaFZf8jErPUDek4bNpAk7w5NjhpnrcShpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "6YdDyLQ5RnKpjcVFCKVe8GURVxFsAVhXwArW9wrRpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "Hoi9Lo8s2PP7EM9mv9bZjQ3aSB7ijyS238sTqQjbpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "Kjfbsbp182yfhECYJG1fHxHXqfY2xCwKVR67oyCpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "3B1ijcocM5EDga6XxQ7JLW7weocQPWWjuhBYG8Vepump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "8JFCj7znRhXr3mu29DYWAmS8dhWnkAXUzZZwoR9EHFpX", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "raydium", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "4icSDMih3sAvz4MpeC3vK5XBZm8XqCEtQmvDitpSpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "6r5fNWCPdXbU9qk3rmBoHHAEzqMBosxwbm3xKYuMpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "7PMX6NsCCGhUJjAxqRsMqhnEapXrWWLMMSBM1duPpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "AjqqPdzMmJF89NBKn5X7SANSWiJa6rG99RC5nRwXpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "5fPCdp2z2w51Nq7FLcQ6Yxiwj1byt9d7xYvUWUw3pump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "39LcFNHBtSQCVq9kCbNGBgyQDqyhMU8Ktji9uRPwpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "BwwZSATzLvwAaMufo6jPqux1d5zZMynFbKkNPGdcC8FQ", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "raydium", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "3TqE8pDPyRuH6SV7igTGZJ5XsTF88yTYq7NKxqYQpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "5EWVPhbNfiTibCiF92LZCuzUvPVyJawha2fiqCTWpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "WwFYrQDbY23micBixSHgGKCgbU1xnx9RPfnZ76Rpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "4AdEATYASNWXRqNLVMpLsWBVCxVC29QPB6KGniUmpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "HMJTbaWRTXmHiKTFQ3fQbUo8JQDk2APn9VmU9VHFpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "3oXdBSBhP7RFgB8hnveBKbhcwK6csiCCLftbg7XXrYWh", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "raydium", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "B6MbTs5V3z5WG73uYxhFgdPNtFhQK8neMYhX4EL8pump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "9tDaDYgaU67fnu2k5NhXgrP7NxXgWXxmtt5gHhgYpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "8ATqb36sxJ2nYsQnKuWVtqt3HSQfYXP7KRmsRpEJpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "7x2KLwHYdsS7FcowLheZAsH7iPrktYDCPc7whyo9Mg6B", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "raydium", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "9E8BL6dsewk7g89i9Tq45YwC94EgACXCKoLuiowMpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "F8Xw9DGmDvGRB6VSyCRsF3e2srCttyyLyK1oqBbKpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "3m7rPnpGiaeZD93oUs3ruLshQHLcPUH58WSQv9uEpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "HdBmDxNwvUmg4PetKdf6JKxXcmRpxL6ogkT5YChLpump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "22W5ZqYkJwtcbS7rsfnHdHzoWTZZJMwcFstUwFoypump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "3p6K6Dh9mbrhFsvSQA4ujYkCYznL5z2MaNYgKyM6pump", + "symbol": "UNKNOWN", + "name": "Unknown", + "chain": "solana", + "dex": "pump.fun", + "mc_at_discovery": 0, + "source": "dexscreener_trending", + "date_added": "2026-02-08", + "scan_status": "pending_helius", + "callers": [], + "notes": "From DexScreener trending/boosted" + }, + { + "ca": "5TATk16oMrt4vsMR8WwQ9AtiPeosdJhXFkp2UhGJpump", + "symbol": "Gentlemen", + "name": "This Is Gentlemen", + "chain": "solana", + "mc_at_discovery": 354704, + "liquidity_at_discovery": 51277.5, + "score": 95, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "alpha_scanned", + "alpha_wallets_found": 0 + }, + { + "ca": "B1RB6i7gvxYoyx8Us1eFrJxr7DZv3RzLmBHdfPwDpump", + "symbol": "$POKEMON30", + "name": "Pok\u00e9mon: Since 1996", + "chain": "solana", + "mc_at_discovery": 159170, + "liquidity_at_discovery": 34894.19, + "score": 85, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "alpha_scanned", + "alpha_wallets_found": 2 + }, + { + "ca": "HjgwHz7QRjdT7DckZL2sJVKZ9iJm6K3oUmHu3bFapump", + "symbol": "ROCK", + "name": "a rock", + "chain": "solana", + "mc_at_discovery": 309253, + "liquidity_at_discovery": 47398.67, + "score": 85, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "alpha_scanned", + "alpha_wallets_found": 4, + "last_seen": "2026-02-11T09:42:05.273350+00:00" + }, + { + "ca": "8QJGmTnGhJAfGmkGrscYzrYKacaUCMYTTQQ2Wb3apump", + "symbol": "Maximoto", + "name": "Pedoshi", + "chain": "solana", + "mc_at_discovery": 73929, + "liquidity_at_discovery": 21743.7, + "score": 85, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "alpha_scanned", + "alpha_wallets_found": 1 + }, + { + "ca": "9MCaWcXJRhCBxaYmqPwmdfqY9qxVwo427wYJu2MjWoyC", + "symbol": "$PENG", + "name": "Chill Penguin", + "chain": "solana", + "mc_at_discovery": 69992, + "liquidity_at_discovery": 22082.41, + "score": 85, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "5TcwTnpmvBv6CZAjzceGCAoR3KubRvtoz86TZoePpump", + "symbol": "WATT", + "name": "WATTCOIN", + "chain": "solana", + "mc_at_discovery": 66430, + "liquidity_at_discovery": 20129.64, + "score": 80, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "88UweYzEAGVFAdjFwjhyPtSHhQf8SwSy85hh5vu4V2Hj", + "symbol": "SKYNET", + "name": "SkynetSociety", + "chain": "solana", + "mc_at_discovery": 6567, + "liquidity_at_discovery": 10095.33, + "score": 75, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "NeT4mWkYNuqBVy9XV2rhRMW59GwqTZLioYM5sktperp", + "symbol": "Perpcoin", + "name": "Perpcoin", + "chain": "solana", + "mc_at_discovery": 22011, + "liquidity_at_discovery": 12128.31, + "score": 65, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "Dwwsv9JyCw3Zxufe7E4YQFX4q9Nf12YzTiPwQHaxpump", + "symbol": "LOTUS", + "name": "Lion Of The United States", + "chain": "solana", + "mc_at_discovery": 10498084, + "liquidity_at_discovery": 261797.68, + "score": 60, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "5fN3pcZiyLJVY7NvzkHTLHRyjETG3NRrQXEaPFoRn2D2", + "symbol": "Rock", + "name": "The viral rock", + "chain": "solana", + "mc_at_discovery": 14874, + "liquidity_at_discovery": 10464.94, + "score": 55, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "9yrjW2ZhxB1t738E3ATFYyyXUBPJUL266hZFzJEYndgL", + "symbol": "NYAN", + "name": "NyanCoin", + "chain": "solana", + "mc_at_discovery": 25561, + "liquidity_at_discovery": 9432.55, + "score": 50, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "9G2ASTJycfKzbMvpUy8EzCtG5cjF274Sx3vW6Rurpump", + "symbol": "BAPE", + "name": "The black ape", + "chain": "solana", + "mc_at_discovery": 35553.46, + "liquidity_at_discovery": 0, + "score": 50, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "6csbmriS9a6GiRi4gZA4nzmRwrstpyA3HXXzo9Q2pump", + "symbol": "Poopcoin", + "name": "Poopcoin", + "chain": "solana", + "mc_at_discovery": 3618, + "liquidity_at_discovery": 5177.84, + "score": 50, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "3d9ZqLpKGvXrE7YKcCRhwMzzVBAcbcp1LYhW1tCWpump", + "symbol": "SEAHAWKS", + "name": "SEAHAWKS LX", + "chain": "solana", + "mc_at_discovery": 6375, + "liquidity_at_discovery": 6700.31, + "score": 50, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "2CwYrUEkfxNKTdBFTrvZaP6kgR5jKGKYmmk9eaNxpump", + "symbol": "BADBUNNY", + "name": "BENITO", + "chain": "solana", + "mc_at_discovery": 2605, + "liquidity_at_discovery": 4058.79, + "score": 45, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "8TVr3U85V3Uazkxd5DJbmzdUWaxhQdEGNNGJ7eNTpump", + "symbol": "TULSA", + "name": "Black Wallstreet \u270a\ud83c\udffe", + "chain": "solana", + "mc_at_discovery": 562260, + "liquidity_at_discovery": 65507.93, + "score": 45, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "Cm6fNnMk7NfzStP9CZpsQA2v3jjzbcYGAxdJySmHpump", + "symbol": "Buttcoin", + "name": "Buttcoin", + "chain": "solana", + "mc_at_discovery": 37186246, + "liquidity_at_discovery": 888587.21, + "score": 40, + "source": "trending_scan", + "source_count": 2, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "7Y2TPeq3hqw21LRTCi4wBWoivDngCpNNJsN1hzhZpump", + "symbol": "SACHI", + "name": "Sachicoin", + "chain": "solana", + "mc_at_discovery": 1550603, + "liquidity_at_discovery": 149937.35, + "score": 40, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "pending_alpha_scan", + "last_seen": "2026-02-12T09:32:24.185743+00:00" + }, + { + "ca": "86WM5NBUtRWTHULKrspS1TdzVFAcZ9buXsGRAiFDpump", + "symbol": "ICEBEAR", + "name": "White Polar Bear", + "chain": "solana", + "mc_at_discovery": 35629, + "liquidity_at_discovery": 16483.62, + "score": 40, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "HG8qtpKpSQ8uPrCBDbWohnT9sh8s5S7oBYzvBwVFpump", + "symbol": "MILK", + "name": "MilkCoin", + "chain": "solana", + "mc_at_discovery": 35487.72, + "liquidity_at_discovery": 0, + "score": 40, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "2k8yZaJjf61unHriuqdmvbxe7CUhEYML5kVJDbcotKjU", + "symbol": "BFS", + "name": "BFS", + "chain": "solana", + "mc_at_discovery": 1418092, + "liquidity_at_discovery": 7283.52, + "score": 35, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "pending_alpha_scan", + "last_seen": "2026-02-12T09:32:24.185743+00:00" + }, + { + "ca": "HDYtwNnQ948isoVGZywWpt4nEFLRukmj2VXqfoDJpump", + "symbol": "UNDERDOG", + "name": "Remy", + "chain": "solana", + "mc_at_discovery": 6632, + "liquidity_at_discovery": 6686.17, + "score": 35, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "DvH9A3dSv2n6s6WArARtXm988kiaS8m47jWa6kTjpump", + "symbol": "BOB", + "name": "Bald Bob", + "chain": "solana", + "mc_at_discovery": 2864, + "liquidity_at_discovery": 4280.34, + "score": 30, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "AZjDNg2WhoZUnhtyfWTXxTbc3Pq6bg1XfUrAAbvCpump", + "symbol": "KidRock", + "name": "Kid Rock", + "chain": "solana", + "mc_at_discovery": 7312, + "liquidity_at_discovery": 7460.37, + "score": 30, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "61Wj56QgGyyB966T7YsMzEAKRLcMvJpDbPzjkrCZc4Bi", + "symbol": "COPPERINU", + "name": "copper inu", + "chain": "solana", + "mc_at_discovery": 7906852, + "liquidity_at_discovery": 390269.78, + "score": 25, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "pending_alpha_scan", + "last_seen": "2026-02-12T09:32:24.185743+00:00" + }, + { + "ca": "8Jx8AAHj86wbQgUTjGuj6GTTL5Ps3cqxKRTvpaJApump", + "symbol": "PENGUIN", + "name": "Nietzschean Penguin", + "chain": "solana", + "mc_at_discovery": 27052981, + "liquidity_at_discovery": 828823.03, + "score": 25, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "pending_alpha_scan", + "last_seen": "2026-02-13T18:03:40.121207+00:00" + }, + { + "ca": "8J69rbLTzWWgUJziFY8jeu5tDwEPBwUz4pKBMr5rpump", + "symbol": "WOJAK", + "name": "Wojak ", + "chain": "solana", + "mc_at_discovery": 12340653, + "liquidity_at_discovery": 555749.87, + "score": 25, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "Dfh5DzRgSvvCFDoYc2ciTkMrbDfRKybA4SoFbPmApump", + "symbol": "pippin", + "name": "Pippin", + "chain": "solana", + "mc_at_discovery": 267206029, + "liquidity_at_discovery": 10059143.26, + "score": 25, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "pending_alpha_scan", + "last_seen": "2026-02-13T18:03:40.121207+00:00" + }, + { + "ca": "a3W4qutoEJA4232T2gwZUfgYJTetr96pU4SJMwppump", + "symbol": "WhiteWhale", + "name": "The White Whale", + "chain": "solana", + "mc_at_discovery": 90749024, + "liquidity_at_discovery": 1330025.83, + "score": 20, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "pending_alpha_scan", + "last_seen": "2026-02-13T18:03:40.121207+00:00" + }, + { + "ca": "USoRyaQjch6E18nCdDvWoRgTo6osQs9MUd8JXEsspWR", + "symbol": "USOR", + "name": "U.S Oil", + "chain": "solana", + "mc_at_discovery": 5578526, + "liquidity_at_discovery": 39062.61, + "score": 10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "75wdZ1M297ngMifL8YFvk1kaumuDWwLpAQ8tdNwDUtEj", + "symbol": "C-13", + "name": "CODEX-13", + "chain": "solana", + "mc_at_discovery": 36689, + "liquidity_at_discovery": 5582.13, + "score": 5, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "3RsYAsFWhztB6mKtp9ZfMaCdMfiyLDrpwSnq9ABfDnGA", + "symbol": "BALTO", + "name": "BALTO", + "chain": "solana", + "mc_at_discovery": 924, + "liquidity_at_discovery": 1166.03, + "score": -10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-09T17:06:48.774359+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "E2HNWS5L6gwmtC9SZPpRq6Yp3V5gzotFrL3dAEP2pump", + "symbol": "BUCKARU", + "name": "BUCKARU", + "chain": "solana", + "mc_at_discovery": 313960, + "liquidity_at_discovery": 50515.79, + "score": 95, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "alpha_scanned", + "alpha_wallets_found": 2 + }, + { + "ca": "8ckfBhNvEDA62udk4YGNbSYcd5wvmQDjhY6kAYsgpump", + "symbol": "#MLM", + "name": "Meme Lives Matter", + "chain": "solana", + "mc_at_discovery": 146047, + "liquidity_at_discovery": 33038.53, + "score": 85, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "alpha_scanned", + "alpha_wallets_found": 2 + }, + { + "ca": "3mHw8CJffDZpY8F6KmGVF3LwwejCkMHG2o2pV5ZVpump", + "symbol": "GROKPEPE", + "name": "GROKPEPE", + "chain": "solana", + "mc_at_discovery": 100209, + "liquidity_at_discovery": 26695.14, + "score": 85, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "alpha_scanned", + "alpha_wallets_found": 1 + }, + { + "ca": "7SYuU1Z6EKfpYQQ9VeTXfLW5ofhigdn8Y7iQsqoepump", + "symbol": "Ferociter", + "name": "Gradatim Ferociter", + "chain": "solana", + "mc_at_discovery": 51870, + "liquidity_at_discovery": 21427.85, + "score": 85, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "alpha_scanned", + "alpha_wallets_found": 2 + }, + { + "ca": "GbqbsRyBHVPHEv7xLEsikXmdpPPiApLTJesDBbL5pump", + "symbol": "GIRAFFES", + "name": "The Giraffes", + "chain": "solana", + "mc_at_discovery": 1748404, + "liquidity_at_discovery": 125976.9, + "score": 85, + "source": "trending_scan", + "source_count": 2, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "alpha_scanned", + "alpha_wallets_found": 2, + "last_seen": "2026-02-13T18:03:40.121207+00:00" + }, + { + "ca": "G9YU3K1MiPTv7Krui5omkPBPP21GChPPE3c9izRKbonk", + "symbol": "SAFEMOON", + "name": "SafeMoon", + "chain": "solana", + "mc_at_discovery": 223160, + "liquidity_at_discovery": 43521.09, + "score": 85, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "alpha_scanned", + "alpha_wallets_found": 2 + }, + { + "ca": "2qT8JVotQ2C1gKbqpuqNatkpSBWxiKHbXkCyTqH9pump", + "symbol": "soluna", + "name": "soluna", + "chain": "solana", + "mc_at_discovery": 901809, + "liquidity_at_discovery": 89702.31, + "score": 85, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "alpha_scanned", + "alpha_wallets_found": 2, + "last_seen": "2026-02-13T18:03:40.121207+00:00" + }, + { + "ca": "CvTMSEB9RzHPhB1CgE7PAkszomozDv3JJNz28sDbpump", + "symbol": "HAL", + "name": "Hal The Giraffe", + "chain": "solana", + "mc_at_discovery": 94434, + "liquidity_at_discovery": 25030.59, + "score": 85, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "alpha_scanned", + "alpha_wallets_found": 1, + "last_seen": "2026-02-12T09:32:24.185743+00:00" + }, + { + "ca": "CMRpNWSaSnyfoMDYhAWdPNXXrwXwPhz3CVEdZmToX9jR", + "symbol": "CMR", + "name": "U.S Critical Mineral Reserve", + "chain": "solana", + "mc_at_discovery": 2431440, + "liquidity_at_discovery": 101080.61, + "score": 75, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "alpha_scanned", + "alpha_wallets_found": 0 + }, + { + "ca": "F6QoH8WfU67V7xP7fnTHGpkR6xdegLUcPGjSLsGQmMD4", + "symbol": "ICF", + "name": "Interstellar Civilization Fund", + "chain": "solana", + "mc_at_discovery": 1077116, + "liquidity_at_discovery": 58710.34, + "score": 75, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "alpha_scanned", + "alpha_wallets_found": 1 + }, + { + "ca": "63Z3Q7JX3SBGDiiwqqnPTVvHcuUk6ixkzsYQbKzhpump", + "symbol": "SHARK", + "name": "Greenland Shark", + "chain": "solana", + "mc_at_discovery": 443816, + "liquidity_at_discovery": 75716.46, + "score": 70, + "source": "trending_scan", + "source_count": 2, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan", + "last_seen": "2026-02-13T18:03:40.121207+00:00" + }, + { + "ca": "USRX8A1BNVzPSWt9tXA1ZjeMWWnpsWktdhueCBDZAjS", + "symbol": "USRX", + "name": "United States RX", + "chain": "solana", + "mc_at_discovery": 7098953, + "liquidity_at_discovery": 246692.93, + "score": 70, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "6Ky1ndumnWVGQBbxauh3mgoVj7Ytr7YmFea1K8Zcpump", + "symbol": "WhiteGRFF", + "name": "The White Giraffe", + "chain": "solana", + "mc_at_discovery": 148297, + "liquidity_at_discovery": 29629, + "score": 65, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "F7FjenqxEcs8aEXnP4MHbstZKNwiEs6FHnWhYH2Xpump", + "symbol": "VALENTINES", + "name": "100M MCAP BEFORE VALENTINES", + "chain": "solana", + "mc_at_discovery": 24274, + "liquidity_at_discovery": 12349.86, + "score": 65, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "DUohwmGsB53vZ4LVntYh3GHXnpzJjH3RgiC4phkypump", + "symbol": "BullishGir", + "name": "Bullish Giraffe", + "chain": "solana", + "mc_at_discovery": 153697, + "liquidity_at_discovery": 30640.91, + "score": 65, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "HuorCKdoLVYbodCaNLiZBDPKfHAQUb4CUzSBf23Bpump", + "symbol": "Bucky", + "name": "Bucky", + "chain": "solana", + "mc_at_discovery": 36468, + "liquidity_at_discovery": 15440.73, + "score": 55, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "7soqpgjvvF1cMn2xVHnGbSZezCdTjMoqHotLEH2Wpump", + "symbol": "REX", + "name": "GeckoTerminal Mascot", + "chain": "solana", + "mc_at_discovery": 22212, + "liquidity_at_discovery": 11493.47, + "score": 55, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "BgNuhimT99WmuKSa7F5znCcsDoXQ6MsX4MWxz8LUnRTs", + "symbol": "Elephants", + "name": "The Ghost Elephants", + "chain": "solana", + "mc_at_discovery": 1304, + "liquidity_at_discovery": 1918.54, + "score": 50, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "wQXEwMUkWqXtxGJ6TRuKq9kTUnNoydwq2EG5gk7HBp5", + "symbol": "LIGHTNING", + "name": "The Lightning", + "chain": "solana", + "mc_at_discovery": 3229, + "liquidity_at_discovery": 3154.69, + "score": 50, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "KVzR8KHCQBj115EjeYTiBPtPGPgq8BhyjH6wGY3pump", + "symbol": "CUPID", + "name": "CUPID", + "chain": "solana", + "mc_at_discovery": 34152.36, + "liquidity_at_discovery": 0, + "score": 50, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "5XUmwpwHscJsUfTRA7somtUCtfmUVi1Hz7YGH3H8pump", + "symbol": "Animals", + "name": "Political Animals", + "chain": "solana", + "mc_at_discovery": 2348819, + "liquidity_at_discovery": 115938.39, + "score": 45, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "57KoEZXm2mJwFqbB7fvcgZmmjc9mivFmKhXA45H3pump", + "symbol": "Preguntale", + "name": "Preguntale", + "chain": "solana", + "mc_at_discovery": 34505.72, + "liquidity_at_discovery": 0, + "score": 40, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan", + "last_seen": "2026-02-13T18:03:40.121207+00:00" + }, + { + "ca": "3ToKnopDeSUAy8fc1bX6rUK25UMCA24Xwe1WXqZspump", + "symbol": "BIT", + "name": "Lil Bit", + "chain": "solana", + "mc_at_discovery": 43763, + "liquidity_at_discovery": 16262.09, + "score": 35, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "DDtXARjuwSPRE16Q9yPCTH7s2ZgCM5SoBbsd5kiApump", + "symbol": "DOGGO", + "name": "Winter Olympics Dog", + "chain": "solana", + "mc_at_discovery": 8052, + "liquidity_at_discovery": 6999.47, + "score": 35, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "Z4KACzcxkRzT7htPqnNsNLtH7zoDDzDFQR5sMJ3perp", + "symbol": "PERPTRADE", + "name": "perptrade.it", + "chain": "solana", + "mc_at_discovery": 3142.46, + "liquidity_at_discovery": 0, + "score": 30, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "2cCbvJChfXcUf3fiQFZqJXT1zQybrAgtqjjinaxNBAGS", + "symbol": "SURVIVAL", + "name": "pay for yourself or you die", + "chain": "solana", + "mc_at_discovery": 14653.79, + "liquidity_at_discovery": 0, + "score": 20, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "FYCyBpzbFfP3gVFVaCBRtjoWg1LzZUtH7DsD2MjVpump", + "symbol": ".gif", + "name": "Giraffe Investment Fund", + "chain": "solana", + "mc_at_discovery": 8856.49, + "liquidity_at_discovery": 0, + "score": 20, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "FqzojLo6YRgNZfaBgaPyv26L4fcL2t2dT3mE225gFWjh", + "symbol": "The", + "name": "Giraffes", + "chain": "solana", + "mc_at_discovery": 196946973, + "liquidity_at_discovery": 20102.28, + "score": 20, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "25TBJCRN7m7EDcWcnKAZkLbTUiN9mUBnEBD6FBNUpump", + "symbol": "MOON", + "name": "The Moon", + "chain": "solana", + "mc_at_discovery": 10673.11, + "liquidity_at_discovery": 0, + "score": 20, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "2Gavi27q6jrF3bhLb4fJg9nVuydPorxmLEvVVAp7pump", + "symbol": "WHITEMICHI", + "name": "The White Michi", + "chain": "solana", + "mc_at_discovery": 33264.86, + "liquidity_at_discovery": 0, + "score": 10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "63XiXdPhsBhg5zZU2trnxuh2J7emXc55CVtn9nvzpump", + "symbol": "NPC", + "name": "Non Playable Character", + "chain": "solana", + "mc_at_discovery": 2318.31, + "liquidity_at_discovery": 0, + "score": 10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "CW3dAZC1RHTTXZeEcmvYGLt2tziXHMv9crLDd5uDpump", + "symbol": "TiktokCoin", + "name": "TiktokCoin", + "chain": "solana", + "mc_at_discovery": 3493.77, + "liquidity_at_discovery": 0, + "score": 10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "2LjA87GjNGnCLgYC5PvduVhKRTRDK7N74zExPeS3dMQP", + "symbol": "Roadrunner", + "name": "The Roadrunner", + "chain": "solana", + "mc_at_discovery": 3587.57, + "liquidity_at_discovery": 0, + "score": 10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "9YyTiaTzHkpxTPNEf8dSaENJLHABb9qsXHFTEqRLpump", + "symbol": "nuralineAI", + "name": "nuralineAI", + "chain": "solana", + "mc_at_discovery": 5309, + "liquidity_at_discovery": 5525.89, + "score": 10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "8gG5C5cVuDnpCyqDFTc6LH6L6oAWNgDkyCp4XnHqpump", + "symbol": "Horse", + "name": "The Horse", + "chain": "solana", + "mc_at_discovery": 1450, + "liquidity_at_discovery": 2891.16, + "score": 5, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "SABfuDo2cGJNumfHCyBYAPxfs8Fnmi5NzDmYS3rpump", + "symbol": "G", + "name": "Act I : The God Prophecy", + "chain": "solana", + "mc_at_discovery": 4047.21, + "liquidity_at_discovery": 0, + "score": 5, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "3a2Hw79jCGcUwgsL5qec78EU4Y8LRkLkUP39HTCopump", + "symbol": "RUBY", + "name": "Pokemon Ruby", + "chain": "solana", + "mc_at_discovery": 16042, + "liquidity_at_discovery": 9569.5, + "score": 5, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "962AZRCREMf6HZXzkiQYGeoowdxiC1KLS4JUa5bDpump", + "symbol": "CHKN", + "name": "chkn computer", + "chain": "solana", + "mc_at_discovery": 13897, + "liquidity_at_discovery": 9026.63, + "score": 0, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "3FnCLcwzTEBmruDx8dkqYHbhxdXctW6Gg4Na2HU6pump", + "symbol": "GIRAFFE", + "name": "Nietzschean Giraffe", + "chain": "solana", + "mc_at_discovery": 33314.16, + "liquidity_at_discovery": 0, + "score": -5, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "81uxcyaof5UyMZE5cjktec93si8qMjJxtSFuEEiGpump", + "symbol": "AURI", + "name": "AURI", + "chain": "solana", + "mc_at_discovery": 33285.4, + "liquidity_at_discovery": 0, + "score": -5, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-11T09:42:05.273350+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "7Gc9WkXewLGBzNDbz9nWZ4PuvEUhy38sAFk1MXoqpump", + "symbol": "ApeLiquid", + "name": "ApeLiquid", + "chain": "solana", + "mc_at_discovery": 66196, + "liquidity_at_discovery": 21080.41, + "score": 105, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "5hAikwRHTxRyXVgDShy6m3g49WWMXMQAVFNdPM7epump", + "symbol": "SHUTDOWN", + "name": "SHUT IT DOWN", + "chain": "solana", + "mc_at_discovery": 352006, + "liquidity_at_discovery": 49717.31, + "score": 105, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "EKgUxSq2ucFYwaoGfwz3sUpqDepky2vSfpr7jCEGpump", + "symbol": "COOPERINU", + "name": "cooper inu", + "chain": "solana", + "mc_at_discovery": 113435, + "liquidity_at_discovery": 51415.03, + "score": 95, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "Gz7VJWyQW6Uqt1Py5S2ZvtYNEFbP4Thmi31n5mx1pump", + "symbol": "BIG", + "name": "Something Big Is Happening", + "chain": "solana", + "mc_at_discovery": 331556, + "liquidity_at_discovery": 54403.12, + "score": 95, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "322UMngby7k5nZ4aKdyNi6E9dv9kuhXeueErqXgopump", + "symbol": "Pepstein", + "name": "Pepstein", + "chain": "solana", + "mc_at_discovery": 107059, + "liquidity_at_discovery": 26078.04, + "score": 95, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "AKuryic4cQ55EMfhvSGTdAXydQYLtRy6u8EfGdLRBAGS", + "symbol": "GIGACHAD", + "name": "Official Gigachad", + "chain": "solana", + "mc_at_discovery": 331672, + "liquidity_at_discovery": 41073.57, + "score": 85, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "84hqMeGHxqegpvf4kGaRp38iVd145DSoEBwnmBTtpump", + "symbol": "MooNutPeng", + "name": "The Fastest Runner", + "chain": "solana", + "mc_at_discovery": 529422, + "liquidity_at_discovery": 61883.82, + "score": 85, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan", + "last_seen": "2026-02-13T18:03:40.121207+00:00" + }, + { + "ca": "HTCiQqiJa4e2L7aB5heTVgb2FYJyWDr6XdgsHwr3MpLR", + "symbol": "HTC", + "name": "HTC", + "chain": "solana", + "mc_at_discovery": 5032038, + "liquidity_at_discovery": 269653.44, + "score": 80, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "Gbu7JAKhTVtGyRryg8cYPiKNhonXpUqbrZuCDjfUpump", + "symbol": "snowball", + "name": "snowball", + "chain": "solana", + "mc_at_discovery": 1004277, + "liquidity_at_discovery": 172934.07, + "score": 70, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "21CnrFRqvEVkQZUTFmTXjcsJTLZhRY51ohoaCPwRpump", + "symbol": "DOG", + "name": "The Crypto Dog", + "chain": "solana", + "mc_at_discovery": 989652, + "liquidity_at_discovery": 107528.95, + "score": 70, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "Fr7vfUAWgmg84L3VuHKiyzTJx3x3V6xU5pn9328Wpump", + "symbol": "Whalentine", + "name": "Whalentine", + "chain": "solana", + "mc_at_discovery": 269952, + "liquidity_at_discovery": 45370.19, + "score": 70, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan", + "last_seen": "2026-02-13T18:03:40.121207+00:00" + }, + { + "ca": "2Ft9y5rriLAFjiCiZ86XWdcu9yVPkMze3QnYzJDEpump", + "symbol": "MAYA", + "name": "Maya", + "chain": "solana", + "mc_at_discovery": 80395, + "liquidity_at_discovery": 22099.24, + "score": 65, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "6SCmisPvGvj2SZCQG9dXMAv4WkBuoN8Eopo4CqBbxp5h", + "symbol": "KimJuAe", + "name": "SUPREME LEADER", + "chain": "solana", + "mc_at_discovery": 129499, + "liquidity_at_discovery": 29317.33, + "score": 65, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "AbP5LEN4sAAjghBy6ww37ngAAT7hnBVfXmXNdCnbpump", + "symbol": "dot", + "name": "Pippin's Friend ", + "chain": "solana", + "mc_at_discovery": 108130, + "liquidity_at_discovery": 35008.84, + "score": 60, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "BLDiYcvm3CLcgZ7XUBPgz6idSAkNmWY6MBbm8Xpjpump", + "symbol": "TRISIG", + "name": "TRI SIGMA", + "chain": "solana", + "mc_at_discovery": 56166, + "liquidity_at_discovery": 43760.25, + "score": 60, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "DNdVqWcvacr98jWfVXYdkcPY6fQFDm8EQxuuaoaKpump", + "symbol": "LOVE", + "name": "LOVE", + "chain": "solana", + "mc_at_discovery": 28899, + "liquidity_at_discovery": 13214.79, + "score": 55, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "412zDygnwP9DzitnQVgRKUFFTDmrYScFch6P2k39pump", + "symbol": "Jellybean", + "name": "Jellybean", + "chain": "solana", + "mc_at_discovery": 49635, + "liquidity_at_discovery": 18562.42, + "score": 55, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "6Bb82T5tRSqQuEi29cJypyK3e2t22k1uffUqPVA4q3Eq", + "symbol": "eterum", + "name": "eterum", + "chain": "solana", + "mc_at_discovery": 6587, + "liquidity_at_discovery": 5495.78, + "score": 55, + "source": "trending_scan", + "source_count": 2, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "Fa5Rf2BnATni1TiAqK57fBhXQZdLf3CPKXGzxrkrpump", + "symbol": "\u0189USK", + "name": "69dogecoin", + "chain": "solana", + "mc_at_discovery": 19837, + "liquidity_at_discovery": 11324.6, + "score": 55, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "CdgUrzLETouEosJqd4c4KXmrnqpdBhFmBRWXueb7pump", + "symbol": "ANIMAL", + "name": "WWF FUND", + "chain": "solana", + "mc_at_discovery": 36495, + "liquidity_at_discovery": 15177.42, + "score": 55, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "3Pq8Y8ApMMYJGemHY8aapdsUZF6pe2LRZJHv2Mwtpump", + "symbol": "GOJO", + "name": "GOJO CAT", + "chain": "solana", + "mc_at_discovery": 2580, + "liquidity_at_discovery": 3880.19, + "score": 45, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "4Y7i2vRw1Ga4WSuw7xk7Lpw6E82i2j86X82DG9Y3bonk", + "symbol": "Dolly", + "name": "Dolly The First Cloned Mammal", + "chain": "solana", + "mc_at_discovery": 12711.78, + "liquidity_at_discovery": 0, + "score": 40, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "CLu3Qzx2xGQjhgc9d4aQERFCG5Ti2uLnzx7T1Gaypump", + "symbol": "conquered", + "name": "I came I saw I conquered", + "chain": "solana", + "mc_at_discovery": 5779, + "liquidity_at_discovery": 5906.19, + "score": 40, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "RhjFpnGcRy1J5SuSnFCzMJoxnY9XHmsF5TEkfrxpump", + "symbol": "kem", + "name": "kem joo aye", + "chain": "solana", + "mc_at_discovery": 23832, + "liquidity_at_discovery": 11842.78, + "score": 35, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "3KFP8QAFZXj78xAss4DxpyecjVQZPU6oMkhm5WaPpump", + "symbol": "GORILLAS", + "name": "The Silverback Mountain Gorillas", + "chain": "solana", + "mc_at_discovery": 2948, + "liquidity_at_discovery": 4197.72, + "score": 35, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "DpHmTPDqvD5KCsDydZxbRHFd1Qmv2siaXNkftx2tJLch", + "symbol": "POPE", + "name": "POPE", + "chain": "solana", + "mc_at_discovery": 3059, + "liquidity_at_discovery": 4513.93, + "score": 30, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "CES8M66kGQpc4bHhR5AQmYSmuKsvYZfDyKrXjUBXpump", + "symbol": "MountSus", + "name": "Mount Susmore", + "chain": "solana", + "mc_at_discovery": 2489.82, + "liquidity_at_discovery": 0, + "score": 30, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "3e5GWG57SScqYYEuYYruxEW4dqDCdEzfKghQUfFapump", + "symbol": "SYNCLAW", + "name": "SynClaw", + "chain": "solana", + "mc_at_discovery": 11834.73, + "liquidity_at_discovery": 0, + "score": 20, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "G8s88jzPhiKdfCmwTKaShErB2VrbrsvDsDBzsXqjpump", + "symbol": "ANTS", + "name": "Ants Colony", + "chain": "solana", + "mc_at_discovery": 33425.1, + "liquidity_at_discovery": 0, + "score": 20, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "6d338JxX6WUsGudT2ncoYmG3zRBj3XoTwckZ7pwKpump", + "symbol": "Heisenduck", + "name": "Breaking Bread", + "chain": "solana", + "mc_at_discovery": 15665, + "liquidity_at_discovery": 9733.29, + "score": 20, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "2dm5teNAFLHn7kGvS8mnccivEe7r33PvFTwWf59ppump", + "symbol": "\uae40\uc8fc\uc560", + "name": "Kim Ju-ae", + "chain": "solana", + "mc_at_discovery": 14324.82, + "liquidity_at_discovery": 0, + "score": 10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "8nJ2N3HEachh7NGK3M6AvpJemo1xHVK9RxTsPBKrpump", + "symbol": "Q", + "name": "Quantum coin", + "chain": "solana", + "mc_at_discovery": 3610, + "liquidity_at_discovery": 4568.17, + "score": 10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "5PczCgEbVC5k6nvLjeXeyVi37FEgdxwcGKY5QY1Qpump", + "symbol": "#1", + "name": "#1 Coin", + "chain": "solana", + "mc_at_discovery": 5001.07, + "liquidity_at_discovery": 0, + "score": 10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "auGdWV6kR5KRZPvpMEZDB72jEWeKgVtHHJ6UswKpump", + "symbol": "Scramble", + "name": "Scramble Cat", + "chain": "solana", + "mc_at_discovery": 19068.37, + "liquidity_at_discovery": 0, + "score": 10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "W8xusrX54FFTtToRYeiP7UxU57vt7ggECfzon97pump", + "symbol": "TRC", + "name": "Terracoin", + "chain": "solana", + "mc_at_discovery": 2631.47, + "liquidity_at_discovery": 0, + "score": 10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "3C1LNRE6ibE5aFmrDf93MDiLNtwdawbH5YP3MqR2pump", + "symbol": "SOGOOD", + "name": "Good At Trading", + "chain": "solana", + "mc_at_discovery": 33088.18, + "liquidity_at_discovery": 0, + "score": 10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "EGSmtPMZesRrnXzj2XCZVUXiFZxZg5V1rAszSABUpump", + "symbol": "FOID", + "name": "Foid", + "chain": "solana", + "mc_at_discovery": 9431, + "liquidity_at_discovery": 7451.45, + "score": 10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "Cg9Augh6WKCobr9nQHF9ALY71kKfy2hPYznXbTSnpump", + "symbol": "bit(ch)", + "name": "bit(ch)coin", + "chain": "solana", + "mc_at_discovery": 2691.93, + "liquidity_at_discovery": 0, + "score": 10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "AzpV894DQhitb3G2e7NVurXYjzeNC6hbt3Tfr1jLqJRk", + "symbol": "Kim Ju Ae", + "name": "\uae40\uc8fc\uc560", + "chain": "solana", + "mc_at_discovery": 7718, + "liquidity_at_discovery": 7029.71, + "score": 10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "CPaDoJV2UJne3XCCMVxHXazsj38ZSnsmoCDH9BbRpump", + "symbol": "Fartsicle", + "name": "Fartsicle", + "chain": "solana", + "mc_at_discovery": 6401.93, + "liquidity_at_discovery": 0, + "score": 5, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-12T09:32:24.185743+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "5T17aqgJ8cM39SNuVBu2LK2cq5MWUpZxcQnnuwNjpump", + "symbol": "LIZARD", + "name": "Official Lizard Coin", + "chain": "solana", + "mc_at_discovery": 221997, + "liquidity_at_discovery": 40615.77, + "score": 105, + "source": "trending_scan", + "source_count": 2, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "alpha_scanned", + "alpha_wallets_found": 4 + }, + { + "ca": "63p6ir6gGQ59ZCDN2iRGUkCrZyJvu2xaacRYBfKopump", + "symbol": "MoonLiquid", + "name": "MoonLiquid", + "chain": "solana", + "mc_at_discovery": 118366, + "liquidity_at_discovery": 30290.35, + "score": 105, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "alpha_scanned", + "alpha_wallets_found": 10 + }, + { + "ca": "58ExX8TFqiDqUpr1ZGiAhhiUsKfT14gwTFykLoVCpump", + "symbol": "hoodrat", + "name": "hoodrat", + "chain": "solana", + "mc_at_discovery": 457305, + "liquidity_at_discovery": 62342.29, + "score": 95, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "alpha_scanned", + "alpha_wallets_found": 2 + }, + { + "ca": "3g3YFfUZLspiKpVmv9mDkaDcKh168CLArcqShR64pump", + "symbol": "hopecoin", + "name": "hopecoin", + "chain": "solana", + "mc_at_discovery": 91436, + "liquidity_at_discovery": 23478.69, + "score": 90, + "source": "trending_scan", + "source_count": 2, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "alpha_scanned", + "alpha_wallets_found": 0 + }, + { + "ca": "58Ghft9TvGNuBiDzy9cFD2Px9rz5cDVZ1XoMFk1xpump", + "symbol": "Buttfish", + "name": "Buttfish Coin", + "chain": "solana", + "mc_at_discovery": 216220, + "liquidity_at_discovery": 39779.93, + "score": 90, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "alpha_scanned", + "alpha_wallets_found": 1 + }, + { + "ca": "EFt9JrrGyLWLU6Wc4oxfTjDKryENPrjbGgZ2V6x8pump", + "symbol": "helicator", + "name": "helicator", + "chain": "solana", + "mc_at_discovery": 62724, + "liquidity_at_discovery": 21969.17, + "score": 85, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "alpha_scanned", + "alpha_wallets_found": 2 + }, + { + "ca": "V6e9AvFGp1hqE7HZBkTar8t1C7JorqZxaa5iS6kpump", + "symbol": "DEW", + "name": "dog in a cats world", + "chain": "solana", + "mc_at_discovery": 68204, + "liquidity_at_discovery": 23540.34, + "score": 85, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "alpha_scanned", + "alpha_wallets_found": 2 + }, + { + "ca": "9ekm6h4pxZcNbdyMw5fWkEnqAStjQCSzZ3TEfZ7tpump", + "symbol": "TOLY", + "name": "Toly The Grey", + "chain": "solana", + "mc_at_discovery": 128753, + "liquidity_at_discovery": 32614.73, + "score": 85, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "alpha_scanned", + "alpha_wallets_found": 2 + }, + { + "ca": "72Ed2QEAbZkbRqJ5vhciuyhGbDqpkh1BE98cuMeepump", + "symbol": "YETI", + "name": "YETI", + "chain": "solana", + "mc_at_discovery": 15782, + "liquidity_at_discovery": 10108.89, + "score": 85, + "source": "trending_scan", + "source_count": 2, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "alpha_scanned", + "alpha_wallets_found": 0 + }, + { + "ca": "Bq9D4BbhVR4kL1qSdsYpQ5JM59q2LzUYzv7zFA1epump", + "symbol": "RATHBUN", + "name": "MJ Rathbun", + "chain": "solana", + "mc_at_discovery": 207877, + "liquidity_at_discovery": 43811.38, + "score": 85, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "alpha_scanned", + "alpha_wallets_found": 3 + }, + { + "ca": "9QFdPG4CKrAc4LXZMwbRH5uTAJKweeqjRo3SxjPHpump", + "symbol": "CLAWBEE", + "name": "Claw Bee", + "chain": "solana", + "mc_at_discovery": 24452, + "liquidity_at_discovery": 13935.29, + "score": 75, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "qSHUQePJLGNaAg9hcSDyx4iuvcQtvngDgEJvDozpump", + "symbol": "usdpipcoin", + "name": "unstable pippin coin", + "chain": "solana", + "mc_at_discovery": 116722, + "liquidity_at_discovery": 27276.44, + "score": 65, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "8fHVrHu7XwoeVEq3AWBnhevJPef1DCPfSezzujhwpump", + "symbol": "WOLF", + "name": "Wolf", + "chain": "solana", + "mc_at_discovery": 111942, + "liquidity_at_discovery": 26531.27, + "score": 65, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "EYESosqrFpCJ2HXFpt5ZCEqi6TZCy6duj4y89chfX3EA", + "symbol": "CITY", + "name": "Cash City", + "chain": "solana", + "mc_at_discovery": 478789, + "liquidity_at_discovery": 57193.34, + "score": 65, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "CxoaKHTGYAUkHwzK5dazVYuG3vvEXExrGznMwX1ipump", + "symbol": "OPENCLAW", + "name": "OpenClaw", + "chain": "solana", + "mc_at_discovery": 806303, + "liquidity_at_discovery": 114401.8, + "score": 60, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "8hccoPdPATEXiZaoZXUJ6rTTDcfTDN3h5huTsn8rpump", + "symbol": "Aliens", + "name": "If aliens visit us", + "chain": "solana", + "mc_at_discovery": 20274, + "liquidity_at_discovery": 11646.52, + "score": 55, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "ApLJtDFLscoocY1Qjt3c3bRmxjw3F9hii4JVUbH63E14", + "symbol": "SAMO", + "name": "Samoyed Coin", + "chain": "solana", + "mc_at_discovery": 14250, + "liquidity_at_discovery": 10113.54, + "score": 55, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "vHXy4HyKLuds72QAM45QZZPzaRvGfKuY6VqXbvMpump", + "symbol": "Chiitan", + "name": "Chiitan", + "chain": "solana", + "mc_at_discovery": 8106, + "liquidity_at_discovery": 7185.5, + "score": 40, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "3VUzZPAEcBnxEQUE6FpXCMuUzATTMpn1zpkWqYKwpump", + "symbol": "hammy", + "name": "hammy", + "chain": "solana", + "mc_at_discovery": 2108, + "liquidity_at_discovery": 3646.75, + "score": 40, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "FNPxzS8DcYmkzmEJKNobS3FQxJNwQii2cXvNq8Tfpump", + "symbol": "CUB", + "name": "The Overfed Cub", + "chain": "solana", + "mc_at_discovery": 19678, + "liquidity_at_discovery": 10828.83, + "score": 35, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "9AvytnUKsLxPxFHFqS6VLxaxt5p6BhYNr53SD2Chpump", + "symbol": "67", + "name": "The Official 67 Coin", + "chain": "solana", + "mc_at_discovery": 4293141, + "liquidity_at_discovery": 370334.01, + "score": 35, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "72qDUjZisehaMKgTsMWp6n2ubiXHvMooNXvHGvJApump", + "symbol": "RUNNER", + "name": "The Wild Stallion", + "chain": "solana", + "mc_at_discovery": 2726, + "liquidity_at_discovery": 4207.53, + "score": 25, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "8FBzgKkHPh3BzZsM5Up1o1uDCGANKm8PpuRszJrFpump", + "symbol": "Lobster ", + "name": "Lobster Cash", + "chain": "solana", + "mc_at_discovery": 2054, + "liquidity_at_discovery": 3500.4, + "score": 25, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "CGc4bfLqov6rPKCv6kwDbY3cms8r5M4FHU72k5uspump", + "symbol": "Whitepin", + "name": "The White Pippin", + "chain": "solana", + "mc_at_discovery": 30503.03, + "liquidity_at_discovery": 0, + "score": 20, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "ED5nyyWEzpPPiWimP8vYm7sD7TD3LAt3Q3gRTWHzPJBY", + "symbol": "MOODENG", + "name": "Moo Deng", + "chain": "solana", + "mc_at_discovery": 52909554, + "liquidity_at_discovery": 2617741.86, + "score": 20, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "LHt5DejiBg9uAQicUxoBAVsVy7WctqqE6TxKh1Lpump", + "symbol": "Devfee", + "name": "Devfee", + "chain": "solana", + "mc_at_discovery": 9688, + "liquidity_at_discovery": 7593.51, + "score": 10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "9wbkLAA2Xa4RUaXGGZB9h1vsmmRtegQ1k8mm9dRhpump", + "symbol": "WMJ", + "name": "Wojak where is my jupuary", + "chain": "solana", + "mc_at_discovery": 3780.36, + "liquidity_at_discovery": 0, + "score": 10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "EZ2M9YVg6nM6ojjNetL3iz9XJspXGqVYsmKWpEVTpump", + "symbol": "poopin", + "name": "poopin", + "chain": "solana", + "mc_at_discovery": 2426.24, + "liquidity_at_discovery": 0, + "score": 10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "CHsBoFL6fXxTTqyiaDchXVKJnqHLpSGabXQCz6Z2bonk", + "symbol": "SQUEEZE", + "name": "The Big Squeeze", + "chain": "solana", + "mc_at_discovery": 2655.99, + "liquidity_at_discovery": 0, + "score": 10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "4kGz1KaqsHLsqKRC8cYV7hWzM8x2kYGu465mpNs2pump", + "symbol": "FIGURE", + "name": "FIGURE", + "chain": "solana", + "mc_at_discovery": 5089.71, + "liquidity_at_discovery": 0, + "score": 10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "BPz9u7EfWYf5KThnsfD4xS1ZEFBmCDzF8x93NPJkpump", + "symbol": "Snorv", + "name": "Snorv", + "chain": "solana", + "mc_at_discovery": 2687.1, + "liquidity_at_discovery": 0, + "score": 10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "Eeztqt962jMRk2jyHoPK1BNQfohbBaGfMM2nqSDLpump", + "symbol": "Cupid", + "name": "Cupid", + "chain": "solana", + "mc_at_discovery": 2524.72, + "liquidity_at_discovery": 0, + "score": 10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "3wQGfqf3ZiMHrU6XpM1YTpQ1PnudZvVuLdgE4fAwpump", + "symbol": "GLC", + "name": "Goldcoin\u2122", + "chain": "solana", + "mc_at_discovery": 13559.76, + "liquidity_at_discovery": 0, + "score": 10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "r2wdotawPs8GPYkghZ3exWCptrKR2ojnLivcmyRpump", + "symbol": "Eincode", + "name": "EINCODE", + "chain": "solana", + "mc_at_discovery": 4171.9, + "liquidity_at_discovery": 0, + "score": 10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "EqB6q66xeBizzBzWmk9uobmpuhp5NDf9dYaiihuvdwJh", + "symbol": "WOLF", + "name": "The Lone Wolf", + "chain": "solana", + "mc_at_discovery": 2693, + "liquidity_at_discovery": 4010.84, + "score": 10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "7EnNdapidW3rD5PyuArhM5CpNTWjgEXTToECAqSwpump", + "symbol": "Dihhead", + "name": "Dihhead", + "chain": "solana", + "mc_at_discovery": 9849.96, + "liquidity_at_discovery": 0, + "score": 10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "2d9qt9GFtPmoYv9rSt3pqW4s7NdcYLSph3KMcBvUpump", + "symbol": "FENNEC", + "name": "Fennec", + "chain": "solana", + "mc_at_discovery": 1731, + "liquidity_at_discovery": 3309.23, + "score": 10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "G1nJ6mmPPP9qXzXLqwNKqrjjrU6Acfjdx8cmXDaSpump", + "symbol": "DIHEAD", + "name": "dihead", + "chain": "solana", + "mc_at_discovery": 3456.26, + "liquidity_at_discovery": 0, + "score": 10, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "7uP2973VKmz33h2H5NCubUavgC7mJn6jkWfTDfADpump", + "symbol": "JustADex", + "name": "JustADex", + "chain": "solana", + "mc_at_discovery": 2182, + "liquidity_at_discovery": 3602.18, + "score": 5, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + }, + { + "ca": "6oZouQCNfA1iaRjNPiFapKVKDDiNYvZq3atntimpump", + "symbol": "POINTLESS", + "name": "pointless", + "chain": "solana", + "mc_at_discovery": 23688.71, + "liquidity_at_discovery": 0, + "score": 5, + "source": "trending_scan", + "source_count": 1, + "discovered_at": "2026-02-13T18:03:40.121207+00:00", + "scan_status": "pending_alpha_scan" + } + ], + "trending_scanned": [ + { + "date": "2026-02-08", + "source": "dexscreener", + "count": 46 + } + ], + "stats": { + "total_tokens": 207, + "pending_alpha_scan": 138, + "last_scan": "2026-02-13T18:03:40.121207+00:00" + } +} \ No newline at end of file diff --git a/memory/track_record.json b/memory/track_record.json new file mode 100644 index 0000000..04ecbf1 --- /dev/null +++ b/memory/track_record.json @@ -0,0 +1,31 @@ +{ + "total_recommendations": 0, + "wins": 0, + "losses": 0, + "win_rate": 0, + "avg_win_pct": 0, + "avg_loss_pct": 0, + "best_call": null, + "worst_call": null, + "by_category": { + "conviction": {"wins": 0, "losses": 0, "avg_return": 0}, + "narrative": {"wins": 0, "losses": 0, "avg_return": 0}, + "trench": {"wins": 0, "losses": 0, "avg_return": 0}, + "yield": {"wins": 0, "losses": 0, "avg_return": 0}, + "short": {"wins": 0, "losses": 0, "avg_return": 0} + }, + "by_source": { + "grok": {"wins": 0, "losses": 0}, + "web": {"wins": 0, "losses": 0}, + "onchain": {"wins": 0, "losses": 0}, + "smart_wallet": {"wins": 0, "losses": 0} + }, + "ev_calibration": { + "estimated_ev_avg": 0, + "actual_return_avg": 0, + "bull_case_hit_rate": 0, + "base_case_hit_rate": 0, + "bear_case_hit_rate": 0 + }, + "lessons": [] +} diff --git a/memory/trending_scans.jsonl b/memory/trending_scans.jsonl new file mode 100644 index 0000000..5ce0c4e --- /dev/null +++ b/memory/trending_scans.jsonl @@ -0,0 +1,4 @@ +{"timestamp": "2026-02-09T17:06:48.774359+00:00", "tokens_scanned": 39, "new_tokens": 32, "enriched": 32, "top10": [{"symbol": "Gentlemen", "ca": "5TATk16oMrt4vsMR8WwQ9AtiPeosdJhXFkp2UhGJpump", "mc": 354704, "score": 95}, {"symbol": "$POKEMON30", "ca": "B1RB6i7gvxYoyx8Us1eFrJxr7DZv3RzLmBHdfPwDpump", "mc": 159170, "score": 85}, {"symbol": "ROCK", "ca": "HjgwHz7QRjdT7DckZL2sJVKZ9iJm6K3oUmHu3bFapump", "mc": 309253, "score": 85}, {"symbol": "Maximoto", "ca": "8QJGmTnGhJAfGmkGrscYzrYKacaUCMYTTQQ2Wb3apump", "mc": 73929, "score": 85}, {"symbol": "$PENG", "ca": "9MCaWcXJRhCBxaYmqPwmdfqY9qxVwo427wYJu2MjWoyC", "mc": 69992, "score": 85}, {"symbol": "WATT", "ca": "5TcwTnpmvBv6CZAjzceGCAoR3KubRvtoz86TZoePpump", "mc": 66430, "score": 80}, {"symbol": "SKYNET", "ca": "88UweYzEAGVFAdjFwjhyPtSHhQf8SwSy85hh5vu4V2Hj", "mc": 6567, "score": 75}, {"symbol": "Perpcoin", "ca": "NeT4mWkYNuqBVy9XV2rhRMW59GwqTZLioYM5sktperp", "mc": 22011, "score": 65}, {"symbol": "LOTUS", "ca": "Dwwsv9JyCw3Zxufe7E4YQFX4q9Nf12YzTiPwQHaxpump", "mc": 10498084, "score": 60}, {"symbol": "Rock", "ca": "5fN3pcZiyLJVY7NvzkHTLHRyjETG3NRrQXEaPFoRn2D2", "mc": 14874, "score": 55}]} +{"timestamp": "2026-02-11T09:42:05.273350+00:00", "tokens_scanned": 60, "new_tokens": 50, "enriched": 40, "top10": [{"symbol": "BUCKARU", "ca": "E2HNWS5L6gwmtC9SZPpRq6Yp3V5gzotFrL3dAEP2pump", "mc": 313960, "score": 95}, {"symbol": "#MLM", "ca": "8ckfBhNvEDA62udk4YGNbSYcd5wvmQDjhY6kAYsgpump", "mc": 146047, "score": 85}, {"symbol": "GROKPEPE", "ca": "3mHw8CJffDZpY8F6KmGVF3LwwejCkMHG2o2pV5ZVpump", "mc": 100209, "score": 85}, {"symbol": "Ferociter", "ca": "7SYuU1Z6EKfpYQQ9VeTXfLW5ofhigdn8Y7iQsqoepump", "mc": 51870, "score": 85}, {"symbol": "GIRAFFES", "ca": "GbqbsRyBHVPHEv7xLEsikXmdpPPiApLTJesDBbL5pump", "mc": 1748404, "score": 85}, {"symbol": "SAFEMOON", "ca": "G9YU3K1MiPTv7Krui5omkPBPP21GChPPE3c9izRKbonk", "mc": 223160, "score": 85}, {"symbol": "soluna", "ca": "2qT8JVotQ2C1gKbqpuqNatkpSBWxiKHbXkCyTqH9pump", "mc": 901809, "score": 85}, {"symbol": "HAL", "ca": "CvTMSEB9RzHPhB1CgE7PAkszomozDv3JJNz28sDbpump", "mc": 94434, "score": 85}, {"symbol": "CMR", "ca": "CMRpNWSaSnyfoMDYhAWdPNXXrwXwPhz3CVEdZmToX9jR", "mc": 2431440, "score": 75}, {"symbol": "ICF", "ca": "F6QoH8WfU67V7xP7fnTHGpkR6xdegLUcPGjSLsGQmMD4", "mc": 1077116, "score": 75}]} +{"timestamp": "2026-02-12T09:32:24.185743+00:00", "tokens_scanned": 59, "new_tokens": 45, "enriched": 40, "top10": [{"symbol": "ApeLiquid", "ca": "7Gc9WkXewLGBzNDbz9nWZ4PuvEUhy38sAFk1MXoqpump", "mc": 66196, "score": 105}, {"symbol": "SHUTDOWN", "ca": "5hAikwRHTxRyXVgDShy6m3g49WWMXMQAVFNdPM7epump", "mc": 352006, "score": 105}, {"symbol": "COOPERINU", "ca": "EKgUxSq2ucFYwaoGfwz3sUpqDepky2vSfpr7jCEGpump", "mc": 113435, "score": 95}, {"symbol": "BIG", "ca": "Gz7VJWyQW6Uqt1Py5S2ZvtYNEFbP4Thmi31n5mx1pump", "mc": 331556, "score": 95}, {"symbol": "Pepstein", "ca": "322UMngby7k5nZ4aKdyNi6E9dv9kuhXeueErqXgopump", "mc": 107059, "score": 95}, {"symbol": "GIGACHAD", "ca": "AKuryic4cQ55EMfhvSGTdAXydQYLtRy6u8EfGdLRBAGS", "mc": 331672, "score": 85}, {"symbol": "MooNutPeng", "ca": "84hqMeGHxqegpvf4kGaRp38iVd145DSoEBwnmBTtpump", "mc": 529422, "score": 85}, {"symbol": "HTC", "ca": "HTCiQqiJa4e2L7aB5heTVgb2FYJyWDr6XdgsHwr3MpLR", "mc": 5032038, "score": 80}, {"symbol": "snowball", "ca": "Gbu7JAKhTVtGyRryg8cYPiKNhonXpUqbrZuCDjfUpump", "mc": 1004277, "score": 70}, {"symbol": "DOG", "ca": "21CnrFRqvEVkQZUTFmTXjcsJTLZhRY51ohoaCPwRpump", "mc": 989652, "score": 70}]} +{"timestamp": "2026-02-13T18:03:40.121207+00:00", "tokens_scanned": 54, "new_tokens": 43, "enriched": 40, "top10": [{"symbol": "LIZARD", "ca": "5T17aqgJ8cM39SNuVBu2LK2cq5MWUpZxcQnnuwNjpump", "mc": 221997, "score": 105}, {"symbol": "MoonLiquid", "ca": "63p6ir6gGQ59ZCDN2iRGUkCrZyJvu2xaacRYBfKopump", "mc": 118366, "score": 105}, {"symbol": "hoodrat", "ca": "58ExX8TFqiDqUpr1ZGiAhhiUsKfT14gwTFykLoVCpump", "mc": 457305, "score": 95}, {"symbol": "hopecoin", "ca": "3g3YFfUZLspiKpVmv9mDkaDcKh168CLArcqShR64pump", "mc": 91436, "score": 90}, {"symbol": "Buttfish", "ca": "58Ghft9TvGNuBiDzy9cFD2Px9rz5cDVZ1XoMFk1xpump", "mc": 216220, "score": 90}, {"symbol": "helicator", "ca": "EFt9JrrGyLWLU6Wc4oxfTjDKryENPrjbGgZ2V6x8pump", "mc": 62724, "score": 85}, {"symbol": "DEW", "ca": "V6e9AvFGp1hqE7HZBkTar8t1C7JorqZxaa5iS6kpump", "mc": 68204, "score": 85}, {"symbol": "TOLY", "ca": "9ekm6h4pxZcNbdyMw5fWkEnqAStjQCSzZ3TEfZ7tpump", "mc": 128753, "score": 85}, {"symbol": "YETI", "ca": "72Ed2QEAbZkbRqJ5vhciuyhGbDqpkh1BE98cuMeepump", "mc": 15782, "score": 85}, {"symbol": "RATHBUN", "ca": "Bq9D4BbhVR4kL1qSdsYpQ5JM59q2LzUYzv7zFA1epump", "mc": 207877, "score": 85}]} diff --git a/memory/wallet_scan_results.json b/memory/wallet_scan_results.json new file mode 100644 index 0000000..057e4ed --- /dev/null +++ b/memory/wallet_scan_results.json @@ -0,0 +1,220 @@ +{ + "scan_time": "2026-02-13T17:49:55.238626+00:00", + "wallets_scanned": 10, + "wallet_interactions": { + "Alpha #27 (from $SAFEMOON)": [ + { + "mint": "G9YU3K1MiPTv7Krui5omkPBPP21GChPPE3c9izRKbonk", + "action": "BUY", + "change": 23662528.485961, + "block_time": 1770849411, + "is_new_position": true, + "is_recent_6h": false + } + ], + "Alpha #25 (from $GIRAFFES)": [ + { + "mint": "kMKX8hBaj3BTRBbeYix9c16EieBP5dih8DTSSwCpump", + "action": "BUY", + "change": 1038580.691142, + "block_time": 1771002275, + "is_new_position": true, + "is_recent_6h": true + } + ], + "Alpha #34 (from $JESTER)": [ + { + "mint": "3wshHmD3aBx3wfHPeGWq2o38BNpVaEf7iFf3gYgRpump", + "action": "SELL", + "change": -5924667.109878, + "block_time": 1770936645, + "is_new_position": false, + "is_recent_6h": false + } + ], + "Alpha #28 (from $SAFEMOON)": [], + "Alpha #26 (from $GIRAFFES)": [ + { + "mint": "2k8yZaJjf61unHriuqdmvbxe7CUhEYML5kVJDbcotKjU", + "action": "SELL", + "change": -45316.61996200029, + "block_time": 1770991649, + "is_new_position": false, + "is_recent_6h": true + }, + { + "mint": "5T17aqgJ8cM39SNuVBu2LK2cq5MWUpZxcQnnuwNjpump", + "action": "BUY", + "change": 805528.3909150008, + "block_time": 1770991649, + "is_new_position": false, + "is_recent_6h": true + }, + { + "mint": "2k8yZaJjf61unHriuqdmvbxe7CUhEYML5kVJDbcotKjU", + "action": "SELL", + "change": -45316.62041600002, + "block_time": 1770991620, + "is_new_position": false, + "is_recent_6h": true + }, + { + "mint": "5T17aqgJ8cM39SNuVBu2LK2cq5MWUpZxcQnnuwNjpump", + "action": "BUY", + "change": 786269.3054189999, + "block_time": 1770991620, + "is_new_position": false, + "is_recent_6h": true + } + ], + "Alpha #32 (from $ICF)": [ + { + "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + "action": "SELL", + "change": -776.342205, + "block_time": 1770854585, + "is_new_position": false, + "is_recent_6h": false + }, + { + "mint": "F6QoH8WfU67V7xP7fnTHGpkR6xdegLUcPGjSLsGQmMD4", + "action": "SELL", + "change": -10829285.818872, + "block_time": 1770840986, + "is_new_position": false, + "is_recent_6h": false + } + ], + "Alpha #36 (from $BLOWFISH)": [], + "Alpha #23 (from $Ferociter)": [ + { + "mint": "3wshHmD3aBx3wfHPeGWq2o38BNpVaEf7iFf3gYgRpump", + "action": "BUY", + "change": 3748085.12495, + "block_time": 1770995844, + "is_new_position": true, + "is_recent_6h": true + }, + { + "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + "action": "SELL", + "change": -505.0, + "block_time": 1770995844, + "is_new_position": false, + "is_recent_6h": true + } + ], + "Alpha #17 (from $Maximoto)": [ + { + "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + "action": "SELL", + "change": -2518.114763, + "block_time": 1770690056, + "is_new_position": false, + "is_recent_6h": false + }, + { + "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + "action": "BUY", + "change": 2518.114763, + "block_time": 1770689172, + "is_new_position": true, + "is_recent_6h": false + } + ], + "Alpha #11 (from $$POKEMON30)": [ + { + "mint": "E7AaqmGaPsYxBzWERpgigt75nNs99eZEBUjKYA3cpump", + "action": "SELL", + "change": -4448221.93391, + "block_time": 1771004755, + "is_new_position": false, + "is_recent_6h": true + }, + { + "mint": "E7AaqmGaPsYxBzWERpgigt75nNs99eZEBUjKYA3cpump", + "action": "BUY", + "change": 428157.8163660001, + "block_time": 1771004735, + "is_new_position": false, + "is_recent_6h": true + }, + { + "mint": "E7AaqmGaPsYxBzWERpgigt75nNs99eZEBUjKYA3cpump", + "action": "SELL", + "change": -84797.97977000009, + "block_time": 1771004685, + "is_new_position": false, + "is_recent_6h": true + }, + { + "mint": "E7AaqmGaPsYxBzWERpgigt75nNs99eZEBUjKYA3cpump", + "action": "SELL", + "change": -51862.59639599966, + "block_time": 1771004639, + "is_new_position": false, + "is_recent_6h": true + } + ] + }, + "convergence_tokens": { + "5T17aqgJ8cM39SNuVBu2LK2cq5MWUpZxcQnnuwNjpump": { + "token_name": "unknown", + "buyer_count": 2, + "buyers": [ + { + "label": "Alpha #26 (from $GIRAFFES)", + "time": 1770991649, + "is_new": false + }, + { + "label": "Alpha #26 (from $GIRAFFES)", + "time": 1770991620, + "is_new": false + } + ] + } + }, + "new_positions_6h": [ + { + "wallet": "Alpha #25 (from $GIRAFFES)", + "mint": "kMKX8hBaj3BTRBbeYix9c16EieBP5dih8DTSSwCpump", + "token_name": "kMKX8hBaj3BTRBbeYix9...", + "is_new_position": true, + "change": 1038580.691142, + "time": "2026-02-13 17:04 UTC" + }, + { + "wallet": "Alpha #26 (from $GIRAFFES)", + "mint": "5T17aqgJ8cM39SNuVBu2LK2cq5MWUpZxcQnnuwNjpump", + "token_name": "5T17aqgJ8cM39SNuVBu2...", + "is_new_position": false, + "change": 805528.3909150008, + "time": "2026-02-13 14:07 UTC" + }, + { + "wallet": "Alpha #26 (from $GIRAFFES)", + "mint": "5T17aqgJ8cM39SNuVBu2LK2cq5MWUpZxcQnnuwNjpump", + "token_name": "5T17aqgJ8cM39SNuVBu2...", + "is_new_position": false, + "change": 786269.3054189999, + "time": "2026-02-13 14:07 UTC" + }, + { + "wallet": "Alpha #23 (from $Ferociter)", + "mint": "3wshHmD3aBx3wfHPeGWq2o38BNpVaEf7iFf3gYgRpump", + "token_name": "3wshHmD3aBx3wfHPeGWq...", + "is_new_position": true, + "change": 3748085.12495, + "time": "2026-02-13 15:17 UTC" + }, + { + "wallet": "Alpha #11 (from $$POKEMON30)", + "mint": "E7AaqmGaPsYxBzWERpgigt75nNs99eZEBUjKYA3cpump", + "token_name": "E7AaqmGaPsYxBzWERpgi...", + "is_new_position": false, + "change": 428157.8163660001, + "time": "2026-02-13 17:45 UTC" + } + ] +} \ No newline at end of file diff --git a/memory/wallet_tracker_alerts.jsonl b/memory/wallet_tracker_alerts.jsonl new file mode 100644 index 0000000..43e8fb3 --- /dev/null +++ b/memory/wallet_tracker_alerts.jsonl @@ -0,0 +1,29 @@ +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "GUBz6J9ojFoVEKHEhgHgv4FfsePY7UE2Hj5sMnvdwhMq", "wallet_label": "hellkatai Alpha #3 - Non-Sniper", "mint": "61Wj56QgGyyB966T7YsMzEAKRLcMvJpDbPzjkrCZc4Bi", "symbol": "COPPERINU", "sol_spent": 0.0, "token_info": {"symbol": "COPPERINU", "name": "copper inu", "mc": 10669132, "price": 0.01066, "liquidity": 444096.69, "volume_24h": 1843690.18, "price_change_24h": 33.18, "url": "https://dexscreener.com/solana/3iut1oaausqkehajkumzjbptihy2yn7awfij2crsuzvc"}, "signature": "2aFhGwtN1c2g1CPWa5iDKQMSnpduqQFGw7qHpk7PQya4SW67U5hiuVTTKLqAM7WtiaGA4XppCcPsTczutn942dgH", "block_time": 1770798094} +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "GUBz6J9ojFoVEKHEhgHgv4FfsePY7UE2Hj5sMnvdwhMq", "wallet_label": "hellkatai Alpha #3 - Non-Sniper", "mint": "61Wj56QgGyyB966T7YsMzEAKRLcMvJpDbPzjkrCZc4Bi", "symbol": "COPPERINU", "sol_spent": 0.0, "token_info": {"symbol": "COPPERINU", "name": "copper inu", "mc": 10669132, "price": 0.01066, "liquidity": 444096.69, "volume_24h": 1843690.18, "price_change_24h": 33.18, "url": "https://dexscreener.com/solana/3iut1oaausqkehajkumzjbptihy2yn7awfij2crsuzvc"}, "signature": "3Yd4H2iZYnL1ARn4MxJsDe8kkyX4RUZ5fRvaVCxujF5DYGoAAdrFSrPhrskcpjMrXHpgvg7Cc7dtoUvqqAUwAmTE", "block_time": 1770798037} +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "GUBz6J9ojFoVEKHEhgHgv4FfsePY7UE2Hj5sMnvdwhMq", "wallet_label": "hellkatai Alpha #3 - Non-Sniper", "mint": "61Wj56QgGyyB966T7YsMzEAKRLcMvJpDbPzjkrCZc4Bi", "symbol": "COPPERINU", "sol_spent": 0.0, "token_info": {"symbol": "COPPERINU", "name": "copper inu", "mc": 10669132, "price": 0.01066, "liquidity": 444096.69, "volume_24h": 1843690.18, "price_change_24h": 33.18, "url": "https://dexscreener.com/solana/3iut1oaausqkehajkumzjbptihy2yn7awfij2crsuzvc"}, "signature": "2oCJoeqmNXPW3Zqh19VtMrMypFA9rPVoXJw9PWyeHRymBTyUYS3g3uf3JajBMJ1v39tU4SX8LJsCpGKJNyVNMj8Q", "block_time": 1770798003} +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "GUBz6J9ojFoVEKHEhgHgv4FfsePY7UE2Hj5sMnvdwhMq", "wallet_label": "hellkatai Alpha #3 - Non-Sniper", "mint": "61Wj56QgGyyB966T7YsMzEAKRLcMvJpDbPzjkrCZc4Bi", "symbol": "COPPERINU", "sol_spent": 0.0002, "token_info": {"symbol": "COPPERINU", "name": "copper inu", "mc": 10669132, "price": 0.01066, "liquidity": 444096.69, "volume_24h": 1843690.18, "price_change_24h": 33.18, "url": "https://dexscreener.com/solana/3iut1oaausqkehajkumzjbptihy2yn7awfij2crsuzvc"}, "signature": "dEx9iikHFoWVCjaEo9HTPU1cm8EsRXjTLrtj1kerXKwhQZQkVLU9A37hi6bs7DWWu2VAGQFVZgDyUws19wZAM5e", "block_time": 1770797974} +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "3q1wAx4qSjADADkC1oYLmBxu5fW1bA1cLGUDmv2oEGSi", "wallet_label": "hellkatai Alpha #5 - Sniper", "mint": "9fRoVpdYbaQgcYq36YEnaj99veXJ8iFmPt7WEZ3jgh2X", "symbol": "9fRoVpdYbaQg", "sol_spent": 0, "token_info": null, "signature": "3HnxckLKTf3rooEZXB3XVwtA7cZsp6z9ApwGFrYPLWjXXdxtAKSJefukwNtUozqSDrrREEzn5qsHPjo8TVLXHRLM", "block_time": 1770653652} +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "DP7G43VPwR5Ab5rcjrCnvJ8UgvRXRHTWscMjRD1eSdGC", "wallet_label": "hellkatai Alpha #6 - TOP PERFORMER", "mint": "FtZjoKJZaDbM54apU81JCXsNxnHfBBjGL8Qjgh9aJKea", "symbol": "IOR50", "sol_spent": 20.1941, "token_info": {"symbol": "IOR50", "name": "IOR50", "mc": 31785, "price": 3.178e-05, "liquidity": 14788.36, "volume_24h": 1451902.57, "price_change_24h": -9.71, "url": "https://dexscreener.com/solana/2n5et2gzrmd9qzqfrbx7dfrwasjrurb6vdmngvnbfh9y"}, "signature": "5tR4dHA7XYnvNRBC2WtpKu4oJABhtTt6iRzw1b69azUjJmwqtowx2W4yk54ojbHB3xqVba3JJB5iTGnuapdrVF4v", "block_time": 1770781189} +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "Fj2uMrBaHkMcadrrTXeT5WSKfS6TCZyMUN1sSnoxQawv", "wallet_label": "Alpha #12 (from $$POKEMON30)", "mint": "FtZjoKJZaDbM54apU81JCXsNxnHfBBjGL8Qjgh9aJKea", "symbol": "IOR50", "sol_spent": 0.25, "token_info": {"symbol": "IOR50", "name": "IOR50", "mc": 31785, "price": 3.178e-05, "liquidity": 14788.36, "volume_24h": 1451902.57, "price_change_24h": -9.71, "url": "https://dexscreener.com/solana/2n5et2gzrmd9qzqfrbx7dfrwasjrurb6vdmngvnbfh9y"}, "signature": "3LEhemi35oWaHJtPdZucgY3Mq4GDkst1ubD4CLfNDEGujH9cDFBQDY3wV9LRGVseJ6joR24F5qQ56RknmDKZkRCw", "block_time": 1770798823} +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "Fj2uMrBaHkMcadrrTXeT5WSKfS6TCZyMUN1sSnoxQawv", "wallet_label": "Alpha #12 (from $$POKEMON30)", "mint": "B1RB6i7gvxYoyx8Us1eFrJxr7DZv3RzLmBHdfPwDpump", "symbol": "$POKEMON30", "sol_spent": 0.1444, "token_info": {"symbol": "$POKEMON30", "name": "Pok\u00e9mon: Since 1996", "mc": 34690, "price": 3.476e-05, "liquidity": 16169.82, "volume_24h": 96606.93, "price_change_24h": -40.69, "url": "https://dexscreener.com/solana/ekmyewxdbhiyh3uqnzhugg84korxmmzczrw9fneunowb"}, "signature": "4BWBiXXsWps47w7dob88iizJYLME37AZYdpwGaicuHN7eVZ6k9i5bygxvem7K9NPujLVUwh6CWCawdCC6zStyrNF", "block_time": 1770798845} +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "EqQZvQDWr1cp96PejiFkJo4UCkmti7nfLZjPuAw9Hz6K", "wallet_label": "Alpha #13 (from $ROCK)", "mint": "UuExMkPriRLoU4JGqnC3pMkgXge6s7aMqe5YAE5pump", "symbol": "CHIP", "sol_spent": 0, "token_info": {"symbol": "CHIP", "name": "CHIP", "mc": 30745, "price": 3.074e-05, "liquidity": 13359.94, "volume_24h": 95946.58, "price_change_24h": -11.32, "url": "https://dexscreener.com/solana/8yh6qarceyxznlggj6cgshadosane2uar3hkfutrbhor"}, "signature": "qhnCWg2zRadMYXgW3B22iFRwGqfbQf1cig85wHhb46NDed3wUJwqMRxxMpYfh2ZLT1rdqC42x3CQyzDQZ9PLnyp", "block_time": 1770782520} +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "Ci8oK32uRq1itnBRzVSwbyBNqJANhbsjuQe3qB5FfKxu", "wallet_label": "Alpha #14 (from $ROCK)", "mint": "HjgwHz7QRjdT7DckZL2sJVKZ9iJm6K3oUmHu3bFapump", "symbol": "ROCK", "sol_spent": 0.4962, "token_info": {"symbol": "ROCK", "name": "a rock", "mc": 95477, "price": 9.547e-05, "liquidity": 28303.96, "volume_24h": 626281.02, "price_change_24h": -73.82, "url": "https://dexscreener.com/solana/4kwtghylj5uqh7artppqa1csqztur2o2c42uwunb96wb"}, "signature": "491eqixen1HCRcJhYdg1M8HNNGMEgxypqJCAG9jWwpXAUfo44711kDYVpULp69KDGkg8jipHFMvbv68dsds3R8Nj", "block_time": 1770788425} +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "Ci8oK32uRq1itnBRzVSwbyBNqJANhbsjuQe3qB5FfKxu", "wallet_label": "Alpha #14 (from $ROCK)", "mint": "HqbqHzaf1NuPno2ya2z28zV9Kksjpe5grAreEfhpump", "symbol": "PENIS", "sol_spent": 1.0054, "token_info": {"symbol": "PENIS", "name": "Micro Penis Coin", "mc": 308498, "price": 0.0003084, "liquidity": 54584.99, "volume_24h": 8071557.63, "price_change_24h": 722, "url": "https://dexscreener.com/solana/xjm3npwtqkvvjekwb9pqfkduuh9ubk9s157nvsq38yq"}, "signature": "g3e7KZVpqee6RNCpCvSd27ruNZR6qCjgQTiJY3euGSRv6fTsMYHnZSp2MvkQk9E7LKKqhQAxUk5w7V3hSAaYdvf", "block_time": 1770768341} +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "75tPJxmQDz612FCQ4eRnP5mL7YnQqg3DtsqXbyZogyX4", "wallet_label": "Alpha #20 (from $#MLM)", "mint": "7N9M1ZhSYNtQWo4ByXwCoAZQtRk2dD2bUrxaCjiHaJUb", "symbol": "00", "sol_spent": 0, "token_info": {"symbol": "00", "name": "The Big Trout", "mc": 2111636589, "price": 0.002111, "liquidity": 84465463.75, "volume_24h": 2100.09, "price_change_24h": -0.02, "url": "https://dexscreener.com/solana/2dr6wkiahhkxco1coxq4kflchdc79czg7tjyj26x4s1c"}, "signature": "2v9JxbhR1gCYN6GdN7MQ3wCYTvheRo1vHaPufWx5FNuRXvqSWoik5o4NE5p8ya1e8UfS7AqffkKEWSiZCYZPhnkP", "block_time": 1770774613} +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "75tPJxmQDz612FCQ4eRnP5mL7YnQqg3DtsqXbyZogyX4", "wallet_label": "Alpha #20 (from $#MLM)", "mint": "8ckfBhNvEDA62udk4YGNbSYcd5wvmQDjhY6kAYsgpump", "symbol": "#MLM", "sol_spent": 0.0001, "token_info": {"symbol": "#MLM", "name": "Meme Lives Matter", "mc": 132142, "price": 0.0001336, "liquidity": 31408.32, "volume_24h": 2475734.67, "price_change_24h": 290, "url": "https://dexscreener.com/solana/8x1uivcsjmmphkj6szh5nsc3zqdwfblkomxpznd6bwke"}, "signature": "56woHvb9XB5S4hxLrcTUoEqXNgM6qAdLFWD1dZ867S3QmYoNhm9CL39B5o8PfQ3q9YCaB6WRe88hCoate9FXT84s", "block_time": 1770774593} +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "75tPJxmQDz612FCQ4eRnP5mL7YnQqg3DtsqXbyZogyX4", "wallet_label": "Alpha #20 (from $#MLM)", "mint": "8ckfBhNvEDA62udk4YGNbSYcd5wvmQDjhY6kAYsgpump", "symbol": "#MLM", "sol_spent": 0.0007, "token_info": {"symbol": "#MLM", "name": "Meme Lives Matter", "mc": 132142, "price": 0.0001336, "liquidity": 31408.32, "volume_24h": 2475734.67, "price_change_24h": 290, "url": "https://dexscreener.com/solana/8x1uivcsjmmphkj6szh5nsc3zqdwfblkomxpznd6bwke"}, "signature": "rRf5fxxZsuq45oLLb3Ku6fMw5dRD4PNwugfsFX1y7xUwLNRsVSdo4S8oKfiw1wQX6kexKhCMPawiU1zaKWL5vWR", "block_time": 1770774148} +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "75tPJxmQDz612FCQ4eRnP5mL7YnQqg3DtsqXbyZogyX4", "wallet_label": "Alpha #20 (from $#MLM)", "mint": "8ckfBhNvEDA62udk4YGNbSYcd5wvmQDjhY6kAYsgpump", "symbol": "#MLM", "sol_spent": 0.0, "token_info": {"symbol": "#MLM", "name": "Meme Lives Matter", "mc": 132142, "price": 0.0001336, "liquidity": 31408.32, "volume_24h": 2475734.67, "price_change_24h": 290, "url": "https://dexscreener.com/solana/8x1uivcsjmmphkj6szh5nsc3zqdwfblkomxpznd6bwke"}, "signature": "29yDAN25DdJZVJ46nXfqNiewZkF52mBSLVLHSg5JDvPL279i2fMFpHi42rKJWXFXn9zHJJArCjwpumuRiRyMPK6m", "block_time": 1770773887} +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "H6KiqN3wwirFumem4ZqxbF3hhHNTjpyps3q7TTLX3n33", "wallet_label": "Alpha #21 (from $#MLM)", "mint": "8ckfBhNvEDA62udk4YGNbSYcd5wvmQDjhY6kAYsgpump", "symbol": "#MLM", "sol_spent": 0.0009, "token_info": {"symbol": "#MLM", "name": "Meme Lives Matter", "mc": 132142, "price": 0.0001336, "liquidity": 31408.32, "volume_24h": 2475734.67, "price_change_24h": 290, "url": "https://dexscreener.com/solana/8x1uivcsjmmphkj6szh5nsc3zqdwfblkomxpznd6bwke"}, "signature": "2zze1etV3vhJr3yEHabNXUaEDkJer1L6a8VYDsRfPDF4cX1hxRLHN8CVHMLaaji2DKiLkm7UpSQ7LEK1D7M1UzpY", "block_time": 1770786015} +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "H6KiqN3wwirFumem4ZqxbF3hhHNTjpyps3q7TTLX3n33", "wallet_label": "Alpha #21 (from $#MLM)", "mint": "4nswj3o1Lo9iWYvvRJxUD8vbCy9ay7QQoXYcncHNbonk", "symbol": "SPSC", "sol_spent": 0.0019, "token_info": {"symbol": "SPSC", "name": "Shit Piss Skin Can", "mc": 1910428, "price": 0.00191, "liquidity": 253303.61, "volume_24h": 1109250.45, "price_change_24h": 78.97, "url": "https://dexscreener.com/solana/6mhj1z5bgc1uitnewrnjfbgtqpupdh2qgdwkemgxt2c5"}, "signature": "3bJR16xYot2CRJLMGo7kLA6KZY2uTEyUm6Euf8CjpoZF5ipAHE7ZVByY87rVLuz6fF2rRoMfs5DBLwVy6mDqG2jA", "block_time": 1770785597} +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "H6KiqN3wwirFumem4ZqxbF3hhHNTjpyps3q7TTLX3n33", "wallet_label": "Alpha #21 (from $#MLM)", "mint": "9zT4rVLrGzXSm16zyihUsv7bemK62axrNqQicLiVCTxw", "symbol": "00", "sol_spent": 0, "token_info": {"symbol": "00", "name": "The Giraffes", "mc": 137639891, "price": 0.001376, "liquidity": 5505601.64, "volume_24h": 2006.96, "price_change_24h": -0.6, "url": "https://dexscreener.com/solana/gjxedsbmzvw6uay3citmcl5sj4et9e19hansvpi1zbpg"}, "signature": "TK5b4eNU5WHyrzRgqg9fshuApvDki2wUx5b9jRc35TfMB9sA1hfy9ENt7GNVeKHs2rPg6PR38qnXSHeVvqpnYsb", "block_time": 1770784374} +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "4qPaGk9s8wpFhxVzncAQAt7dhGkp2byeG7qxU3AuKg1u", "wallet_label": "Alpha #23 (from $Ferociter)", "mint": "BGGFZLb29NZSqDz5T6K5Bj5VcwWM7YJc1XAKS8oSBAGS", "symbol": "STARCRAFT", "sol_spent": 0.0045, "token_info": {"symbol": "STARCRAFT", "name": "Starcraft", "mc": 398803, "price": 0.0003988, "liquidity": 43199.16, "volume_24h": 201537.4, "price_change_24h": 81.94, "url": "https://dexscreener.com/solana/3aue63ja4f8ropwwdcgbzal9e2tpr1last5lxyu3sisf"}, "signature": "4uZAhHJGRJ2aA2URxJKPgWrtDrusvdGD2JBK9hy16jPpobdjwvCcCrpQTAMkpLryeRWX8x7bBAtWmMwn6TxVyXE5", "block_time": 1770783665} +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "8WXKcUjwMU5TxiEN4mjw52iP4uPKx8VpXGozqMadqhyq", "wallet_label": "Alpha #26 (from $GIRAFFES)", "mint": "GbqbsRyBHVPHEv7xLEsikXmdpPPiApLTJesDBbL5pump", "symbol": "GIRAFFES", "sol_spent": 0.0001, "token_info": {"symbol": "GIRAFFES", "name": "The Giraffes", "mc": 1601761, "price": 0.001601, "liquidity": 120492.14, "volume_24h": 6630387.57, "price_change_24h": -26.52, "url": "https://dexscreener.com/solana/2zerywypw8kue4excbfweweql2ia1tzden6x9j2uu6yo"}, "signature": "4LND2MKNAACgdByXk6UzYD9n68pFneuXT9hGd2crLtE5qCHNLQUM1zxbqUCzei9nQoFmYoUuTN5TKeSeEVwxd5ve", "block_time": 1770772331} +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "8WXKcUjwMU5TxiEN4mjw52iP4uPKx8VpXGozqMadqhyq", "wallet_label": "Alpha #26 (from $GIRAFFES)", "mint": "2k8yZaJjf61unHriuqdmvbxe7CUhEYML5kVJDbcotKjU", "symbol": "BFS", "sol_spent": 0.0001, "token_info": {"symbol": "BFS", "name": "BFS", "mc": 3410675, "price": 0.00341, "liquidity": 17123.91, "volume_24h": 873689.16, "price_change_24h": 164, "url": "https://dexscreener.com/solana/81wvsfrdpdxj5goxmtermv8gydbhnknszh7zkiakbb9g"}, "signature": "4g7ddB5s2cnkRpB6Mfu2UmnrtJabqHD1KvsxTsgfwUujiX73DwTkKsrtC3RQ2pLpHmg7PeFutKNGPDrCQDYrGUko", "block_time": 1770772289} +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "8WXKcUjwMU5TxiEN4mjw52iP4uPKx8VpXGozqMadqhyq", "wallet_label": "Alpha #26 (from $GIRAFFES)", "mint": "2k8yZaJjf61unHriuqdmvbxe7CUhEYML5kVJDbcotKjU", "symbol": "BFS", "sol_spent": 0.0001, "token_info": {"symbol": "BFS", "name": "BFS", "mc": 3410675, "price": 0.00341, "liquidity": 17123.91, "volume_24h": 873689.16, "price_change_24h": 164, "url": "https://dexscreener.com/solana/81wvsfrdpdxj5goxmtermv8gydbhnknszh7zkiakbb9g"}, "signature": "B42BuqQbYNnwLSP3mCaP2opwVwLfdFShh5UEyLhZmx7S8axowyK7SVEPLHRBfBV1xf4gK6rf9A8D9DoV17zgXG3", "block_time": 1770772264} +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "8WXKcUjwMU5TxiEN4mjw52iP4uPKx8VpXGozqMadqhyq", "wallet_label": "Alpha #26 (from $GIRAFFES)", "mint": "2k8yZaJjf61unHriuqdmvbxe7CUhEYML5kVJDbcotKjU", "symbol": "BFS", "sol_spent": 0.0001, "token_info": {"symbol": "BFS", "name": "BFS", "mc": 3410675, "price": 0.00341, "liquidity": 17123.91, "volume_24h": 873689.16, "price_change_24h": 164, "url": "https://dexscreener.com/solana/81wvsfrdpdxj5goxmtermv8gydbhnknszh7zkiakbb9g"}, "signature": "2aZaz9WnDiWat6srfromnpprLkPJvsR4xw7BdGcYKNkMpmcKXdCCY69upBNXqWRrXJWNCHcv3zBnU2yxdr7Ardtq", "block_time": 1770772205} +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "Cqj2kGj9Wap4ghLuJkJ3HC1ZC2Brd2dVi7HweXLPH1b1", "wallet_label": "Alpha #27 (from $SAFEMOON)", "mint": "G9YU3K1MiPTv7Krui5omkPBPP21GChPPE3c9izRKbonk", "symbol": "SAFEMOON", "sol_spent": 0.003, "token_info": {"symbol": "SAFEMOON", "name": "SafeMoon", "mc": 220438, "price": 0.0002204, "liquidity": 43021.91, "volume_24h": 2280172.98, "price_change_24h": -9.49, "url": "https://dexscreener.com/solana/d4ulntjx6vathqvym9flt6trgmsxcjlzntp9rtdu4oge"}, "signature": "5wyDmVwEQygBpFHG7sueKkesZvsuqA7Wemjv6qpXybYh4zEJpsySdbk3ytfRcxxeijbDcxGDNJsSQwcRvjn4Giop", "block_time": 1770692839} +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "EXWGUMiuxxTB1TL1ZguYkDSyo4DwVfpDDZE3aox1pYzP", "wallet_label": "Alpha #28 (from $SAFEMOON)", "mint": "8e68924CdV1cctXmHCvNAUMJNzZGuv8DXgGpFjAeBAGS", "symbol": "SUBWAY", "sol_spent": 0.0021, "token_info": {"symbol": "SUBWAY", "name": "Subway Queen", "mc": 63846, "price": 6.384e-05, "liquidity": 17240.86, "volume_24h": 106100.19, "price_change_24h": 158, "url": "https://dexscreener.com/solana/4uya7rigffinyhkvwp6dsabhcmppprzaevh62bvezjk5"}, "signature": "GqPz5sTVMRQGi7s9tiPDjao7HpBRF5CN8pFFnyG2sGxQRCYHD5C5cVEjtwhehrLYTkZVJbXRwtMqRjDh82e82U2", "block_time": 1770793472} +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "BC8yiFFQWFEKrEEj75zYsuK3ZDCfv6QEeMRif9oZZ9TW", "wallet_label": "Alpha #29 (from $soluna)", "mint": "2qT8JVotQ2C1gKbqpuqNatkpSBWxiKHbXkCyTqH9pump", "symbol": "soluna", "sol_spent": 10.0, "token_info": {"symbol": "soluna", "name": "soluna", "mc": 1427256, "price": 0.001427, "liquidity": 113306.98, "volume_24h": 7322260.97, "price_change_24h": 4004, "url": "https://dexscreener.com/solana/fmhnbt1zrjliyd3guqkrjrzcz677kukn7olkq5nll5wg"}, "signature": "56tvWBpMJTwhGNCPD7c5Yk5KHrRAWpSrYitbZc2zn1sYA2xGKprtNhWYArh43cfyQ9dTuxhDpPFChRyJbci7Xd7q", "block_time": 1770771242} +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "DM3LKCMnZEmjnW57WVeWodRbur9ivBytjo2dkHKEfhQP", "wallet_label": "Alpha #32 (from $ICF)", "mint": "F6QoH8WfU67V7xP7fnTHGpkR6xdegLUcPGjSLsGQmMD4", "symbol": "ICF", "sol_spent": 0.0, "token_info": {"symbol": "ICF", "name": "Interstellar Civilization Fund", "mc": 1155784, "price": 0.001155, "liquidity": 60816.1, "volume_24h": 253017.74, "price_change_24h": 131, "url": "https://dexscreener.com/solana/5a32wjrdhkejf7wt2u1uqowkbz2rnwchqvzvrh3mcy3c"}, "signature": "3uAMsx2utKmTtUCTCcU6PyjpvpW7WURHoaf7spTYn4nZpwZLQ8GZX4Z17QLmSd6BQAXfQZyLeTm2rXeTVTLcsSKK", "block_time": 1770783320} +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "DM3LKCMnZEmjnW57WVeWodRbur9ivBytjo2dkHKEfhQP", "wallet_label": "Alpha #32 (from $ICF)", "mint": "F6QoH8WfU67V7xP7fnTHGpkR6xdegLUcPGjSLsGQmMD4", "symbol": "ICF", "sol_spent": 0.0, "token_info": {"symbol": "ICF", "name": "Interstellar Civilization Fund", "mc": 1155784, "price": 0.001155, "liquidity": 60816.1, "volume_24h": 253017.74, "price_change_24h": 131, "url": "https://dexscreener.com/solana/5a32wjrdhkejf7wt2u1uqowkbz2rnwchqvzvrh3mcy3c"}, "signature": "3EMEEDZbxENHe7nQLBBLWjWYEo5TRH5ijcKk47nY2GwMEdFV2ohSCEQsbRJFRtwBvLrzF6brrnx6eUojXFEwE4xb", "block_time": 1770783311} +{"timestamp": "2026-02-11T10:32:51.583487+00:00", "wallet": "DM3LKCMnZEmjnW57WVeWodRbur9ivBytjo2dkHKEfhQP", "wallet_label": "Alpha #32 (from $ICF)", "mint": "F6QoH8WfU67V7xP7fnTHGpkR6xdegLUcPGjSLsGQmMD4", "symbol": "ICF", "sol_spent": 0.0, "token_info": {"symbol": "ICF", "name": "Interstellar Civilization Fund", "mc": 1155784, "price": 0.001155, "liquidity": 60816.1, "volume_24h": 253017.74, "price_change_24h": 131, "url": "https://dexscreener.com/solana/5a32wjrdhkejf7wt2u1uqowkbz2rnwchqvzvrh3mcy3c"}, "signature": "4jCF9tjARYLd3ZJsKD5iwooETkTNAoZu2rNNjL45QKpfbLPFQKn4HYaCZqDmtXaUBscfcufawZujza7cxLfE8Ayt", "block_time": 1770771395} diff --git a/memory/wallet_tracker_state.json b/memory/wallet_tracker_state.json new file mode 100644 index 0000000..7cb7091 --- /dev/null +++ b/memory/wallet_tracker_state.json @@ -0,0 +1,31 @@ +{ + "gasTzr94Pmp4Gf8vknQnqxeYxdgwFjbgdJa4msYRpnB": "4j5A86srajAexKbDNbx9xiik9az5E9VReqsAf1nfyHkwjPYBnBTSQqfyjkUMe1CZtvwWVW8T5YGX2D2KsgJHtVT", + "62nvXUcG8bKp1BFqJfFr5Rz223QrLrHdSE4oupDAGsvF": "4PyvKMeNsMPRMCFCDLmqnYuDKDqeZE92uC15ZkBriqLdmW2HiCoP5rUdf175o9Vnx7qX1LT7uJif61JVLiSkgRVg", + "3nak6DM3bAkc27wQ71WH5mfXUVN9vhLfYWENTea2fbEE": "baeRNVp17rC6oipLFHh4Y77ZWGsfSv4j6FMXqW4QtUYtAVMWbSjiVXcXkhPVt2uDjr88oDXfBB85TeQXtJKJMAA", + "GUBz6J9ojFoVEKHEhgHgv4FfsePY7UE2Hj5sMnvdwhMq": "2aFhGwtN1c2g1CPWa5iDKQMSnpduqQFGw7qHpk7PQya4SW67U5hiuVTTKLqAM7WtiaGA4XppCcPsTczutn942dgH", + "AowTUid5daQr9EqwazF7hDm3jBTQSisv6LaHGhQL8k92": "5haKsSYbTewHfZt21i2VdmLhjXXFSBcAeVQspKECgdq92WnBS4zHknRwgUK2ki8xxPBVXjnA2nN2y3rthP4hBVCm", + "3q1wAx4qSjADADkC1oYLmBxu5fW1bA1cLGUDmv2oEGSi": "3HnxckLKTf3rooEZXB3XVwtA7cZsp6z9ApwGFrYPLWjXXdxtAKSJefukwNtUozqSDrrREEzn5qsHPjo8TVLXHRLM", + "DP7G43VPwR5Ab5rcjrCnvJ8UgvRXRHTWscMjRD1eSdGC": "qsNNybCuYfTobbiaKJwZaHFTj3wuM5QcYqBXYUGaoZGNbBa3magTg3U5iGpgBTNwwXFY8JdA4dJ6kAwE3gk6qBn", + "GjPSeaLm72QgTqzo38WbVajxnmRfZ6YQx8q5C3nEpq4p": "591u1qSwzRvzurpFNtyMvSmyrkUqPv52N8H2wdQvALjRjDFcNu8gRwnnJoWXoo6YrY5RvtJRQEYR2KpdTSJJCXU8", + "Fj2uMrBaHkMcadrrTXeT5WSKfS6TCZyMUN1sSnoxQawv": "2jhsR4Ytk9pokxqNofG7K94bsmj2UyyGRS9MHtFzRozSiBkFUf4uih9L4FMGGHeeSkNUDJ9zxcshuvEHpRMBM3zW", + "EqQZvQDWr1cp96PejiFkJo4UCkmti7nfLZjPuAw9Hz6K": "qhnCWg2zRadMYXgW3B22iFRwGqfbQf1cig85wHhb46NDed3wUJwqMRxxMpYfh2ZLT1rdqC42x3CQyzDQZ9PLnyp", + "Ci8oK32uRq1itnBRzVSwbyBNqJANhbsjuQe3qB5FfKxu": "4Lp2HAuj1oSkJzGzXqpiRAWgr6PEqzH6bgvKiGB5knVd2Woyi1fsiSmPMfKynZuDnhVVN7t1Cu3nDC2mdx5nctwS", + "3AGkLzoHJ6pz3qARi2vc7gDGyVNDaPj9dwBcCj2qMY16": "4HSVBoknH8ZXXiUegfhPMM7vTR4SNSm3xjE7tvq9PxStyQEQbmEz4A62nH1MxdVKWfgNLcbQACPrBNdiESztCBV8", + "FnRQiKnfcudnBLk5KmsSCWFgKvgfpaZd9guz31ghLRkF": "3xjKxHs4KwK7PJyTXgDoj32Fe1Tjsk3RovmWzHBqSxm7oCkPbVB5B5NWvM5BynjTGKjiS26iZuNuydWQBqrpCjkX", + "ND8nFkaHP9kwQXnhb3ELMEWqgHUu6ww2pzYcg7UfGCe": "58pqwES9RqCAdm8buAd2duZip6iab8jtsTKvkQnwXkpK6hGJRVPw4ybQBjt38wiqUc5uWFGp5fvkxCSQNY3YDndy", + "3ABA191xHH2eVAdBXu8wv2W1kfUWvZoNYbF7Yhkn418G": "ixuCMKQcxjeFzuzjE2KCwcuyAMfzUx5WSNKVFCZWa38FuJFsHopQ4S8UZBmxd8r9aDroLPUnxMRvipecRXBCK58", + "5T229oePmJGE5Cefys8jE9Jq8C7qfGNNWy3RVA7SmwEP": "3XRmGELAARXWUmViYgeUJhKxRotU6QUbmqWrZVzekaCir2amz1N1bEQaQKKbjnaPotGf5RUAucUXnonMqewRKD5Z", + "75tPJxmQDz612FCQ4eRnP5mL7YnQqg3DtsqXbyZogyX4": "2v9JxbhR1gCYN6GdN7MQ3wCYTvheRo1vHaPufWx5FNuRXvqSWoik5o4NE5p8ya1e8UfS7AqffkKEWSiZCYZPhnkP", + "H6KiqN3wwirFumem4ZqxbF3hhHNTjpyps3q7TTLX3n33": "4FCrCR7MzPu2bn4ENJkg37gepQzpUy5BDEDALJPeNB3Si5mzMXFPYxc4rPTS7LKTafU3Eg43r2ZrSfgmpsCEeiWw", + "2z24tiA9QR4PA1nBUK8Wpvo5viDAxVZpAeprKQqeyHeW": "4WYCRW3A4JmHe3LPRYvwKWadHnxed1F3XDsVJGpci4fg9bW4JaRoJjmh4RD8AecJBNHuSEzPiuqypdoAhVPAQCex", + "4qPaGk9s8wpFhxVzncAQAt7dhGkp2byeG7qxU3AuKg1u": "3RzpwUBEfgWayq8Kks2NJRSGaB5xQpGPnGtmJ2Kd4ncq3pXPLoHQarAtPA8sLwBsWqaeaB7zfa1nQ7tcHNLzF9gp", + "B5hhu1W6E3qgqgd5WYGiBPdg4zShUyFXLoH3KA2NEB5t": "5S3SF9T4jantSEfTMEcgQ7sgLkFnWLDnw7mzDxNjxRytfDvRR3Njjvj1o6WxfpjUm42HeXuDrrAfcLppgza6tki6", + "87rRdssFiTJKY4MGARa4G5vQ31hmR7MxSmhzeaJ5AAxJ": "2rxhRJzB1ZDwnq2YYb1dTmXEhBDL36AU49bszEjbrvU2sej65wcpEiuSzvKWRNvrEQJniZU5i49gUpmMuHc5HYzT", + "8WXKcUjwMU5TxiEN4mjw52iP4uPKx8VpXGozqMadqhyq": "5XGWPywWGft9W3wtJW7vJBuf2TJzWpkGuqXrrciEWAGyyJvfUkx1e2kkGt6kFWj4i2NNhVNFkXbQT8PmBUcDf4ZJ", + "Cqj2kGj9Wap4ghLuJkJ3HC1ZC2Brd2dVi7HweXLPH1b1": "4qmo8rcJ94jidupTmbGDSmtPjzMqx5bjsaWBSeBWY9oWC3S9WWpCMqY5BCJU89mvhWAyvR2W8z9osQMzJWch5obc", + "EXWGUMiuxxTB1TL1ZguYkDSyo4DwVfpDDZE3aox1pYzP": "2ABmJYwZDa5oSu6VUAENHFFGPAvcPekYsiXDMes8UGcvUUrjNgwrBeDVfwSoRaGpErAjUkhUzDDUJcNNmAJwL42m", + "BC8yiFFQWFEKrEEj75zYsuK3ZDCfv6QEeMRif9oZZ9TW": "5br7ZbeqTY2oeYt7SANAazP77VCMQ8BAyWGc1EAWEH873vctVSHp31eFdr4UkSA31m14osmN2mYCf4QGrDsact83", + "4QodqLUiQ57XF3W2X6AjYhKW2NGUuVdreGLQJkbWkVa2": "4dpkuUYNQX1hM8Q9ZK8pmw39YxhppHedaVCB1ncQAAmskXbgqGywqnZfi221cx1brHPSMCNfnthTvU6iPSijvT83", + "CjHKLXKPCC8rf6sdYznkmMxsMEDoLgJsawsWaheAqTRa": "3ZTwj7E9FbvUv5zHEJNfY8rjHwNEH15BFdBh8Fm3c7RckK3kt1ixjiaJC47XY6a8mtCc5WyJ7JaFWQu8CMw9o257", + "DM3LKCMnZEmjnW57WVeWodRbur9ivBytjo2dkHKEfhQP": "3p4ezPRqSWS4r517yZXfYr35zxTypk63sg5JkKXetPnvE6xNkHuF2MxuapaujhD23iCZzwjLS4gKiYicKMsqDuMQ" +} \ No newline at end of file diff --git a/memory/watchlist.json b/memory/watchlist.json new file mode 100644 index 0000000..93cc1fb --- /dev/null +++ b/memory/watchlist.json @@ -0,0 +1,190 @@ +{ + "protocols": [ + { + "name": "Hyperliquid", + "ticker": "HYPE", + "status": "active_position", + "watch_for": "HIP-4 prediction market launch, March 6 unlock reduction decision", + "trigger": "Break above $40 = add, break below $24 = exit", + "last_checked": "2026-02-08" + }, + { + "name": "Aave", + "ticker": "AAVE", + "status": "active_position", + "watch_for": "V4 launch date, revenue sharing implementation", + "trigger": "V4 launch confirmation = add, below $100 = exit", + "last_checked": "2026-02-08" + }, + { + "name": "Ondo Finance", + "ticker": "ONDO", + "status": "active_position", + "watch_for": "Unlock selling exhaustion, MetaMask adoption metrics, TVL growth", + "trigger": "Break above $0.40 with volume = add, break below $0.18 = exit", + "last_checked": "2026-02-08" + }, + { + "name": "Lighter", + "ticker": null, + "status": "farming", + "watch_for": "Token announcement, points program details", + "trigger": "Token launch announcement = prepare for claim", + "last_checked": "2026-02-08" + }, + { + "name": "OpenSea", + "ticker": "SEA", + "status": "pending_airdrop", + "watch_for": "Q1 2026 token launch, claim details", + "trigger": "Claim goes live = claim immediately", + "last_checked": "2026-02-08" + }, + { + "name": "Monad", + "ticker": null, + "status": "farming", + "watch_for": "Mainnet timeline, airdrop criteria", + "trigger": "Mainnet announcement = prepare for token launch", + "last_checked": "2026-02-08" + }, + { + "name": "Berachain", + "ticker": "BERA", + "status": "avoid", + "watch_for": "Unlock selling completion, TVL stabilization", + "trigger": "If unlock selling absorbed + TVL holds = reconsider in 4-8 weeks", + "last_checked": "2026-02-08" + }, + { + "name": "Lumen", + "ticker": "LUMEN", + "chain": "Base", + "ca": "0xa9FEE7b2F54781A14c85A1B8815345AefbE1EB07", + "status": "watching", + "watch_for": "AI agent experiment by Albert Wenger (USV). Bankr fee redirection to Lumen wallet. Future utility announcements.", + "trigger": "Dip to sub-2M MC = potential entry. New utility announcement from @albertwenger = add.", + "last_checked": "2026-02-08", + "notes": "Launched Feb 4. Sub-200K → 5M+ MC. Base AI agent narrative. Creator = USV partner (Coinbase/Etsy investor)." + }, + { + "name": "Juno Agent", + "ticker": "JUNO", + "chain": "Base", + "ca": "0x4E6c9f48f73E54EE5F3AB7e2992B2d733D0d0b07", + "status": "watching", + "watch_for": "Zero-human company thesis execution. New agent partnerships. Creator @tomosman updates.", + "trigger": "Dip to sub-500K MC = potential entry. New AI agent partnerships = add.", + "last_checked": "2026-02-08", + "notes": "Launched Feb 7. AI agent hunting/incubating zero-human companies. Creator followed by Bezos/pmarca. +2354% in hours." + } + ], + "wallets": [ + { + "label": "Trend Research", + "note": "$1.8B ETH collateral on Aave, $958M borrowed. Monitor health factor.", + "chain": "ethereum" + }, + { + "label": "White Whale (Hyperliquid)", + "note": "Top HL trader, $50M+ profit in 30 days. Need to identify on-chain wallet.", + "chain": "hyperliquid" + } + ], + "narratives": [ + { + "name": "DeFi Resilience", + "status": "active", + "lifecycle": "early_recognition", + "description": "DeFi TVL holding up while token prices crash. Real yield protocols outperforming." + }, + { + "name": "RWA Tokenization", + "status": "active", + "lifecycle": "infrastructure_building", + "description": "BlackRock, Goldman involvement. MetaMask integration. Volume up 2695% but tokens crushed by unlocks." + }, + { + "name": "Solana Infrastructure Evolution", + "status": "developing", + "lifecycle": "narrative_forming", + "description": "Shift from memecoins to micropayments. Alpenglow + Firedancer upgrades. Institutional adoption." + }, + { + "name": "Capitulation Bottom Formation", + "status": "active", + "lifecycle": "early_stage", + "description": "Multiple on-chain metrics at levels seen at 2015/2019/2022 bottoms. But ETF outflows haven't reversed." + }, + { + "name": "Base AI Agent Tokens", + "status": "active", + "lifecycle": "early_recognition", + "description": "New meta: AI agents with tokens on Base. $LUMEN (USV/Albert Wenger), $JUNO (zero-human companies), $CLAW, $KELLYCLAUDE. VC-connected creators, organic discovery in trenches. Same early callers across multiple tokens." + } + ], + "airdrops": [ + { + "name": "Lighter Exchange", + "status": "farming", + "expected_date": "2026 H1", + "strategy": "Trade on platform to accumulate points" + }, + { + "name": "OpenSea SEA", + "status": "pending_claim", + "expected_date": "Q1 2026", + "strategy": "Check eligibility, claim when live" + }, + { + "name": "Monad", + "status": "farming", + "expected_date": "2026", + "strategy": "Interact with testnet regularly" + }, + { + "name": "MetaMask/Linea", + "status": "farming", + "expected_date": "2026", + "strategy": "Swap tokens via MetaMask to earn points" + }, + { + "name": "Hyperliquid Season 2", + "status": "farming", + "expected_date": "2026", + "strategy": "Active trading on Hyperliquid" + } + ], + "unlocks": [ + { + "token": "MOVE", + "date": "2026-02-09", + "details": "Early backers unlock, 31.79% of total supply already released", + "risk": "medium" + }, + { + "token": "JUP", + "date": "2026-02-28", + "details": "200M JUP cliff (6.27% impact)", + "risk": "high" + }, + { + "token": "HYPE", + "date": "2026-03-06", + "details": "9.92M HYPE ($309M) for Core Contributors, 1% of total supply", + "risk": "medium-high" + } + ], + "hyperliquid_positions": [ + { + "trader": "White Whale", + "note": "Top 30-day PnL, $50M+ profit, momentum following strategy", + "last_checked": "2026-02-08" + }, + { + "trader": "James Wynn", + "note": "High-profile trader, track for directional signals", + "last_checked": "2026-02-08" + } + ] +} diff --git a/memory/x_profiles.json b/memory/x_profiles.json new file mode 100644 index 0000000..d69cae5 --- /dev/null +++ b/memory/x_profiles.json @@ -0,0 +1,195 @@ +{ + "description": "Master registry of X/Twitter profiles tracked for alpha. Includes callers, creators, trackers, and wallet sharers.", + "last_updated": "2026-02-08", + "profiles": [ + { + "handle": "@WavexCaller", + "category": "caller", + "chain_focus": "solana", + "reliability_score": 8, + "verification_status": "verified_early_pump", + "tokens_called": 7, + "avg_multiple": "22x", + "telegram": "t.me/WaveXCalls", + "notes": "VERIFIED: Posts CAs during early pump (2-5x, 5min in). NOT pre-pump. TG group may call earlier.", + "follow_priority": "critical", + "last_checked": "2026-02-08" + }, + { + "handle": "@AidenJackCrypto", + "category": "caller", + "chain_focus": "base", + "reliability_score": 9, + "verification_status": "unverified", + "tokens_called": 2, + "avg_multiple": "23x", + "telegram": null, + "notes": "Base AI agent specialist. Early to LUMEN(40x) and JUNO(6x). Needs timestamp verification.", + "follow_priority": "critical", + "last_checked": "2026-02-08" + }, + { + "handle": "@BioStone_chad", + "category": "caller", + "chain_focus": "base", + "reliability_score": 8, + "verification_status": "unverified", + "tokens_called": 2, + "avg_multiple": "31x", + "telegram": null, + "notes": "Base chain focus. Early to LUMEN(60x) and JUNO(2x). Needs timestamp verification.", + "follow_priority": "critical", + "last_checked": "2026-02-08" + }, + { + "handle": "@0zutta", + "category": "caller", + "chain_focus": "solana", + "reliability_score": 4, + "verification_status": "partially_debunked", + "tokens_called": 7, + "avg_multiple": "unknown", + "telegram": null, + "notes": "PARTIALLY DEBUNKED: Wrong CA for $Goyim. Posts 44min after @WavexCaller. Likely reposter.", + "follow_priority": "low", + "last_checked": "2026-02-08" + }, + { + "handle": "@Peter1015160", + "category": "caller", + "chain_focus": "solana", + "reliability_score": 2, + "verification_status": "debunked", + "tokens_called": 2, + "avg_multiple": "fake", + "telegram": null, + "notes": "FULLY DEBUNKED: All claims retroactive. Posted AFTER pumps. Selling TG access via fake track record.", + "follow_priority": "ignore", + "last_checked": "2026-02-08" + }, + { + "handle": "@ELCharpo45", + "category": "caller", + "chain_focus": "solana", + "reliability_score": 7, + "verification_status": "unverified", + "tokens_called": 1, + "avg_multiple": "15.8x", + "telegram": null, + "notes": "JESTERGOON at 15K MC (pre-graduation). Needs more data points + timestamp verification.", + "follow_priority": "high", + "last_checked": "2026-02-08" + }, + { + "handle": "@cfm_sol", + "category": "caller", + "chain_focus": "base", + "reliability_score": 7, + "verification_status": "unverified", + "tokens_called": 1, + "avg_multiple": "5x", + "telegram": null, + "notes": "Good narrative researcher. LUMEN with detailed VC thesis.", + "follow_priority": "high", + "last_checked": "2026-02-08" + }, + { + "handle": "@JMania402", + "category": "caller", + "chain_focus": "base", + "reliability_score": 7, + "verification_status": "unverified", + "tokens_called": 1, + "avg_multiple": "5.5x", + "telegram": null, + "notes": "Repeat updater — posts multiple times per token including dip analysis.", + "follow_priority": "high", + "last_checked": "2026-02-08" + }, + { + "handle": "@EricCryptoman", + "category": "caller", + "chain_focus": "base", + "reliability_score": 7, + "verification_status": "unverified", + "tokens_called": 1, + "avg_multiple": "2x+", + "telegram": null, + "notes": "High-engagement account. JUNO call got massive visibility (189 likes, 40K+ views).", + "follow_priority": "high", + "last_checked": "2026-02-08" + }, + { + "handle": "@TheWhiteWhaleX", + "category": "caller", + "chain_focus": "solana", + "reliability_score": 6, + "verification_status": "unverified", + "tokens_called": 1, + "avg_multiple": "4.7x", + "telegram": null, + "notes": "JESTERGOON at 30K MC. Needs more data points.", + "follow_priority": "medium", + "last_checked": "2026-02-08" + }, + { + "handle": "@0xWiz7", + "category": "caller", + "chain_focus": "base", + "reliability_score": 6, + "verification_status": "unverified", + "tokens_called": 1, + "avg_multiple": "5x", + "telegram": null, + "notes": "LUMEN caller. Needs more data points.", + "follow_priority": "medium", + "last_checked": "2026-02-08" + }, + { + "handle": "@hellkatai", + "category": "wallet_tracker", + "chain_focus": "solana", + "reliability_score": 7, + "verification_status": "unverified", + "tokens_called": 0, + "avg_multiple": "n/a", + "telegram": null, + "notes": "Wallet tracker using cielo.finance. Source of 6 alpha wallets ($592K combined PnL). Wallets need on-chain verification.", + "follow_priority": "high", + "last_checked": "2026-02-08" + }, + { + "handle": "@tomosman", + "category": "creator", + "chain_focus": "base", + "reliability_score": null, + "verification_status": "n/a", + "tokens_called": 0, + "avg_multiple": "n/a", + "telegram": null, + "notes": "CREATOR of $JUNO. Followed by Jeff Bezos, pmarca. Watch future launches.", + "follow_priority": "watch_launches", + "last_checked": "2026-02-08" + }, + { + "handle": "@albertwenger", + "category": "creator", + "chain_focus": "base", + "reliability_score": null, + "verification_status": "n/a", + "tokens_called": 0, + "avg_multiple": "n/a", + "telegram": null, + "notes": "CREATOR of $LUMEN. USV partner (Coinbase/Etsy investor). Watch future launches.", + "follow_priority": "watch_launches", + "last_checked": "2026-02-08" + } + ], + "stats": { + "total_profiles": 14, + "verified": 1, + "debunked": 2, + "unverified": 9, + "creators": 2 + } +} diff --git a/monitor_rex.py b/monitor_rex.py new file mode 100644 index 0000000..d836eb1 --- /dev/null +++ b/monitor_rex.py @@ -0,0 +1,326 @@ +#!/usr/bin/env python3 +""" +$Rex (CoinGecko Mascot) — 10-Minute Monitor +On-chain + X intelligence monitor. + +Usage: python3 monitor_rex.py (single run) + python3 monitor_rex.py loop (10min loop) +""" + +import json +import os +import ssl +import subprocess +import sys +import time +from datetime import datetime, timezone +from urllib.request import Request, urlopen +from urllib.error import HTTPError, URLError + +# SSL context for proxied environments +SSL_CTX = ssl.create_default_context() +SSL_CTX.check_hostname = False +SSL_CTX.verify_mode = ssl.CERT_NONE + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) +env_path = os.path.join(SCRIPT_DIR, '.env') +if os.path.exists(env_path): + with open(env_path) as f: + for line in f: + line = line.strip() + if '=' in line and not line.startswith('#'): + key, val = line.split('=', 1) + os.environ[key] = val + +HELIUS_RPC = os.environ.get('HELIUS_RPC_URL', '') +XAI_API_KEY = os.environ.get('XAI_API_KEY', '') +MINT = 'HXvQAQwytoLngKWQtge3oJnLHsaLwTxPbX48DctLpump' +SYMBOL = 'Rex' +RPC_DELAY = 0.3 + +# Previous snapshot for comparison +SNAPSHOT_FILE = os.path.join(SCRIPT_DIR, 'memory', 'rex_snapshots.jsonl') + + +def rpc_call(method, params): + try: + payload = json.dumps({'jsonrpc': '2.0', 'id': 1, 'method': method, 'params': params}).encode() + req = Request(HELIUS_RPC, data=payload, headers={'Content-Type': 'application/json'}) + with urlopen(req, timeout=15) as resp: + data = json.loads(resp.read()) + if 'error' in data: + return None + return data.get('result') + except Exception: + return None + + +def get_dexscreener(): + """Get live token data from DexScreener.""" + try: + url = f"https://api.dexscreener.com/tokens/v1/solana/{MINT}" + req = Request(url, headers={'Accept': 'application/json', 'User-Agent': 'Mozilla/5.0'}) + with urlopen(req, timeout=10, context=SSL_CTX) as resp: + data = json.loads(resp.read()) + if data and isinstance(data, list) and len(data) > 0: + p = data[0] + return { + 'name': p.get('baseToken', {}).get('name', '?'), + 'symbol': p.get('baseToken', {}).get('symbol', '?'), + 'price': float(p.get('priceUsd', 0) or 0), + 'mc': p.get('marketCap', 0), + 'liq': (p.get('liquidity') or {}).get('usd', 0), + 'vol_24h': p.get('volume', {}).get('h24', 0), + 'vol_1h': p.get('volume', {}).get('h1', 0), + 'price_5m': p.get('priceChange', {}).get('m5', 0), + 'price_1h': p.get('priceChange', {}).get('h1', 0), + 'price_6h': p.get('priceChange', {}).get('h6', 0), + 'price_24h': p.get('priceChange', {}).get('h24', 0), + 'buys_1h': p.get('txns', {}).get('h1', {}).get('buys', 0), + 'sells_1h': p.get('txns', {}).get('h1', {}).get('sells', 0), + 'buys_24h': p.get('txns', {}).get('h24', {}).get('buys', 0), + 'sells_24h': p.get('txns', {}).get('h24', {}).get('sells', 0), + 'created': p.get('pairCreatedAt', 0), + } + except Exception as e: + print(f" DexScreener error: {e}") + return None + + +def get_top_holders(): + """Get top 20 holders with SOL balances.""" + result = rpc_call('getTokenLargestAccounts', [MINT]) + if not result: + return [] + + holders = [] + for acc in result.get('value', [])[:20]: + token_account = acc['address'] + balance = float(acc.get('uiAmount', 0) or acc.get('amount', 0)) + + time.sleep(RPC_DELAY) + info = rpc_call('getAccountInfo', [token_account, {'encoding': 'jsonParsed'}]) + if not info or not info.get('value'): + continue + + try: + owner = info['value']['data']['parsed']['info']['owner'] + except (KeyError, TypeError): + continue + + time.sleep(RPC_DELAY) + bal = rpc_call('getBalance', [owner]) + sol = (bal.get('value', 0) if bal else 0) / 1e9 + + holders.append({'wallet': owner, 'balance': balance, 'sol': sol}) + + return holders + + +def get_mint_activity(): + """Get recent mint activity — buys, sells, net pressure.""" + time.sleep(RPC_DELAY) + sigs = rpc_call('getSignaturesForAddress', [MINT, {'limit': 50}]) + if not sigs: + return None + + now = time.time() + recent = [s for s in sigs if not s.get('err') and s.get('blockTime', 0) > now - 600] # last 10 min + + buys = 0 + sells = 0 + buy_sol = 0 + sell_sol = 0 + wallets = set() + + for sig_info in recent[:20]: # Parse up to 20 txs for speed + time.sleep(RPC_DELAY) + tx = rpc_call('getTransaction', [sig_info['signature'], + {'encoding': 'jsonParsed', 'maxSupportedTransactionVersion': 0}]) + if not tx: + continue + + meta = tx.get('meta', {}) + if meta.get('err'): + continue + + pre_balances = meta.get('preTokenBalances', []) + post_balances = meta.get('postTokenBalances', []) + + for pb in post_balances: + if pb.get('mint') != MINT: + continue + owner = pb.get('owner', '') + wallets.add(owner) + + post_amt = float(pb.get('uiTokenAmount', {}).get('uiAmount', 0) or 0) + pre_amt = 0 + for prb in pre_balances: + if prb.get('mint') == MINT and prb.get('owner') == owner: + pre_amt = float(prb.get('uiTokenAmount', {}).get('uiAmount', 0) or 0) + break + + diff = post_amt - pre_amt + if diff > 0: + buys += 1 + # Estimate SOL cost from balance changes + account_keys = tx.get('transaction', {}).get('message', {}).get('accountKeys', []) + for i, key in enumerate(account_keys): + pubkey = key.get('pubkey', '') if isinstance(key, dict) else key + if pubkey == owner: + pre_sol = (meta.get('preBalances', [0]*(i+1))[i]) / 1e9 + post_sol = (meta.get('postBalances', [0]*(i+1))[i]) / 1e9 + sol_delta = pre_sol - post_sol + if sol_delta > 0: + buy_sol += sol_delta + break + elif diff < 0: + sells += 1 + account_keys = tx.get('transaction', {}).get('message', {}).get('accountKeys', []) + for i, key in enumerate(account_keys): + pubkey = key.get('pubkey', '') if isinstance(key, dict) else key + if pubkey == owner: + pre_sol = (meta.get('preBalances', [0]*(i+1))[i]) / 1e9 + post_sol = (meta.get('postBalances', [0]*(i+1))[i]) / 1e9 + sol_delta = post_sol - pre_sol + if sol_delta > 0: + sell_sol += sol_delta + break + + return { + 'total_recent': len(recent), + 'parsed': min(len(recent), 20), + 'buys': buys, + 'sells': sells, + 'buy_sol': round(buy_sol, 2), + 'sell_sol': round(sell_sol, 2), + 'net_sol': round(buy_sol - sell_sol, 2), + 'unique_wallets': len(wallets), + } + + +def grok_search(query): + """Search X via Grok (uses curl — Python urlopen blocked by proxy).""" + if not XAI_API_KEY: + return "No XAI_API_KEY" + try: + payload = json.dumps({ + "model": "grok-4-1-fast", + "input": query, + "tools": [{"type": "x_search"}] + }) + result = subprocess.run([ + 'curl', '-s', '-X', 'POST', 'https://api.x.ai/v1/responses', + '-H', 'Content-Type: application/json', + '-H', f'Authorization: Bearer {XAI_API_KEY}', + '-d', payload + ], capture_output=True, text=True, timeout=60) + if result.returncode != 0: + return f"Grok curl error: {result.stderr[:200]}" + data = json.loads(result.stdout) + if 'output_text' in data: + return data['output_text'] + for item in data.get('output', []): + if item.get('type') == 'message': + for c in item.get('content', []): + if c.get('type') == 'output_text': + return c.get('text', '') + return str(data)[:1000] + except Exception as e: + return f"Grok error: {e}" + + +def run_check(): + """Run a single monitoring check.""" + now = datetime.now(timezone.utc) + ts = now.strftime('%H:%M UTC') + print(f"\n{'='*60}") + print(f" $Rex Monitor — {now.strftime('%Y-%m-%d %H:%M:%S UTC')}") + print(f"{'='*60}") + + # 1. DexScreener data + print("\n[1/4] DexScreener...") + dex = get_dexscreener() + if dex: + print(f" MC: ${dex['mc']:,.0f} | Price: ${dex['price']:.7f}") + print(f" 5m: {dex['price_5m']}% | 1h: {dex['price_1h']}% | 6h: {dex['price_6h']}% | 24h: {dex['price_24h']}%") + print(f" Vol 1h: ${dex['vol_1h']:,.0f} | Vol 24h: ${dex['vol_24h']:,.0f}") + print(f" Buys/Sells 1h: {dex['buys_1h']}/{dex['sells_1h']} | 24h: {dex['buys_24h']}/{dex['sells_24h']}") + print(f" Liquidity: ${dex['liq']:,.0f}") + else: + print(" DexScreener failed") + + # 2. Top holders + print("\n[2/4] Top 10 holders...") + holders = get_top_holders() + whales = [] + for i, h in enumerate(holders[:10]): + tag = "" + if h['sol'] < 0.01: + tag = " [LP/POOL]" if i == 0 else " [DUST]" + elif h['sol'] > 50: + tag = " [WHALE]" + whales.append(h) + elif h['sol'] > 10: + tag = " [FUNDED]" + whales.append(h) + print(f" #{i+1}: {h['wallet'][:16]}... | {h['balance']:>12,.0f} | {h['sol']:>8.2f} SOL{tag}") + + # 3. Recent activity + print("\n[3/4] Last 10min activity...") + activity = get_mint_activity() + if activity: + net_label = "BUY PRESSURE" if activity['net_sol'] > 0 else "SELL PRESSURE" if activity['net_sol'] < 0 else "NEUTRAL" + print(f" Txs: {activity['total_recent']} | Parsed: {activity['parsed']}") + print(f" Buys: {activity['buys']} ({activity['buy_sol']} SOL) | Sells: {activity['sells']} ({activity['sell_sol']} SOL)") + print(f" Net: {activity['net_sol']:+.2f} SOL — {net_label}") + print(f" Unique wallets: {activity['unique_wallets']}") + else: + print(" Activity fetch failed") + + # 4. X intelligence (1 focused search) + print("\n[4/4] X intelligence...") + x_intel = grok_search(f"$Rex CoinGecko mascot solana token — latest posts, who's talking about it, sentiment, any callers?") + # Summarize to first 500 chars + x_summary = x_intel[:500] if x_intel else "No X data" + print(f" {x_summary[:200]}...") + + # Save snapshot + snapshot = { + 'timestamp': now.isoformat(), + 'mc': dex.get('mc', 0) if dex else 0, + 'price': dex.get('price', 0) if dex else 0, + 'liq': dex.get('liq', 0) if dex else 0, + 'buys_10m': activity.get('buys', 0) if activity else 0, + 'sells_10m': activity.get('sells', 0) if activity else 0, + 'net_sol': activity.get('net_sol', 0) if activity else 0, + 'top_holder_count': len(holders), + 'whale_count': len(whales), + } + os.makedirs(os.path.dirname(SNAPSHOT_FILE), exist_ok=True) + with open(SNAPSHOT_FILE, 'a') as f: + f.write(json.dumps(snapshot) + '\n') + + return snapshot + + +def main(): + if len(sys.argv) > 1 and sys.argv[1] == 'loop': + print("Starting $Rex monitor — 10 minute intervals. Ctrl+C to stop.") + while True: + try: + run_check() + print(f"\n Next check in 10 minutes...") + time.sleep(600) + except KeyboardInterrupt: + print("\nStopped.") + break + except Exception as e: + print(f"\n Error: {e}") + time.sleep(60) + else: + run_check() + + +if __name__ == '__main__': + main() diff --git a/monitor_wallets.py b/monitor_wallets.py new file mode 100755 index 0000000..f57b3fa --- /dev/null +++ b/monitor_wallets.py @@ -0,0 +1,280 @@ +#!/usr/bin/env python3 +""" +Alpha Wallet Monitor — Watches tracked wallets for new token buys. +Runs every 1 minute. When an alpha wallet buys a new token, triggers buy signal. + +Usage: + python3 monitor_wallets.py # Run once + python3 monitor_wallets.py daemon # Run continuously (every 60s) +""" + +import json +import sys +import os +import time +import fcntl +from datetime import datetime, timezone +from urllib.request import Request, urlopen + +# Signal bus — cross-pipeline intelligence +from signal_bus import cross_reference_all, execute_ultra_buy, log_ultra_signal +from trade_executor import check_positions + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) + +# Load env +env_path = os.path.join(SCRIPT_DIR, '.env') +if os.path.exists(env_path): + with open(env_path) as f: + for line in f: + line = line.strip() + if '=' in line and not line.startswith('#'): + key, val = line.split('=', 1) + os.environ[key] = val + +HELIUS_RPC = os.environ.get('HELIUS_RPC_URL', '') +HELIUS_API_KEY = HELIUS_RPC.split('api-key=')[1].split('&')[0] if 'api-key=' in HELIUS_RPC else '' + +ALPHA_WALLETS_FILE = os.path.join(SCRIPT_DIR, 'memory', 'smart_wallets.json') +SIGNALS_FILE = os.path.join(SCRIPT_DIR, 'memory', 'wallet_signals.jsonl') +LAST_SIGS_FILE = os.path.join(SCRIPT_DIR, 'memory', 'wallet_last_sigs.json') + +# Known addresses to ignore (DEXes, system programs, etc.) +IGNORE_MINTS = { + 'So11111111111111111111111111111111111111112', # Wrapped SOL + 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', # USDC + 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB', # USDT +} + + +def helius_parsed_tx(address, limit=10): + """Get recent parsed transactions from Helius enhanced API.""" + url = f"https://api.helius.dev/v0/addresses/{address}/transactions?api-key={HELIUS_API_KEY}&limit={limit}" + try: + req = Request(url, headers={'Content-Type': 'application/json'}) + with urlopen(req, timeout=30) as resp: + return json.loads(resp.read()) + except Exception as e: + # Fix N4: Log Helius errors instead of silently swallowing + print(f" [Helius] API error for {address[:12]}...: {e}") + return [] + + +def load_last_sigs(): + """Load last seen signatures per wallet.""" + if os.path.exists(LAST_SIGS_FILE): + with open(LAST_SIGS_FILE) as f: + return json.load(f) + return {} + + +def save_last_sigs(data): + with open(LAST_SIGS_FILE, 'w') as f: + json.dump(data, f, indent=2) + + +def log_signal(signal): + with open(SIGNALS_FILE, 'a') as f: + fcntl.flock(f, fcntl.LOCK_EX) + f.write(json.dumps(signal) + '\n') + fcntl.flock(f, fcntl.LOCK_UN) + + +def extract_token_buys(txs, wallet_address): + """Extract token BUY events from parsed transactions. + Only counts tokens RECEIVED by the tracked wallet (not sent/sold). + """ + buys = [] + for tx in txs: + tx_type = tx.get("type", "") + desc = tx.get("description", "") + sig = tx.get("signature", "") + ts = tx.get("timestamp", 0) + + # Look for SWAP events (buys) + if tx_type in ("SWAP", "TRANSFER"): + token_transfers = tx.get("tokenTransfers", []) + + for tt in token_transfers: + mint = tt.get("mint", "") + if mint and mint not in IGNORE_MINTS: + to_user = tt.get("toUserAccount", "") + from_user = tt.get("fromUserAccount", "") + amount = tt.get("tokenAmount", 0) + # Only count tokens RECEIVED by tracked wallet (not sent/sold) + if amount > 0 and to_user == wallet_address and from_user != wallet_address: + buys.append({ + "mint": mint, + "amount": amount, + "signature": sig, + "timestamp": ts, + "type": tx_type, + "description": desc[:200] + }) + return buys + + +def check_wallet(address, label, last_sig): + """Check a wallet for new token buys since last check.""" + txs = helius_parsed_tx(address, limit=5) + if not txs: + return [], last_sig + + new_sig = txs[0].get("signature", "") + + # If same as last check, no new activity + if new_sig == last_sig: + return [], last_sig + + # Find new transactions + new_txs = [] + for tx in txs: + if tx.get("signature") == last_sig: + break + new_txs.append(tx) + + if not new_txs: + return [], new_sig + + # Extract buys (only tokens RECEIVED by this wallet) + buys = extract_token_buys(new_txs, address) + + signals = [] + for buy in buys: + signal = { + "date": datetime.now(timezone.utc).isoformat(), + "wallet": address, + "wallet_label": label, + "mint": buy["mint"], + "amount": buy["amount"], + "tx_type": buy["type"], + "signature": buy["signature"], + "action": "ALPHA_WALLET_BUY" + } + signals.append(signal) + print(f" SIGNAL: {label} bought token {buy['mint'][:20]}... | tx: {buy['signature'][:20]}...") + + return signals, new_sig + + +def run_scan(): + """Scan all alpha wallets once.""" + # Load alpha wallets (only Solana, reliability_score >= 6) + if not os.path.exists(ALPHA_WALLETS_FILE): + print("No smart_wallets.json found") + return [] + + with open(ALPHA_WALLETS_FILE) as f: + data = json.load(f) + + # Fix #6: Raised threshold from >=2 to >=6 (all current wallets are sol_spent=0 distributor bots) + # Fix: Use startswith("active") to include "active, needs_verification" wallets + wallets = [w for w in data.get("wallets", []) + if w.get("chain") == "solana" + and w.get("address", "unknown") != "unknown" + and w.get("status", "").startswith("active") + and (w.get("reliability_score") or 0) >= 6] + + if not wallets: + print("No trackable Solana wallets") + return [] + + last_sigs = load_last_sigs() + all_signals = [] + + print(f"Scanning {len(wallets)} alpha wallets...") + + for w in wallets: + addr = w["address"] + label = w.get("label", addr[:12]) + last_sig = last_sigs.get(addr, "") + + try: + signals, new_sig = check_wallet(addr, label, last_sig) + last_sigs[addr] = new_sig + all_signals.extend(signals) + except Exception as e: + print(f" Error checking {addr[:12]}...: {e}") + + time.sleep(0.5) # Rate limit + + save_last_sigs(last_sigs) + + # Log all wallet buy signals to disk (for cross-cycle persistence) + for s in all_signals: + log_signal(s) + + # Cross-reference against ALL historical signals (wallets + X callers) + # This checks new wallet buys against: + # - All previous wallet buy signals ever recorded (no time limit) + # - Recent X caller mentions (6-hour lookback) + # Only ULTRA conviction (wallet + X caller) triggers auto-buy + if all_signals: + new_mints = list(set(s["mint"] for s in all_signals)) + print(f" Cross-referencing {len(new_mints)} new mints against X signals + wallet history...") + + conviction_signals = cross_reference_all( + new_tickers=[], + new_mints=new_mints, + source="wallet_monitor" + ) + + if conviction_signals: + print(f"\n === {len(conviction_signals)} CONVICTION SIGNALS ===") + for sig in conviction_signals: + level = sig["conviction"] + ticker = sig.get("ticker", "UNKNOWN") + reason = sig.get("reason", "") + print(f" [{level}] ${ticker}: {reason}") + + if level == "ULTRA" and not sig.get("already_bought"): + # ULTRA = wallet buy + X caller = AUTO-BUY + print(f"\n *** ULTRA CONVICTION: ${ticker} ***") + execute_ultra_buy(sig) + elif level == "HIGH": + log_ultra_signal({**sig, "action": "HIGH_CONVICTION_LOGGED"}) + print(f" [HIGH] Logged: ${ticker}") + else: + print(" No cross-pipeline conviction signals.") + + return all_signals + + +def daemon(): + """Run continuously every 60 seconds.""" + print(f"Alpha Wallet Monitor started at {datetime.now(timezone.utc).isoformat()}") + print("Scanning every 60 seconds...") + + try: + while True: + try: + signals = run_scan() + ts = datetime.now(timezone.utc).strftime('%H:%M:%S') + if signals: + print(f" [{ts}] {len(signals)} new signals") + else: + print(f" [{ts}] No new activity") + except Exception as e: + print(f" Scan error: {e}") + import traceback + traceback.print_exc() + + # Check SL/TP on every cycle + try: + actions = check_positions() + if actions: + print(f" [{datetime.now(timezone.utc).strftime('%H:%M:%S')}] SL/TP actions: {len(actions)}") + except Exception as e: + print(f" Position check error: {e}") + + time.sleep(60) + except KeyboardInterrupt: + print(f"\n Daemon stopped at {datetime.now(timezone.utc).strftime('%H:%M:%S UTC')}") + + +if __name__ == "__main__": + if len(sys.argv) > 1 and sys.argv[1] == "daemon": + daemon() + else: + signals = run_scan() + print(f"\nTotal signals: {len(signals)}") diff --git a/on_chain_dd.sh b/on_chain_dd.sh new file mode 100755 index 0000000..2baa3f6 --- /dev/null +++ b/on_chain_dd.sh @@ -0,0 +1,460 @@ +#!/bin/bash +# on_chain_dd.sh — On-chain due diligence tool inspired by @nikshepsvn's approach +# Uses Helius RPC + Grok AI to trace transaction flows and verify protocol legitimacy +# +# Usage: +# ./on_chain_dd.sh tx — Trace a Solana transaction +# ./on_chain_dd.sh wallet
— Analyze a Solana wallet +# ./on_chain_dd.sh token — Analyze a Solana token +# ./on_chain_dd.sh program — Verify a Solana program + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +if [ -f "$SCRIPT_DIR/.env" ]; then + set -a; source "$SCRIPT_DIR/.env"; set +a +fi + +HELIUS_RPC="${HELIUS_RPC_URL:-}" +XAI_KEY="${XAI_API_KEY:-}" +OUTPUT_DIR="$SCRIPT_DIR/dd_reports" +mkdir -p "$OUTPUT_DIR" + +if [ -z "$HELIUS_RPC" ]; then + echo "ERROR: HELIUS_RPC_URL not set in .env" + exit 1 +fi + +# ─── RPC helpers ─── + +rpc_call() { + local method="$1" + local params="$2" + local result + result=$(curl -s -m 60 "$HELIUS_RPC" \ + -X POST -H "Content-Type: application/json" \ + -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"$method\",\"params\":$params}" 2>/dev/null || echo '{"error":"RPC timeout or connection error"}') + if [ -z "$result" ]; then + echo '{"error":"Empty RPC response"}' + else + echo "$result" + fi +} + +helius_api() { + local endpoint="$1" + local data="$2" + local api_key + api_key=$(echo "$HELIUS_RPC" | grep -oP 'api-key=\K[^&]+') + curl -s -m 30 "https://api.helius.dev/$endpoint?api-key=$api_key" \ + -X POST -H "Content-Type: application/json" \ + -d "$data" +} + +# ─── AI analysis via Grok ─── + +ai_analyze() { + local prompt="$1" + if [ -z "$XAI_KEY" ]; then + echo "[No Grok API key — raw data only]" + return + fi + local escaped_prompt + escaped_prompt=$(python3 -c "import json,sys; print(json.dumps(sys.stdin.read()))" <<< "$prompt") + + local response + response=$(curl -s -m 120 "https://api.x.ai/v1/responses" \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $XAI_KEY" \ + -d "{ + \"model\": \"grok-4-1-fast\", + \"input\": $escaped_prompt + }" 2>&1) + + echo "$response" | python3 -c " +import json, sys +try: + data = json.load(sys.stdin) + for item in data.get('output', []): + if 'content' in item: + for c in item['content']: + if c.get('type') == 'output_text': + print(c['text']) +except: + print('[AI analysis unavailable]') +" +} + +# ─── Commands ─── + +cmd_tx() { + local sig="$1" + echo "═══ TRANSACTION TRACE: $sig ═══" + echo "" + + # Fetch full transaction + echo ">> Fetching transaction..." + local tx_data + tx_data=$(rpc_call "getTransaction" "[\"$sig\",{\"encoding\":\"jsonParsed\",\"maxSupportedTransactionVersion\":0}]") + + if echo "$tx_data" | python3 -c "import json,sys; d=json.load(sys.stdin); assert d.get('result') is not None" 2>/dev/null; then + echo ">> Transaction found. Parsing..." + else + echo "ERROR: Transaction not found or RPC error" + echo "$tx_data" | python3 -c "import json,sys; print(json.dumps(json.load(sys.stdin),indent=2))" 2>/dev/null + return 1 + fi + + # Extract key fields + local parsed + parsed=$(echo "$tx_data" | python3 << 'PYEOF' +import json, sys +data = json.load(sys.stdin)["result"] +meta = data.get("meta", {}) +tx = data.get("transaction", {}) +msg = tx.get("message", {}) + +out = { + "slot": data.get("slot"), + "blockTime": data.get("blockTime"), + "fee": meta.get("fee"), + "err": meta.get("err"), + "computeUnitsConsumed": meta.get("computeUnitsConsumed"), + "logMessages": meta.get("logMessages", [])[:30], + "preBalances": meta.get("preBalances", [])[:5], + "postBalances": meta.get("postBalances", [])[:5], + "preTokenBalances": meta.get("preTokenBalances", [])[:10], + "postTokenBalances": meta.get("postTokenBalances", [])[:10], + "accountKeys": [k.get("pubkey","") if isinstance(k,dict) else k for k in msg.get("accountKeys", [])[:15]], + "instructions": [], + "innerInstructions": [] +} + +for ix in msg.get("instructions", []): + entry = { + "programId": ix.get("programId",""), + "program": ix.get("program",""), + } + if "parsed" in ix: + entry["parsed"] = ix["parsed"] + elif "data" in ix: + entry["data_preview"] = str(ix["data"])[:100] + out["instructions"].append(entry) + +for inner in meta.get("innerInstructions", [])[:5]: + inner_ixs = [] + for ix in inner.get("instructions", [])[:10]: + entry = {"programId": ix.get("programId",""), "program": ix.get("program","")} + if "parsed" in ix: + entry["parsed"] = ix["parsed"] + inner_ixs.append(entry) + out["innerInstructions"].append({"index": inner.get("index"), "instructions": inner_ixs}) + +print(json.dumps(out, indent=2)) +PYEOF + ) + + echo "$parsed" + echo "" + + # AI analysis + echo ">> AI Analysis..." + local report + report=$(ai_analyze "You are an on-chain security researcher. Analyze this Solana transaction trace and provide a DD report. Flag any risks: rug indicators, unverified programs, suspicious patterns, token drains, authority concerns. Also identify: what the tx does, which programs are invoked, any cross-program invocations, token balance changes, and whether this looks legitimate or suspicious. Be specific and technical. + +Transaction data: +$parsed") + + echo "$report" + + # Save report + local outfile="$OUTPUT_DIR/tx_$(echo "$sig" | cut -c1-12)_$(date +%Y%m%d_%H%M%S).txt" + { + echo "═══ TRANSACTION DD REPORT ═══" + echo "Signature: $sig" + echo "Date: $(date -u +%Y-%m-%dT%H:%M:%SZ)" + echo "" + echo "── Raw Data ──" + echo "$parsed" + echo "" + echo "── AI Analysis ──" + echo "$report" + } > "$outfile" + echo "" + echo ">> Report saved: $outfile" +} + +cmd_wallet() { + local addr="$1" + echo "═══ WALLET ANALYSIS: $addr ═══" + echo "" + + # Get SOL balance + echo ">> Fetching balance..." + local balance + balance=$(rpc_call "getBalance" "[\"$addr\"]") + local sol_balance + sol_balance=$(echo "$balance" | python3 -c "import json,sys; print(json.load(sys.stdin).get('result',{}).get('value',0) / 1e9)" 2>/dev/null || echo "error") + echo "SOL Balance: $sol_balance" + + # Get token accounts + echo ">> Fetching token holdings..." + local tokens + tokens=$(rpc_call "getTokenAccountsByOwner" "[\"$addr\",{\"programId\":\"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA\"},{\"encoding\":\"jsonParsed\"}]") + + local token_summary + token_summary=$(echo "$tokens" | python3 << 'PYEOF' +import json, sys +try: + data = json.load(sys.stdin) + accounts = data.get("result", {}).get("value", []) + holdings = [] + for acc in accounts: + info = acc.get("account", {}).get("data", {}).get("parsed", {}).get("info", {}) + amount = info.get("tokenAmount", {}) + if float(amount.get("uiAmount", 0) or 0) > 0: + holdings.append({ + "mint": info.get("mint", ""), + "amount": amount.get("uiAmountString", "0"), + "decimals": amount.get("decimals", 0) + }) + holdings.sort(key=lambda x: float(x["amount"]), reverse=True) + print(json.dumps(holdings[:20], indent=2)) +except Exception as e: + print(json.dumps({"error": str(e), "holdings": []})) +PYEOF + ) + echo "Token Holdings (top 20):" + echo "$token_summary" + + # Get recent transactions via Helius enhanced API + echo "" + echo ">> Fetching recent transactions (Helius)..." + local recent_txs + recent_txs=$(helius_api "v0/addresses/$addr/transactions" '{}' 2>/dev/null || echo "[]") + + local tx_summary + tx_summary=$(echo "$recent_txs" | python3 << 'PYEOF' +import json, sys +try: + txs = json.load(sys.stdin) + if not isinstance(txs, list): + print("No enhanced tx data available") + sys.exit(0) + summary = [] + for tx in txs[:15]: + summary.append({ + "sig": tx.get("signature","")[:20] + "...", + "type": tx.get("type","unknown"), + "description": tx.get("description","")[:120], + "fee": tx.get("fee",0), + "timestamp": tx.get("timestamp",""), + "nativeTransfers": len(tx.get("nativeTransfers",[])), + "tokenTransfers": len(tx.get("tokenTransfers",[])) + }) + print(json.dumps(summary, indent=2)) +except: + print("No enhanced tx data available") +PYEOF + ) + echo "$tx_summary" + + # AI analysis + echo "" + echo ">> AI Analysis..." + local report + report=$(ai_analyze "You are an on-chain wallet analyst. Analyze this Solana wallet and provide a DD report. Identify: wallet type (smart money, bot, whale, retail), trading patterns, risk flags (wash trading, rug deployment, suspicious approvals), notable holdings, and recent activity patterns. + +Wallet: $addr +SOL Balance: $sol_balance +Token Holdings: $token_summary +Recent Transactions: $tx_summary") + + echo "$report" + + local outfile="$OUTPUT_DIR/wallet_$(echo "$addr" | cut -c1-8)_$(date +%Y%m%d_%H%M%S).txt" + { + echo "═══ WALLET DD REPORT ═══" + echo "Address: $addr" + echo "Date: $(date -u +%Y-%m-%dT%H:%M:%SZ)" + echo "SOL Balance: $sol_balance" + echo "" + echo "── Token Holdings ──" + echo "$token_summary" + echo "" + echo "── Recent Transactions ──" + echo "$tx_summary" + echo "" + echo "── AI Analysis ──" + echo "$report" + } > "$outfile" + echo "" + echo ">> Report saved: $outfile" +} + +cmd_token() { + local mint="$1" + echo "═══ TOKEN ANALYSIS: $mint ═══" + echo "" + + # Get token supply + echo ">> Fetching supply..." + local supply + supply=$(rpc_call "getTokenSupply" "[\"$mint\"]") + echo "Supply: $(echo "$supply" | python3 -c "import json,sys; r=json.load(sys.stdin).get('result',{}).get('value',{}); print(r.get('uiAmountString','unknown'))" 2>/dev/null)" + + # Get largest holders + echo ">> Fetching top holders..." + local holders + holders=$(rpc_call "getTokenLargestAccounts" "[\"$mint\"]") + local holder_summary + holder_summary=$(echo "$holders" | python3 << 'PYEOF' +import json, sys +try: + data = json.load(sys.stdin) + accounts = data.get("result", {}).get("value", []) + summary = [] + for acc in accounts[:10]: + summary.append({ + "address": acc.get("address", ""), + "amount": acc.get("uiAmountString", "0"), + "pct_hint": "check vs total supply" + }) + print(json.dumps(summary, indent=2)) +except Exception as e: + print(json.dumps({"error": str(e), "holders": []})) +PYEOF + ) + echo "$holder_summary" + + # Get account info (mint authority, freeze authority) + echo "" + echo ">> Fetching mint info..." + local mint_info + mint_info=$(rpc_call "getAccountInfo" "[\"$mint\",{\"encoding\":\"jsonParsed\"}]") + local mint_details + mint_details=$(echo "$mint_info" | python3 << 'PYEOF' +import json, sys +try: + data = json.load(sys.stdin) + parsed = data.get("result",{}).get("value",{}).get("data",{}).get("parsed",{}).get("info",{}) + out = { + "mintAuthority": parsed.get("mintAuthority"), + "freezeAuthority": parsed.get("freezeAuthority"), + "decimals": parsed.get("decimals"), + "supply": parsed.get("supply"), + "isInitialized": parsed.get("isInitialized") + } + print(json.dumps(out, indent=2)) +except Exception as e: + print(json.dumps({"error": str(e)})) +PYEOF + ) + echo "$mint_details" + + # AI analysis + echo "" + echo ">> AI Analysis..." + local report + report=$(ai_analyze "You are an on-chain token analyst. Analyze this Solana token and provide a DD/risk report. Check for: rug indicators (mint authority still active = can mint infinite tokens, freeze authority = can freeze wallets), holder concentration (top 10 holders vs supply), supply distribution health. Flag all risks clearly. + +Token Mint: $mint +Mint Details: $mint_details +Top Holders: $holder_summary") + + echo "$report" + + local outfile="$OUTPUT_DIR/token_$(echo "$mint" | cut -c1-8)_$(date +%Y%m%d_%H%M%S).txt" + { + echo "═══ TOKEN DD REPORT ═══" + echo "Mint: $mint" + echo "Date: $(date -u +%Y-%m-%dT%H:%M:%SZ)" + echo "" + echo "── Mint Details ──" + echo "$mint_details" + echo "" + echo "── Top Holders ──" + echo "$holder_summary" + echo "" + echo "── AI Analysis ──" + echo "$report" + } > "$outfile" + echo "" + echo ">> Report saved: $outfile" +} + +cmd_program() { + local prog_id="$1" + echo "═══ PROGRAM VERIFICATION: $prog_id ═══" + echo "" + + # Get program account info + echo ">> Fetching program info..." + local prog_info + prog_info=$(rpc_call "getAccountInfo" "[\"$prog_id\",{\"encoding\":\"jsonParsed\"}]") + + local prog_details + prog_details=$(echo "$prog_info" | python3 << 'PYEOF' +import json, sys +try: + data = json.load(sys.stdin) + value = data.get("result",{}).get("value",{}) + out = { + "executable": value.get("executable"), + "owner": value.get("owner"), + "lamports": value.get("lamports"), + "rentEpoch": value.get("rentEpoch"), + "space": value.get("space", len(str(value.get("data","")))) + } + print(json.dumps(out, indent=2)) +except Exception as e: + print(json.dumps({"error": str(e)})) +PYEOF + ) + echo "$prog_details" + + echo "" + echo ">> AI Analysis..." + local report + report=$(ai_analyze "You are a Solana program security researcher. Analyze this program account and provide a verification report. Key checks: Is it executable? Is it upgradeable (owner = BPFLoaderUpgradeab1e = upgradeable, BPFLoader2 = immutable)? What are the security implications? Is the upgrade authority a multisig or single key? + +Program ID: $prog_id +Account Details: $prog_details") + + echo "$report" + + local outfile="$OUTPUT_DIR/program_$(echo "$prog_id" | cut -c1-8)_$(date +%Y%m%d_%H%M%S).txt" + { + echo "═══ PROGRAM DD REPORT ═══" + echo "Program: $prog_id" + echo "Date: $(date -u +%Y-%m-%dT%H:%M:%SZ)" + echo "" + echo "── Account Details ──" + echo "$prog_details" + echo "" + echo "── AI Analysis ──" + echo "$report" + } > "$outfile" + echo "" + echo ">> Report saved: $outfile" +} + +# ─── Main ─── + +case "${1:-help}" in + tx) cmd_tx "${2:?Usage: $0 tx }" ;; + wallet) cmd_wallet "${2:?Usage: $0 wallet
}" ;; + token) cmd_token "${2:?Usage: $0 token }" ;; + program) cmd_program "${2:?Usage: $0 program }" ;; + *) + echo "On-Chain DD Tool (inspired by @nikshepsvn)" + echo "" + echo "Usage:" + echo " $0 tx Trace a Solana transaction" + echo " $0 wallet
Analyze a Solana wallet" + echo " $0 token Analyze a Solana token" + echo " $0 program Verify a Solana program" + echo "" + echo "Reports saved to: $OUTPUT_DIR/" + ;; +esac diff --git a/realtime_scanner.py b/realtime_scanner.py new file mode 100644 index 0000000..fce5ada --- /dev/null +++ b/realtime_scanner.py @@ -0,0 +1,480 @@ +#!/usr/bin/env python3 +""" +Real-Time Token Scanner — runs every 60 seconds. +Lightweight: DexScreener boosts/profiles + GeckoTerminal trending/new. +Only enriches NEW tokens not already seen. Logs high-score finds. +Designed for VPS cron (every minute) or as a daemon loop. + +Usage: + python3 realtime_scanner.py # single run (for cron) + python3 realtime_scanner.py loop # continuous loop (60s interval) +""" + +import json +import os +import subprocess +import ssl +import sys +import time +from datetime import datetime, timezone +from urllib.request import Request, urlopen + +# ── Paths ─────────────────────────────────────────────────────────────────── +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) +MEMORY_DIR = os.path.join(SCRIPT_DIR, "memory") +SEEN_FILE = os.path.join(MEMORY_DIR, "realtime_seen.json") +ALERTS_LOG = os.path.join(MEMORY_DIR, "realtime_alerts.jsonl") +TOKENS_FILE = os.path.join(MEMORY_DIR, "tokens.json") +SMART_WALLETS_FILE = os.path.join(MEMORY_DIR, "smart_wallets.json") +LOG_DIR = os.path.join(SCRIPT_DIR, "logs") + +os.makedirs(MEMORY_DIR, exist_ok=True) +os.makedirs(LOG_DIR, exist_ok=True) + +# ── Load env ──────────────────────────────────────────────────────────────── +env_path = os.path.join(SCRIPT_DIR, ".env") +if os.path.exists(env_path): + with open(env_path) as f: + for line in f: + line = line.strip() + if "=" in line and not line.startswith("#"): + key, val = line.split("=", 1) + os.environ[key.strip()] = val.strip().strip('"').strip("'") + +HELIUS_RPC = os.environ.get("HELIUS_RPC_URL", "") + +# SSL context for DexScreener (proxy workaround) +SSL_CTX = ssl.create_default_context() +SSL_CTX.check_hostname = False +SSL_CTX.verify_mode = ssl.CERT_NONE + +# ── Helpers ───────────────────────────────────────────────────────────────── +def log(msg): + ts = datetime.now(timezone.utc).strftime("%H:%M:%S") + print(f"[{ts}] {msg}", flush=True) + + +def http_get(url, timeout=10): + """GET with SSL workaround and error handling.""" + try: + req = Request(url, headers={"Accept": "application/json", "User-Agent": "Mozilla/5.0"}) + with urlopen(req, timeout=timeout, context=SSL_CTX) as resp: + return json.loads(resp.read()) + except Exception as e: + log(f" HTTP error {url[:50]}: {e}") + return None + + +def curl_get(url, timeout=10): + """Fallback GET via curl (bypasses proxy restrictions).""" + try: + r = subprocess.run( + ["curl", "-s", "--max-time", str(timeout), url], + capture_output=True, text=True, timeout=timeout + 5, + ) + if r.returncode == 0 and r.stdout.strip(): + return json.loads(r.stdout) + except Exception as e: + log(f" curl error {url[:50]}: {e}") + return None + + +def load_seen(): + """Load set of already-seen CAs (to avoid re-alerting).""" + if os.path.exists(SEEN_FILE): + try: + with open(SEEN_FILE) as f: + data = json.load(f) + return set(data.get("cas", [])), data.get("last_run", "") + except Exception: + pass + return set(), "" + + +def save_seen(seen_set): + """Save seen CAs.""" + with open(SEEN_FILE, "w") as f: + json.dump({ + "cas": list(seen_set), + "last_run": datetime.now(timezone.utc).isoformat(), + "count": len(seen_set), + }, f) + + +def load_known_wallets(): + """Load tracked alpha wallets for cross-reference.""" + if os.path.exists(SMART_WALLETS_FILE): + try: + with open(SMART_WALLETS_FILE) as f: + data = json.load(f) + return {w["address"] for w in data.get("wallets", [])} + except Exception: + pass + return set() + + +# ── Data Sources (lightweight, no Grok — that's too slow for 1-min) ──────── +def fetch_dexscreener_boosts(): + """Top boosted tokens — Solana only.""" + data = curl_get("https://api.dexscreener.com/token-boosts/top/v1") or http_get("https://api.dexscreener.com/token-boosts/top/v1") + if not data: + return [] + return [ + {"ca": t["tokenAddress"], "source": "boost", "boost": t.get("totalAmount", 0)} + for t in data if t.get("chainId") == "solana" and t.get("tokenAddress") + ][:25] + + +def fetch_dexscreener_profiles(): + """Latest token profiles — Solana only.""" + data = curl_get("https://api.dexscreener.com/token-profiles/latest/v1") or http_get("https://api.dexscreener.com/token-profiles/latest/v1") + if not data: + return [] + return [ + {"ca": t["tokenAddress"], "source": "profile"} + for t in data if t.get("chainId") == "solana" and t.get("tokenAddress") + ][:25] + + +def fetch_gecko_trending(): + """GeckoTerminal trending pools — Solana.""" + data = curl_get("https://api.geckoterminal.com/api/v2/networks/solana/trending_pools?page=1") or http_get("https://api.geckoterminal.com/api/v2/networks/solana/trending_pools?page=1") + if not data: + return [] + tokens = [] + for p in data.get("data", []): + rels = p.get("relationships", {}) + base_id = rels.get("base_token", {}).get("data", {}).get("id", "") + ca = base_id.replace("solana_", "") if base_id.startswith("solana_") else "" + if ca: + tokens.append({"ca": ca, "source": "gecko_trend"}) + return tokens[:20] + + +def fetch_gecko_new(): + """GeckoTerminal new pools — Solana, filtered by volume.""" + data = curl_get("https://api.geckoterminal.com/api/v2/networks/solana/new_pools?page=1") or http_get("https://api.geckoterminal.com/api/v2/networks/solana/new_pools?page=1") + if not data: + return [] + tokens = [] + for p in data.get("data", []): + attr = p.get("attributes", {}) + vol = 0 + try: + vol = float(attr.get("volume_usd", {}).get("h24", 0) or 0) + except (TypeError, ValueError): + pass + rels = p.get("relationships", {}) + base_id = rels.get("base_token", {}).get("data", {}).get("id", "") + ca = base_id.replace("solana_", "") if base_id.startswith("solana_") else "" + if ca and vol >= 20000: + tokens.append({"ca": ca, "source": "gecko_new", "vol": vol}) + return tokens[:20] + + +# ── Enrichment & Scoring ─────────────────────────────────────────────────── +def enrich(ca): + """Get token details from DexScreener.""" + data = curl_get(f"https://api.dexscreener.com/tokens/v1/solana/{ca}") or http_get(f"https://api.dexscreener.com/tokens/v1/solana/{ca}") + if not data or not isinstance(data, list) or len(data) == 0: + return None + p = data[0] + bt = p.get("baseToken", {}) + mc = p.get("marketCap") or p.get("fdv") or 0 + liq = (p.get("liquidity") or {}).get("usd", 0) or 0 + vol_24h = (p.get("volume") or {}).get("h24", 0) or 0 + vol_1h = (p.get("volume") or {}).get("h1", 0) or 0 + age_ms = 0 + created = p.get("pairCreatedAt") + if created: + age_ms = int(time.time() * 1000) - created + txns_1h = p.get("txns", {}).get("h1", {}) + txns_24h = p.get("txns", {}).get("h24", {}) + chg = p.get("priceChange", {}) + return { + "symbol": bt.get("symbol", "?"), + "name": bt.get("name", "Unknown"), + "ca": ca, + "mc": mc, "liq": liq, + "vol_24h": vol_24h, "vol_1h": vol_1h, + "buys_1h": txns_1h.get("buys", 0) or 0, + "sells_1h": txns_1h.get("sells", 0) or 0, + "buys_24h": txns_24h.get("buys", 0) or 0, + "sells_24h": txns_24h.get("sells", 0) or 0, + "age_hours": age_ms / (1000 * 3600) if age_ms else 0, + "price_usd": float(p.get("priceUsd", 0) or 0), + "chg_5m": chg.get("m5", 0) or 0, + "chg_1h": chg.get("h1", 0) or 0, + "chg_6h": chg.get("h6", 0) or 0, + "chg_24h": chg.get("h24", 0) or 0, + } + + +def score(t, source_count): + """Score token for alerting. Returns (score, reasons).""" + s = 0 + reasons = [] + mc = t.get("mc", 0) or 0 + liq = t.get("liq", 0) or 0 + vol = t.get("vol_24h", 0) or 0 + vol_1h = t.get("vol_1h", 0) or 0 + age = t.get("age_hours", 0) or 0 + buys_1h = t.get("buys_1h", 0) or 0 + sells_1h = t.get("sells_1h", 0) or 0 + + # MC sweet spot + if 50_000 <= mc <= 500_000: + s += 30 + reasons.append("MC sweet spot ($50K-$500K)") + elif 500_000 < mc <= 5_000_000: + s += 20 + reasons.append("Small cap ($500K-$5M)") + elif mc > 5_000_000: + s += 5 + + # Liquidity floor + if liq >= 50_000: + s += 15 + reasons.append(f"Strong liq ${liq:,.0f}") + elif liq >= 10_000: + s += 5 + else: + s -= 20 + reasons.append("LOW LIQUIDITY") + + # Vol/MC ratio + if mc > 0: + vmr = vol / mc + if vmr > 1.0: + s += 25 + reasons.append(f"Extreme vol/MC {vmr:.1f}x") + elif vmr > 0.5: + s += 15 + reasons.append(f"High vol/MC {vmr:.1f}x") + elif vmr > 0.2: + s += 5 + + # 1h momentum + if vol_1h > 50_000: + s += 15 + reasons.append(f"$1h vol ${vol_1h:,.0f}") + elif vol_1h > 10_000: + s += 5 + + # Age + if 0.5 <= age <= 6: + s += 30 + reasons.append(f"FRESH ({age:.1f}h old)") + elif 6 < age <= 24: + s += 20 + reasons.append(f"New ({age:.0f}h)") + elif 24 < age <= 72: + s += 10 + elif age < 0.5: + s += 5 + reasons.append("Very new (<30min)") + + # Buy pressure (1h) + if buys_1h > 0 and sells_1h > 0: + ratio = buys_1h / sells_1h + if ratio > 2.0: + s += 20 + reasons.append(f"Strong buy pressure {ratio:.1f}x") + elif ratio > 1.3: + s += 10 + reasons.append(f"Buy pressure {ratio:.1f}x") + elif ratio < 0.5: + s -= 15 + reasons.append("DUMP signal") + + # Multi-source bonus + if source_count >= 3: + s += 25 + reasons.append(f"Multi-source ({source_count})") + elif source_count >= 2: + s += 15 + reasons.append(f"Dual-source ({source_count})") + + # Price momentum + chg_1h = t.get("chg_1h", 0) or 0 + if chg_1h > 100: + s += 15 + reasons.append(f"1h pump +{chg_1h:.0f}%") + elif chg_1h > 30: + s += 5 + + return s, reasons + + +# ── Quick Alpha Wallet Check (top 5 holders, fast) ───────────────────────── +def quick_holder_check(ca): + """Check top 5 holders for known alpha wallets. Fast: 6 RPC calls max.""" + if not HELIUS_RPC: + return [] + alpha_wallets = load_known_wallets() + if not alpha_wallets: + return [] + + try: + # Get top 5 holders + body = json.dumps({"jsonrpc": "2.0", "id": 1, "method": "getTokenLargestAccounts", "params": [ca]}).encode() + req = Request(HELIUS_RPC, data=body, headers={"Content-Type": "application/json"}) + with urlopen(req, timeout=10) as resp: + res = json.loads(resp.read()) + largest = res.get("result", {}).get("value", [])[:5] + + matches = [] + for acct in largest: + token_addr = acct["address"] + time.sleep(0.2) + body2 = json.dumps({"jsonrpc": "2.0", "id": 2, "method": "getAccountInfo", "params": [token_addr, {"encoding": "jsonParsed"}]}).encode() + req2 = Request(HELIUS_RPC, data=body2, headers={"Content-Type": "application/json"}) + with urlopen(req2, timeout=10) as resp2: + info = json.loads(resp2.read()) + try: + owner = info["result"]["value"]["data"]["parsed"]["info"]["owner"] + if owner in alpha_wallets: + matches.append(owner) + except (KeyError, TypeError): + pass + + return matches + except Exception: + return [] + + +# ── Main Scanner ──────────────────────────────────────────────────────────── +def scan_once(): + """Single scan iteration. Returns list of alerts sent.""" + now = datetime.now(timezone.utc) + log(f"Scan starting...") + + # Load previously seen CAs + seen, last_run = load_seen() + + # Fetch from all sources in parallel-ish (sequential but fast) + all_raw = [] + all_raw.extend(fetch_dexscreener_boosts()) + all_raw.extend(fetch_dexscreener_profiles()) + all_raw.extend(fetch_gecko_trending()) + all_raw.extend(fetch_gecko_new()) + + # Deduplicate and count sources per CA + ca_sources = {} + for t in all_raw: + ca = t["ca"] + if ca not in ca_sources: + ca_sources[ca] = set() + ca_sources[ca].add(t["source"]) + + total_cas = len(ca_sources) + new_cas = {ca for ca in ca_sources if ca not in seen} + + log(f" Found {total_cas} CAs, {len(new_cas)} new") + + if not new_cas: + save_seen(seen) + log(" No new tokens. Done.") + return [] + + # Enrich only new CAs (limit to 15 per run to stay fast) + alerts = [] + enriched_count = 0 + for ca in list(new_cas)[:15]: + info = enrich(ca) + if not info or not info.get("mc"): + seen.add(ca) + continue + + src_count = len(ca_sources.get(ca, set())) + token_score, reasons = score(info, src_count) + info["score"] = token_score + info["reasons"] = reasons + info["source_count"] = src_count + info["sources"] = list(ca_sources.get(ca, set())) + enriched_count += 1 + + # ALERT threshold: score >= 60 + if token_score >= 60: + # Quick alpha wallet check for high-score tokens + alpha_matches = [] + if token_score >= 80 and HELIUS_RPC: + alpha_matches = quick_holder_check(ca) + if alpha_matches: + token_score += 30 + info["score"] = token_score + reasons.append(f"ALPHA WALLET in top 5! ({len(alpha_matches)})") + + # Build alert message + sym = info["symbol"] + mc = info["mc"] + liq = info["liq"] + age = info["age_hours"] + vol = info["vol_24h"] + chg_1h = info.get("chg_1h", 0) + reasons_str = " | ".join(reasons[:5]) + + age_str = f"{age:.1f}h" if age < 48 else f"{age/24:.1f}d" + alert_emoji = "🔴" if token_score >= 100 else "🟡" if token_score >= 80 else "🟢" + + alert_msg = ( + f"{alert_emoji} **NEW: ${sym}** | Score: **{token_score}**\n" + f"MC: ${mc:,.0f} | Liq: ${liq:,.0f} | Vol24h: ${vol:,.0f} | Age: {age_str}\n" + f"1h: {chg_1h:+.1f}% | B/S 1h: {info['buys_1h']}/{info['sells_1h']} | Sources: {src_count}\n" + f"`{ca}`\n" + f"Signals: {reasons_str}" + ) + + if alpha_matches: + alert_msg += f"\n**ALPHA WALLET MATCH:** {', '.join(m[:12]+'...' for m in alpha_matches)}" + + alerts.append(info) + + log(f" ALERT: ${sym} | Score {token_score} | MC ${mc:,.0f} | {reasons_str}") + + # Log alert + with open(ALERTS_LOG, "a") as f: + f.write(json.dumps({ + "timestamp": now.isoformat(), + "symbol": sym, "ca": ca, + "mc": mc, "score": token_score, + "reasons": reasons, + "alpha_wallets": alpha_matches, + }) + "\n") + + seen.add(ca) + time.sleep(0.3) # Rate limit enrichment + + # Save updated seen set (cap at 5000 to prevent bloat) + if len(seen) > 5000: + seen = set(list(seen)[-3000:]) + save_seen(seen) + + log(f" Enriched {enriched_count}, sent {len(alerts)} alerts. Done.") + return alerts + + +# ── Entry Point ───────────────────────────────────────────────────────────── +def main(): + mode = sys.argv[1] if len(sys.argv) > 1 else "once" + + if mode == "loop": + log("Starting real-time scanner (60s loop)...") + cycle = 0 + while True: + try: + cycle += 1 + alerts = scan_once() + if cycle % 30 == 0: + # Every 30 min, post a heartbeat + seen, _ = load_seen() + log(f" Heartbeat: {len(seen)} CAs tracked, cycle #{cycle}") + except Exception as e: + log(f" ERROR: {e}") + time.sleep(60) + else: + scan_once() + + +if __name__ == "__main__": + main() diff --git a/reports/ftx2_analysis_20260213.md b/reports/ftx2_analysis_20260213.md new file mode 100644 index 0000000..b8c1857 --- /dev/null +++ b/reports/ftx2_analysis_20260213.md @@ -0,0 +1,145 @@ +# FTX 2.0 ($FTX2.0) — Full Intelligence Report +**CA:** `ANVWi3AAkjXRnesAMtAQNRPcrhSnKKbQwsRVe7xpump` +**Date:** 2026-02-13 | **Chain:** Solana (PumpSwap) + +--- + +## Token Overview +| Metric | Value | +|--------|-------| +| Name | FTX 2.0 ($FTX2.0) | +| Market Cap | $194,446 | +| FDV | $196,776 | +| Liquidity | $36,558 | +| 24h Volume | $889,921 | +| Price | $0.0001944 | +| Supply | 1,000,000,000 (1B) | +| Created | Dec 11, 2024 | +| Graduated pump.fun | Feb 10, 2026 | +| Pair | 7DJMtWE8Nnbvpd9TGawpD6K1J3HR7JxW5d4oYJyttJAa | + +### Price Performance +- **24h:** +10,625% +- **6h:** +11,076% +- **1h:** -32.31% (dumping) +- **5m:** -18.18% + +### Trading Activity +- 24h: 7,444 buys / 5,522 sells (1.35 ratio — slightly buy-heavy) +- 15,000+ signatures in last 2 hours = extremely active + +--- + +## Catalyst: SBF Tweet +SBF posted "wow what an honor" at **11:37 GMT today** (screenshot of the token). This is the **OG FTX 2.0** — created 3 days BEFORE SBF's tweet. Creator rewards/fees allocated to SBF's wallet. At least 4 copycat tokens launched after the tweet, most flagged as bundled scams. + +--- + +## Top 20 Holders Analysis + +| # | % | Tokens | SOL Bal | Wallet Age | Funder | Notes | +|---|---|--------|---------|------------|--------|-------| +| 1 | 9.73% | 97.3M | - | - | - | **PumpSwap Pool** (not a holder) | +| 2 | 2.81% | 28.1M | 0.00 | 02/11 | 2snHHreXbpJ7... | Drained wallet, still holding | +| 3 | 2.35% | 23.5M | 1.02 | 12/10/2025 | SELF | Old wallet, 1000+ txs | +| 4 | 2.23% | 22.3M | **155.76** | 01/24 | HeF5Wx4CxUbm... | **WHALE** | +| 5 | 2.09% | 20.9M | 0.02 | 07/27/2025 | SELF | Old wallet | +| 6 | 1.86% | 18.6M | 15.83 | 02/06 | **ABNL41SwMLV...** | **BUNDLER CLUSTER** | +| 7 | 1.71% | 17.1M | 0.08 | 01/07 | 3qW19QKhrAKK... | | +| 8 | 1.68% | 16.8M | 26.75 | 02/06 | **ABNL41SwMLV...** | **BUNDLER CLUSTER** | +| 9 | 1.44% | 14.4M | 42.86 | 02/06 | E9vf42zJXFv8... | Active trader | +| 10 | 1.40% | 14.0M | 3.58 | 02/06 | SELF | | +| 11 | 1.27% | 12.7M | 0.07 | 01/14 | ExRKJFJ7fC7v... | | +| 12 | 1.30% | 13.0M | 3.75 | 02/07 | SELF | | +| 13 | 1.24% | 12.4M | **62.51** | 02/06 | 5tzFkiKscXHK... | **WHALE** | +| 14 | 1.23% | 12.3M | 21.00 | 07/2024 | BmFdpraQhkiD... | Oldest wallet | +| 15 | 1.17% | 11.7M | 0.34 | 02/07 | AF8VuwCncKd5... | | +| 16 | 1.05% | 10.5M | 15.95 | 02/09 | SELF | | +| 17 | 1.00% | 10.0M | 1.21 | 02/10 | 3WKdQGUpBHVL... | | +| 18 | 1.00% | 10.0M | 0.10 | 02/10 | SELF | Exact 10M = possible round buy | +| 19 | 0.98% | 9.8M | 26.65 | 01/17 | Axiom... | **Axiom user** | +| 20 | 0.95% | 9.5M | 0.01 | 02/13 | is6MTRHEgyFL... | **NEW TODAY** (31 txs only) | + +**Top 20 combined:** ~34.5% of supply (ex pool) + +--- + +## BUNDLER CLUSTER DETECTED + +**Funder:** `ABNL41SwMLVRaCq6okEWsWyvLwm56nazUNwMrTHgmuyf` +- **SOL Balance:** 485.14 SOL (MASSIVE) +- Controls: **Holder #6** (1.86%) + **Holder #8** (1.68%) = **3.54% combined** +- Both wallets created on same day (02/06) +- **IDENTICAL transaction timestamps:** 15:54:04, 15:49:48, 15:48:43, 15:47:59, 14:21:09/11, 14:20:43, 13:59:02 +- This is a coordinated operator running both wallets in parallel +- Funder also recently sent SOL to 2 other wallets (Ab2baa... 9.37 SOL, EcEZQ5... 2.97 SOL) + +**VERDICT: CONFIRMED BUNDLER** — Same operator, synchronized trades, well-funded + +--- + +## SNIPERS ANALYSIS (First 30 Transactions) + +**ALL 30 earliest transactions occurred at EXACTLY 14:46:35-14:47:20 UTC** — within 45 seconds of each other. This was a bot-sniped launch. + +### Key Snipers + +| Wallet | Initial Tokens | Current Holdings | SOL Balance | Status | +|--------|---------------|-----------------|-------------|--------| +| `8w1Zdm1GEz...` | **67,059,397 (6.7%)** | 450,397 (0.05%) | 46.39 | **DUMPED 99.3%** | +| `4ydhY1paBSe...` | 2,157,693 (8 buys!) | 0 | 148.06 | **FULLY SOLD** | +| `CatyeC3LgBx...` | 862,529 (3 buys) | 0 | 69.51 | **FULLY SOLD** | +| `HvFdDWS3Rqy...` | 808,221 (3 buys) | 0 | 455.03 | **FULLY SOLD** | +| `atom2VuiFEhg...` | 0 (3 txs, 0 tokens) | 0 | 185.32 | Deployer/setup? | +| `gtagyESa99t...` | 251,913 | 0 | **1,183.53** | **FULLY SOLD** (mega wallet) | +| `7dGrdJRYtsN...` | 251,913 | 0 | 189.79 | **FULLY SOLD** | +| `HHRE5LtQV3Y...` | 111,617 (0.51 SOL) | 0 | 18.12 | **FULLY SOLD** | + +### Sniper Characteristics +- All are **professional bot wallets** with 1000+ total transactions +- All show SELF as earliest funder (too many txs to trace original source) +- Rich wallets: **1,183 SOL**, 455 SOL, 189 SOL, 185 SOL, 148 SOL +- **Every single early sniper has FULLY EXITED** (bearish signal) + +### Suspected Deployer +`atom2VuiFEhgGSggRokWuXfsZaS6mxHKwKUSFnECshJ` — 3 early txs, 0 tokens received, 185 SOL balance. Likely the wallet that created/deployed the token. + +--- + +## Red Flags Summary + +| Flag | Severity | Detail | +|------|----------|--------| +| All snipers dumped | HIGH | Every early buyer from the first 45 seconds has fully exited | +| Mega sniper dumped 99.3% | HIGH | 6.7% holder → 0.05%, took massive profits | +| Bundler cluster (#6 + #8) | MEDIUM | 3.54% controlled by one entity, synchronized trading | +| Bot-sniped launch | MEDIUM | First 30 txs within 45 seconds, professional bots | +| Dropping price | MEDIUM | -32% in last hour, -18% in last 5 min | +| Many new wallets | LOW | Several top holders created Feb 2026, could be rotation | +| Holder #20 brand new | LOW | Created today, only 31 txs | + +--- + +## Positive Signals + +| Signal | Detail | +|--------|--------| +| SBF catalyst | Legitimate tweet driving organic interest | +| OG token | Created Dec 2024, not a copycat | +| No honeypot detected | Normal buy/sell activity | +| Graduated pump.fun | 100% graduation, legitimate migration | +| Copycats flagged as scams | OG positioned as "the real one" | +| High volume | $890K/24h on $194K MC = 4.6x turnover | + +--- + +## Conclusion + +**FTX 2.0 is the OG token riding the SBF tweet catalyst.** However: +1. It was **heavily bot-sniped at launch** — all early snipers have FULLY DUMPED +2. A **confirmed bundler cluster** controls 3.54% across 2 wallets +3. The mega sniper who held 6.7% dumped 99.3% of their position +4. Price is currently in a **downtrend** (-32% last hour) +5. Top 20 holders collectively hold ~34.5% — moderate concentration + +**The smart money (snipers) has already exited.** Current holders appear to be retail/organic buyers. Exercise extreme caution — the initial pump has been extracted by bots. Any further upside depends on continued SBF narrative and fresh buying pressure. diff --git a/rex_analysis.py b/rex_analysis.py new file mode 100644 index 0000000..87ac5bd --- /dev/null +++ b/rex_analysis.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python3 +"""Quick Rex ($REX / CoinGecko Mascot) holder + bundle check.""" +import json, time +from urllib.request import Request, urlopen +from collections import defaultdict +from datetime import datetime, timezone + +MINT = "HXvQAQwytoLngKWQtge3oJnLHsaLwTxPbX48DctLpump" +RPC = "https://mainnet.helius-rpc.com/?api-key=28d0e718-6052-4054-a8c8-c38c3897ac15" + +def rpc(method, params): + body = json.dumps({"jsonrpc":"2.0","id":1,"method":method,"params":params}).encode() + for i in range(3): + try: + req = Request(RPC, data=body, headers={"Content-Type":"application/json"}) + resp = urlopen(req, timeout=30) + data = json.loads(resp.read()) + return data.get("result") + except Exception as e: + if i < 2: time.sleep(2**i) + return None + +def short(a): return f"{a[:8]}...{a[-6:]}" if len(a)>16 else a + +print("="*80) +print(" REX (CoinGecko Mascot) — QUICK HOLDER + BUNDLE ANALYSIS") +print(f" Mint: {MINT}") +print("="*80) + +# Top holders +result = rpc("getTokenLargestAccounts", [MINT]) +accounts = result["value"][:20] + +holders = [] +for i, acc in enumerate(accounts): + ta = acc["address"] + bal = int(acc["amount"]) / (10**acc["decimals"]) + info = rpc("getAccountInfo", [ta, {"encoding":"jsonParsed"}]) + time.sleep(0.4) + owner = "unknown" + if info and info.get("value"): + p = info["value"].get("data",{}) + if isinstance(p,dict) and "parsed" in p: + owner = p["parsed"].get("info",{}).get("owner","unknown") + + # SOL balance + sb = rpc("getBalance", [owner]) + sol = (sb["value"]/1e9) if sb and "value" in sb else 0 + time.sleep(0.3) + + holders.append({"rank":i+1,"wallet":owner,"ta":ta,"balance":bal,"sol":sol}) + print(f" #{i+1:2d} | {owner:>44s} | {bal:>18,.2f} REX | {sol:>8.2f} SOL") + +total = sum(h["balance"] for h in holders) +print(f"\n Total in top 20: {total:,.2f}") + +# Check token account txs for bundles +print(f"\n Checking for same-slot purchases among top holders...") +slot_map = defaultdict(list) +for h in holders: + sigs = rpc("getSignaturesForAddress", [h["ta"], {"limit":10}]) + time.sleep(0.4) + if sigs: + for s in sigs: + slot_map[s["slot"]].append({"wallet":h["wallet"],"rank":h["rank"],"bal":h["balance"],"sig":s["signature"]}) + +bundles = [(sl,ws) for sl,ws in slot_map.items() if len(ws)>=2] +# Dedupe by unique wallets per slot +real_bundles = [] +for sl, ws in bundles: + unique = {} + for w in ws: + if w["wallet"] not in unique: + unique[w["wallet"]] = w + if len(unique) >= 2: + real_bundles.append((sl, list(unique.values()))) + +if real_bundles: + print(f"\n BUNDLES DETECTED: {len(real_bundles)}") + for sl, ws in real_bundles: + print(f"\n Slot {sl}:") + for w in ws: + print(f" #{w['rank']} {w['wallet']} | {w['bal']:,.2f} REX") +else: + print(" No same-slot bundles among top 20.") + +# Earliest mint txs +print(f"\n Checking earliest mint transactions...") +mint_sigs = rpc("getSignaturesForAddress", [MINT, {"limit":30}]) +time.sleep(0.4) +if mint_sigs: + mint_sigs.sort(key=lambda x: x.get("blockTime",0) or 0) + holder_set = set(h["wallet"] for h in holders) + early_slots = defaultdict(list) + + for sig_info in mint_sigs[:20]: + sig = sig_info["signature"] + bt = sig_info.get("blockTime",0) + slot = sig_info.get("slot",0) + tx = rpc("getTransaction", [sig, {"encoding":"jsonParsed","maxSupportedTransactionVersion":0}]) + time.sleep(0.4) + if not tx: continue + + acct_keys = tx.get("transaction",{}).get("message",{}).get("accountKeys",[]) + buyer = "unknown" + for ak in acct_keys: + if isinstance(ak,dict) and ak.get("signer"): + buyer = ak["pubkey"] + break + + dt_str = datetime.fromtimestamp(bt,tz=timezone.utc).strftime("%H:%M:%S") if bt else "?" + is_top = buyer in holder_set + early_slots[slot].append(buyer) + tag = " <-- TOP HOLDER" if is_top else "" + bundle_tag = " [BUNDLE]" if len(early_slots[slot])>1 else "" + print(f" {dt_str} | Slot {slot} | {buyer}{tag}{bundle_tag}") + +# Concentration analysis +print(f"\n CONCENTRATION:") +top5 = sum(h["balance"] for h in holders[:5]) +top10 = sum(h["balance"] for h in holders[:10]) +print(f" Top 5: {top5:>18,.2f} ({top5/10_000_000_00*100:.1f}% of 1B supply)") +print(f" Top 10: {top10:>18,.2f} ({top10/10_000_000_00*100:.1f}% of 1B supply)") +print(f" Top 20: {total:>18,.2f} ({total/10_000_000_00*100:.1f}% of 1B supply)") + +# Whale check (>10 SOL) +whales = [h for h in holders if h["sol"] > 10] +print(f"\n WHALES (>10 SOL): {len(whales)}") +for w in whales: + print(f" #{w['rank']} {w['wallet']} | {w['sol']:.2f} SOL | {w['balance']:,.2f} REX") + +print(f"\n{'='*80}") diff --git a/run_alpha_pipeline.sh b/run_alpha_pipeline.sh new file mode 100644 index 0000000..da8a1f9 --- /dev/null +++ b/run_alpha_pipeline.sh @@ -0,0 +1,86 @@ +#!/bin/bash +# Alpha Pipeline — Runs the full trending → alpha wallet → cross-reference chain +# Scheduled twice daily: 14:00 CET (US open) and 02:00 CET (US evening) +# +# Pipeline: +# 1. scan_trending_new.py → finds trending tokens, scores them, saves top to scan_queue.json +# 2. alpha_wallet_scanner.py → scans holders of queued tokens, detects alpha wallets +# 3. cross_reference.py --all → cross-refs new alpha wallets against all tracked tokens +# +# Usage: bash run_alpha_pipeline.sh +# bash run_alpha_pipeline.sh --trending-only (skip alpha scan) + +set -euo pipefail + +cd /opt/cute-panel 2>/dev/null || cd "$(dirname "$0")" + +LOG_PREFIX="[$(date '+%Y-%m-%d %H:%M:%S')]" + +echo "$LOG_PREFIX ===============================" +echo "$LOG_PREFIX Alpha Pipeline — Starting" +echo "$LOG_PREFIX ===============================" + +# Source .env +if [ -f .env ]; then + set -a + source .env + set +a +fi + +# Step 1: Trending scan +echo "$LOG_PREFIX Step 1: Scanning trending tokens..." +if python3 scan_trending_new.py 2>&1; then + echo "$LOG_PREFIX Step 1: COMPLETE" +else + echo "$LOG_PREFIX Step 1: FAILED (continuing anyway)" +fi + +# Check if --trending-only flag +if [ "${1:-}" = "--trending-only" ]; then + echo "$LOG_PREFIX Trending-only mode, stopping here." + exit 0 +fi + +# Step 2: Alpha wallet scan on queued tokens +echo "" +echo "$LOG_PREFIX Step 2: Scanning alpha wallets..." +if [ -f memory/scan_queue.json ]; then + if python3 alpha_wallet_scanner.py 2>&1; then + echo "$LOG_PREFIX Step 2: COMPLETE" + else + echo "$LOG_PREFIX Step 2: FAILED or timed out (continuing anyway)" + fi +else + echo "$LOG_PREFIX Step 2: SKIPPED (no scan_queue.json)" +fi + +# Step 3: Cross-reference (only if we have smart wallets) +echo "" +echo "$LOG_PREFIX Step 3: Cross-referencing wallets..." +if [ -f memory/smart_wallets.json ]; then + # Cross-ref the most recently scanned token against all others + if python3 cross_reference.py --all 2>&1; then + echo "$LOG_PREFIX Step 3: COMPLETE" + else + echo "$LOG_PREFIX Step 3: FAILED (non-critical)" + fi +else + echo "$LOG_PREFIX Step 3: SKIPPED (no smart_wallets.json)" +fi + +# Commit results to git (so GitHub Actions / auto_deploy can sync) +echo "" +echo "$LOG_PREFIX Committing results..." +git add memory/ 2>/dev/null || true +if ! git diff --staged --quiet 2>/dev/null; then + git commit -m "Auto: alpha pipeline results $(date -u +%Y-%m-%d_%H:%M)" 2>/dev/null || true + git push origin claude/crypto-intelligence-system-8oO0s 2>/dev/null || true + echo "$LOG_PREFIX Results committed and pushed." +else + echo "$LOG_PREFIX No new results to commit." +fi + +echo "" +echo "$LOG_PREFIX ===============================" +echo "$LOG_PREFIX Alpha Pipeline — DONE" +echo "$LOG_PREFIX ===============================" diff --git a/run_full_scan.sh b/run_full_scan.sh new file mode 100755 index 0000000..9e24a77 --- /dev/null +++ b/run_full_scan.sh @@ -0,0 +1,58 @@ +#!/bin/bash +# Full early buyer scan: scans all CAs via Helius +# Triggered by auto_deploy.sh when scan_trigger.json exists, or run manually +# Usage: bash run_full_scan.sh + +cd /opt/cute-panel 2>/dev/null || cd "$(dirname "$0")" || exit 1 + +# Load env +set -a +source .env 2>/dev/null || true +set +a + +echo "[$(date)] === EARLY BUYER SCAN STARTING ===" + +# Verify Helius +if [ -z "$HELIUS_RPC_URL" ]; then + echo "ERROR: HELIUS_RPC_URL not set" + exit 1 +fi + +HELIUS_TEST=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$HELIUS_RPC_URL" \ + -H "Content-Type: application/json" \ + -d '{"jsonrpc":"2.0","id":1,"method":"getHealth"}' 2>/dev/null) + +if [ "$HELIUS_TEST" != "200" ]; then + echo "ERROR: Helius not accessible (HTTP $HELIUS_TEST). Are you on VPS?" + exit 1 +fi +echo "[$(date)] Helius API OK" + +# Determine token file +TOKENS_FILE="tokens_to_scan.txt" +if [ ! -f "$TOKENS_FILE" ]; then + echo "ERROR: $TOKENS_FILE not found" + exit 1 +fi + +TOKEN_COUNT=$(wc -l < "$TOKENS_FILE") +echo "[$(date)] Scanning $TOKEN_COUNT tokens..." + +# Run the scan (output to log and terminal) +python3 scan_early_buyers.py --file "$TOKENS_FILE" 2>&1 | tee /tmp/scan_output.txt + +# Process results +RESULTS="memory/early_buyer_scan.json" +if [ ! -f "$RESULTS" ]; then + echo "[$(date)] WARNING: No results file generated" + exit 1 +fi + +TOTAL=$(python3 -c "import json; d=json.load(open('$RESULTS')); print(d.get('total_unique_wallets', 0))") +MULTI=$(python3 -c "import json; d=json.load(open('$RESULTS')); print(len(d.get('multi_token_wallets', [])))") +echo "" +echo "[$(date)] === SCAN COMPLETE ===" +echo " Unique wallets: $TOTAL" +echo " Multi-token wallets: $MULTI" + +echo "[$(date)] Done. Results: $RESULTS | Output: /tmp/scan_output.txt" diff --git a/run_intel.sh b/run_intel.sh new file mode 100755 index 0000000..6910d9c --- /dev/null +++ b/run_intel.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# Crypto Intelligence System — Daily Runner +# Runs the full intelligence protocol via Claude Code +# Schedule: Daily at 08:00 Poland time (07:00 UTC in winter, 06:00 UTC in summer) + +cd /home/user/Cute-Panel + +# Load API keys from .env file +if [ -f /home/user/Cute-Panel/.env ]; then + set -a + source /home/user/Cute-Panel/.env + set +a +fi + +DATE=$(date -u +%Y-%m-%d) +echo "[$(date -u)] Starting daily crypto intelligence session for ${DATE}..." + +# Run Claude Code with the intelligence protocol +claude -p "Load all memory files from /home/user/Cute-Panel/memory/. Execute full pre-flight sequence: check previous session state, update all active recommendation prices, check smart wallets, review developing signals. Then run all 6 Grok sub-agents using the Responses API (POST https://api.x.ai/v1/responses with model grok-4-1-fast and tools:[{type:x_search}]) for live X/Twitter intelligence. Run parallel web research across all 6 intelligence domains (market structure, DeFi ecosystem, Solana trenches, alpha hunting, risk scanning, contrarian analysis). Cross-reference Grok social intel against web data. Investigate top findings. Compile full report as crypto_intel_${DATE}.md. Update all memory files. Commit and push to branch claude/crypto-intelligence-system-8oO0s." 2>&1 | tee -a /home/user/Cute-Panel/intel_runner.log + +echo "[$(date -u)] Daily cycle complete." diff --git a/run_scan_now.py b/run_scan_now.py new file mode 100644 index 0000000..40accb1 --- /dev/null +++ b/run_scan_now.py @@ -0,0 +1,494 @@ +#!/usr/bin/env python3 +""" +Patched trending scanner runner. +Fixes: SSL context for DexScreener, curl for Grok API, returns top 15. +""" + +import json +import os +import re +import ssl +import subprocess +import sys +import time +from datetime import datetime, timezone +from urllib.request import Request, urlopen + +SCRIPT_DIR = "/home/user/Cute-Panel" + +# Load env +env_path = os.path.join(SCRIPT_DIR, '.env') +if os.path.exists(env_path): + with open(env_path) as f: + for line in f: + line = line.strip() + if '=' in line and not line.startswith('#'): + key, val = line.split('=', 1) + os.environ[key] = val + +XAI_API_KEY = os.environ.get('XAI_API_KEY', '') +HELIUS_RPC = os.environ.get('HELIUS_RPC_URL', '') + +TOKENS_FILE = os.path.join(SCRIPT_DIR, 'memory', 'tokens.json') +TRENDING_LOG = os.path.join(SCRIPT_DIR, 'memory', 'trending_scans.jsonl') +SCAN_QUEUE = os.path.join(SCRIPT_DIR, 'memory', 'scan_queue.json') + +# SSL context for DexScreener (proxy issues) +ssl_ctx = ssl.create_default_context() +ssl_ctx.check_hostname = False +ssl_ctx.verify_mode = ssl.CERT_NONE + + +def http_get(url, timeout=15, use_ssl_ctx=False): + """GET request with error handling.""" + try: + req = Request(url, headers={ + 'Accept': 'application/json', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' + }) + ctx = ssl_ctx if use_ssl_ctx else None + with urlopen(req, timeout=timeout, context=ctx) as resp: + return json.loads(resp.read()) + except Exception as e: + print(f" HTTP error for {url[:80]}: {e}") + return None + + +def grok_curl(query, timeout=120): + """Call Grok API via curl (Python urlopen gets 403 from proxy).""" + if not XAI_API_KEY: + return None + payload = json.dumps({ + "model": "grok-4-1-fast", + "tools": [{"type": "x_search"}], + "input": query, + }) + try: + result = subprocess.run( + ["curl", "-s", "-X", "POST", "https://api.x.ai/v1/responses", + "-H", "Content-Type: application/json", + "-H", f"Authorization: Bearer {XAI_API_KEY}", + "-d", payload], + capture_output=True, text=True, timeout=timeout + ) + if result.returncode == 0 and result.stdout: + return json.loads(result.stdout) + except Exception as e: + print(f" Grok curl error: {e}") + return None + + +# ===== SOURCE 1: DexScreener Boosted Tokens ===== +def scan_dexscreener_boosts(): + print("\n[1/5] DexScreener Boosted Tokens...") + data = http_get("https://api.dexscreener.com/token-boosts/top/v1", use_ssl_ctx=True) + if not data: + return [] + tokens = [] + for t in data: + if t.get('chainId') != 'solana': + continue + ca = t.get('tokenAddress', '') + if not ca: + continue + tokens.append({ + 'ca': ca, + 'source': 'dexscreener_boost', + 'boost_amount': t.get('totalAmount', 0), + }) + print(f" Found {len(tokens)} Solana boosted tokens") + return tokens[:25] + + +# ===== SOURCE 2: DexScreener Token Profiles ===== +def scan_dexscreener_profiles(): + print("\n[2/5] DexScreener Token Profiles...") + data = http_get("https://api.dexscreener.com/token-profiles/latest/v1", use_ssl_ctx=True) + if not data: + return [] + tokens = [] + for t in data: + if t.get('chainId') != 'solana': + continue + ca = t.get('tokenAddress', '') + if not ca: + continue + tokens.append({ + 'ca': ca, + 'source': 'dexscreener_profile', + 'has_links': bool(t.get('links')), + }) + print(f" Found {len(tokens)} Solana profiles") + return tokens[:25] + + +# ===== SOURCE 3: GeckoTerminal Trending Pools ===== +def scan_gecko_trending(): + print("\n[3/5] GeckoTerminal Trending Pools (Solana)...") + data = http_get("https://api.geckoterminal.com/api/v2/networks/solana/trending_pools?page=1") + if not data: + return [] + tokens = [] + for p in data.get('data', []): + attr = p.get('attributes', {}) + name = attr.get('name', '') + vol_24h = 0 + try: + vol_24h = float(attr.get('volume_usd', {}).get('h24', 0) or 0) + except (TypeError, ValueError): + pass + rels = p.get('relationships', {}) + base = rels.get('base_token', {}).get('data', {}).get('id', '') + ca = base.replace('solana_', '') if base.startswith('solana_') else '' + if not ca: + continue + tokens.append({ + 'ca': ca, + 'source': 'geckoterminal_trending', + 'name': name, + 'vol_24h': vol_24h, + }) + print(f" Found {len(tokens)} trending pools") + return tokens[:25] + + +# ===== SOURCE 4: GeckoTerminal New Pools ===== +def scan_gecko_new_pools(): + print("\n[4/5] GeckoTerminal New Pools (Solana)...") + data = http_get("https://api.geckoterminal.com/api/v2/networks/solana/new_pools?page=1") + if not data: + return [] + tokens = [] + for p in data.get('data', []): + attr = p.get('attributes', {}) + name = attr.get('name', '') + vol_24h = 0 + try: + vol_24h = float(attr.get('volume_usd', {}).get('h24', 0) or 0) + except (TypeError, ValueError): + pass + rels = p.get('relationships', {}) + base = rels.get('base_token', {}).get('data', {}).get('id', '') + ca = base.replace('solana_', '') if base.startswith('solana_') else '' + if not ca: + continue + if vol_24h < 30000: + continue + tokens.append({ + 'ca': ca, + 'source': 'geckoterminal_new', + 'name': name, + 'vol_24h': vol_24h, + }) + print(f" Found {len(tokens)} new pools with >$30K vol") + return tokens[:25] + + +# ===== SOURCE 5: Grok X Search ===== +def scan_grok_x_trending(): + if not XAI_API_KEY: + print("\n[5/5] Grok X Search... SKIPPED (no API key)") + return [] + + print("\n[5/5] Grok X Search for trending Solana memecoins...") + + queries = [ + "Search X for the top 10 trending Solana memecoins being discussed RIGHT NOW (last 6 hours). For each token provide: token name/ticker, contract address (CA) if mentioned, approximate market cap. Focus on NEW tokens launched in last 48 hours with organic buzz, not established tokens like SOL JUP BONK. Include pump.fun launches that are trending.", + "Search X for 'solana CA' OR 'new solana gem' OR 'pump fun trending' OR 'king of the hill' from last 6 hours. Find specific Solana contract addresses being shared. List every CA you find with token name.", + ] + + all_tokens = [] + for qi, q in enumerate(queries): + print(f" Grok query {qi+1}/{len(queries)}...") + resp = grok_curl(q) + if not resp: + print(f" No response from Grok") + continue + + # Extract text from response + text = resp.get('output_text', '') + if not text: + for out in resp.get('output', []): + if out.get('type') == 'message' and out.get('role') == 'assistant': + for c in out.get('content', []): + if c.get('type') in ('output_text', 'text'): + text = c.get('text', '') + break + + if text: + # Extract Solana CAs (base58, 32-44 chars) + cas = re.findall(r'\b([1-9A-HJ-NP-Za-km-z]{32,44})\b', text) + # Filter known system addresses + skip = { + 'TokenkegQfeE2cNFBpZjxo3WcsKrpLBCq4SzZhScigCZ', + 'So11111111111111111111111111111111111111112', + 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL', + '11111111111111111111111111111111', + } + for ca in cas: + if len(ca) >= 32 and ca not in skip: + all_tokens.append({ + 'ca': ca, + 'source': 'grok_x_search', + }) + print(f" Found {len(cas)} potential CAs in response") + # Also print a snippet of the response + print(f" Response snippet: {text[:300]}...") + time.sleep(3) + + # Deduplicate + seen = set() + unique = [] + for t in all_tokens: + if t['ca'] not in seen: + seen.add(t['ca']) + unique.append(t) + + print(f" Total unique CAs from X: {len(unique)}") + return unique[:30] + + +# ===== ENRICHMENT ===== +def enrich_token(ca): + """Get token details from DexScreener.""" + data = http_get(f"https://api.dexscreener.com/tokens/v1/solana/{ca}", use_ssl_ctx=True) + if not data or not isinstance(data, list) or len(data) == 0: + return None + p = data[0] + bt = p.get('baseToken', {}) + mc = p.get('marketCap') or p.get('fdv') or 0 + liq = (p.get('liquidity') or {}).get('usd', 0) or 0 + vol_24h = (p.get('volume') or {}).get('h24', 0) or 0 + age_ms = 0 + created = p.get('pairCreatedAt') + if created: + age_ms = int(time.time() * 1000) - created + txns = p.get('txns', {}).get('h24', {}) + buys = txns.get('buys', 0) or 0 + sells = txns.get('sells', 0) or 0 + return { + 'symbol': bt.get('symbol', 'UNKNOWN'), + 'name': bt.get('name', 'Unknown'), + 'ca': ca, + 'mc': mc, + 'liquidity': liq, + 'vol_24h': vol_24h, + 'buys_24h': buys, + 'sells_24h': sells, + 'age_hours': age_ms / (1000 * 3600) if age_ms else 0, + 'price_usd': float(p.get('priceUsd', 0) or 0), + 'price_change_24h': (p.get('priceChange') or {}).get('h24', 0) or 0, + } + + +# ===== SCORING ===== +def score_token(token_info, source_list): + score = 0 + mc = token_info.get('mc', 0) or 0 + liq = token_info.get('liquidity', 0) or 0 + vol = token_info.get('vol_24h', 0) or 0 + age = token_info.get('age_hours', 0) or 0 + buys = token_info.get('buys_24h', 0) or 0 + sells = token_info.get('sells_24h', 0) or 0 + + # MC sweet spot + if 50_000 <= mc <= 500_000: + score += 30 + elif 500_000 < mc <= 5_000_000: + score += 20 + elif mc > 5_000_000: + score += 5 + + # Liquidity + if liq >= 50_000: + score += 15 + elif liq >= 10_000: + score += 5 + else: + score -= 20 + + # Volume/MC ratio + if mc > 0: + vmr = vol / mc + if vmr > 0.5: + score += 20 + elif vmr > 0.2: + score += 10 + + # Age + if 2 <= age <= 48: + score += 25 + elif 48 < age <= 168: + score += 10 + elif age < 2: + score += 5 + + # Buy/sell ratio + if buys > 0 and sells > 0: + ratio = buys / sells + if ratio > 1.5: + score += 15 + elif ratio > 1.0: + score += 5 + elif ratio < 0.5: + score -= 10 + + # Multi-source bonus + sources = set(s.get('source', '') for s in source_list) + if len(sources) >= 3: + score += 25 + elif len(sources) >= 2: + score += 15 + if 'grok_x_search' in sources: + score += 10 + + # Boost amount + for s in source_list: + boost = s.get('boost_amount', 0) or 0 + if boost >= 500: + score += 10 + elif boost >= 200: + score += 5 + + return score + + +# ===== MAIN ===== +def main(): + now = datetime.now(timezone.utc) + print(f"{'='*70}") + print(f" TRENDING TOKEN SCAN - {now.strftime('%Y-%m-%d %H:%M UTC')}") + print(f"{'='*70}") + + # Phase 1: Gather from all 5 sources + all_raw = [] + + results = scan_dexscreener_boosts() + all_raw.extend(results) + time.sleep(1) + + results = scan_dexscreener_profiles() + all_raw.extend(results) + time.sleep(1) + + results = scan_gecko_trending() + all_raw.extend(results) + time.sleep(1) + + results = scan_gecko_new_pools() + all_raw.extend(results) + time.sleep(1) + + results = scan_grok_x_trending() + all_raw.extend(results) + + # Deduplicate by CA, merge sources + ca_map = {} + for t in all_raw: + ca = t['ca'] + if ca not in ca_map: + ca_map[ca] = [] + ca_map[ca].append(t) + + print(f"\n{'='*70}") + print(f" PHASE 2: ENRICHMENT") + print(f"{'='*70}") + print(f"Total unique CAs collected: {len(ca_map)}") + + # Phase 2: Enrich all tokens via DexScreener + enriched = [] + total = min(len(ca_map), 60) # limit API calls + for i, (ca, sources) in enumerate(list(ca_map.items())[:60]): + if (i+1) % 10 == 0 or i == 0: + print(f" Enriching {i+1}/{total}...") + info = enrich_token(ca) + if info and info.get('mc', 0) > 0: + info['sources'] = sources + info['source_names'] = list(set(s.get('source', '') for s in sources)) + info['source_count'] = len(info['source_names']) + info['score'] = score_token(info, sources) + enriched.append(info) + time.sleep(0.4) + + # Sort by score + enriched.sort(key=lambda x: x.get('score', 0), reverse=True) + top15 = enriched[:15] + + # Print results + print(f"\n{'='*70}") + print(f" TOP 15 TRENDING TOKENS (sorted by score)") + print(f"{'='*70}") + print(f"{'#':<3} {'Symbol':<12} {'MC':>12} {'Liq':>10} {'Vol24h':>12} {'Age':>8} {'B/S':>6} {'Srcs':>4} {'Score':>5}") + print(f"{'-'*3} {'-'*12} {'-'*12} {'-'*10} {'-'*12} {'-'*8} {'-'*6} {'-'*4} {'-'*5}") + + for i, t in enumerate(top15): + mc_str = f"${t['mc']:,.0f}" if t['mc'] else "$0" + liq_str = f"${t['liquidity']:,.0f}" if t['liquidity'] else "$0" + vol_str = f"${t['vol_24h']:,.0f}" if t['vol_24h'] else "$0" + age = t.get('age_hours', 0) + age_str = f"{age:.0f}h" if age < 48 else f"{age/24:.1f}d" + buys = t.get('buys_24h', 0) + sells = t.get('sells_24h', 0) + bs_str = f"{buys/sells:.1f}" if sells > 0 else "N/A" + src = t.get('source_count', 1) + score = t.get('score', 0) + + print(f"{i+1:<3} ${t['symbol']:<11} {mc_str:>12} {liq_str:>10} {vol_str:>12} {age_str:>8} {bs_str:>6} {src:>4} {score:>5}") + print(f" CA: {t['ca']}") + print(f" Sources: {', '.join(t.get('source_names', []))}") + if t.get('price_change_24h'): + print(f" 24h Change: {t['price_change_24h']}%") + print() + + # Save scan queue + queue = { + 'queued_at': now.isoformat(), + 'tokens': [{ + 'ca': t['ca'], + 'symbol': t['symbol'], + 'name': t['name'], + 'mc': t['mc'], + 'liquidity': t['liquidity'], + 'vol_24h': t['vol_24h'], + 'score': t['score'], + 'source_count': t.get('source_count', 1), + 'source_names': t.get('source_names', []), + 'age_hours': t.get('age_hours', 0), + 'buys_24h': t.get('buys_24h', 0), + 'sells_24h': t.get('sells_24h', 0), + } for t in top15], + } + os.makedirs(os.path.dirname(SCAN_QUEUE), exist_ok=True) + with open(SCAN_QUEUE, 'w') as f: + json.dump(queue, f, indent=2) + print(f"Scan queue saved to {SCAN_QUEUE}") + + # Append to trending log + log_entry = { + 'timestamp': now.isoformat(), + 'total_cas': len(ca_map), + 'enriched': len(enriched), + 'top15': [{'symbol': t['symbol'], 'ca': t['ca'], 'mc': t['mc'], 'score': t['score']} for t in top15], + } + with open(TRENDING_LOG, 'a') as f: + f.write(json.dumps(log_entry) + '\n') + + # Summary stats + print(f"\n{'='*70}") + print(f" SCAN SUMMARY") + print(f"{'='*70}") + src_counts = {} + for t in all_raw: + s = t.get('source', 'unknown') + src_counts[s] = src_counts.get(s, 0) + 1 + for src, cnt in sorted(src_counts.items()): + print(f" {src}: {cnt} tokens") + print(f" Total unique CAs: {len(ca_map)}") + print(f" Successfully enriched: {len(enriched)}") + print(f" Top 15 avg score: {sum(t['score'] for t in top15)/len(top15):.1f}" if top15 else " No tokens found") + + return top15 + + +if __name__ == "__main__": + main() diff --git a/run_scan_rpc.py b/run_scan_rpc.py new file mode 100644 index 0000000..0bda597 --- /dev/null +++ b/run_scan_rpc.py @@ -0,0 +1,281 @@ +#!/usr/bin/env python3 +""" +RPC-Only Wallet Scanner — scans known alpha wallets for their token trades. +Uses standard Solana JSON-RPC via Helius RPC endpoint (mainnet.helius-rpc.com). +Much more efficient than scanning mints (wallets have 100s of txs, not 100Ks). +""" +import json, sys, os, time +from datetime import datetime, timezone +from urllib.request import Request, urlopen +from collections import defaultdict + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) +env_path = os.path.join(SCRIPT_DIR, '.env') +if os.path.exists(env_path): + with open(env_path) as f: + for line in f: + line = line.strip() + if '=' in line and not line.startswith('#'): + key, val = line.split('=', 1) + os.environ[key] = val + +HELIUS_RPC = os.environ.get('HELIUS_RPC_URL', '') +SMART_WALLETS_FILE = os.path.join(SCRIPT_DIR, 'memory', 'smart_wallets.json') +TOKENS_REGISTRY = os.path.join(SCRIPT_DIR, 'memory', 'tokens.json') +RESULTS_FILE = os.path.join(SCRIPT_DIR, 'memory', 'wallet_scan_results.json') + +SOL_MINT = 'So11111111111111111111111111111111111111112' +IGNORE_MINTS = {SOL_MINT, 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB'} + + +def rpc_call(method, params, retries=4): + data = json.dumps({"jsonrpc": "2.0", "id": 1, "method": method, "params": params}).encode() + for attempt in range(retries): + try: + req = Request(HELIUS_RPC, data=data, headers={'Content-Type': 'application/json'}) + with urlopen(req, timeout=30) as resp: + result = json.loads(resp.read()) + if 'error' in result: + return None + return result.get('result') + except Exception as e: + wait = 3 * (2 ** attempt) + if attempt < retries - 1: + time.sleep(wait) + else: + print(f" RPC failed: {e}") + return None + + +def get_token_accounts(wallet): + """Get all SPL token accounts for a wallet.""" + accounts = [] + for program in ["TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"]: + result = rpc_call("getTokenAccountsByOwner", [ + wallet, {"programId": program}, {"encoding": "jsonParsed"} + ]) + if result and 'value' in result: + for acct in result['value']: + info = acct.get('account', {}).get('data', {}).get('parsed', {}).get('info', {}) + mint = info.get('mint', '') + amount = info.get('tokenAmount', {}) + if mint and mint not in IGNORE_MINTS: + accounts.append({ + 'mint': mint, + 'balance': float(amount.get('uiAmountString', '0') or '0'), + 'decimals': amount.get('decimals', 0), + }) + time.sleep(1) + return accounts + + +def get_sol_balance(wallet): + result = rpc_call("getBalance", [wallet]) + if result and 'value' in result: + return result['value'] / 1e9 + return 0 + + +def parse_tx_tokens(tx_result, wallet): + """Parse a transaction to find token buys/sells by a specific wallet.""" + if not tx_result: + return None + meta = tx_result.get('meta', {}) + if meta.get('err'): + return None + + pre_tb = meta.get('preTokenBalances', []) + post_tb = meta.get('postTokenBalances', []) + ts = tx_result.get('blockTime', 0) + + pre_by_mint = {} + post_by_mint = {} + for tb in pre_tb: + if tb.get('owner') == wallet: + pre_by_mint[tb.get('mint', '')] = float(tb.get('uiTokenAmount', {}).get('uiAmountString', '0') or '0') + for tb in post_tb: + if tb.get('owner') == wallet: + post_by_mint[tb.get('mint', '')] = float(tb.get('uiTokenAmount', {}).get('uiAmountString', '0') or '0') + + changes = [] + all_mints = set(pre_by_mint.keys()) | set(post_by_mint.keys()) + for mint in all_mints: + if mint in IGNORE_MINTS: + continue + pre_amt = pre_by_mint.get(mint, 0) + post_amt = post_by_mint.get(mint, 0) + diff = post_amt - pre_amt + if abs(diff) > 0: + changes.append({ + 'mint': mint, + 'change': diff, + 'action': 'buy' if diff > 0 else 'sell', + 'timestamp': ts, + }) + return changes if changes else None + + +def dexscreener_batch(mints): + """Get DexScreener info for multiple mints.""" + info = {} + for batch_start in range(0, len(mints), 25): + batch = mints[batch_start:batch_start + 25] + addresses = ','.join(batch) + try: + url = f"https://api.dexscreener.com/tokens/v1/solana/{addresses}" + req = Request(url, headers={'Accept': 'application/json', 'User-Agent': 'Mozilla/5.0'}) + with urlopen(req, timeout=15) as resp: + pairs = json.loads(resp.read()) + if isinstance(pairs, list): + for p in pairs: + mint = p.get('baseToken', {}).get('address', '') + if mint and mint not in info: + info[mint] = { + 'symbol': p.get('baseToken', {}).get('symbol', 'UNKNOWN'), + 'name': p.get('baseToken', {}).get('name', 'Unknown'), + 'mc': p.get('marketCap') or p.get('fdv') or 0, + 'price_usd': float(p.get('priceUsd', '0') or '0'), + 'liq': (p.get('liquidity') or {}).get('usd') or 0, + } + except Exception as e: + print(f" DexScreener error: {e}") + time.sleep(1) + return info + + +def scan_wallet(wallet_addr, label=""): + """Full scan: holdings + recent trades.""" + print(f"\n {'='*55}") + print(f" {label} | {wallet_addr[:32]}...") + print(f" {'='*55}") + + sol = get_sol_balance(wallet_addr) + time.sleep(1) + tokens = get_token_accounts(wallet_addr) + held = [t for t in tokens if t['balance'] > 0] + print(f" SOL: {sol:.4f} | Holdings: {len(held)} tokens") + + # Get recent sigs + sigs = rpc_call("getSignaturesForAddress", [wallet_addr, {"limit": 50}]) or [] + time.sleep(1) + print(f" Recent txs: {len(sigs)}") + + # Parse recent txs + trades = [] + for i, sig_info in enumerate(sigs[:25]): + tx_result = rpc_call("getTransaction", [sig_info['signature'], {"encoding": "jsonParsed", "maxSupportedTransactionVersion": 0}]) + if tx_result: + changes = parse_tx_tokens(tx_result, wallet_addr) + if changes: + trades.extend(changes) + time.sleep(1.5) + if (i + 1) % 10 == 0: + print(f" ...parsed {i+1}/25 txs") + + # Aggregate trades by mint + trade_summary = defaultdict(lambda: {'buys': 0, 'sells': 0, 'buy_count': 0, 'sell_count': 0, 'last_ts': 0}) + for t in trades: + mint = t['mint'] + ts = t.get('timestamp', 0) + if t['action'] == 'buy': + trade_summary[mint]['buys'] += t['change'] + trade_summary[mint]['buy_count'] += 1 + else: + trade_summary[mint]['sells'] += abs(t['change']) + trade_summary[mint]['sell_count'] += 1 + if ts and ts > trade_summary[mint]['last_ts']: + trade_summary[mint]['last_ts'] = ts + + # DexScreener lookup + all_mints = list(set([t['mint'] for t in held] + list(trade_summary.keys()))) + dex_info = dexscreener_batch(all_mints) if all_mints else {} + + # Print holdings + if held: + print(f"\n Holdings:") + for t in sorted(held, key=lambda x: x['balance'], reverse=True)[:15]: + info = dex_info.get(t['mint'], {}) + sym = info.get('symbol', t['mint'][:10]) + mc = info.get('mc', 0) + price = info.get('price_usd', 0) + val = t['balance'] * price if price else 0 + print(f" ${sym:<12} {t['balance']:>14,.2f} MC: ${mc:>10,.0f} Val: ${val:>8,.0f}") + + # Print recent trades + if trade_summary: + print(f"\n Recent Trades:") + for mint, data in sorted(trade_summary.items(), key=lambda x: x[1]['last_ts'], reverse=True)[:10]: + info = dex_info.get(mint, {}) + sym = info.get('symbol', mint[:12]) + ts_str = datetime.fromtimestamp(data['last_ts'], tz=timezone.utc).strftime("%m-%d %H:%M") if data['last_ts'] else "?" + print(f" ${sym:<12} {data['buy_count']}B/{data['sell_count']}S buys:{data['buys']:>12,.0f} sells:{data['sells']:>12,.0f} last:{ts_str}") + + return { + 'wallet': wallet_addr, 'label': label, 'sol_balance': sol, + 'holdings': [{**t, 'info': dex_info.get(t['mint'], {})} for t in held], + 'trade_summary': {m: {**d, 'info': dex_info.get(m, {})} for m, d in trade_summary.items()}, + 'total_trades': len(trades), 'unique_tokens_traded': len(trade_summary), + } + + +def main(): + if not HELIUS_RPC: + print("ERROR: HELIUS_RPC_URL not set") + sys.exit(1) + + with open(SMART_WALLETS_FILE) as f: + sw = json.load(f) + + wallets = [w for w in sw.get('wallets', []) + if w.get('address', 'unknown') != 'unknown' and w.get('chain') == 'solana'] + + if len(sys.argv) > 1: + wallets = [{'address': sys.argv[1], 'label': 'Manual'}] + + print(f"{'='*60}") + print(f" WALLET SCANNER (RPC-Only)") + print(f" {len(wallets)} wallets | {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M UTC')}") + print(f"{'='*60}") + + all_results = [] + + for w in wallets: + result = scan_wallet(w['address'], w.get('label', '')) + all_results.append(result) + time.sleep(2) + + # Cross-reference + print(f"\n{'='*60}") + print(f" CROSS-REFERENCE: Tokens across wallets") + print(f"{'='*60}") + + mint_wallets = defaultdict(list) + for r in all_results: + for h in r.get('holdings', []): + if r['label'] not in mint_wallets[h['mint']]: + mint_wallets[h['mint']].append(r['label']) + for m in r.get('trade_summary', {}).keys(): + if r['label'] not in mint_wallets[m]: + mint_wallets[m].append(r['label']) + + shared = {m: ws for m, ws in mint_wallets.items() if len(ws) >= 2} + if shared: + shared_info = dexscreener_batch(list(shared.keys())) + for mint, ws in sorted(shared.items(), key=lambda x: len(x[1]), reverse=True)[:10]: + info = shared_info.get(mint, {}) + sym = info.get('symbol', mint[:12]) + mc = info.get('mc', 0) + print(f" ${sym} (MC: ${mc:,.0f}) — {len(ws)} wallets: {', '.join(ws)}") + else: + print(" No shared tokens found") + + # Save + os.makedirs(os.path.dirname(RESULTS_FILE), exist_ok=True) + with open(RESULTS_FILE, 'w') as f: + json.dump({'scan_date': datetime.now(timezone.utc).isoformat(), 'results': all_results, 'shared': {m: ws for m, ws in shared.items()} if shared else {}}, f, indent=2, default=str) + print(f"\n Saved: {RESULTS_FILE}") + print(f" DONE") + + +if __name__ == "__main__": + main() diff --git a/scan_60min_whales.py b/scan_60min_whales.py new file mode 100644 index 0000000..bb88f97 --- /dev/null +++ b/scan_60min_whales.py @@ -0,0 +1,294 @@ +#!/usr/bin/env python3 +"""Scan ALL Solana wallets for last 60-minute activity. Find accumulators & whales.""" + +import json +import time +import sys +from urllib.request import Request, urlopen +from urllib.error import URLError, HTTPError +from datetime import datetime, timezone +from collections import defaultdict + +# Load env +RPC_URL = None +with open("/home/user/Cute-Panel/.env") as f: + for line in f: + if line.startswith("HELIUS_RPC_URL="): + RPC_URL = line.strip().split("=", 1)[1] + break + +if not RPC_URL: + print("ERROR: HELIUS_RPC_URL not found in .env") + sys.exit(1) + +# Load wallets +with open("/home/user/Cute-Panel/memory/smart_wallets.json") as f: + data = json.load(f) + +# Get ALL Solana wallets +solana_wallets = [] +for w in data["wallets"]: + if w.get("chain") != "solana": + continue + if w.get("address", "unknown") == "unknown": + continue + score = w.get("alpha_score", 0) or (w.get("reliability_score", 0) or 0) * 15 + solana_wallets.append({ + "address": w["address"], + "label": w["label"], + "score": score + }) + +solana_wallets.sort(key=lambda x: x["score"], reverse=True) +print(f"Scanning {len(solana_wallets)} Solana wallets for last 60min activity...") +print(f"Current time: {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M UTC')}") +print() + +SIXTY_MIN_AGO = time.time() - 3600 + +def rpc_call(method, params): + payload = json.dumps({ + "jsonrpc": "2.0", + "id": 1, + "method": method, + "params": params + }).encode() + req = Request(RPC_URL, data=payload, headers={"Content-Type": "application/json"}) + try: + resp = urlopen(req, timeout=30) + result = json.loads(resp.read()) + if "error" in result: + return None + return result.get("result") + except (URLError, HTTPError): + return None + +# Track all recent activity +recent_buys = [] # {wallet, label, mint, amount, block_time, is_new} +recent_sells = [] +token_activity = defaultdict(lambda: {"buys": [], "sells": [], "total_buy_amount": 0, "total_sell_amount": 0}) +wallet_activity = defaultdict(lambda: {"buys": 0, "sells": 0, "tokens_touched": set()}) + +for wi, wallet in enumerate(solana_wallets): + addr = wallet["address"] + label = wallet["label"] + + time.sleep(0.4) + sigs_result = rpc_call("getSignaturesForAddress", [addr, {"limit": 10}]) + + if not sigs_result: + continue + + # Filter to last 60min only + recent_sigs = [s for s in sigs_result if s.get("blockTime", 0) > SIXTY_MIN_AGO] + + if not recent_sigs: + sys.stdout.write(f" [{wi+1}/{len(solana_wallets)}] {label}: no recent txs\r") + sys.stdout.flush() + continue + + print(f" [{wi+1}/{len(solana_wallets)}] {label}: {len(recent_sigs)} txs in last 60min") + + for sig_info in recent_sigs[:5]: + sig = sig_info["signature"] + block_time = sig_info.get("blockTime", 0) + tx_time = datetime.fromtimestamp(block_time, tz=timezone.utc).strftime("%H:%M UTC") if block_time else "?" + + time.sleep(0.4) + tx_result = rpc_call("getTransaction", [sig, {"encoding": "jsonParsed", "maxSupportedTransactionVersion": 0}]) + + if not tx_result: + continue + + meta = tx_result.get("meta", {}) + if not meta: + continue + + pre_balances = meta.get("preTokenBalances", []) + post_balances = meta.get("postTokenBalances", []) + + pre_map = {} + for b in pre_balances: + owner = b.get("owner", "") + mint = b.get("mint", "") + amount = float(b.get("uiTokenAmount", {}).get("uiAmount") or 0) + pre_map[(owner, mint)] = amount + + post_map = {} + for b in post_balances: + owner = b.get("owner", "") + mint = b.get("mint", "") + amount = float(b.get("uiTokenAmount", {}).get("uiAmount") or 0) + post_map[(owner, mint)] = amount + + all_mints = set() + for (owner, mint) in list(pre_map.keys()) + list(post_map.keys()): + if owner == addr: + all_mints.add(mint) + + for mint in all_mints: + if mint == "So11111111111111111111111111111111111111112": + continue + + pre_amt = pre_map.get((addr, mint), 0) + post_amt = post_map.get((addr, mint), 0) + change = post_amt - pre_amt + + if abs(change) < 0.000001: + continue + + is_new = (pre_amt == 0 and post_amt > 0) + is_full_sell = (post_amt == 0 and pre_amt > 0) + action = "BUY" if change > 0 else "SELL" + + entry = { + "wallet": addr, + "label": label, + "score": wallet["score"], + "mint": mint, + "action": action, + "pre_amount": pre_amt, + "post_amount": post_amt, + "change": change, + "is_new_position": is_new, + "is_full_sell": is_full_sell, + "block_time": block_time, + "time_str": tx_time, + "tx_sig": sig + } + + if action == "BUY": + recent_buys.append(entry) + token_activity[mint]["buys"].append(entry) + token_activity[mint]["total_buy_amount"] += abs(change) + else: + recent_sells.append(entry) + token_activity[mint]["sells"].append(entry) + token_activity[mint]["total_sell_amount"] += abs(change) + + wallet_activity[addr]["buys" if action == "BUY" else "sells"] += 1 + wallet_activity[addr]["tokens_touched"].add(mint) + wallet_activity[addr]["label"] = label + + flag = "" + if is_new: flag = " [NEW POS]" + elif is_full_sell: flag = " [FULL EXIT]" + print(f" {action} {mint[:24]}... | {change:+.2f} | {tx_time}{flag}") + +# === RESULTS === +print(f"\n{'='*70}") +print(f"=== LAST 60 MINUTES ACTIVITY REPORT ===") +print(f"{'='*70}") +print(f"Total BUYs: {len(recent_buys)} | Total SELLs: {len(recent_sells)}") +print(f"Unique tokens: {len(token_activity)}") +print(f"Active wallets: {len(wallet_activity)}") + +# Accumulators: wallets with multiple buys or large buys +print(f"\n--- TOP ACCUMULATORS (wallets buying) ---") +accumulators = [] +for addr, activity in wallet_activity.items(): + if activity["buys"] > 0: + accumulators.append({ + "address": addr, + "label": activity["label"], + "buy_count": activity["buys"], + "sell_count": activity["sells"], + "tokens": list(activity["tokens_touched"]) + }) + +accumulators.sort(key=lambda x: x["buy_count"], reverse=True) +for acc in accumulators: + ratio = "PURE BUY" if acc["sell_count"] == 0 else f"B/S: {acc['buy_count']}/{acc['sell_count']}" + print(f" {acc['label']}: {acc['buy_count']} buys ({ratio})") + for mint in acc["tokens"]: + # Find buy entries for this wallet+token + buys_for = [b for b in recent_buys if b["wallet"] == acc["address"] and b["mint"] == mint] + sells_for = [s for s in recent_sells if s["wallet"] == acc["address"] and s["mint"] == mint] + buy_total = sum(b["change"] for b in buys_for) + sell_total = sum(abs(s["change"]) for s in sells_for) + new_flag = " [BRAND NEW]" if any(b["is_new_position"] for b in buys_for) else "" + print(f" Token: {mint}") + if buy_total > 0: + print(f" Bought: +{buy_total:,.2f}{new_flag}") + if sell_total > 0: + print(f" Sold: -{sell_total:,.2f}") + +# Tokens with multi-wallet interest +print(f"\n--- CONVERGENCE: Tokens bought by 2+ wallets ---") +convergence_tokens = [] +for mint, data in token_activity.items(): + unique_buyers = set(b["wallet"] for b in data["buys"]) + if len(unique_buyers) >= 2: + convergence_tokens.append({ + "mint": mint, + "buyer_count": len(unique_buyers), + "buyers": [{"label": b["label"], "time": b["time_str"], "change": b["change"]} for b in data["buys"]], + "total_bought": data["total_buy_amount"] + }) + +convergence_tokens.sort(key=lambda x: x["buyer_count"], reverse=True) +if convergence_tokens: + for ct in convergence_tokens: + print(f"\n *** {ct['mint']} ***") + print(f" Bought by {ct['buyer_count']} wallets:") + for b in ct["buyers"]: + print(f" - {b['label']} at {b['time']} (+{b['change']:,.2f})") +else: + print(" No multi-wallet convergence in last 60 min.") + +# Whale moves: largest single transactions +print(f"\n--- WHALE MOVES (largest transactions) ---") +all_moves = recent_buys + recent_sells +all_moves.sort(key=lambda x: abs(x["change"]), reverse=True) +for move in all_moves[:15]: + direction = "BOUGHT" if move["action"] == "BUY" else "SOLD" + flag = "" + if move.get("is_new_position"): flag = " [NEW POS]" + if move.get("is_full_sell"): flag = " [FULL EXIT]" + print(f" {move['label']} {direction} {abs(move['change']):,.2f} of {move['mint'][:30]}... at {move['time_str']}{flag}") + +# New positions (brand new entries) +print(f"\n--- BRAND NEW POSITIONS ---") +new_positions = [b for b in recent_buys if b["is_new_position"]] +if new_positions: + for np in new_positions: + print(f" {np['label']} opened NEW position: {np['mint']}") + print(f" Amount: {np['change']:,.2f} at {np['time_str']}") +else: + print(" No brand new positions in last 60 min.") + +# Full exits +print(f"\n--- FULL EXITS (dumped entire position) ---") +full_exits = [s for s in recent_sells if s.get("is_full_sell")] +if full_exits: + for fe in full_exits: + print(f" {fe['label']} EXITED: {fe['mint']}") + print(f" Dumped: {abs(fe['change']):,.2f} at {fe['time_str']}") +else: + print(" No full exits in last 60 min.") + +# Print unique token CAs for DexScreener lookup +print(f"\n--- UNIQUE TOKEN CAs (for DexScreener lookup) ---") +for mint in token_activity: + buy_ct = len(token_activity[mint]["buys"]) + sell_ct = len(token_activity[mint]["sells"]) + print(f" {mint} (buys: {buy_ct}, sells: {sell_ct})") + +# Save results +results = { + "scan_time": datetime.now(timezone.utc).isoformat(), + "window": "60min", + "total_buys": len(recent_buys), + "total_sells": len(recent_sells), + "unique_tokens": list(token_activity.keys()), + "accumulators": accumulators, + "convergence": convergence_tokens, + "new_positions": [{"label": b["label"], "mint": b["mint"], "amount": b["change"], "time": b["time_str"]} for b in new_positions], + "full_exits": [{"label": s["label"], "mint": s["mint"], "amount": abs(s["change"]), "time": s["time_str"]} for s in full_exits], + "whale_moves": [{"label": m["label"], "action": m["action"], "mint": m["mint"], "change": m["change"], "time": m["time_str"]} for m in all_moves[:15]] +} +with open("/home/user/Cute-Panel/memory/scan_60min_results.json", "w") as f: + json.dump(results, f, indent=2, default=str) + +print(f"\nResults saved to memory/scan_60min_results.json") +print(f"Scan complete at {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M UTC')}") diff --git a/scan_early_buyers.py b/scan_early_buyers.py new file mode 100644 index 0000000..ca29785 --- /dev/null +++ b/scan_early_buyers.py @@ -0,0 +1,513 @@ +#!/usr/bin/env python3 +""" +Early Buyer Scanner — Alpha Wallet Discovery Tool +Scans Pump.fun tokens via Helius to find wallets that bought early (pre-graduation). + +Finds wallets with actual SOL spent during the bonding curve phase. +Cross-references across multiple tokens to identify repeat early buyers. + +Usage: + python3 scan_early_buyers.py ... + python3 scan_early_buyers.py --file tokens.txt +""" + +import json +import sys +import os +import time +from datetime import datetime, timezone +from urllib.request import Request, urlopen +from collections import defaultdict + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) + +# Load env +env_path = os.path.join(SCRIPT_DIR, '.env') +if os.path.exists(env_path): + with open(env_path) as f: + for line in f: + line = line.strip() + if '=' in line and not line.startswith('#'): + key, val = line.split('=', 1) + os.environ[key] = val + +HELIUS_RPC = os.environ.get('HELIUS_RPC_URL', '') +HELIUS_API_KEY = HELIUS_RPC.split('api-key=')[1].split('&')[0] if 'api-key=' in HELIUS_RPC else '' + +SMART_WALLETS_FILE = os.path.join(SCRIPT_DIR, 'memory', 'smart_wallets.json') +EARLY_CALLERS_FILE = os.path.join(SCRIPT_DIR, 'memory', 'early_callers.json') +TOKENS_REGISTRY = os.path.join(SCRIPT_DIR, 'memory', 'tokens.json') +SCAN_RESULTS_DIR = os.path.join(SCRIPT_DIR, 'memory') + +# Pump.fun program ID +PUMP_FUN_PROGRAM = '6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P' + +# System/DEX addresses to ignore +IGNORE_WALLETS = { + '11111111111111111111111111111111', + 'So11111111111111111111111111111111111111112', + 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', + 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL', + 'ComputeBudget111111111111111111111111111111', + '6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P', # Pump.fun + 'Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1', # Pump.fun fee + 'CebN5WGQ4jvEPvsVU4EoHEpgF6Mhf1MhPi7YQV6VeCoB', # PumpSwap + 'FWsHKABNQkBPcPo5NgkEPxQBRjmAHcTh1TsqyKKRhB8c', # PumpSwap AMM + 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', # USDC + 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB', # USDT +} + + +def helius_rpc(method, params): + """Call Helius RPC endpoint.""" + data = json.dumps({ + "jsonrpc": "2.0", + "id": 1, + "method": method, + "params": params + }).encode() + + try: + req = Request(HELIUS_RPC, data=data, + headers={'Content-Type': 'application/json'}) + with urlopen(req, timeout=30) as resp: + result = json.loads(resp.read()) + if 'error' in result: + print(f" RPC error: {result['error']}") + return None + return result.get('result') + except Exception as e: + print(f" RPC error: {e}") + return None + + +def helius_enhanced_tx(address, limit=100): + """Get parsed transactions from Helius enhanced API.""" + url = f"https://api.helius.dev/v0/addresses/{address}/transactions?api-key={HELIUS_API_KEY}&limit={limit}" + try: + req = Request(url, headers={'Content-Type': 'application/json'}) + with urlopen(req, timeout=30) as resp: + return json.loads(resp.read()) + except Exception as e: + print(f" Helius enhanced error: {e}") + return [] + + +def helius_parse_txs(signatures): + """Parse multiple transactions via Helius.""" + url = f"https://api.helius.dev/v0/transactions?api-key={HELIUS_API_KEY}" + data = json.dumps({"transactions": signatures}).encode() + try: + req = Request(url, data=data, + headers={'Content-Type': 'application/json'}) + with urlopen(req, timeout=60) as resp: + return json.loads(resp.read()) + except Exception as e: + print(f" Helius parse error: {e}") + return [] + + +def get_all_signatures(mint, limit=1000): + """Get all transaction signatures for a mint address, oldest first.""" + all_sigs = [] + before = None + + while len(all_sigs) < limit: + params = [mint, {"limit": 100}] + if before: + params[1]["before"] = before + + result = helius_rpc("getSignaturesForAddress", params) + if not result: + break + + all_sigs.extend(result) + if len(result) < 100: + break # No more signatures + + before = result[-1]["signature"] + time.sleep(0.3) + + # Reverse to get oldest first + all_sigs.reverse() + return all_sigs + + +def extract_early_buyers(mint, max_tx=200): + """ + Scan a token mint for early buyers. + Returns list of {wallet, sol_spent, timestamp, tx_signature, tx_index}. + """ + print(f"\n Scanning early transactions for {mint[:20]}...") + + # Step 1: Get all signatures for the mint (oldest first) + sigs = get_all_signatures(mint, limit=max_tx) + if not sigs: + print(f" No signatures found") + return [] + + print(f" Found {len(sigs)} total signatures") + + # Step 2: Take the earliest transactions (first N) + # For pump.fun tokens, the first transactions are the bonding curve buys + early_sigs = sigs[:min(100, len(sigs))] + sig_list = [s["signature"] for s in early_sigs] + + # Step 3: Parse transactions in batches of 20 + all_buyers = [] + for batch_start in range(0, len(sig_list), 20): + batch = sig_list[batch_start:batch_start + 20] + parsed = helius_parse_txs(batch) + + if not parsed: + continue + + for i, tx in enumerate(parsed): + tx_type = tx.get("type", "") + sig = tx.get("signature", "") + ts = tx.get("timestamp", 0) + desc = tx.get("description", "") + fee_payer = tx.get("feePayer", "") + + # Look for token buys: SOL out, token in + native_transfers = tx.get("nativeTransfers", []) + token_transfers = tx.get("tokenTransfers", []) + + # Calculate SOL spent by the fee payer (buyer) + sol_spent = 0 + for nt in native_transfers: + if nt.get("fromUserAccount") == fee_payer: + sol_spent += nt.get("amount", 0) / 1e9 + + # Check if they received the target token + tokens_received = 0 + for tt in token_transfers: + if tt.get("mint") == mint and tt.get("toUserAccount") == fee_payer: + tokens_received += tt.get("tokenAmount", 0) + + # Only count if they spent SOL and received the token + if sol_spent > 0.001 and tokens_received > 0 and fee_payer not in IGNORE_WALLETS: + all_buyers.append({ + "wallet": fee_payer, + "sol_spent": round(sol_spent, 4), + "tokens_received": tokens_received, + "timestamp": ts, + "signature": sig, + "tx_index": batch_start + i, + "description": desc[:200] + }) + + time.sleep(0.5) + + print(f" Found {len(all_buyers)} early buy transactions") + return all_buyers + + +def dexscreener_info(mint): + """Get token info from DexScreener.""" + try: + url = f"https://api.dexscreener.com/latest/dex/tokens/{mint}" + req = Request(url, headers={'Accept': 'application/json', 'User-Agent': 'Mozilla/5.0'}) + with urlopen(req, timeout=15) as resp: + data = json.loads(resp.read()) + pairs = data.get("pairs") or [] + if pairs: + p = pairs[0] + return { + "name": p.get("baseToken", {}).get("name", "Unknown"), + "symbol": p.get("baseToken", {}).get("symbol", "UNKNOWN"), + "mc": p.get("marketCap") or 0, + "liq": (p.get("liquidity") or {}).get("usd") or 0, + "dex": p.get("dexId", "unknown"), + "created": p.get("pairCreatedAt") or 0, + "price_change_24h": (p.get("priceChange") or {}).get("h24") or 0 + } + except Exception as e: + print(f" DexScreener error: {e}") + return None + + +def scan_tokens(mints): + """ + Scan multiple tokens, extract early buyers, cross-reference. + """ + print(f"\n{'='*60}") + print(f" EARLY BUYER SCANNER — {len(mints)} tokens") + print(f" {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M UTC')}") + print(f"{'='*60}") + + # Track wallet → token buys across all tokens + wallet_activity = defaultdict(list) # wallet → [{mint, sol_spent, ts, ...}] + token_info = {} + + for mint in mints: + # Get DexScreener info + info = dexscreener_info(mint) + if info: + token_info[mint] = info + print(f"\n Token: ${info['symbol']} ({info['name']})") + print(f" MC: ${info['mc']:,.0f} | Liq: ${info['liq']:,.0f} | DEX: {info['dex']}") + else: + print(f"\n Token: {mint[:20]}... (no DexScreener data)") + + # Scan early buyers + buyers = extract_early_buyers(mint) + + # Aggregate by wallet + wallet_totals = defaultdict(lambda: {"sol_spent": 0, "tokens": 0, "first_tx": None, "tx_count": 0}) + for buy in buyers: + w = buy["wallet"] + wallet_totals[w]["sol_spent"] += buy["sol_spent"] + wallet_totals[w]["tokens"] += buy["tokens_received"] + wallet_totals[w]["tx_count"] += 1 + if wallet_totals[w]["first_tx"] is None or buy["timestamp"] < wallet_totals[w]["first_tx"]: + wallet_totals[w]["first_tx"] = buy["timestamp"] + + # Sort by earliest buy + sorted_wallets = sorted(wallet_totals.items(), key=lambda x: x[1]["first_tx"] or 0) + + symbol = info["symbol"] if info else mint[:12] + print(f"\n Top 15 earliest buyers of ${symbol}:") + print(f" {'Wallet':<48} {'SOL Spent':>10} {'Txs':>5} {'Time':>20}") + print(f" {'-'*48} {'-'*10} {'-'*5} {'-'*20}") + + for wallet, data in sorted_wallets[:15]: + ts_str = datetime.fromtimestamp(data["first_tx"], tz=timezone.utc).strftime("%Y-%m-%d %H:%M") if data["first_tx"] else "?" + print(f" {wallet:<48} {data['sol_spent']:>10.3f} {data['tx_count']:>5} {ts_str:>20}") + + # Track cross-token activity + wallet_activity[wallet].append({ + "mint": mint, + "symbol": symbol, + "sol_spent": data["sol_spent"], + "tx_count": data["tx_count"], + "first_buy": data["first_tx"] + }) + + time.sleep(1) + + # Phase 2: Cross-reference — find wallets that were early to MULTIPLE tokens + print(f"\n{'='*60}") + print(f" CROSS-REFERENCE: Wallets early to multiple tokens") + print(f"{'='*60}") + + multi_token_wallets = {w: buys for w, buys in wallet_activity.items() if len(buys) >= 2} + + if multi_token_wallets: + # Sort by number of tokens (desc), then total SOL spent (desc) + ranked = sorted(multi_token_wallets.items(), + key=lambda x: (len(x[1]), sum(b["sol_spent"] for b in x[1])), + reverse=True) + + print(f"\n Found {len(ranked)} wallets early to 2+ tokens:\n") + for wallet, buys in ranked[:20]: + total_sol = sum(b["sol_spent"] for b in buys) + tokens_str = ", ".join(f"${b['symbol']}({b['sol_spent']:.2f} SOL)" for b in buys) + print(f" [{len(buys)} tokens] {wallet}") + print(f" Total: {total_sol:.3f} SOL | {tokens_str}") + else: + print(" No wallets found early to multiple tokens.") + + # Phase 3: Rank ALL wallets by alpha potential + print(f"\n{'='*60}") + print(f" ALPHA WALLET RANKING") + print(f"{'='*60}") + + # Score = tokens_count * 10 + sol_spent * 2 + early_bonus + scored = [] + for wallet, buys in wallet_activity.items(): + token_count = len(buys) + total_sol = sum(b["sol_spent"] for b in buys) + # Early bonus: higher if they were in the first 20 transactions + score = token_count * 10 + min(total_sol, 20) * 2 + scored.append({ + "wallet": wallet, + "score": score, + "token_count": token_count, + "total_sol": total_sol, + "buys": buys + }) + + scored.sort(key=lambda x: x["score"], reverse=True) + + print(f"\n Top 25 Alpha Wallets:") + print(f" {'Rank':>4} {'Wallet':<48} {'Score':>6} {'Tokens':>7} {'SOL':>8}") + print(f" {'-'*4} {'-'*48} {'-'*6} {'-'*7} {'-'*8}") + + for i, entry in enumerate(scored[:25], 1): + tokens_str = ",".join(f"${b['symbol']}" for b in entry["buys"]) + print(f" {i:>4} {entry['wallet']:<48} {entry['score']:>6.1f} {entry['token_count']:>7} {entry['total_sol']:>8.3f}") + print(f" Tokens: {tokens_str}") + + # Save results + results = { + "scan_date": datetime.now(timezone.utc).isoformat(), + "tokens_scanned": [{"mint": m, "info": token_info.get(m, {})} for m in mints], + "multi_token_wallets": [ + { + "wallet": w, + "token_count": len(buys), + "total_sol": sum(b["sol_spent"] for b in buys), + "buys": buys + } + for w, buys in sorted(multi_token_wallets.items(), + key=lambda x: len(x[1]), reverse=True) + ], + "top_wallets": scored[:50], + "total_unique_wallets": len(wallet_activity) + } + + results_file = os.path.join(SCAN_RESULTS_DIR, "early_buyer_scan.json") + with open(results_file, 'w') as f: + json.dump(results, f, indent=2) + print(f"\n Results saved to {results_file}") + + # Auto-update smart_wallets.json with multi-token wallets + if multi_token_wallets: + update_smart_wallets(ranked[:10]) + + # Update tokens registry with scan status + update_tokens_registry(mints, token_info) + + return results + + +def update_smart_wallets(ranked_wallets): + """Add discovered alpha wallets to smart_wallets.json.""" + if os.path.exists(SMART_WALLETS_FILE): + with open(SMART_WALLETS_FILE) as f: + data = json.load(f) + else: + data = {"wallets": [], "last_updated": "", "discovery_queue": []} + + existing = {w["address"] for w in data["wallets"]} + + added = 0 + for wallet, buys in ranked_wallets: + if wallet in existing: + continue + + total_sol = sum(b["sol_spent"] for b in buys) + tokens_str = ", ".join(f"${b['symbol']}" for b in buys) + + entry = { + "address": wallet, + "chain": "solana", + "label": f"Early Buyer ({len(buys)} tokens)", + "category": "early_buyer", + "first_spotted": datetime.now(timezone.utc).strftime("%Y-%m-%d"), + "reason": f"Early buyer of {tokens_str}. Total {total_sol:.2f} SOL spent across {len(buys)} tokens.", + "reliability_score": min(6 + len(buys), 10), # 6 base + 1 per additional token + "notable_trades": [ + { + "date": datetime.fromtimestamp(b["first_buy"], tz=timezone.utc).strftime("%Y-%m-%d") if b.get("first_buy") else "unknown", + "action": f"Early buy ${b['symbol']} ({b['sol_spent']:.2f} SOL)", + "outcome": "pending" + } + for b in buys + ], + "current_holdings": "Unknown", + "last_checked": datetime.now(timezone.utc).strftime("%Y-%m-%d"), + "status": "active", + "notes": f"Discovered by early buyer scanner. {len(buys)} tokens tracked." + } + data["wallets"].append(entry) + existing.add(wallet) + added += 1 + + if added: + data["last_updated"] = datetime.now(timezone.utc).isoformat() + with open(SMART_WALLETS_FILE, 'w') as f: + json.dump(data, f, indent=2) + print(f"\n Added {added} alpha wallets to smart_wallets.json") + + +def update_tokens_registry(scanned_mints, token_info): + """Update memory/tokens.json with scan results.""" + if not os.path.exists(TOKENS_REGISTRY): + # Initialize the file if it doesn't exist + data = { + "description": "Master registry of ALL token contract addresses scanned or tracked.", + "last_updated": datetime.now(timezone.utc).strftime("%Y-%m-%d"), + "tokens": [], + "trending_scanned": [], + "stats": {"total_tokens": 0, "pending_helius_scan": 0, "completed_scans": 0} + } + else: + try: + with open(TOKENS_REGISTRY) as f: + data = json.load(f) + except Exception: + data = { + "description": "Master registry of ALL token contract addresses scanned or tracked.", + "last_updated": datetime.now(timezone.utc).strftime("%Y-%m-%d"), + "tokens": [], + "trending_scanned": [], + "stats": {"total_tokens": 0, "pending_helius_scan": 0, "completed_scans": 0} + } + + # Ensure required keys exist + data.setdefault('tokens', []) + data.setdefault('stats', {"total_tokens": 0, "pending_helius_scan": 0, "completed_scans": 0}) + + existing_cas = {t['ca']: i for i, t in enumerate(data.get('tokens', []))} + now = datetime.now(timezone.utc).strftime("%Y-%m-%d") + + for mint in scanned_mints: + if mint in existing_cas: + idx = existing_cas[mint] + data['tokens'][idx]['scan_status'] = 'completed' + data['tokens'][idx]['last_scanned'] = now + info = token_info.get(mint) + if info: + data['tokens'][idx]['symbol'] = info.get('symbol', data['tokens'][idx].get('symbol', 'UNKNOWN')) + data['tokens'][idx]['name'] = info.get('name', data['tokens'][idx].get('name', 'Unknown')) + data['tokens'][idx]['mc_at_discovery'] = info.get('mc', 0) or data['tokens'][idx].get('mc_at_discovery', 0) + else: + info = token_info.get(mint, {}) + data['tokens'].append({ + 'ca': mint, + 'symbol': info.get('symbol', 'UNKNOWN'), + 'name': info.get('name', 'Unknown'), + 'chain': 'solana', + 'dex': info.get('dex', 'unknown'), + 'mc_at_discovery': info.get('mc', 0), + 'source': 'scan_early_buyers', + 'date_added': now, + 'scan_status': 'completed', + 'last_scanned': now, + 'callers': [], + 'notes': 'Added during early buyer scan' + }) + + data['last_updated'] = now + data['stats']['total_tokens'] = len(data['tokens']) + data['stats']['pending_helius_scan'] = sum(1 for t in data['tokens'] if t.get('scan_status') == 'pending_helius') + data['stats']['completed_scans'] = sum(1 for t in data['tokens'] if t.get('scan_status') == 'completed') + + os.makedirs(os.path.dirname(TOKENS_REGISTRY), exist_ok=True) + with open(TOKENS_REGISTRY, 'w') as f: + json.dump(data, f, indent=2) + print(f"\n Updated tokens.json: {data['stats']['completed_scans']}/{data['stats']['total_tokens']} scanned") + + +if __name__ == "__main__": + if not HELIUS_API_KEY: + print("ERROR: HELIUS_RPC_URL not set in .env") + sys.exit(1) + + mints = [] + + if len(sys.argv) > 1: + if sys.argv[1] == "--file": + with open(sys.argv[2]) as f: + mints = [line.strip() for line in f if line.strip()] + else: + mints = [arg.strip() for arg in sys.argv[1:] if arg.strip()] + + if not mints: + print("Usage: python3 scan_early_buyers.py ...") + print(" python3 scan_early_buyers.py --file tokens.txt") + sys.exit(1) + + scan_tokens(mints) diff --git a/scan_early_wallets.py b/scan_early_wallets.py new file mode 100644 index 0000000..a928a3a --- /dev/null +++ b/scan_early_wallets.py @@ -0,0 +1,375 @@ +#!/usr/bin/env python3 +""" +Early Wallet Scanner — Finds wallets that consistently buy tokens early on pump.fun +before migration. Scans transaction history for the first N buyers of each token, +then cross-references to find repeat winners. + +Usage: + python3 scan_early_wallets.py # Scan all tokens in /tmp/token_cas.json + python3 scan_early_wallets.py # Scan specific mints +""" + +import json +import sys +import os +import time +from urllib.request import Request, urlopen +from urllib.error import URLError +from collections import defaultdict +from datetime import datetime + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) + +# Load env +env_path = os.path.join(SCRIPT_DIR, '.env') +if os.path.exists(env_path): + with open(env_path) as f: + for line in f: + line = line.strip() + if '=' in line and not line.startswith('#'): + key, val = line.split('=', 1) + os.environ[key] = val + +HELIUS_RPC = os.environ.get('HELIUS_RPC_URL', '') +HELIUS_API_KEY = '' +if 'api-key=' in HELIUS_RPC: + HELIUS_API_KEY = HELIUS_RPC.split('api-key=')[1].split('&')[0] + +if not HELIUS_RPC: + print("ERROR: HELIUS_RPC_URL not set") + sys.exit(1) + +# Known system addresses to skip +SKIP_ADDRESSES = { + '11111111111111111111111111111111', + 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', + 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL', + 'ComputeBudget111111111111111111111111111111', + 'SysvarRent111111111111111111111111111111111', + 'SysvarC1ock11111111111111111111111111111111', + '6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P', # pump.fun program + 'Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1', # pump.fun fee + 'CebN5WGQ4jvEPvsVU4EoHEpgzq1VV7AbCJ3LFQ59iQNR', # pump.fun authority + '5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1', # Raydium + '675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8', # Raydium AMM + 'So11111111111111111111111111111111111111112', # Wrapped SOL + 'metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s', # Metaplex +} + +def rpc_call(method, params, retries=3): + """Make an RPC call to Helius with retries.""" + data = json.dumps({ + "jsonrpc": "2.0", + "id": 1, + "method": method, + "params": params + }).encode() + + for attempt in range(retries): + try: + req = Request(HELIUS_RPC, data=data, headers={'Content-Type': 'application/json'}) + with urlopen(req, timeout=60) as resp: + result = json.loads(resp.read()) + if 'error' in result: + print(f" RPC error: {result['error']}") + return None + return result.get('result') + except Exception as e: + if attempt < retries - 1: + time.sleep(2 ** attempt) + else: + print(f" RPC failed after {retries} attempts: {e}") + return None + return None + + +def helius_parsed_transactions(address, limit=100): + """Use Helius enhanced API to get parsed transactions.""" + url = f"https://api.helius.dev/v0/addresses/{address}/transactions?api-key={HELIUS_API_KEY}&limit={limit}" + try: + req = Request(url, headers={'Content-Type': 'application/json'}) + with urlopen(req, timeout=60) as resp: + return json.loads(resp.read()) + except Exception as e: + print(f" Helius API error: {e}") + return [] + + +def get_earliest_signatures(mint, limit=50): + """Get the earliest transaction signatures for a token mint.""" + # Get all signatures (returns newest first) + all_sigs = [] + before = None + + for _ in range(5): # Max 5 pages = 5000 txs + params = [mint, {"limit": 1000}] + if before: + params[1]["before"] = before + + result = rpc_call("getSignaturesForAddress", params) + if not result or len(result) == 0: + break + + all_sigs.extend(result) + before = result[-1]["signature"] + + # If we got less than 1000, we've reached the end + if len(result) < 1000: + break + + time.sleep(0.5) # Rate limit + + if not all_sigs: + return [] + + # Sort by slot (ascending = earliest first) + all_sigs.sort(key=lambda x: x.get('slot', 0)) + + # Return earliest N + return all_sigs[:limit] + + +def extract_buyers_from_tx(sig): + """Parse a transaction to find who bought the token (sent SOL, received tokens).""" + result = rpc_call("getTransaction", [sig, {"encoding": "jsonParsed", "maxSupportedTransactionVersion": 0}]) + if not result: + return [] + + meta = result.get("meta", {}) + tx = result.get("transaction", {}) + msg = tx.get("message", {}) + + # Get account keys + account_keys = [] + for k in msg.get("accountKeys", []): + if isinstance(k, dict): + account_keys.append(k.get("pubkey", "")) + else: + account_keys.append(k) + + # Check for errors + if meta.get("err"): + return [] + + buyers = [] + + # Method 1: Check pre/post token balances + pre_token = {b.get("accountIndex"): b for b in meta.get("preTokenBalances", [])} + post_token = {b.get("accountIndex"): b for b in meta.get("postTokenBalances", [])} + + for idx, post_bal in post_token.items(): + pre_bal = pre_token.get(idx, {}) + pre_amount = float(pre_bal.get("uiTokenAmount", {}).get("uiAmount", 0) or 0) + post_amount = float(post_bal.get("uiTokenAmount", {}).get("uiAmount", 0) or 0) + + if post_amount > pre_amount: + # This account received tokens + owner = post_bal.get("owner", "") + if owner and owner not in SKIP_ADDRESSES: + buyers.append({ + "wallet": owner, + "tokens_received": post_amount - pre_amount, + "slot": result.get("slot", 0), + "blockTime": result.get("blockTime", 0), + "signature": sig + }) + + # Method 2: Check SOL balance changes (buyers send SOL) + pre_balances = meta.get("preBalances", []) + post_balances = meta.get("postBalances", []) + + for i, (pre, post) in enumerate(zip(pre_balances, post_balances)): + if i < len(account_keys): + sol_change = (post - pre) / 1e9 + wallet = account_keys[i] + # If wallet sent SOL (negative change) and is already in buyers, add SOL info + if sol_change < -0.01 and wallet not in SKIP_ADDRESSES: + for b in buyers: + if b["wallet"] == wallet: + b["sol_spent"] = abs(sol_change) + + return buyers + + +def scan_token(mint, ticker="UNKNOWN"): + """Scan a single token for early buyers.""" + print(f"\n{'='*60}") + print(f"Scanning ${ticker} | {mint}") + print(f"{'='*60}") + + # Get earliest transactions + print(" Fetching earliest transactions...") + sigs = get_earliest_signatures(mint, limit=30) + + if not sigs: + print(" No transactions found. Skipping.") + return [] + + print(f" Found {len(sigs)} earliest transactions (out of total)") + print(f" Earliest tx slot: {sigs[0].get('slot', '?')}") + + # Parse each transaction for buyers + all_buyers = [] + for i, sig_info in enumerate(sigs[:20]): # First 20 txs + sig = sig_info["signature"] + buyers = extract_buyers_from_tx(sig) + all_buyers.extend(buyers) + + if (i + 1) % 5 == 0: + print(f" Parsed {i+1}/20 transactions, found {len(all_buyers)} buyers so far...") + time.sleep(0.3) # Rate limit + + # Deduplicate by wallet + wallet_data = {} + for b in all_buyers: + w = b["wallet"] + if w not in wallet_data or b["slot"] < wallet_data[w]["slot"]: + wallet_data[w] = b + + print(f" Found {len(wallet_data)} unique early buyers") + + # Sort by slot (earliest first) + sorted_wallets = sorted(wallet_data.values(), key=lambda x: x["slot"]) + + for i, w in enumerate(sorted_wallets[:10], 1): + ts = datetime.utcfromtimestamp(w['blockTime']).strftime('%Y-%m-%d %H:%M') if w.get('blockTime') else '?' + sol = f" ({w.get('sol_spent', '?'):.2f} SOL)" if isinstance(w.get('sol_spent'), (int, float)) else "" + print(f" #{i} {w['wallet'][:12]}... | slot {w['slot']} | {ts}{sol}") + + return [{"wallet": w["wallet"], "slot": w["slot"], "blockTime": w.get("blockTime", 0), + "tokens": w.get("tokens_received", 0), "sol_spent": w.get("sol_spent", 0), + "token_mint": mint, "token_ticker": ticker} + for w in sorted_wallets] + + +def cross_reference(all_scan_results): + """Find wallets that appear as early buyers across multiple tokens.""" + wallet_appearances = defaultdict(list) + + for entry in all_scan_results: + wallet_appearances[entry["wallet"]].append({ + "token": entry["token_ticker"], + "mint": entry["token_mint"], + "slot": entry["slot"], + "blockTime": entry.get("blockTime", 0), + "sol_spent": entry.get("sol_spent", 0) + }) + + # Filter: wallets that appear in 2+ different tokens + repeat_winners = {} + for wallet, appearances in wallet_appearances.items(): + unique_tokens = set(a["mint"] for a in appearances) + if len(unique_tokens) >= 2: + repeat_winners[wallet] = { + "wallet": wallet, + "token_count": len(unique_tokens), + "tokens": appearances, + "total_sol_spent": sum(a.get("sol_spent", 0) for a in appearances) + } + + # Sort by number of tokens (most first) + ranked = sorted(repeat_winners.values(), key=lambda x: x["token_count"], reverse=True) + return ranked + + +def main(): + # Determine token list + if len(sys.argv) > 1: + # CAs passed as arguments + tokens = {addr: {"ticker": "UNKNOWN"} for addr in sys.argv[1:]} + else: + # Load from file + cas_file = '/tmp/token_cas.json' + if os.path.exists(cas_file): + with open(cas_file) as f: + tokens = json.load(f) + else: + print("No tokens to scan. Pass CAs as arguments or create /tmp/token_cas.json") + sys.exit(1) + + print(f"{'='*60}") + print(f"EARLY WALLET SCANNER") + print(f"Scanning {len(tokens)} tokens for early buyers") + print(f"{'='*60}") + + all_results = [] + scanned = 0 + + for mint, info in tokens.items(): + ticker = info.get("ticker", "UNKNOWN") if isinstance(info, dict) else "UNKNOWN" + + try: + results = scan_token(mint, ticker) + all_results.extend(results) + scanned += 1 + except Exception as e: + print(f" ERROR scanning {mint}: {e}") + + time.sleep(1) # Rate limit between tokens + + print(f"\n{'='*60}") + print(f"CROSS-REFERENCE ANALYSIS") + print(f"Scanned {scanned} tokens, found {len(all_results)} total early buyer entries") + print(f"{'='*60}") + + # Cross-reference + repeat_winners = cross_reference(all_results) + + print(f"\nFound {len(repeat_winners)} wallets that were early to 2+ tokens:") + print() + + for i, w in enumerate(repeat_winners[:50], 1): + tokens_str = ", ".join(f"${t['token']}" for t in w["tokens"]) + print(f" #{i} [{w['token_count']} tokens] {w['wallet']}") + print(f" Tokens: {tokens_str}") + print() + + # Save results + output = { + "scan_date": datetime.utcnow().isoformat(), + "tokens_scanned": scanned, + "total_early_buyers": len(all_results), + "repeat_winners_count": len(repeat_winners), + "repeat_winners": repeat_winners[:100], + "all_early_buyers": all_results + } + + output_path = os.path.join(SCRIPT_DIR, 'memory', 'alpha_wallets_scan.json') + with open(output_path, 'w') as f: + json.dump(output, f, indent=2) + print(f"\nResults saved to: {output_path}") + + # Also update smart_wallets.json with top repeat winners + smart_wallets_path = os.path.join(SCRIPT_DIR, 'memory', 'smart_wallets.json') + if os.path.exists(smart_wallets_path): + with open(smart_wallets_path) as f: + smart = json.load(f) + + for w in repeat_winners[:20]: + # Check if already tracked + existing = [x for x in smart.get("wallets", []) if x.get("address") == w["wallet"]] + if not existing: + smart["wallets"].append({ + "address": w["wallet"], + "chain": "solana", + "label": f"Alpha Scanner: early to {w['token_count']} tokens", + "category": "alpha_wallet", + "first_spotted": datetime.utcnow().strftime("%Y-%m-%d"), + "reason": f"Early buyer in {w['token_count']} tokens: {', '.join(t['token'] for t in w['tokens'])}", + "reliability_score": min(10, w['token_count'] * 3), + "notable_trades": w["tokens"], + "status": "active", + "notes": "Found by early wallet scanner. Track for new buys." + }) + + smart["last_updated"] = datetime.utcnow().strftime("%Y-%m-%d") + + with open(smart_wallets_path, 'w') as f: + json.dump(smart, f, indent=2) + print(f"Updated smart_wallets.json with {min(20, len(repeat_winners))} new alpha wallets") + + return repeat_winners + + +if __name__ == "__main__": + winners = main() diff --git a/scan_trending_new.py b/scan_trending_new.py new file mode 100644 index 0000000..a130441 --- /dev/null +++ b/scan_trending_new.py @@ -0,0 +1,523 @@ +#!/usr/bin/env python3 +""" +Trending Token Scanner — Finds top 10 new trending Solana tokens. +Sources: DexScreener (boosts + profiles), GeckoTerminal (trending pools), Grok X search. +Runs twice daily: 14:00 CET (US open + Asia evening), 02:00 CET (US evening + Asia morning). +Each new CA is saved to tokens.json and queued for alpha_wallet_scanner.py. +""" + +import json +import os +import subprocess +import sys +import time +from datetime import datetime, timezone, timedelta +from urllib.request import Request, urlopen +from urllib.error import HTTPError, URLError + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) + +# Load env +env_path = os.path.join(SCRIPT_DIR, '.env') +if os.path.exists(env_path): + with open(env_path) as f: + for line in f: + line = line.strip() + if '=' in line and not line.startswith('#'): + key, val = line.split('=', 1) + os.environ[key] = val + +XAI_API_KEY = os.environ.get('XAI_API_KEY', '') +HELIUS_RPC = os.environ.get('HELIUS_RPC_URL', '') + +TOKENS_FILE = os.path.join(SCRIPT_DIR, 'memory', 'tokens.json') +TRENDING_LOG = os.path.join(SCRIPT_DIR, 'memory', 'trending_scans.jsonl') +SCAN_QUEUE = os.path.join(SCRIPT_DIR, 'memory', 'scan_queue.json') + + +def http_get(url, timeout=15): + """GET request with error handling.""" + try: + req = Request(url, headers={ + 'Accept': 'application/json', + 'User-Agent': 'Mozilla/5.0' + }) + with urlopen(req, timeout=timeout) as resp: + return json.loads(resp.read()) + except Exception as e: + print(f" HTTP error for {url[:60]}: {e}") + return None + + +def http_post(url, data, headers=None, timeout=30): + """POST request with error handling.""" + try: + payload = json.dumps(data).encode() + hdrs = {'Content-Type': 'application/json'} + if headers: + hdrs.update(headers) + req = Request(url, data=payload, headers=hdrs, method='POST') + with urlopen(req, timeout=timeout) as resp: + return json.loads(resp.read()) + except Exception as e: + print(f" HTTP POST error: {e}") + return None + + +def scan_dexscreener_boosts(): + """Get top boosted tokens on DexScreener (Solana only).""" + print("[DexScreener] Scanning boosted tokens...") + data = http_get("https://api.dexscreener.com/token-boosts/top/v1") + if not data: + return [] + + tokens = [] + for t in data: + if t.get('chainId') != 'solana': + continue + ca = t.get('tokenAddress', '') + boost = t.get('totalAmount', 0) + if not ca: + continue + tokens.append({ + 'ca': ca, + 'source': 'dexscreener_boost', + 'boost_amount': boost, + }) + + print(f" Found {len(tokens)} Solana boosted tokens") + return tokens[:20] + + +def scan_dexscreener_profiles(): + """Get latest token profiles on DexScreener (Solana only, new tokens with profiles).""" + print("[DexScreener] Scanning latest profiles...") + data = http_get("https://api.dexscreener.com/token-profiles/latest/v1") + if not data: + return [] + + tokens = [] + for t in data: + if t.get('chainId') != 'solana': + continue + ca = t.get('tokenAddress', '') + if not ca: + continue + tokens.append({ + 'ca': ca, + 'source': 'dexscreener_profile', + 'has_links': bool(t.get('links')), + }) + + print(f" Found {len(tokens)} Solana profiles") + return tokens[:20] + + +def scan_gecko_trending(): + """Get trending pools from GeckoTerminal (Solana).""" + print("[GeckoTerminal] Scanning trending pools...") + data = http_get( + "https://api.geckoterminal.com/api/v2/networks/solana/trending_pools?page=1" + ) + if not data: + return [] + + tokens = [] + for p in data.get('data', []): + attr = p.get('attributes', {}) + name = attr.get('name', '') + vol_24h = 0 + try: + vol_24h = float(attr.get('volume_usd', {}).get('h24', 0) or 0) + except (TypeError, ValueError): + pass + + # Extract token address from relationships + rels = p.get('relationships', {}) + base = rels.get('base_token', {}).get('data', {}).get('id', '') + # Format: "solana_
" + ca = base.replace('solana_', '') if base.startswith('solana_') else '' + + if not ca: + continue + + tokens.append({ + 'ca': ca, + 'source': 'geckoterminal_trending', + 'name': name, + 'vol_24h': vol_24h, + }) + + print(f" Found {len(tokens)} trending pools") + return tokens[:20] + + +def scan_gecko_new_pools(): + """Get new pools from GeckoTerminal (Solana).""" + print("[GeckoTerminal] Scanning new pools...") + data = http_get( + "https://api.geckoterminal.com/api/v2/networks/solana/new_pools?page=1" + ) + if not data: + return [] + + tokens = [] + for p in data.get('data', []): + attr = p.get('attributes', {}) + name = attr.get('name', '') + vol_24h = 0 + try: + vol_24h = float(attr.get('volume_usd', {}).get('h24', 0) or 0) + except (TypeError, ValueError): + pass + + rels = p.get('relationships', {}) + base = rels.get('base_token', {}).get('data', {}).get('id', '') + ca = base.replace('solana_', '') if base.startswith('solana_') else '' + + if not ca or vol_24h < 50000: + continue + + tokens.append({ + 'ca': ca, + 'source': 'geckoterminal_new', + 'name': name, + 'vol_24h': vol_24h, + }) + + print(f" Found {len(tokens)} new pools with >$50K vol") + return tokens[:20] + + +def scan_grok_x_trending(): + """Search X/Twitter for trending Solana tokens via Grok API.""" + if not XAI_API_KEY: + print("[Grok] No API key, skipping X search") + return [] + + print("[Grok] Searching X for trending Solana tokens...") + + queries = [ + "Search X for the top 10 trending Solana memecoins and tokens being discussed RIGHT NOW (last 6 hours). For each token, provide: 1) Token name/ticker 2) Contract address (CA) if mentioned 3) Approximate market cap if known 4) Number of mentions/engagement 5) Key callers mentioning it. Focus on NEW tokens (launched in last 48 hours) with organic buzz, not established tokens like SOL/JUP/BONK. Include pump.fun launches that are trending.", + "Search X for 'solana CA' OR 'pump fun trending' OR 'king of the hill solana' from the last 6 hours. Find specific contract addresses (CAs) being shared for new Solana tokens. List every CA you find with the token name and who posted it.", + ] + + all_tokens = [] + for q in queries: + resp = http_post( + "https://api.x.ai/v1/responses", + data={ + "model": "grok-4-1-fast", + "tools": [{"type": "x_search"}], + "input": q, + }, + headers={"Authorization": f"Bearer {XAI_API_KEY}"}, + timeout=120, + ) + + if not resp: + continue + + text = resp.get('output_text', '') + if not text: + # Try extracting from output array + for out in resp.get('output', []): + if out.get('type') == 'message' and out.get('role') == 'assistant': + for c in out.get('content', []): + if c.get('type') == 'output_text': + text = c.get('text', '') + elif c.get('type') == 'text': + text = c.get('text', '') + + if text: + # Extract CAs from the text (Solana addresses are 32-44 chars, base58) + import re + cas = re.findall(r'\b([1-9A-HJ-NP-Za-km-z]{32,44})\b', text) + # Filter to likely token CAs (often end in 'pump' for pump.fun) + for ca in cas: + if len(ca) >= 32 and ca not in [ + 'TokenkegQfeE2cNFBpZjxo3WcsKrpLBCq4SzZhScigCZ', + 'So11111111111111111111111111111111111111112', + ]: + all_tokens.append({ + 'ca': ca, + 'source': 'grok_x_search', + 'raw_context': text[:200], + }) + + print(f" Grok query returned {len(cas)} potential CAs") + time.sleep(3) + + # Deduplicate + seen = set() + unique = [] + for t in all_tokens: + if t['ca'] not in seen: + seen.add(t['ca']) + unique.append(t) + + print(f" Total unique CAs from X: {len(unique)}") + return unique[:30] + + +def enrich_token(ca): + """Get token details from DexScreener.""" + data = http_get(f"https://api.dexscreener.com/tokens/v1/solana/{ca}") + if not data or not isinstance(data, list) or len(data) == 0: + return None + + p = data[0] + bt = p.get('baseToken', {}) + info = p.get('info', {}) + + mc = p.get('marketCap') or p.get('fdv') or 0 + liq = (p.get('liquidity') or {}).get('usd', 0) or 0 + vol_24h = (p.get('volume') or {}).get('h24', 0) or 0 + age_ms = 0 + created = p.get('pairCreatedAt') + if created: + age_ms = int(time.time() * 1000) - created + + txns = p.get('txns', {}).get('h24', {}) + buys = txns.get('buys', 0) or 0 + sells = txns.get('sells', 0) or 0 + + return { + 'symbol': bt.get('symbol', 'UNKNOWN'), + 'name': bt.get('name', 'Unknown'), + 'ca': ca, + 'chain': 'solana', + 'mc': mc, + 'liquidity': liq, + 'vol_24h': vol_24h, + 'buys_24h': buys, + 'sells_24h': sells, + 'age_hours': age_ms / (1000 * 3600) if age_ms else 0, + 'pair_address': p.get('pairAddress', ''), + 'price_usd': float(p.get('priceUsd', 0) or 0), + 'price_change_24h': (p.get('priceChange') or {}).get('h24', 0) or 0, + 'website': (info.get('websites') or [{}])[0].get('url', '') if info.get('websites') else '', + 'twitter': next((s.get('url', '') for s in (info.get('socials') or []) if s.get('type') == 'twitter'), ''), + } + + +def score_token(token_info, source_data): + """Score a token for interest (higher = more interesting).""" + score = 0 + + mc = token_info.get('mc', 0) or 0 + liq = token_info.get('liquidity', 0) or 0 + vol = token_info.get('vol_24h', 0) or 0 + age = token_info.get('age_hours', 0) or 0 + buys = token_info.get('buys_24h', 0) or 0 + sells = token_info.get('sells_24h', 0) or 0 + + # MC sweet spot: $50K - $5M (early but has traction) + if 50_000 <= mc <= 500_000: + score += 30 # Micro-cap, early + elif 500_000 < mc <= 5_000_000: + score += 20 # Small-cap, growing + elif mc > 5_000_000: + score += 5 # Already big, less alpha + + # Liquidity check (min $10K to avoid rugs) + if liq >= 50_000: + score += 15 + elif liq >= 10_000: + score += 5 + else: + score -= 20 # Too thin + + # Volume to MC ratio (higher = more active) + if mc > 0 and vol / mc > 0.5: + score += 20 # Very active trading + elif mc > 0 and vol / mc > 0.2: + score += 10 + + # Age: newer is better for alpha (but not too new) + if 2 <= age <= 48: + score += 25 # Sweet spot: 2-48 hours old + elif 48 < age <= 168: + score += 10 # 2-7 days + elif age < 2: + score += 5 # Very new, higher rug risk + + # Buy/sell ratio + if buys > 0 and sells > 0: + ratio = buys / sells + if ratio > 1.5: + score += 15 # Strong buying + elif ratio > 1.0: + score += 5 + elif ratio < 0.5: + score -= 10 # Dumping + + # Source multiplier + sources = set() + if isinstance(source_data, list): + for s in source_data: + sources.add(s.get('source', '')) + elif isinstance(source_data, dict): + sources.add(source_data.get('source', '')) + + if len(sources) >= 3: + score += 25 # Found on 3+ sources = strong signal + elif len(sources) >= 2: + score += 15 # Found on 2 sources + if 'grok_x_search' in sources: + score += 10 # X buzz adds value + + # Boost amount (DexScreener) + for s in (source_data if isinstance(source_data, list) else [source_data]): + boost = s.get('boost_amount', 0) or 0 + if boost >= 500: + score += 10 + elif boost >= 200: + score += 5 + + return score + + +def load_tokens_registry(): + """Load existing token registry.""" + if os.path.exists(TOKENS_FILE): + try: + with open(TOKENS_FILE) as f: + return json.load(f) + except Exception: + pass + return {"tokens": [], "stats": {"total_tokens": 0}} + + +def save_tokens_registry(registry): + """Save token registry.""" + os.makedirs(os.path.dirname(TOKENS_FILE), exist_ok=True) + with open(TOKENS_FILE, 'w') as f: + json.dump(registry, f, indent=2) + + +def main(): + now = datetime.now(timezone.utc) + print(f"[{now.isoformat()}] Starting trending token scan...") + + # Phase 1: Gather CAs from all sources + all_raw = [] + all_raw.extend(scan_dexscreener_boosts()) + time.sleep(1) + all_raw.extend(scan_dexscreener_profiles()) + time.sleep(1) + all_raw.extend(scan_gecko_trending()) + time.sleep(1) + all_raw.extend(scan_gecko_new_pools()) + time.sleep(1) + all_raw.extend(scan_grok_x_trending()) + + # Deduplicate and merge sources + ca_map = {} + for t in all_raw: + ca = t['ca'] + if ca not in ca_map: + ca_map[ca] = [] + ca_map[ca].append(t) + + print(f"\nTotal unique CAs found: {len(ca_map)}") + + # Phase 2: Load existing registry to skip known tokens + registry = load_tokens_registry() + existing_cas = {t['ca'] for t in registry.get('tokens', [])} + new_cas = {ca for ca in ca_map if ca not in existing_cas} + print(f"New CAs (not in registry): {len(new_cas)}") + + # Phase 3: Enrich new tokens via DexScreener + enriched = [] + for i, ca in enumerate(list(new_cas)[:40]): # Limit to 40 lookups + print(f" Enriching {i+1}/{min(len(new_cas), 40)}: {ca[:20]}...") + info = enrich_token(ca) + if info and info.get('mc', 0) > 0: + info['sources'] = ca_map[ca] + info['score'] = score_token(info, ca_map[ca]) + info['discovered_at'] = now.isoformat() + info['scan_status'] = 'pending_alpha_scan' + enriched.append(info) + time.sleep(0.5) + + # Also enrich existing-but-seen-again tokens (multi-source bonus) + for ca in ca_map: + if ca in existing_cas: + sources = ca_map[ca] + for t in registry['tokens']: + if t['ca'] == ca: + old_sources = t.get('source_count', 1) + t['source_count'] = max(old_sources, len(sources)) + t['last_seen'] = now.isoformat() + + # Phase 4: Score and rank + enriched.sort(key=lambda x: x.get('score', 0), reverse=True) + top10 = enriched[:10] + + print(f"\n{'='*60}") + print(f"TOP 10 NEW TRENDING TOKENS") + print(f"{'='*60}") + for i, t in enumerate(top10): + print(f" #{i+1}: ${t['symbol']} | MC: ${t['mc']:,.0f} | Liq: ${t['liquidity']:,.0f} | " + f"Score: {t['score']} | Age: {t['age_hours']:.1f}h | " + f"Sources: {len(t.get('sources', []))}") + print(f" CA: {t['ca']}") + + # Phase 5: Save to registry + scan queue + for t in enriched: + registry['tokens'].append({ + 'ca': t['ca'], + 'symbol': t['symbol'], + 'name': t['name'], + 'chain': 'solana', + 'mc_at_discovery': t['mc'], + 'liquidity_at_discovery': t['liquidity'], + 'score': t['score'], + 'source': 'trending_scan', + 'source_count': len(t.get('sources', [])), + 'discovered_at': t['discovered_at'], + 'scan_status': 'pending_alpha_scan', + }) + + registry['stats'] = { + 'total_tokens': len(registry['tokens']), + 'pending_alpha_scan': len([t for t in registry['tokens'] if t.get('scan_status') == 'pending_alpha_scan']), + 'last_scan': now.isoformat(), + } + save_tokens_registry(registry) + + # Save scan queue (CAs that need alpha wallet scanning) + queue = { + 'queued_at': now.isoformat(), + 'tokens': [{ + 'ca': t['ca'], + 'symbol': t['symbol'], + 'mc': t['mc'], + 'score': t['score'], + } for t in top10], + } + os.makedirs(os.path.dirname(SCAN_QUEUE), exist_ok=True) + with open(SCAN_QUEUE, 'w') as f: + json.dump(queue, f, indent=2) + + # Phase 6: Log scan + log_entry = { + 'timestamp': now.isoformat(), + 'tokens_scanned': len(ca_map), + 'new_tokens': len(new_cas), + 'enriched': len(enriched), + 'top10': [{'symbol': t['symbol'], 'ca': t['ca'], 'mc': t['mc'], 'score': t['score']} for t in top10], + } + os.makedirs(os.path.dirname(TRENDING_LOG), exist_ok=True) + with open(TRENDING_LOG, 'a') as f: + f.write(json.dumps(log_entry) + '\n') + + print(f"\n[{datetime.now(timezone.utc).isoformat()}] Scan complete. " + f"{len(enriched)} new tokens added, {len(top10)} queued for alpha scan.") + + return top10 + + +if __name__ == "__main__": + results = main() diff --git a/scan_trending_wallets.py b/scan_trending_wallets.py new file mode 100644 index 0000000..8ddf039 --- /dev/null +++ b/scan_trending_wallets.py @@ -0,0 +1,462 @@ +#!/usr/bin/env python3 +""" +Trending Wallet Scanner — Hourly Alpha Discovery +Scans trending tokens across DexScreener, then uses Grok x_search to find +early callers. Feeds discovered wallets into scan_early_buyers.py for on-chain +verification via Helius (VPS only). + +Sources checked (no duplicates): + 1. DexScreener trending Solana tokens (new pairs, volume gainers) + 2. Grok x_search for pump.fun / GMGN / Axiom / Birdeye / DexTools mentions + 3. Cross-reference with tracked early callers + +Usage: + python3 scan_trending_wallets.py # Run once + python3 scan_trending_wallets.py daemon # Run every hour +""" + +import json +import sys +import os +import time +from datetime import datetime, timezone +from urllib.request import Request, urlopen + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) + +# Load env +env_path = os.path.join(SCRIPT_DIR, '.env') +if os.path.exists(env_path): + with open(env_path) as f: + for line in f: + line = line.strip() + if '=' in line and not line.startswith('#'): + key, val = line.split('=', 1) + os.environ[key] = val + +XAI_API_KEY = os.environ.get('XAI_API_KEY', '') +HELIUS_RPC = os.environ.get('HELIUS_RPC_URL', '') +HELIUS_API_KEY = HELIUS_RPC.split('api-key=')[1].split('&')[0] if 'api-key=' in HELIUS_RPC else '' + +TRENDING_LOG = os.path.join(SCRIPT_DIR, 'memory', 'trending_scans.jsonl') +EARLY_CALLERS_FILE = os.path.join(SCRIPT_DIR, 'memory', 'early_callers.json') +SCANNED_TOKENS_FILE = os.path.join(SCRIPT_DIR, 'memory', 'scanned_tokens.json') +TOKENS_REGISTRY = os.path.join(SCRIPT_DIR, 'memory', 'tokens.json') + +# Tokens we've already scanned (avoid duplicates) +def load_scanned(): + if os.path.exists(SCANNED_TOKENS_FILE): + with open(SCANNED_TOKENS_FILE) as f: + return json.load(f) + return {"tokens": {}, "last_updated": ""} + +def save_scanned(data): + data["last_updated"] = datetime.now(timezone.utc).isoformat() + with open(SCANNED_TOKENS_FILE, 'w') as f: + json.dump(data, f, indent=2) + + +def log_trending(entry): + import fcntl + with open(TRENDING_LOG, 'a') as f: + fcntl.flock(f, fcntl.LOCK_EX) + f.write(json.dumps(entry) + '\n') + fcntl.flock(f, fcntl.LOCK_UN) + + +def dexscreener_trending(): + """Get trending Solana tokens from DexScreener new pairs + boosted.""" + tokens = [] + + # DexScreener token profiles (recently boosted) + try: + url = "https://api.dexscreener.com/token-boosts/top/v1" + req = Request(url, headers={'Accept': 'application/json', 'User-Agent': 'Mozilla/5.0'}) + with urlopen(req, timeout=15) as resp: + data = json.loads(resp.read()) + if not isinstance(data, list): + print(f" DexScreener boost: unexpected response type {type(data).__name__}") + data = [] + for item in data: + if item.get("chainId") == "solana": + tokens.append({ + "mint": item.get("tokenAddress", ""), + "source": "dexscreener_boost", + "description": (item.get("description") or "")[:100] + }) + except Exception as e: + print(f" DexScreener boost error: {e}") + + # DexScreener latest Solana pairs + try: + url = "https://api.dexscreener.com/token-profiles/latest/v1" + req = Request(url, headers={'Accept': 'application/json', 'User-Agent': 'Mozilla/5.0'}) + with urlopen(req, timeout=15) as resp: + data = json.loads(resp.read()) + if not isinstance(data, list): + print(f" DexScreener profiles: unexpected response type {type(data).__name__}") + data = [] + for item in data: + if item.get("chainId") == "solana": + mint = item.get("tokenAddress", "") + if mint and mint not in [t["mint"] for t in tokens]: + tokens.append({ + "mint": mint, + "source": "dexscreener_profile", + "description": (item.get("description") or "")[:100] + }) + except Exception as e: + print(f" DexScreener profiles error: {e}") + + return tokens[:30] # Cap at 30 + + +def enrich_with_dexscreener(mint): + """Get full token data from DexScreener.""" + try: + url = f"https://api.dexscreener.com/latest/dex/tokens/{mint}" + req = Request(url, headers={'Accept': 'application/json', 'User-Agent': 'Mozilla/5.0'}) + with urlopen(req, timeout=15) as resp: + data = json.loads(resp.read()) + pairs = data.get("pairs") or [] + if pairs: + p = pairs[0] + return { + "name": p.get("baseToken", {}).get("name", "Unknown"), + "symbol": p.get("baseToken", {}).get("symbol", "UNKNOWN"), + "mc": p.get("marketCap") or 0, + "liq": (p.get("liquidity") or {}).get("usd") or 0, + "vol_24h": (p.get("volume") or {}).get("h24") or 0, + "change_24h": (p.get("priceChange") or {}).get("h24") or 0, + "buys_24h": (p.get("txns") or {}).get("h24", {}).get("buys") or 0, + "sells_24h": (p.get("txns") or {}).get("h24", {}).get("sells") or 0, + "dex": p.get("dexId", "unknown"), + "created": p.get("pairCreatedAt") or 0 + } + except Exception as e: + print(f" DexScreener detail error for {mint[:16]}: {e}") + return None + + +def grok_search(query, max_retries=2): + """Search X via Grok API with rate limit retry.""" + if not XAI_API_KEY: + return None + + payload = json.dumps({ + "model": "grok-4-1-fast", + "tools": [{"type": "x_search"}], + "input": query + }).encode() + + for attempt in range(max_retries + 1): + try: + req = Request("https://api.x.ai/v1/responses", + data=payload, + headers={ + 'Content-Type': 'application/json', + 'Authorization': f'Bearer {XAI_API_KEY}' + }) + with urlopen(req, timeout=120) as resp: + result = json.loads(resp.read()) + for item in result.get('output', []): + if 'content' in item: + for c in item['content']: + if c.get('type') == 'output_text': + return c['text'] + return None + except Exception as e: + err_str = str(e) + if '429' in err_str and attempt < max_retries: + wait = 30 * (attempt + 1) + print(f" Grok rate limited (429), retrying in {wait}s (attempt {attempt + 1}/{max_retries})...") + time.sleep(wait) + continue + print(f" Grok error: {e}") + return None + + +def grok_find_early_callers(tokens_batch): + """Use Grok to find early callers for a batch of tokens.""" + if not tokens_batch: + return {} + + # Load tracked callers for cross-reference + tracked = [] + if os.path.exists(EARLY_CALLERS_FILE): + with open(EARLY_CALLERS_FILE) as f: + data = json.load(f) + tracked = [c["handle"] for c in data.get("callers", []) + if c.get("follow_priority") in ("critical", "high")] + + token_list = "\n".join( + f"- ${t.get('symbol', '?')} ({t['mint']}) MC: ${t.get('mc', 0):,.0f}" + for t in tokens_batch + ) + tracked_str = " ".join(tracked) if tracked else "(none tracked yet)" + + query = ( + f"Search X for the earliest callers/buyers of these Solana tokens. " + f"For each, find: who posted about it first, at what MC, any wallet " + f"addresses shared, Solscan/GMGN links, PnL screenshots.\n\n" + f"Tokens:\n{token_list}\n\n" + f"Check if any of these tracked callers mentioned them: {tracked_str}\n\n" + f"Give me: X handle, MC at call, any wallet addresses, and whether " + f"any tracked callers were involved." + ) + + result = grok_search(query) + if not result: + return {} + + return {"raw": result, "tokens": [t["mint"] for t in tokens_batch]} + + +def _init_tokens_registry(): + """Create tokens.json with default structure if it doesn't exist.""" + data = { + "description": "Master registry of ALL token contract addresses scanned or tracked. Updated automatically by scanners.", + "last_updated": datetime.now(timezone.utc).strftime("%Y-%m-%d"), + "tokens": [], + "trending_scanned": [], + "stats": { + "total_tokens": 0, + "pending_helius_scan": 0, + "completed_scans": 0 + } + } + os.makedirs(os.path.dirname(TOKENS_REGISTRY), exist_ok=True) + with open(TOKENS_REGISTRY, 'w') as f: + json.dump(data, f, indent=2) + return data + + +def save_to_tokens_registry(tokens_enriched): + """Save newly discovered CAs to memory/tokens.json for early buyer scanning.""" + if not os.path.exists(TOKENS_REGISTRY): + data = _init_tokens_registry() + else: + try: + with open(TOKENS_REGISTRY) as f: + data = json.load(f) + except Exception: + data = _init_tokens_registry() + + # Ensure required keys exist + data.setdefault('tokens', []) + data.setdefault('stats', {"total_tokens": 0, "pending_helius_scan": 0, "completed_scans": 0}) + + existing_cas = {t['ca'] for t in data.get('tokens', [])} + now = datetime.now(timezone.utc).strftime("%Y-%m-%d") + added = 0 + + for t in tokens_enriched: + mint = t.get("mint", "") + if not mint or mint in existing_cas: + continue + + vol_24h = t.get('vol_24h') or 0 + change_24h = t.get('change_24h') or 0 + + data['tokens'].append({ + 'ca': mint, + 'symbol': t.get('symbol', 'UNKNOWN'), + 'name': t.get('name', 'Unknown'), + 'chain': 'solana', + 'dex': t.get('dex', 'unknown'), + 'mc_at_discovery': t.get('mc') or 0, + 'source': 'trending_scanner', + 'date_added': now, + 'scan_status': 'pending_helius', + 'last_scanned': None, + 'callers': [], + 'notes': f"Discovered by hourly trending scanner. Vol: ${vol_24h:,.0f}, 24h: {change_24h:+.1f}%" + }) + existing_cas.add(mint) + added += 1 + + if added: + data['last_updated'] = now + data['stats']['total_tokens'] = len(data['tokens']) + data['stats']['pending_helius_scan'] = sum(1 for t in data['tokens'] if t.get('scan_status') == 'pending_helius') + with open(TOKENS_REGISTRY, 'w') as f: + json.dump(data, f, indent=2) + + return added + + +def _get_pending_helius_mints(limit=10): + """Get token CAs from tokens.json that still need Helius early buyer scanning.""" + if not os.path.exists(TOKENS_REGISTRY): + return [] + try: + with open(TOKENS_REGISTRY) as f: + data = json.load(f) + pending = [t['ca'] for t in data.get('tokens', []) + if t.get('scan_status') == 'pending_helius' and t.get('ca')] + return pending[:limit] + except Exception: + return [] + + +def filter_interesting(tokens_data): + """Filter for tokens worth investigating (new, pumping, volume).""" + interesting = [] + for t in tokens_data: + mc = t.get("mc") or 0 + vol = t.get("vol_24h") or 0 + change = t.get("change_24h") or 0 + liq = t.get("liq") or 0 + created = t.get("created") or 0 + + # Filters: + # - MC between $50K and $5M (sweet spot for early alpha) + # - Volume > $100K in 24h (real activity) + # - Liquidity > $10K (not dead) + # - Change > 50% in 24h (pumping) OR new (created < 24h ago) + if 50000 <= mc <= 5000000 and vol > 100000 and liq > 10000: + if change > 50 or created > (time.time() - 86400) * 1000: + interesting.append(t) + + return interesting + + +def run_scan(): + """Full trending scan cycle.""" + now = datetime.now(timezone.utc) + print(f"\n{'='*60}") + print(f" TRENDING WALLET SCANNER @ {now.strftime('%Y-%m-%d %H:%M UTC')}") + print(f"{'='*60}") + + scanned = load_scanned() + already_scanned = set(scanned.get("tokens", {}).keys()) + + # Phase 1: DexScreener trending tokens + print("\n [1/4] Checking DexScreener trending Solana tokens...") + trending = dexscreener_trending() + print(f" Found {len(trending)} trending tokens") + + # Filter out already scanned + new_trending = [t for t in trending if t["mint"] not in already_scanned] + print(f" {len(new_trending)} are new (not previously scanned)") + + # Phase 2: Enrich with full DexScreener data + print("\n [2/4] Enriching token data from DexScreener...") + enriched = [] + for t in new_trending[:20]: # Cap at 20 to save API calls + info = enrich_with_dexscreener(t["mint"]) + if info: + enriched.append({**t, **info}) + time.sleep(0.3) + + print(f" Enriched {len(enriched)} tokens") + + # Phase 3: Filter for interesting tokens + print("\n [3/4] Filtering for interesting tokens...") + interesting = filter_interesting(enriched) + print(f" {len(interesting)} tokens pass filters") + + if interesting: + print(f"\n Interesting tokens found:") + for t in interesting: + print(f" ${t.get('symbol', '?'):12s} MC: ${t.get('mc', 0):>10,.0f} | " + f"Vol: ${t.get('vol_24h', 0):>10,.0f} | " + f"24h: {t.get('change_24h', 0):>+8.1f}% | {t['mint'][:20]}...") + + # Phase 4: Grok search for early callers (batch of up to 5) + if interesting and XAI_API_KEY: + print(f"\n [4/4] Searching X for early callers (batch of {min(5, len(interesting))})...") + batch = interesting[:5] + grok_result = grok_find_early_callers(batch) + + if grok_result.get("raw"): + print(f"\n --- Grok Early Caller Results ---") + print(grok_result["raw"][:2000]) + + # Log results + log_trending({ + "date": now.isoformat(), + "tokens_scanned": len(interesting), + "grok_results": grok_result.get("raw", "")[:3000], + "token_mints": [t["mint"] for t in batch] + }) + else: + if not interesting: + print("\n [4/4] No interesting tokens to search for callers.") + else: + print("\n [4/4] XAI_API_KEY not set, skipping Grok search.") + + # Mark all enriched tokens as scanned + for t in enriched: + scanned.setdefault("tokens", {})[t["mint"]] = { + "symbol": t.get("symbol", "?"), + "mc_at_scan": t.get("mc", 0), + "scanned_at": now.isoformat(), + "interesting": t["mint"] in [i["mint"] for i in interesting] + } + save_scanned(scanned) + + # Save ALL enriched tokens (and interesting ones) to tokens.json for early buyer pipeline + all_to_register = enriched if enriched else [] + added = save_to_tokens_registry(all_to_register) + if added: + print(f" Added {added} new CAs to tokens.json registry") + + # Phase 5: If on VPS (Helius available), auto-run early buyer scan + # Scan both interesting tokens AND pending backlog from tokens.json + if HELIUS_API_KEY: + mints_to_scan = [t["mint"] for t in interesting[:6]] if interesting else [] + + # Also pick up pending_helius backlog from tokens.json (max 10 per cycle) + pending_mints = _get_pending_helius_mints(limit=10) + for pm in pending_mints: + if pm not in mints_to_scan: + mints_to_scan.append(pm) + + if mints_to_scan: + print(f"\n [BONUS] Helius available — scanning {len(mints_to_scan)} tokens " + f"({len(interesting)} interesting + {len(pending_mints)} backlog)...") + try: + from scan_early_buyers import scan_tokens + scan_tokens(mints_to_scan[:16]) # Cap at 16 to stay within API limits + except Exception as e: + print(f" Early buyer scan error: {e}") + mints_str = " ".join(mints_to_scan[:6]) + print(f" Run manually: python3 scan_early_buyers.py {mints_str}") + else: + print(f"\n [5/4] No tokens pending Helius scan.") + elif interesting: + mints_str = " ".join(t["mint"] for t in interesting[:6]) + print(f"\n Run on VPS: python3 scan_early_buyers.py {mints_str}") + + print(f"\n Scan complete: {len(enriched)} tokens checked, {len(interesting)} interesting") + return interesting + + +def daemon(): + """Run every hour.""" + print(f"Trending Wallet Scanner started at {datetime.now(timezone.utc).isoformat()}") + print("Scanning every 60 minutes...") + + try: + while True: + try: + interesting = run_scan() + ts = datetime.now(timezone.utc).strftime('%H:%M:%S') + print(f"\n [{ts}] {len(interesting)} interesting tokens found") + except Exception as e: + print(f" Scan error: {e}") + import traceback + traceback.print_exc() + + print(f"\n Next scan in 60 minutes. Press Ctrl+C to stop.") + time.sleep(3600) # 1 hour + except KeyboardInterrupt: + print(f"\n Daemon stopped at {datetime.now(timezone.utc).strftime('%H:%M:%S UTC')}") + + +if __name__ == "__main__": + if len(sys.argv) > 1 and sys.argv[1] == "daemon": + daemon() + else: + run_scan() diff --git a/scan_trigger.json b/scan_trigger.json new file mode 100644 index 0000000..d8e1b5a --- /dev/null +++ b/scan_trigger.json @@ -0,0 +1,8 @@ +{ + "triggered_at": "2026-02-09T12:00:00Z", + "triggered_by": "claude_session_5", + "tokens_file": "tokens_to_scan.txt", + "token_count": 55, + "description": "Re-trigger: Full Helius scan for 9 user CAs + 46 DexScreener trending. All 55 still pending_helius.", + "retry": true +} diff --git a/scan_wallet_positions.py b/scan_wallet_positions.py new file mode 100644 index 0000000..f87b1a0 --- /dev/null +++ b/scan_wallet_positions.py @@ -0,0 +1,308 @@ +#!/usr/bin/env python3 +"""Scan top alpha wallets for recent token positions via Helius RPC.""" + +import json +import time +import os +import sys +from urllib.request import Request, urlopen +from urllib.error import URLError, HTTPError +from datetime import datetime, timezone +from collections import defaultdict + +# Load env +RPC_URL = None +with open("/home/user/Cute-Panel/.env") as f: + for line in f: + if line.startswith("HELIUS_RPC_URL="): + RPC_URL = line.strip().split("=", 1)[1] + break + +if not RPC_URL: + print("ERROR: HELIUS_RPC_URL not found in .env") + sys.exit(1) + +# Load wallets +with open("/home/user/Cute-Panel/memory/smart_wallets.json") as f: + data = json.load(f) + +# Filter Solana wallets and sort by score +solana_wallets = [] +for w in data["wallets"]: + if w.get("chain") != "solana": + continue + if w.get("address", "unknown") == "unknown": + continue + # Normalize score: use alpha_score if present, otherwise reliability_score * 15 + score = w.get("alpha_score", 0) or (w.get("reliability_score", 0) or 0) * 15 + solana_wallets.append({ + "address": w["address"], + "label": w["label"], + "score": score + }) + +solana_wallets.sort(key=lambda x: x["score"], reverse=True) +top_wallets = solana_wallets[:10] + +print(f"=== TOP 10 ALPHA WALLETS BY SCORE ===") +for i, w in enumerate(top_wallets): + print(f" {i+1}. [{w['score']}] {w['label']}: {w['address'][:16]}...") +print() + +def rpc_call(method, params): + """Make a JSON-RPC call to Helius.""" + payload = json.dumps({ + "jsonrpc": "2.0", + "id": 1, + "method": method, + "params": params + }).encode() + req = Request(RPC_URL, data=payload, headers={"Content-Type": "application/json"}) + try: + resp = urlopen(req, timeout=30) + result = json.loads(resp.read()) + if "error" in result: + print(f" RPC error: {result['error']}") + return None + return result.get("result") + except (URLError, HTTPError) as e: + print(f" RPC request failed: {e}") + return None + +# Known token labels (from memory) +KNOWN_TOKENS = { + "B1RB6i7gvxYoyx8Us1eFrJxr7DZv3RzLmBHdfPwDpump": "POKEMON30", + "HjgwHz7QRjdT7DckZL2sJVKZ9iJm6K3oUmHu3bFapump": "ROCK", + "8QJGmTnGhJAfGmkGrscYzrYKacaUCMYTTQQ2Wb3apump": "Maximoto", + "So11111111111111111111111111111111111111112": "SOL (wrapped)", +} + +# Track all token interactions across wallets +all_wallet_tokens = {} # wallet_addr -> list of {mint, action, amount_change, tx_sig, block_time} +token_buyers = defaultdict(list) # mint -> list of wallet labels that bought +SIX_HOURS_AGO = time.time() - (6 * 3600) + +for wi, wallet in enumerate(top_wallets): + addr = wallet["address"] + label = wallet["label"] + print(f"\n{'='*60}") + print(f"[{wi+1}/10] Scanning: {label}") + print(f" Address: {addr}") + + # Step 1: Get recent signatures + time.sleep(0.5) + sigs_result = rpc_call("getSignaturesForAddress", [ + addr, + {"limit": 20} + ]) + + if not sigs_result: + print(" No signatures found or RPC error.") + all_wallet_tokens[addr] = [] + continue + + print(f" Found {len(sigs_result)} recent transactions") + + # Step 2: Get details of most recent 5 transactions + token_interactions = [] + tx_count = 0 + + for sig_info in sigs_result[:5]: + sig = sig_info["signature"] + block_time = sig_info.get("blockTime", 0) + tx_time_str = datetime.fromtimestamp(block_time, tz=timezone.utc).strftime("%Y-%m-%d %H:%M UTC") if block_time else "unknown" + + time.sleep(0.5) + tx_result = rpc_call("getTransaction", [ + sig, + {"encoding": "jsonParsed", "maxSupportedTransactionVersion": 0} + ]) + + if not tx_result: + print(f" TX {sig[:16]}... - failed to fetch") + continue + + tx_count += 1 + meta = tx_result.get("meta", {}) + if not meta: + continue + + pre_balances = meta.get("preTokenBalances", []) + post_balances = meta.get("postTokenBalances", []) + + # Build maps: {(owner, mint): amount} + pre_map = {} + for b in pre_balances: + owner = b.get("owner", "") + mint = b.get("mint", "") + amount = float(b.get("uiTokenAmount", {}).get("uiAmount") or 0) + pre_map[(owner, mint)] = amount + + post_map = {} + for b in post_balances: + owner = b.get("owner", "") + mint = b.get("mint", "") + amount = float(b.get("uiTokenAmount", {}).get("uiAmount") or 0) + post_map[(owner, mint)] = amount + + # Find token changes for THIS wallet + all_mints = set() + for (owner, mint) in list(pre_map.keys()) + list(post_map.keys()): + if owner == addr: + all_mints.add(mint) + + for mint in all_mints: + pre_amt = pre_map.get((addr, mint), 0) + post_amt = post_map.get((addr, mint), 0) + change = post_amt - pre_amt + + if abs(change) < 0.000001: + continue + + # Skip wrapped SOL + if mint == "So11111111111111111111111111111111111111112": + continue + + action = "BUY" if change > 0 else "SELL" + token_name = KNOWN_TOKENS.get(mint, mint[:20] + "...") + is_new = (pre_amt == 0 and post_amt > 0) + is_recent = block_time > SIX_HOURS_AGO if block_time else False + + interaction = { + "mint": mint, + "token_name": token_name, + "action": action, + "pre_amount": pre_amt, + "post_amount": post_amt, + "change": change, + "tx_sig": sig, + "block_time": block_time, + "time_str": tx_time_str, + "is_new_position": is_new, + "is_recent_6h": is_recent + } + token_interactions.append(interaction) + + if action == "BUY": + token_buyers[mint].append({ + "wallet": addr, + "label": label, + "time": block_time, + "is_new": is_new + }) + + flag = "" + if is_new: + flag += " [NEW POSITION]" + if is_recent: + flag += " [LAST 6H]" + + print(f" {action}: {token_name} | change: {change:+.4f} | {tx_time_str}{flag}") + + all_wallet_tokens[addr] = token_interactions + + if not token_interactions: + print(" No token interactions found in recent 5 txs (may be SOL-only transfers)") + + print(f" Processed {tx_count}/5 transactions") + +# === ANALYSIS === +print(f"\n{'='*60}") +print(f"{'='*60}") +print(f"\n=== CONVERGENCE ANALYSIS ===") +print(f"(Tokens bought by 2+ wallets)\n") + +convergence_found = False +for mint, buyers in sorted(token_buyers.items(), key=lambda x: len(x[1]), reverse=True): + if len(buyers) >= 2: + convergence_found = True + token_name = KNOWN_TOKENS.get(mint, mint) + print(f" *** CONVERGENCE: {token_name} ***") + print(f" Mint: {mint}") + print(f" Bought by {len(buyers)} wallets:") + for b in buyers: + t = datetime.fromtimestamp(b["time"], tz=timezone.utc).strftime("%Y-%m-%d %H:%M UTC") if b["time"] else "?" + new_flag = " [NEW POS]" if b["is_new"] else "" + print(f" - {b['label']} at {t}{new_flag}") + print() + +if not convergence_found: + print(" No convergence detected in recent transactions.") + +print(f"\n=== NEW POSITIONS (Last 6 Hours) ===\n") +new_found = False +for addr, interactions in all_wallet_tokens.items(): + wallet_label = next((w["label"] for w in top_wallets if w["address"] == addr), addr[:16]) + for ix in interactions: + if ix["is_recent_6h"] and ix["action"] == "BUY": + new_found = True + new_flag = " [BRAND NEW]" if ix["is_new_position"] else " [ADDING]" + print(f" {wallet_label}: {ix['action']} {ix['token_name']}{new_flag}") + print(f" Mint: {ix['mint']}") + print(f" Amount: {ix['post_amount']:.4f} (change: {ix['change']:+.4f})") + print(f" Time: {ix['time_str']}") + print() + +if not new_found: + print(" No new buys detected in the last 6 hours.") + +print(f"\n=== ALL TOKEN INTERACTIONS SUMMARY ===\n") +for addr, interactions in all_wallet_tokens.items(): + wallet_label = next((w["label"] for w in top_wallets if w["address"] == addr), addr[:16]) + if interactions: + print(f" {wallet_label}:") + for ix in interactions: + flag = "" + if ix["is_new_position"]: flag += " [NEW]" + if ix["is_recent_6h"]: flag += " [6H]" + print(f" {ix['action']:4s} {ix['token_name']} | {ix['change']:+.6f} | {ix['time_str']}{flag}") + print() + +# Save results +results = { + "scan_time": datetime.now(timezone.utc).isoformat(), + "wallets_scanned": len(top_wallets), + "wallet_interactions": {}, + "convergence_tokens": {}, + "new_positions_6h": [] +} + +for addr, interactions in all_wallet_tokens.items(): + wallet_label = next((w["label"] for w in top_wallets if w["address"] == addr), addr[:16]) + results["wallet_interactions"][wallet_label] = [ + { + "mint": ix["mint"], + "action": ix["action"], + "change": ix["change"], + "block_time": ix["block_time"], + "is_new_position": ix["is_new_position"], + "is_recent_6h": ix["is_recent_6h"] + } + for ix in interactions + ] + +for mint, buyers in token_buyers.items(): + if len(buyers) >= 2: + results["convergence_tokens"][mint] = { + "token_name": KNOWN_TOKENS.get(mint, "unknown"), + "buyer_count": len(buyers), + "buyers": [{"label": b["label"], "time": b["time"], "is_new": b["is_new"]} for b in buyers] + } + +for addr, interactions in all_wallet_tokens.items(): + wallet_label = next((w["label"] for w in top_wallets if w["address"] == addr), addr[:16]) + for ix in interactions: + if ix["is_recent_6h"] and ix["action"] == "BUY": + results["new_positions_6h"].append({ + "wallet": wallet_label, + "mint": ix["mint"], + "token_name": ix["token_name"], + "is_new_position": ix["is_new_position"], + "change": ix["change"], + "time": ix["time_str"] + }) + +with open("/home/user/Cute-Panel/memory/wallet_scan_results.json", "w") as f: + json.dump(results, f, indent=2) +print(f"\nResults saved to memory/wallet_scan_results.json") +print(f"Scan complete at {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M UTC')}") diff --git a/scan_x_alpha.py b/scan_x_alpha.py new file mode 100755 index 0000000..96d0c20 --- /dev/null +++ b/scan_x_alpha.py @@ -0,0 +1,422 @@ +#!/usr/bin/env python3 +""" +X Alpha Scanner — "The Degen" Sub-Agent +Hunts for alpha in the Solana trenches via Grok x_search. + +Two scan modes: + 1. Caller scan: Check tracked early-caller accounts for new token mentions + 2. Trending scan: Broad sweep for trending Solana tokens, new launches, pump.fun gems + +Cross-references signals: 2+ callers OR caller + trending = HIGH CONVICTION → auto-buy. + +Usage: + python3 scan_x_alpha.py # Run once (both modes) + python3 scan_x_alpha.py daemon # Run continuously (every 15 min) +""" + +import json +import sys +import os +import re +import time +import traceback +from datetime import datetime, timezone +from urllib.request import Request, urlopen + +# Signal bus — cross-pipeline intelligence +from signal_bus import (cross_reference_all, execute_ultra_buy, log_ultra_signal, + save_scam_addresses, validate_addresses, IGNORE_TICKERS) + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) + +# Load env +env_path = os.path.join(SCRIPT_DIR, '.env') +if os.path.exists(env_path): + with open(env_path) as f: + for line in f: + line = line.strip() + if '=' in line and not line.startswith('#'): + key, val = line.split('=', 1) + key = key.strip() + val = val.strip() + if len(val) >= 2 and val[0] == val[-1] and val[0] in ('"', "'"): + val = val[1:-1] + os.environ[key] = val + +XAI_API_KEY = os.environ.get('XAI_API_KEY', '') +EARLY_CALLERS_FILE = os.path.join(SCRIPT_DIR, 'memory', 'early_callers.json') +X_SIGNALS_FILE = os.path.join(SCRIPT_DIR, 'memory', 'x_signals.jsonl') +X_LAST_CHECK_FILE = os.path.join(SCRIPT_DIR, 'memory', 'x_last_check.json') +WATCHLIST_FILE = os.path.join(SCRIPT_DIR, 'memory', 'watchlist.json') + +# ─── The Degen Agent Persona ─── +# This is the system context fed to Grok for all alpha-hunting queries. +# It makes Grok think like a trench-hardened degen rather than a generic assistant. + +DEGEN_SYSTEM = ( + "You are The Degen — an elite Solana alpha hunter. You live in the trenches: " + "pump.fun, DexScreener, Axiom PULSE, Raydium, Meteora. You track early callers, " + "sniper wallets, and dev wallets. You know the difference between a coordinated " + "pump, an organic discovery, and a rug. You ignore noise and only surface tokens " + "with real momentum or credible callers behind them.\n\n" + "CRITICAL RULES:\n" + "- Always include $TICKER format and Solana contract addresses (CAs) when available\n" + "- Flag scams/rugs explicitly (honeypots, mint authority retained, LP not burned)\n" + "- Distinguish between organic hype vs coordinated shill campaigns\n" + "- Note market cap, holder count, and liquidity if visible\n" + "- If a token is mentioned by known alpha callers, emphasize that\n" + "- If no actionable alpha found, say 'NO ALPHA' — don't invent signals\n" +) + + +def grok_search(query, use_degen=True): + """Search X via Grok API with optional Degen persona.""" + if not XAI_API_KEY: + return None + + if use_degen: + full_input = f"{DEGEN_SYSTEM}\n\nNow execute this search:\n{query}" + else: + full_input = query + + data = json.dumps({ + "model": "grok-4-1-fast", + "tools": [{"type": "x_search"}], + "input": full_input + }).encode() + + try: + req = Request("https://api.x.ai/v1/responses", + data=data, + headers={ + 'Content-Type': 'application/json', + 'Authorization': f'Bearer {XAI_API_KEY}' + }) + with urlopen(req, timeout=120) as resp: + result = json.loads(resp.read()) + + # Extract text from response + for item in result.get('output', []): + if 'content' in item: + for c in item['content']: + if c.get('type') == 'output_text': + return c['text'] + except Exception as e: + print(f" Grok error: {e}") + return None + + +def extract_solana_addresses(text): + """Find Solana addresses in text. Validates via base58 decode (Fix #12).""" + addresses = re.findall(r'[1-9A-HJ-NP-Za-km-z]{32,44}', text) + candidates = [] + for addr in addresses: + if 32 <= len(addr) <= 50: + if not addr.startswith('http') and 'status' not in addr.lower(): + candidates.append(addr) + return validate_addresses(list(set(candidates))) + + +def extract_tickers(text): + """Find $TICKER mentions, excluding common tickers that cause false positives.""" + raw = set(re.findall(r'\$([A-Z]{2,12})', text)) + return list(raw - IGNORE_TICKERS) + + +def load_last_check(): + if os.path.exists(X_LAST_CHECK_FILE): + with open(X_LAST_CHECK_FILE) as f: + return json.load(f) + return {} + + +def save_last_check(data): + with open(X_LAST_CHECK_FILE, 'w') as f: + json.dump(data, f, indent=2) + + +def log_signal(signal): + import fcntl + with open(X_SIGNALS_FILE, 'a') as f: + fcntl.flock(f, fcntl.LOCK_EX) + f.write(json.dumps(signal) + '\n') + fcntl.flock(f, fcntl.LOCK_UN) + + +def scan_caller(handle, priority): + """Check a single X account for new token mentions using The Degen.""" + clean_handle = handle.lstrip('@') + + query = ( + f"Search X for the LATEST posts from @{clean_handle} in the last 6 hours. " + f"This account is a tracked alpha caller (priority: {priority}). " + f"I need to know:\n" + f"1. Did they mention any new crypto tokens? Give me exact $TICKERS and CAs.\n" + f"2. Did they post any pump.fun links, DexScreener links, or buy calls?\n" + f"3. What's the sentiment — are they bullish on something specific?\n" + f"4. Any warnings or sells they mentioned?\n\n" + f"Format: list each token mentioned with its CA if available, plus the context " + f"of what @{clean_handle} said about it.\n" + f"If no new posts in 6 hours, say 'NO ALPHA'." + ) + + print(f" [Degen] Checking {handle} ({priority})...") + result = grok_search(query) + + if not result or 'NO ALPHA' in result.upper() or 'NO NEW POSTS' in result.upper(): + return [] + + tickers = extract_tickers(result) + addresses = extract_solana_addresses(result) + + signals = [] + if tickers or addresses: + signal = { + "date": datetime.now(timezone.utc).isoformat(), + "caller": handle, + "priority": priority, + "tickers": tickers, + "addresses": addresses, + "raw_text": result[:800], + "action": "X_ALPHA_CALL", + "agent": "degen" + } + signals.append(signal) + print(f" FOUND: tickers={tickers}, addresses={len(addresses)}") + + return signals + + +def scan_trending(): + """Broad sweep: what's trending in Solana trenches right now.""" + query = ( + "Search X for the hottest Solana token launches and trending memecoins " + "in the LAST 6 HOURS. I want:\n" + "1. Tokens getting the most organic buzz (not paid shills)\n" + "2. New pump.fun launches with real volume (over $50K)\n" + "3. Any token that multiple credible accounts are talking about\n" + "4. DexScreener trending tokens on Solana\n" + "5. Any new Raydium or Meteora pool launches getting attention\n\n" + "For EACH token give me: $TICKER, CA (contract address) if available, " + "approximate market cap, key callers mentioning it, and your rug assessment " + "(safe/caution/likely rug).\n\n" + "Skip: obvious scams, fake airdrops, phishing links, tokens with zero volume. " + "If nothing notable is trending, say 'NO ALPHA'." + ) + + print(" [Degen] Scanning trending Solana tokens...") + result = grok_search(query) + + if not result or 'NO ALPHA' in result.upper(): + return [] + + tickers = extract_tickers(result) + addresses = extract_solana_addresses(result) + + signals = [] + if tickers or addresses: + signal = { + "date": datetime.now(timezone.utc).isoformat(), + "source": "trending_scan", + "tickers": tickers, + "addresses": addresses, + "raw_text": result[:1200], + "action": "X_TRENDING", + "agent": "degen" + } + signals.append(signal) + print(f" TRENDING: tickers={tickers}, addresses={len(addresses)}") + + return signals + + +def scan_scam_warnings(): + """Check for active scam/rug warnings to avoid bad buys.""" + query = ( + "Search X for the latest Solana SCAM WARNINGS and RUG PULLS " + "in the last 6 hours. I need:\n" + "1. Tokens confirmed rugged — give me their $TICKER and CA\n" + "2. Active phishing campaigns targeting Solana users\n" + "3. Dev wallets dumping on newly launched tokens\n" + "4. Honeypots detected (can buy but not sell)\n\n" + "Give me CAs so I can add them to a blacklist. " + "If no major scams reported, say 'NO ALPHA'." + ) + + print(" [Degen] Checking scam warnings...") + result = grok_search(query) + + if not result or 'NO ALPHA' in result.upper(): + return [] + + addresses = extract_solana_addresses(result) + tickers = extract_tickers(result) + + signals = [] + if tickers or addresses: + signal = { + "date": datetime.now(timezone.utc).isoformat(), + "source": "scam_scan", + "tickers": tickers, + "blacklist_addresses": addresses, + "raw_text": result[:800], + "action": "SCAM_WARNING", + "agent": "degen" + } + signals.append(signal) + print(f" SCAM ALERT: {len(tickers)} tickers, {len(addresses)} addresses flagged") + + return signals + + +def run_scan(): + """Full Degen scan: callers + trending + scam filter.""" + now = datetime.now(timezone.utc) + print(f"\n{'='*50}") + print(f" THE DEGEN — Alpha Scan @ {now.strftime('%Y-%m-%d %H:%M UTC')}") + print(f"{'='*50}") + + all_signals = [] + scam_addresses = set() + + # Phase 1: Scam warnings (build blacklist first) + try: + scam_signals = scan_scam_warnings() + for s in scam_signals: + scam_addresses.update(s.get("blacklist_addresses", [])) + log_signal(s) + all_signals.extend(scam_signals) + # Persist scam blacklist across cycles + if scam_addresses: + save_scam_addresses(list(scam_addresses)) + except Exception as e: + print(f" Scam scan error: {e}") + + time.sleep(2) + + # Phase 2: Scan tracked callers + if os.path.exists(EARLY_CALLERS_FILE): + with open(EARLY_CALLERS_FILE) as f: + data = json.load(f) + + callers = data.get("callers", []) + critical = [c for c in callers if c.get("follow_priority") == "critical"] + high = [c for c in callers if c.get("follow_priority") == "high"] + scan_list = critical + high + + if scan_list: + print(f"\n Scanning {len(scan_list)} tracked callers...") + for caller in scan_list: + handle = caller.get("handle", "") + priority = caller.get("follow_priority", "unknown") + try: + signals = scan_caller(handle, priority) + # Filter out scam addresses + for s in signals: + s["addresses"] = [a for a in s.get("addresses", []) + if a not in scam_addresses] + all_signals.extend(signals) + except Exception as e: + print(f" Error scanning {handle}: {e}") + time.sleep(2) + else: + print(" No early_callers.json found, skipping caller scan") + + time.sleep(2) + + # Phase 3: Broad trending scan + try: + trending = scan_trending() + for s in trending: + s["addresses"] = [a for a in s.get("addresses", []) + if a not in scam_addresses] + all_signals.extend(trending) + except Exception as e: + print(f" Trending scan error: {e}") + + # Phase 4: Log current scan signals to disk (for cross-cycle persistence) + for s in all_signals: + if s.get("action") != "SCAM_WARNING": + log_signal(s) + + # Phase 5: Cross-reference against ALL historical signals (X + wallet) + # This is the core intelligence — checks current scan against: + # - All previous X scan signals (6-hour lookback) + # - ALL wallet buy signals ever recorded (no time limit) + print(f"\n Cross-referencing against historical signals (X + wallets)...") + + # Collect tickers and addresses from current scan + new_tickers = set() + new_mints = set() + for s in all_signals: + if s.get("action") == "SCAM_WARNING": + continue + for t in s.get("tickers", []): + new_tickers.add(t) + for a in s.get("addresses", []): + if a not in scam_addresses: + new_mints.add(a) + + conviction_signals = cross_reference_all( + new_tickers=list(new_tickers), + new_mints=list(new_mints), + source="x_scanner" + ) + + if conviction_signals: + print(f"\n === {len(conviction_signals)} CONVICTION SIGNALS ===") + for sig in conviction_signals: + level = sig["conviction"] + ticker = sig.get("ticker", "UNKNOWN") + reason = sig.get("reason", "") + print(f" [{level}] ${ticker}: {reason}") + + if level == "ULTRA" and not sig.get("already_bought"): + # ULTRA = wallet buy + X caller confirmation = AUTO-BUY + print(f"\n *** ULTRA CONVICTION: ${ticker} ***") + execute_ultra_buy(sig) + elif level == "HIGH": + # HIGH = log (no auto-buy) + log_ultra_signal({**sig, "action": "HIGH_CONVICTION_LOGGED"}) + print(f" [HIGH] Logged: ${ticker}") + else: + print(" No cross-pipeline conviction signals this cycle.") + + # Save last check timestamp + save_last_check({ + "last_scan": now.isoformat(), + "signals_found": len(all_signals), + "conviction_signals": len(conviction_signals) if conviction_signals else 0, + "scam_addresses_blacklisted": len(scam_addresses) + }) + + print(f"\n Scan complete: {len(all_signals)} signals, {len(conviction_signals) if conviction_signals else 0} convictions") + return all_signals + + +def daemon(): + """Run continuously every 15 minutes.""" + print(f"The Degen — X Alpha Scanner started at {datetime.now(timezone.utc).isoformat()}") + print("Scanning every 15 minutes...") + + while True: + try: + signals = run_scan() + ts = datetime.now(timezone.utc).strftime('%H:%M:%S') + if signals: + print(f" [{ts}] {len(signals)} signals found") + else: + print(f" [{ts}] No alpha") + except Exception as e: + print(f" Error: {e}") + traceback.print_exc() + + time.sleep(900) # 15 minutes + + +if __name__ == "__main__": + if len(sys.argv) > 1 and sys.argv[1] == "daemon": + daemon() + else: + signals = run_scan() + print(f"\nTotal signals: {len(signals)}") diff --git a/setup.sh b/setup.sh new file mode 100755 index 0000000..3c91213 --- /dev/null +++ b/setup.sh @@ -0,0 +1,22 @@ +#!/bin/bash +# Tiny bootstrap — run this on VPS: +# apt install -y git && bash <(curl -sL bit.ly/cute-setup) +# OR just type on VPS: +# apt install -y git +# git clone -b claude/crypto-intelligence-system-8oO0s https://github.com/KatriaDopex/Cute-Panel.git /opt/cute-panel +# bash /opt/cute-panel/vps_setup.sh + +set -euo pipefail +BRANCH="claude/crypto-intelligence-system-8oO0s" +REPO="https://github.com/KatriaDopex/Cute-Panel.git" +DIR="/opt/cute-panel" + +apt-get update -qq && apt-get install -y -qq git + +if [ -d "$DIR" ]; then + cd "$DIR" && git pull origin "$BRANCH" +else + git clone -b "$BRANCH" "$REPO" "$DIR" +fi + +bash "$DIR/vps_setup.sh" diff --git a/signal_bus.py b/signal_bus.py new file mode 100644 index 0000000..14ae20d --- /dev/null +++ b/signal_bus.py @@ -0,0 +1,790 @@ +#!/usr/bin/env python3 +""" +Signal Bus — Shared intelligence layer connecting all scanners. + +Both scan_x_alpha.py and monitor_wallets.py import this module. +It provides: + 1. Historical signal lookback (cross-reference across scan cycles) + 2. Cross-pipeline correlation (X mentions + wallet buys together) + 3. Honeypot detection (mint authority, freeze authority, LP check) — FAIL-CLOSED + 4. Duplicate buy prevention with file locking + 5. Conviction scoring with ULTRA threshold requiring 2+ callers OR 2+ wallets + 6. Persistent scam blacklist + 7. Solana address validation (base58 decode) + 9. JSONL log rotation + 10. Failed mint cooldown (no infinite retries) + 11. Common ticker exclusion ($SOL, $ETH, $BTC, etc.) + +CONVICTION LEVELS: + ULTRA = Wallet buy + 2+ X callers, OR 2+ wallets + X caller = AUTO-BUY + HIGH = 3+ wallets OR 2+ callers mention same token = LOG + MEDIUM = 2 wallets OR 1 caller + trending = LOG only +""" + +import json +import os +import time +import fcntl +import logging +import tempfile +import base58 +from datetime import datetime, timezone, timedelta +# ─── Logging ─── +logger = logging.getLogger("signal_bus") +if not logger.handlers: + handler = logging.StreamHandler() + handler.setFormatter(logging.Formatter("[%(asctime)s] %(name)s %(levelname)s: %(message)s")) + logger.addHandler(handler) + logger.setLevel(logging.INFO) + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) + +# Signal files +X_SIGNALS_FILE = os.path.join(SCRIPT_DIR, 'memory', 'x_signals.jsonl') +WALLET_SIGNALS_FILE = os.path.join(SCRIPT_DIR, 'memory', 'wallet_signals.jsonl') +BOUGHT_MINTS_FILE = os.path.join(SCRIPT_DIR, 'memory', 'bought_mints.json') +ULTRA_SIGNALS_FILE = os.path.join(SCRIPT_DIR, 'memory', 'ultra_signals.jsonl') +POSITIONS_FILE = os.path.join(SCRIPT_DIR, 'memory', 'positions.json') +SCAM_BLACKLIST_FILE = os.path.join(SCRIPT_DIR, 'memory', 'scam_blacklist.json') +FAILED_MINTS_FILE = os.path.join(SCRIPT_DIR, 'memory', 'failed_mints.json') + +# Load env +env_path = os.path.join(SCRIPT_DIR, '.env') +if os.path.exists(env_path): + with open(env_path) as f: + for line in f: + line = line.strip() + if '=' in line and not line.startswith('#'): + key, val = line.split('=', 1) + os.environ[key] = val + +HELIUS_RPC = os.environ.get('HELIUS_RPC_URL', '') + +# ─── Lookback windows ─── +X_LOOKBACK_HOURS = 6 # X signals: 6-hour window +WALLET_ULTRA_MAX_AGE = 24 # Wallet signals older than 24hr don't trigger ULTRA + +# Fix #18: Common tickers to exclude (too generic, cause false positives) +IGNORE_TICKERS = { + 'SOL', 'ETH', 'BTC', 'USDC', 'USDT', 'BONK', 'WIF', 'JUP', + 'RAY', 'ORCA', 'PYTH', 'JTO', 'RENDER', 'HNT', 'MOBILE', + 'USD', 'WSOL', 'WETH', 'WBTC', 'DAI', 'BUSD', 'PEPE', + 'DOGE', 'SHIB', 'LINK', 'UNI', 'AAVE', 'CRV', 'APE', +} + +# Fix #14: Failed mint cooldown (hours) +FAILED_MINT_COOLDOWN_HOURS = 6 +MAX_RETRIES_PER_MINT = 3 + + +# ─── Solana Address Validation (Fix #12) ─── + +def is_valid_solana_address(addr): + """Validate that a string is a real Solana address (32-byte base58-encoded public key).""" + try: + decoded = base58.b58decode(addr) + return len(decoded) == 32 + except Exception: + return False + + +def validate_addresses(addresses): + """Filter a list to only valid Solana addresses.""" + return [a for a in addresses if is_valid_solana_address(a)] + + +# ─── Atomic File Writes (Fix #10) ─── + +def atomic_json_write(filepath, data): + """Write JSON atomically: write to temp file, then rename. + Prevents corruption on crash/power loss. + """ + dirpath = os.path.dirname(filepath) + try: + fd, tmp_path = tempfile.mkstemp(dir=dirpath, suffix='.tmp') + with os.fdopen(fd, 'w') as f: + json.dump(data, f) + os.rename(tmp_path, filepath) + except Exception as e: + logger.error(f"Atomic write failed for {filepath}: {e}") + # Clean up temp file if rename failed + try: + os.unlink(tmp_path) + except Exception: + pass + + +# ─── JSONL Log Rotation (Fix #19) ─── + +def rotate_jsonl(filepath, max_lines=5000, keep_lines=2000): + """Rotate JSONL file if it exceeds max_lines. Keeps the most recent keep_lines. + Uses LOCK_EX to prevent data loss from concurrent writers. + """ + try: + if not os.path.exists(filepath): + return + with open(filepath, 'r+') as f: + fcntl.flock(f, fcntl.LOCK_EX) + try: + lines = f.readlines() + if len(lines) <= max_lines: + return + logger.info(f"Rotating {filepath}: {len(lines)} -> {keep_lines} lines") + f.seek(0) + f.truncate() + f.writelines(lines[-keep_lines:]) + finally: + fcntl.flock(f, fcntl.LOCK_UN) + except Exception as e: + logger.error(f"JSONL rotation failed for {filepath}: {e}") + + +_last_rotation_check = 0 +ROTATION_CHECK_INTERVAL = 3600 # Check rotation at most every hour + +def rotate_all_logs(): + """Rotate all JSONL signal files. Rate-limited to once per hour.""" + global _last_rotation_check + now = time.time() + if now - _last_rotation_check < ROTATION_CHECK_INTERVAL: + return + _last_rotation_check = now + rotate_jsonl(X_SIGNALS_FILE) + rotate_jsonl(WALLET_SIGNALS_FILE) + rotate_jsonl(ULTRA_SIGNALS_FILE) + + +# ─── Failed Mint Cooldown (Fix #14) ─── + +def load_failed_mints(): + """Load failed mint attempts with timestamps and retry counts.""" + if not os.path.exists(FAILED_MINTS_FILE): + return {} + try: + with open(FAILED_MINTS_FILE) as f: + return json.load(f) + except Exception as e: + logger.error(f"Failed to load failed_mints: {e}") + return {} + + +def save_failed_mint(mint, reason=""): + """Record a failed buy attempt for a mint.""" + try: + failed = load_failed_mints() + now = datetime.now(timezone.utc).isoformat() + if mint in failed: + failed[mint]["count"] += 1 + failed[mint]["last_attempt"] = now + failed[mint]["last_reason"] = reason + else: + failed[mint] = {"count": 1, "first_attempt": now, "last_attempt": now, "last_reason": reason} + atomic_json_write(FAILED_MINTS_FILE, failed) + except Exception as e: + logger.error(f"Failed to save failed_mint: {e}") + + +def is_mint_in_cooldown(mint): + """Check if a mint is in cooldown after failed attempts.""" + failed = load_failed_mints() + if mint not in failed: + return False, "" + entry = failed[mint] + if entry["count"] >= MAX_RETRIES_PER_MINT: + return True, f"max_retries_exceeded:{entry['count']}" + try: + last = datetime.fromisoformat(entry["last_attempt"]) + cooldown_until = last + timedelta(hours=FAILED_MINT_COOLDOWN_HOURS) + if datetime.now(timezone.utc) < cooldown_until: + return True, f"cooldown_until:{cooldown_until.isoformat()}" + except Exception: + pass + return False, "" + + +# ─── Timestamp Parsing (Fix #16) ─── + +def parse_iso_timestamp(ts_str): + """Parse ISO timestamp string to datetime. Handles timezone variants.""" + if not ts_str: + return None + try: + # Handle both +00:00 and Z formats + ts_str = ts_str.replace('Z', '+00:00') + return datetime.fromisoformat(ts_str) + except Exception: + return None + + +# ─── Signal Loading ─── + +def load_recent_x_signals(hours=X_LOOKBACK_HOURS): + """Load X signals from last N hours.""" + cutoff = datetime.now(timezone.utc) - timedelta(hours=hours) + signals = [] + if not os.path.exists(X_SIGNALS_FILE): + return signals + try: + with open(X_SIGNALS_FILE) as f: + for line in f: + line = line.strip() + if not line: + continue + try: + s = json.loads(line) + sig_date = parse_iso_timestamp(s.get("date", "")) + if sig_date and sig_date > cutoff: + signals.append(s) + except json.JSONDecodeError: + continue + except Exception as e: + logger.error(f"Failed to load X signals: {e}") + return signals + + +def load_recent_wallet_signals(hours=None): + """Load wallet signals. No time limit by default — wallets are permanent alpha. + Every wallet buy ever recorded is kept for cross-reference. + Only use hours param if you need recent-only for rate limiting. + """ + cutoff = None + if hours is not None: + cutoff = datetime.now(timezone.utc) - timedelta(hours=hours) + signals = [] + if not os.path.exists(WALLET_SIGNALS_FILE): + return signals + try: + with open(WALLET_SIGNALS_FILE) as f: + for line in f: + line = line.strip() + if not line: + continue + try: + s = json.loads(line) + if cutoff: + sig_date = parse_iso_timestamp(s.get("date", "")) + # Skip signals with unparseable dates when cutoff is set + # (consistent with load_recent_x_signals behavior) + if not sig_date or sig_date < cutoff: + continue + signals.append(s) + except json.JSONDecodeError: + continue + except Exception as e: + logger.error(f"Failed to load wallet signals: {e}") + return signals + + +# ─── Bought Mints Management ─── + +def load_bought_mints(): + """Load set of mints we've already bought or attempted. + ALWAYS merges bought_mints.json + positions.json (no early return). + """ + bought = set() + # Source 1: bought_mints.json + if os.path.exists(BOUGHT_MINTS_FILE): + try: + with open(BOUGHT_MINTS_FILE) as f: + fcntl.flock(f, fcntl.LOCK_SH) + bought.update(json.load(f)) + fcntl.flock(f, fcntl.LOCK_UN) + except Exception as e: + logger.error(f"Failed to load bought_mints.json: {e}") + # Source 2: positions.json (ALWAYS checked) + if os.path.exists(POSITIONS_FILE): + try: + with open(POSITIONS_FILE) as f: + fcntl.flock(f, fcntl.LOCK_SH) + data = json.load(f) + fcntl.flock(f, fcntl.LOCK_UN) + for p in data.get("positions", []): + if p.get("mint"): + bought.add(p["mint"]) + except Exception as e: + logger.error(f"Failed to load positions.json: {e}") + return bought + + +def save_bought_mint(mint): + """Mark a mint as bought. Uses atomic write to prevent corruption.""" + try: + # Read with exclusive lock + bought = set() + if os.path.exists(BOUGHT_MINTS_FILE): + fd = os.open(BOUGHT_MINTS_FILE, os.O_RDWR) + with os.fdopen(fd, 'r+') as f: + fcntl.flock(f, fcntl.LOCK_EX) + try: + content = f.read() + bought = set(json.loads(content)) if content.strip() else set() + except (json.JSONDecodeError, ValueError): + bought = set() + bought.add(mint) + f.seek(0) + f.truncate() + json.dump(list(bought), f) + fcntl.flock(f, fcntl.LOCK_UN) + else: + # Fix #10: Create atomically (no TOCTOU race) + atomic_json_write(BOUGHT_MINTS_FILE, [mint]) + except Exception as e: + logger.error(f"Failed to save bought_mint {mint}: {e}") + + +def remove_bought_mint(mint): + """Remove a mint from bought list (used when buy fails).""" + try: + if not os.path.exists(BOUGHT_MINTS_FILE): + return + with open(BOUGHT_MINTS_FILE, 'r+') as f: + fcntl.flock(f, fcntl.LOCK_EX) + try: + bought = set(json.loads(f.read())) + except (json.JSONDecodeError, ValueError): + bought = set() + bought.discard(mint) + f.seek(0) + f.truncate() + json.dump(list(bought), f) + fcntl.flock(f, fcntl.LOCK_UN) + except Exception as e: + logger.error(f"Failed to remove bought_mint {mint}: {e}") + + +def log_ultra_signal(signal): + """Log ULTRA/HIGH conviction signals to dedicated file.""" + try: + with open(ULTRA_SIGNALS_FILE, 'a') as f: + fcntl.flock(f, fcntl.LOCK_EX) + f.write(json.dumps(signal) + '\n') + fcntl.flock(f, fcntl.LOCK_UN) + except Exception as e: + logger.error(f"Failed to log ultra signal: {e}") + + +# ─── Persistent Scam Blacklist ─── + +def load_scam_blacklist(): + """Load persistent scam blacklist (addresses flagged across all scan cycles).""" + if not os.path.exists(SCAM_BLACKLIST_FILE): + return set() + try: + with open(SCAM_BLACKLIST_FILE) as f: + data = json.load(f) + cutoff = datetime.now(timezone.utc) - timedelta(days=7) + active = [] + for e in data: + dt = parse_iso_timestamp(e.get("date", "")) + if dt and dt > cutoff: + active.append(e) + return set(e["address"] for e in active) + except Exception as e: + logger.error(f"Failed to load scam blacklist: {e}") + return set() + + +def save_scam_addresses(addresses): + """Add new scam addresses to persistent blacklist. + Uses LOCK_EX around entire read-modify-write to prevent lost updates. + """ + if not addresses: + return + try: + now = datetime.now(timezone.utc).isoformat() + if os.path.exists(SCAM_BLACKLIST_FILE): + with open(SCAM_BLACKLIST_FILE, 'r+') as f: + fcntl.flock(f, fcntl.LOCK_EX) + try: + try: + existing = json.load(f) + except (json.JSONDecodeError, ValueError): + existing = [] + existing_addrs = set(e["address"] for e in existing) + for addr in addresses: + if addr not in existing_addrs: + existing.append({"address": addr, "date": now}) + f.seek(0) + f.truncate() + json.dump(existing, f) + finally: + fcntl.flock(f, fcntl.LOCK_UN) + else: + new_data = [{"address": addr, "date": now} for addr in addresses] + atomic_json_write(SCAM_BLACKLIST_FILE, new_data) + except Exception as e: + logger.error(f"Failed to save scam addresses: {e}") + + +# ─── Honeypot Detection (FAIL-CLOSED) + LP Check (Fix #8) ─── + +def check_honeypot(mint): + """Check if token is a honeypot before buying. + Returns (is_safe, reason) tuple. + FAIL-CLOSED: if we can't verify, we DON'T buy. + Also checks for minimum liquidity (LP burn/lock). + """ + if not HELIUS_RPC: + return False, "no_rpc_cannot_verify" + + try: + data = json.dumps({ + "jsonrpc": "2.0", "id": 1, + "method": "getAccountInfo", + "params": [mint, {"encoding": "jsonParsed"}] + }).encode() + req = Request(HELIUS_RPC, data=data, headers={'Content-Type': 'application/json'}) + with urlopen(req, timeout=15) as resp: + result = json.loads(resp.read()) + + account = result.get("result", {}).get("value", {}) + if not account: + return False, "mint_account_not_found" + + parsed = account.get("data", {}).get("parsed", {}) + if not parsed: + return False, "unparseable_mint_data" + + info = parsed.get("info", {}) + + # Check mint authority (if retained, dev can mint infinite tokens = rug) + mint_authority = info.get("mintAuthority") + if mint_authority: + return False, f"mint_authority_retained:{mint_authority[:12]}" + + # Check freeze authority (if set, dev can freeze your tokens) + freeze_authority = info.get("freezeAuthority") + if freeze_authority: + return False, f"freeze_authority_set:{freeze_authority[:12]}" + + # Fix #8: Check supply — zero supply = fake token + supply = int(info.get("supply", 0)) + if supply == 0: + return False, "zero_supply" + + return True, "safe" + except Exception as e: + return False, f"check_failed:{str(e)[:50]}" + + +def check_liquidity(mint): + """Check if token has minimum liquidity via Jupiter price API. + Returns (has_liquidity, estimated_value_usd). + """ + try: + url = f"https://api.jup.ag/price/v2?ids={mint}" + req = Request(url, headers={'Accept': 'application/json'}) + with urlopen(req, timeout=10) as resp: + data = json.loads(resp.read()) + price_data = data.get("data", {}).get(mint, {}) + price = float(price_data.get("price", 0)) + if price <= 0: + return False, 0 + return True, price + except Exception as e: + logger.warning(f"Liquidity check failed for {mint}: {e}") + return False, 0 + + +# ─── Core Cross-Reference Engine ─── + +def cross_reference_all(new_tickers=None, new_mints=None, source="unknown"): + """Cross-reference new signals against ALL historical signals (X + wallet). + + This is the core function. It checks: + 1. Did any tracked X callers recently mention the same token? + 2. Did any tracked wallets recently buy the same token? + 3. Is it trending AND mentioned by a caller? + + Returns list of conviction signals with levels: ULTRA, HIGH, MEDIUM. + """ + if new_tickers is None: + new_tickers = [] + if new_mints is None: + new_mints = [] + + # Fix #18: Filter common tickers + new_tickers = [t for t in new_tickers if t not in IGNORE_TICKERS] + + # Fix #12: Validate addresses + new_mints = validate_addresses(new_mints) + + results = [] + bought = load_bought_mints() + scam_blacklist = load_scam_blacklist() + + # Rotate logs periodically + rotate_all_logs() + + # Load all recent signals from both pipelines + x_signals = load_recent_x_signals() + wallet_signals = load_recent_wallet_signals() + + # Fix #5: Load wallet signals with ULTRA age limit for ULTRA scoring + wallet_signals_recent = load_recent_wallet_signals(hours=WALLET_ULTRA_MAX_AGE) + + # Build lookup: ticker -> [sources] + # Fix #7: Only associate addresses from SINGLE-ticker signals to prevent cross-contamination + x_ticker_sources = {} + for s in x_signals: + if s.get("action") == "SCAM_WARNING": + continue + src = s.get("caller", s.get("source", "unknown")) + signal_tickers = s.get("tickers", []) + signal_addrs = s.get("addresses", []) + for ticker in signal_tickers: + if ticker in IGNORE_TICKERS: + continue + if ticker not in x_ticker_sources: + x_ticker_sources[ticker] = {"sources": [], "addresses": []} + x_ticker_sources[ticker]["sources"].append(src) + # Fix #7: Only associate addresses if this is a single-ticker signal + if len(signal_tickers) == 1: + x_ticker_sources[ticker]["addresses"].extend(signal_addrs) + + # Build lookup: mint -> [wallet labels] (all-time for general, recent for ULTRA) + wallet_mint_sources = {} + wallet_mint_sources_recent = {} # Fix #5: for ULTRA scoring only + + for s in wallet_signals: + if s.get("action") != "ALPHA_WALLET_BUY": + continue + mint = s.get("mint", "") + if mint in scam_blacklist: + continue + label = s.get("wallet_label", "unknown") + if mint not in wallet_mint_sources: + wallet_mint_sources[mint] = [] + wallet_mint_sources[mint].append(label) + + for s in wallet_signals_recent: + if s.get("action") != "ALPHA_WALLET_BUY": + continue + mint = s.get("mint", "") + if mint in scam_blacklist: + continue + label = s.get("wallet_label", "unknown") + if mint not in wallet_mint_sources_recent: + wallet_mint_sources_recent[mint] = [] + wallet_mint_sources_recent[mint].append(label) + + # ─── TICKER LOOP: Check new tickers against wallet buys ─── + for ticker in new_tickers: + x_data = x_ticker_sources.get(ticker, {"sources": [], "addresses": []}) + all_x_sources = list(set(x_data["sources"])) + all_addresses = list(set(x_data["addresses"])) + + # Filter out scam addresses and validate + all_addresses = [a for a in all_addresses if a not in scam_blacklist and is_valid_solana_address(a)] + + # Count callers (exclude "trending_scan" as a caller) + caller_sources = [s for s in all_x_sources if s not in ("trending_scan", "scam_scan", "unknown")] + trending_mentioned = "trending_scan" in all_x_sources + + # Check if ANY address FOR THIS TICKER matches a wallet buy + wallet_confirmation = False + wallet_confirmation_recent = False + wallet_names = [] + for addr in all_addresses: + if addr in wallet_mint_sources: + wallet_confirmation = True + wallet_names.extend(wallet_mint_sources[addr]) + # Fix #5: Check recent wallet signals for ULTRA eligibility + if addr in wallet_mint_sources_recent: + wallet_confirmation_recent = True + + wallet_names = list(set(wallet_names)) + + # ─── CONVICTION SCORING (Fix #13: Raised ULTRA threshold) ─── + if wallet_confirmation_recent and len(caller_sources) >= 2: + conviction = "ULTRA" + elif wallet_confirmation_recent and len(caller_sources) >= 1 and len(wallet_names) >= 2: + conviction = "ULTRA" + elif len(caller_sources) >= 2: + conviction = "HIGH" + elif len(caller_sources) >= 1 and trending_mentioned: + conviction = "HIGH" + elif len(wallet_names) >= 3: + conviction = "HIGH" + elif len(wallet_names) >= 2: + conviction = "MEDIUM" + elif len(caller_sources) >= 1: + conviction = "MEDIUM" + else: + continue + + skip_buy = any(addr in bought for addr in all_addresses) + + results.append({ + "date": datetime.now(timezone.utc).isoformat(), + "ticker": ticker, + "conviction": conviction, + "x_callers": caller_sources, + "x_caller_count": len(caller_sources), + "wallet_buyers": wallet_names, + "wallet_count": len(wallet_names), + "trending": trending_mentioned, + "addresses": all_addresses[:5], + "source_pipeline": source, + "already_bought": skip_buy, + "reason": build_reason(conviction, caller_sources, wallet_names, trending_mentioned) + }) + + # ─── MINT LOOP: Check new mints against X callers ─── + for mint in new_mints: + if mint in bought or mint in scam_blacklist: + continue + + x_mentions = [] + x_tickers_for_mint = [] + for s in x_signals: + if s.get("action") == "SCAM_WARNING": + continue + if mint in s.get("addresses", []): + src = s.get("caller", s.get("source", "unknown")) + x_mentions.append(src) + x_tickers_for_mint.extend(s.get("tickers", [])) + + wallet_names = wallet_mint_sources.get(mint, []) + wallet_names_recent = wallet_mint_sources_recent.get(mint, []) + wallet_count = len(wallet_names) + wallet_count_recent = len(wallet_names_recent) + + caller_mentions = [m for m in x_mentions if m not in ("trending_scan", "scam_scan", "unknown")] + trending_mentioned = "trending_scan" in x_mentions + + # Symmetric conviction scoring (Fix #13: Raised ULTRA threshold) + if len(set(caller_mentions)) >= 2 and wallet_count_recent >= 1: + conviction = "ULTRA" + elif len(set(caller_mentions)) >= 1 and wallet_count_recent >= 2: + conviction = "ULTRA" + elif len(set(caller_mentions)) >= 2: + conviction = "HIGH" + elif len(set(caller_mentions)) >= 1 and trending_mentioned: + conviction = "HIGH" + elif wallet_count >= 3: + conviction = "HIGH" + elif wallet_count >= 2: + conviction = "MEDIUM" + elif len(set(caller_mentions)) >= 1: + conviction = "MEDIUM" + else: + continue + + already_covered = any(mint in r.get("addresses", []) for r in results) + if already_covered: + continue + + results.append({ + "date": datetime.now(timezone.utc).isoformat(), + "mint": mint, + "ticker": x_tickers_for_mint[0] if x_tickers_for_mint else "UNKNOWN", + "conviction": conviction, + "x_callers": list(set(caller_mentions)), + "x_caller_count": len(set(caller_mentions)), + "wallet_buyers": list(set(wallet_names)), + "wallet_count": wallet_count, + "trending": trending_mentioned, + "addresses": [mint], + "source_pipeline": source, + "already_bought": False, + "reason": build_reason(conviction, caller_mentions, wallet_names, trending_mentioned) + }) + + return results + + +def build_reason(conviction, callers, wallets, trending): + parts = [] + if callers: + parts.append(f"{len(callers)} X caller(s): {', '.join(callers[:3])}") + if wallets: + parts.append(f"{len(wallets)} wallet(s): {', '.join(wallets[:3])}") + if trending: + parts.append("trending on X") + return f"[{conviction}] {' + '.join(parts)}" + + +def should_auto_buy(signal): + """Only ULTRA conviction with honeypot check passes = auto-buy. + Returns (should_buy, reason) tuple. + """ + if signal.get("already_bought"): + return False, "already_bought" + + if signal.get("conviction") != "ULTRA": + return False, f"conviction_too_low:{signal.get('conviction')}" + + addresses = signal.get("addresses", []) + if not addresses: + return False, "no_address" + + mint = addresses[0] + + # Fix #12: Validate address + if not is_valid_solana_address(mint): + return False, f"invalid_solana_address:{mint[:20]}" + + # Re-check bought_mints with lock (prevents race condition between daemons) + bought = load_bought_mints() + if mint in bought: + return False, "already_bought_race_check" + + # Fix #14: Check failed mint cooldown + in_cooldown, cooldown_reason = is_mint_in_cooldown(mint) + if in_cooldown: + return False, f"cooldown:{cooldown_reason}" + + # Honeypot check (FAIL-CLOSED: errors = don't buy) + is_safe, reason = check_honeypot(mint) + if not is_safe: + return False, f"honeypot:{reason}" + + # Fix #8: Liquidity check + has_liq, price = check_liquidity(mint) + if not has_liq: + return False, "no_liquidity_on_jupiter" + + return True, "ULTRA_conviction_safe" + + +def execute_ultra_buy(signal): + """Execute an ULTRA conviction buy. Returns success boolean. + Fix #1: No retry in this function — let next scan cycle retry naturally. + """ + should_buy, reason = should_auto_buy(signal) + + if not should_buy: + logger.info(f"SKIP buy: {reason}") + log_ultra_signal({**signal, "action": "SKIP", "skip_reason": reason}) + return False + + mint = signal["addresses"][0] + ticker = signal.get("ticker", "UNKNOWN") + + logger.info(f"ULTRA CONVICTION: ${ticker} | {mint}") + print(f"\n *** ULTRA CONVICTION: ${ticker} ***") + print(f" Reason: {signal.get('reason', '')}") + print(f" Mint: {mint}") + + # Mark as bought BEFORE execution (with file locking to prevent race) + save_bought_mint(mint) + + try: + from trade_executor import cmd_buy + success = cmd_buy(mint) + log_ultra_signal({ + **signal, + "action": "BUY_EXECUTED" if success else "BUY_FAILED", + "mint": mint + }) + if not success: + remove_bought_mint(mint) + save_failed_mint(mint, "buy_returned_false") + return success + except Exception as e: + logger.error(f"Buy error for ${ticker}: {e}") + log_ultra_signal({**signal, "action": "BUY_ERROR", "error": str(e)}) + remove_bought_mint(mint) + save_failed_mint(mint, str(e)[:100]) + return False diff --git a/sniper_daemon.sh b/sniper_daemon.sh new file mode 100755 index 0000000..6a03fd1 --- /dev/null +++ b/sniper_daemon.sh @@ -0,0 +1,118 @@ +#!/bin/bash +# sniper_daemon.sh — Master daemon that runs all monitoring processes +# Runs: wallet monitor (every 1 min) + X scanner (every 15 min) +# +# Usage: +# ./sniper_daemon.sh start # Start all monitors in background +# ./sniper_daemon.sh stop # Stop all monitors +# ./sniper_daemon.sh status # Check if running + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PID_DIR="$SCRIPT_DIR/.pids" +LOG_DIR="$SCRIPT_DIR/logs" + +mkdir -p "$PID_DIR" "$LOG_DIR" + +if [ -f "$SCRIPT_DIR/.env" ]; then + set -a; source "$SCRIPT_DIR/.env"; set +a +fi + +start_daemon() { + echo "Starting Sniper Daemon..." + + # Start wallet monitor (every 1 min) + if [ -f "$PID_DIR/wallet_monitor.pid" ] && kill -0 "$(cat "$PID_DIR/wallet_monitor.pid")" 2>/dev/null; then + echo " Wallet monitor already running (PID $(cat "$PID_DIR/wallet_monitor.pid"))" + else + nohup python3 "$SCRIPT_DIR/monitor_wallets.py" daemon \ + >> "$LOG_DIR/wallet_monitor.log" 2>&1 & + echo $! > "$PID_DIR/wallet_monitor.pid" + echo " Wallet monitor started (PID $!)" + fi + + # Start X alpha scanner (every 15 min) + if [ -f "$PID_DIR/x_scanner.pid" ] && kill -0 "$(cat "$PID_DIR/x_scanner.pid")" 2>/dev/null; then + echo " X scanner already running (PID $(cat "$PID_DIR/x_scanner.pid"))" + else + nohup python3 "$SCRIPT_DIR/scan_x_alpha.py" daemon \ + >> "$LOG_DIR/x_scanner.log" 2>&1 & + echo $! > "$PID_DIR/x_scanner.pid" + echo " X alpha scanner started (PID $!)" + fi + + echo "" + echo "Logs:" + echo " tail -f $LOG_DIR/wallet_monitor.log" + echo " tail -f $LOG_DIR/x_scanner.log" + echo "" + echo "Trading enabled: $TRADING_ENABLED" + echo "Wallet: $(python3 -c " +import base58, nacl.signing, os +sk = base58.b58decode(os.environ.get('SOL_PRIVATE_KEY','')) +pk = nacl.signing.SigningKey(sk[:32]).verify_key +print(base58.b58encode(bytes(pk)).decode()) +" 2>/dev/null || echo 'error')" +} + +stop_daemon() { + echo "Stopping Sniper Daemon..." + + for pidfile in "$PID_DIR"/*.pid; do + if [ -f "$pidfile" ]; then + pid=$(cat "$pidfile") + name=$(basename "$pidfile" .pid) + if kill -0 "$pid" 2>/dev/null; then + kill "$pid" + echo " Stopped $name (PID $pid)" + else + echo " $name was not running" + fi + rm -f "$pidfile" + fi + done +} + +status_daemon() { + echo "Sniper Daemon Status:" + echo "" + + for pidfile in "$PID_DIR"/*.pid; do + if [ -f "$pidfile" ]; then + pid=$(cat "$pidfile") + name=$(basename "$pidfile" .pid) + if kill -0 "$pid" 2>/dev/null; then + echo " $name: RUNNING (PID $pid)" + else + echo " $name: STOPPED (stale PID $pid)" + fi + fi + done + + if [ ! -f "$PID_DIR/wallet_monitor.pid" ] && [ ! -f "$PID_DIR/x_scanner.pid" ]; then + echo " No daemons running" + fi + + echo "" + echo "Trading enabled: ${TRADING_ENABLED:-false}" + + # Show last activity + if [ -f "$LOG_DIR/wallet_monitor.log" ]; then + echo "" + echo "Last wallet monitor activity:" + tail -3 "$LOG_DIR/wallet_monitor.log" 2>/dev/null + fi + if [ -f "$LOG_DIR/x_scanner.log" ]; then + echo "" + echo "Last X scanner activity:" + tail -3 "$LOG_DIR/x_scanner.log" 2>/dev/null + fi +} + +case "${1:-status}" in + start) start_daemon ;; + stop) stop_daemon ;; + status) status_daemon ;; + *) + echo "Usage: $0 {start|stop|status}" + ;; +esac diff --git a/tokens_to_scan.txt b/tokens_to_scan.txt new file mode 100644 index 0000000..4d711c6 --- /dev/null +++ b/tokens_to_scan.txt @@ -0,0 +1,55 @@ +HBQB6j9RkAroc3wotE94dyFBx2SntfnVNrKLiJSBpump +9gPMDSwfwtByWSgBxGCpFJE3q91ap58e3VFMprshpump +9S8edqWxoWz5LYLnxWUmWBJnePg35WfdYQp7HQkUpump +4YxQxZLkfwmhbw5W9HaDpUYX5zo1J8ycqBSJWjRF6Mby +71mfKdePwyWXtiF1mqu2aaCdMKnKuN664z2vEM2Xpump +FzLMPzqz9Ybn26qRzPKDKwsLV6Kpvugh31jF7T7npump +9XR4tUgg3yLMRV4D9cx5RZqoDg6AGNxPsAP9ZFnspump +2NGBAfNMXBU85gjqYutA39b6BCBG5i5MZ4Jvjtdcpump +EKwF2HD6X4rHHr4322EJeK9QBGkqhpHZQSanSUmWkecG +8UDpkzHn1zdsJG3vZGn7GGpA3xhsqRYT1SEni1nmpump +14uHdFLjwUrDoTmuYkprYar4uwK5YQDPVKVagbHtpump +HYdBgwSvEWHJKsagcwhKNNKThe91qYPk1aDvZjqzpump +8opvqaWysX1oYbXuTL8PHaoaTiXD69VFYAX4smPebonk +6sQFHSpofBoerhKm5QmcoMbrHi5V3hLCUiQes4Upump +ECgC6Avhwai9rHUQH3CgZ8TX29qXD4rAReF8tvFVpump +BAuqzCH4gm2LrdUoWR33VabbGhoBK5iP7iugvqPDpump +GDmSzyg3F3CqgusT4CcxhjaKKfaucN98L4EUePeqpump +CV38eqqRKfhvqZ5yyuwuNFGTfof1wYvNguJXt2mZDRMj +9ANxaLYH4cFzWKoMnwK4CSwPGHE39h97dk9S6dYkpump +6GTBQj1w2AH7xTLrCGijFTHFyjBUZL1Zq2jX1AdSpump +89q6aHpZ1fXhuwpnrBgqmCvuAX4GaCrRPQNp5xVHpump +7k74YrjdUY6EaATMUXQ57HjUURm8V9SFYksfa6prpump +ARv3GX3PkKMkQXSxvTSwKnRMwrVNvQtm5YfTrkkppump +8MdkXe5G77xaMheVQxLqAYV8e2m2Dfc5ZbuXup2epump +CgghGMyu1cnSxP1GnZ5aurLrTbCQvH6vjABgZHMApump +Hmb4JjcBSvLdbtxiTk9sLFp5AmirofEu5vQpEzsDpump +GP77ba3oTaFZf8jErPUDek4bNpAk7w5NjhpnrcShpump +6YdDyLQ5RnKpjcVFCKVe8GURVxFsAVhXwArW9wrRpump +Hoi9Lo8s2PP7EM9mv9bZjQ3aSB7ijyS238sTqQjbpump +Kjfbsbp182yfhECYJG1fHxHXqfY2xCwKVR67oyCpump +3B1ijcocM5EDga6XxQ7JLW7weocQPWWjuhBYG8Vepump +8JFCj7znRhXr3mu29DYWAmS8dhWnkAXUzZZwoR9EHFpX +4icSDMih3sAvz4MpeC3vK5XBZm8XqCEtQmvDitpSpump +6r5fNWCPdXbU9qk3rmBoHHAEzqMBosxwbm3xKYuMpump +7PMX6NsCCGhUJjAxqRsMqhnEapXrWWLMMSBM1duPpump +AjqqPdzMmJF89NBKn5X7SANSWiJa6rG99RC5nRwXpump +5fPCdp2z2w51Nq7FLcQ6Yxiwj1byt9d7xYvUWUw3pump +39LcFNHBtSQCVq9kCbNGBgyQDqyhMU8Ktji9uRPwpump +BwwZSATzLvwAaMufo6jPqux1d5zZMynFbKkNPGdcC8FQ +3TqE8pDPyRuH6SV7igTGZJ5XsTF88yTYq7NKxqYQpump +5EWVPhbNfiTibCiF92LZCuzUvPVyJawha2fiqCTWpump +WwFYrQDbY23micBixSHgGKCgbU1xnx9RPfnZ76Rpump +4AdEATYASNWXRqNLVMpLsWBVCxVC29QPB6KGniUmpump +HMJTbaWRTXmHiKTFQ3fQbUo8JQDk2APn9VmU9VHFpump +3oXdBSBhP7RFgB8hnveBKbhcwK6csiCCLftbg7XXrYWh +B6MbTs5V3z5WG73uYxhFgdPNtFhQK8neMYhX4EL8pump +9tDaDYgaU67fnu2k5NhXgrP7NxXgWXxmtt5gHhgYpump +8ATqb36sxJ2nYsQnKuWVtqt3HSQfYXP7KRmsRpEJpump +7x2KLwHYdsS7FcowLheZAsH7iPrktYDCPc7whyo9Mg6B +9E8BL6dsewk7g89i9Tq45YwC94EgACXCKoLuiowMpump +F8Xw9DGmDvGRB6VSyCRsF3e2srCttyyLyK1oqBbKpump +3m7rPnpGiaeZD93oUs3ruLshQHLcPUH58WSQv9uEpump +HdBmDxNwvUmg4PetKdf6JKxXcmRpxL6ogkT5YChLpump +22W5ZqYkJwtcbS7rsfnHdHzoWTZZJMwcFstUwFoypump +3p6K6Dh9mbrhFsvSQA4ujYkCYznL5z2MaNYgKyM6pump diff --git a/trade_executor.py b/trade_executor.py new file mode 100755 index 0000000..ec001c0 --- /dev/null +++ b/trade_executor.py @@ -0,0 +1,826 @@ +#!/usr/bin/env python3 +""" +Trade Executor — Autonomous Solana token buyer/seller +Routes: Jupiter V6 API (primary) → pump.fun direct (pre-migration) → Meteora (bags) + +Features: + - Transaction confirmation (getSignatureStatuses polling) + - File-locked positions.json (safe for concurrent daemon access) + - Automated stop-loss (-50%) and take-profit (+100%) via check_positions() + - Proper logging (no silent exception swallowing) + +Usage: + python3 trade_executor.py buy [amount_sol] # Buy token + python3 trade_executor.py sell [pct] # Sell token (100=all) + python3 trade_executor.py balance # Check wallet + python3 trade_executor.py positions # Show open positions + python3 trade_executor.py pnl # Show PNL summary + python3 trade_executor.py check # Check SL/TP for all positions +""" + +import json +import sys +import os +import time +import base58 +import struct +import fcntl +import logging +from datetime import datetime, timezone +from urllib.request import Request, urlopen +from urllib.error import URLError, HTTPError +import nacl.signing + +# ─── Logging (Fix #20) ─── +logger = logging.getLogger("trade_executor") +if not logger.handlers: + handler = logging.StreamHandler() + handler.setFormatter(logging.Formatter("[%(asctime)s] %(name)s %(levelname)s: %(message)s")) + logger.addHandler(handler) + logger.setLevel(logging.INFO) + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) + +# Load env +env_path = os.path.join(SCRIPT_DIR, '.env') +if os.path.exists(env_path): + with open(env_path) as f: + for line in f: + line = line.strip() + if '=' in line and not line.startswith('#'): + key, val = line.split('=', 1) + key = key.strip() + val = val.strip() + if len(val) >= 2 and val[0] == val[-1] and val[0] in ('"', "'"): + val = val[1:-1] + os.environ[key] = val + +HELIUS_RPC = os.environ.get('HELIUS_RPC_URL', '') +HELIUS_API_KEY = HELIUS_RPC.split('api-key=')[1].split('&')[0] if 'api-key=' in HELIUS_RPC else '' +PRIVATE_KEY_B58 = os.environ.get('SOL_PRIVATE_KEY', '') +MAX_BUY_SOL = float(os.environ.get('MAX_BUY_SOL', '1')) +MAX_BUYS_PER_DAY = int(os.environ.get('MAX_BUYS_PER_DAY', '10')) +TRADING_ENABLED = os.environ.get('TRADING_ENABLED', 'false').lower() == 'true' + +# Fix #9: Stop-loss / take-profit settings +STOP_LOSS_PCT = float(os.environ.get('STOP_LOSS_PCT', '-50')) # -50% default +TAKE_PROFIT_PCT = float(os.environ.get('TAKE_PROFIT_PCT', '100')) # +100% default + +WSOL_MINT = 'So11111111111111111111111111111111111111112' +POSITIONS_FILE = os.path.join(SCRIPT_DIR, 'memory', 'positions.json') +TRADES_LOG = os.path.join(SCRIPT_DIR, 'memory', 'trades_log.jsonl') + +# Pump.fun program +PUMP_FUN_PROGRAM = '6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P' + + +def get_keypair(): + """Derive keypair from base58 private key.""" + secret_key = base58.b58decode(PRIVATE_KEY_B58) + signing_key = nacl.signing.SigningKey(secret_key[:32]) + pubkey_bytes = bytes(signing_key.verify_key) + wallet_address = base58.b58encode(pubkey_bytes).decode() + return signing_key, wallet_address + + +def rpc_call(method, params, retries=3): + """Make Helius RPC call.""" + data = json.dumps({"jsonrpc": "2.0", "id": 1, "method": method, "params": params}).encode() + for attempt in range(retries): + try: + req = Request(HELIUS_RPC, data=data, headers={'Content-Type': 'application/json'}) + with urlopen(req, timeout=60) as resp: + result = json.loads(resp.read()) + return result.get('result') + except Exception as e: + if attempt < retries - 1: + time.sleep(2 ** attempt) + else: + logger.error(f"RPC error after {retries} retries: {e}") + return None + + +# ─── Fix #2: Transaction Confirmation ─── + +def confirm_transaction(signature, max_wait=60): + """Poll getSignatureStatuses until confirmed or timeout. + Returns True if transaction confirmed on-chain, False otherwise. + """ + start = time.time() + poll_interval = 2 + while time.time() - start < max_wait: + try: + result = rpc_call("getSignatureStatuses", [[signature], {"searchTransactionHistory": True}]) + if result and result.get("value"): + status = result["value"][0] + if status: + err = status.get("err") + if err: + logger.error(f"Transaction {signature[:20]}... failed on-chain: {err}") + return False + conf = status.get("confirmationStatus", "") + if conf in ("confirmed", "finalized"): + logger.info(f"Transaction {signature[:20]}... {conf}") + return True + except Exception as e: + logger.warning(f"Confirmation poll error: {e}") + time.sleep(poll_interval) + poll_interval = min(poll_interval * 1.5, 10) + logger.warning(f"Transaction {signature[:20]}... confirmation timed out after {max_wait}s") + return False + + +def get_sol_balance(address): + """Get SOL balance.""" + result = rpc_call("getBalance", [address]) + if result: + return result.get("value", 0) / 1e9 + return 0 + + +def get_token_balance(wallet, mint): + """Get token balance for a specific mint (human-readable uiAmount).""" + result = rpc_call("getTokenAccountsByOwner", [ + wallet, + {"mint": mint}, + {"encoding": "jsonParsed"} + ]) + if result: + accounts = result.get("value", []) + total = 0 + for acc in accounts: + info = acc.get("account", {}).get("data", {}).get("parsed", {}).get("info", {}) + amount = info.get("tokenAmount", {}) + total += float(amount.get("uiAmount", 0) or 0) + return total + return 0 + + +def get_token_balance_raw(wallet, mint): + """Get token balance in raw atomic units (for Jupiter swap input). + Fix N1: Jupiter expects raw lamport-like amounts, not human-readable floats. + """ + result = rpc_call("getTokenAccountsByOwner", [ + wallet, + {"mint": mint}, + {"encoding": "jsonParsed"} + ]) + if result: + accounts = result.get("value", []) + total = 0 + for acc in accounts: + info = acc.get("account", {}).get("data", {}).get("parsed", {}).get("info", {}) + amount = info.get("tokenAmount", {}) + total += int(amount.get("amount", "0")) + return total + return 0 + + +def get_token_price_sol(mint): + """Get token price in SOL via Jupiter.""" + try: + url = f"https://api.jup.ag/price/v2?ids={mint}&vsToken={WSOL_MINT}" + req = Request(url, headers={'Accept': 'application/json'}) + with urlopen(req, timeout=15) as resp: + data = json.loads(resp.read()) + price_data = data.get("data", {}).get(mint, {}) + price = float(price_data.get("price", 0)) + return price + except Exception as e: + logger.warning(f"Price fetch error for {mint[:20]}: {e}") + return 0 + + +def is_pump_fun_token(mint): + """Check if token is still on pump.fun bonding curve (not migrated to Raydium).""" + if mint.endswith('pump'): + try: + url = f"https://api.jup.ag/price/v2?ids={mint}" + req = Request(url, headers={'Accept': 'application/json'}) + with urlopen(req, timeout=10) as resp: + data = json.loads(resp.read()) + price_data = data.get("data", {}).get(mint) + if price_data and float(price_data.get("price", 0)) > 0: + return False # Has Jupiter price = migrated + return True # No Jupiter price = still on bonding curve + except Exception as e: + logger.warning(f"pump.fun check error: {e}") + return True # Assume bonding curve if can't check + return False + + +def jupiter_swap(input_mint, output_mint, amount_lamports, wallet_address, signing_key): + """Execute swap via Jupiter V6 API.""" + # Step 1: Get quote + quote_url = ( + f"https://quote-api.jup.ag/v6/quote?" + f"inputMint={input_mint}&outputMint={output_mint}" + f"&amount={amount_lamports}&slippageBps=500" # 5% slippage for memecoins + f"&onlyDirectRoutes=false" + ) + + try: + req = Request(quote_url, headers={'Accept': 'application/json'}) + with urlopen(req, timeout=30) as resp: + quote = json.loads(resp.read()) + except Exception as e: + return {"success": False, "error": f"Quote failed: {e}"} + + if not quote or 'routePlan' not in quote: + return {"success": False, "error": f"No route found: {json.dumps(quote)[:200]}"} + + out_amount = int(quote.get("outAmount", 0)) + print(f" Quote: {amount_lamports/1e9:.4f} SOL → {out_amount} tokens") + + # Step 2: Get swap transaction + swap_url = "https://quote-api.jup.ag/v6/swap" + swap_data = json.dumps({ + "quoteResponse": quote, + "userPublicKey": wallet_address, + "wrapAndUnwrapSol": True, + "dynamicComputeUnitLimit": True, + "prioritizationFeeLamports": "auto" + }).encode() + + try: + req = Request(swap_url, data=swap_data, headers={ + 'Content-Type': 'application/json', + 'Accept': 'application/json' + }) + with urlopen(req, timeout=30) as resp: + swap_result = json.loads(resp.read()) + except Exception as e: + return {"success": False, "error": f"Swap tx build failed: {e}"} + + swap_tx_b64 = swap_result.get("swapTransaction") + if not swap_tx_b64: + return {"success": False, "error": f"No swap tx: {json.dumps(swap_result)[:200]}"} + + # Step 3: Deserialize, sign, send + import base64 + tx_bytes = base64.b64decode(swap_tx_b64) + + try: + signed_tx = sign_versioned_transaction(tx_bytes, signing_key) + except Exception as e: + return {"success": False, "error": f"Signing failed: {e}"} + + # Step 4: Send transaction + tx_b64 = base64.b64encode(signed_tx).decode() + result = rpc_call("sendTransaction", [tx_b64, { + "encoding": "base64", + "skipPreflight": True, + "maxRetries": 3 + }]) + + if result: + # Fix #2: Confirm transaction on-chain before declaring success + confirmed = confirm_transaction(result) + if confirmed: + return {"success": True, "signature": result, "out_amount": out_amount} + else: + return {"success": False, "error": f"tx_sent_but_not_confirmed:{result[:20]}"} + else: + return {"success": False, "error": "sendTransaction returned null"} + + +def sign_versioned_transaction(tx_bytes, signing_key): + """Sign a versioned Solana transaction.""" + import base64 + num_sigs = tx_bytes[0] + sig_section_size = 1 + (num_sigs * 64) + message_bytes = tx_bytes[sig_section_size:] + signed = signing_key.sign(message_bytes) + signature = signed.signature # 64 bytes + new_tx = bytes([num_sigs]) + signature + tx_bytes[65:sig_section_size] + message_bytes + return new_tx + + +def pump_fun_buy(mint, amount_sol, wallet_address, signing_key): + """Buy token directly on pump.fun bonding curve via their trade API.""" + try: + url = "https://pumpportal.fun/api/trade-local" + trade_data = json.dumps({ + "publicKey": wallet_address, + "action": "buy", + "mint": mint, + "amount": amount_sol, # SOL amount + "denominatedInSol": "true", + "slippage": 10, # 10% slippage for pump.fun + "priorityFee": 0.005 + }).encode() + + req = Request(url, data=trade_data, headers={ + 'Content-Type': 'application/json' + }) + with urlopen(req, timeout=30) as resp: + tx_bytes = resp.read() + + if not tx_bytes or len(tx_bytes) < 100: + return {"success": False, "error": "Empty pump.fun response"} + + signed_tx = sign_versioned_transaction(tx_bytes, signing_key) + + import base64 + tx_b64 = base64.b64encode(signed_tx).decode() + result = rpc_call("sendTransaction", [tx_b64, { + "encoding": "base64", + "skipPreflight": True, + "maxRetries": 3 + }]) + + if result: + # Fix #2: Confirm on-chain + confirmed = confirm_transaction(result) + if confirmed: + return {"success": True, "signature": result} + else: + return {"success": False, "error": f"tx_sent_but_not_confirmed:{result[:20]}"} + else: + return {"success": False, "error": "sendTransaction returned null"} + except Exception as e: + return {"success": False, "error": f"pump.fun buy failed: {e}"} + + +# ─── Fix #11: File-locked positions management ─── + +def load_positions(): + """Load current positions with exclusive file lock (Fix N2: prevent RMW race).""" + if os.path.exists(POSITIONS_FILE): + try: + with open(POSITIONS_FILE) as f: + fcntl.flock(f, fcntl.LOCK_EX) + data = json.load(f) + fcntl.flock(f, fcntl.LOCK_UN) + return data + except Exception as e: + logger.error(f"Failed to load positions: {e}") + return {"positions": [], "stats": {"total_buys": 0, "total_sells": 0, "total_sol_spent": 0, "total_sol_received": 0, "buys_today": 0, "last_buy_date": ""}} + + +def save_positions(data): + """Save positions with exclusive file lock + atomic write.""" + import tempfile + try: + dirpath = os.path.dirname(POSITIONS_FILE) + fd, tmp_path = tempfile.mkstemp(dir=dirpath, suffix='.tmp') + with os.fdopen(fd, 'w') as f: + json.dump(data, f, indent=2) + os.rename(tmp_path, POSITIONS_FILE) + except Exception as e: + logger.error(f"Failed to save positions: {e}") + try: + os.unlink(tmp_path) + except Exception: + pass + + +def log_trade(trade): + """Append trade to log with file locking.""" + try: + with open(TRADES_LOG, 'a') as f: + fcntl.flock(f, fcntl.LOCK_EX) + f.write(json.dumps(trade) + '\n') + fcntl.flock(f, fcntl.LOCK_UN) + except Exception as e: + logger.error(f"Failed to log trade: {e}") + + +def check_daily_limit(): + """Check if we've hit the daily buy limit. Uses file lock to prevent race.""" + data = load_positions() + today = datetime.now(timezone.utc).strftime('%Y-%m-%d') + if data["stats"]["last_buy_date"] != today: + data["stats"]["buys_today"] = 0 + data["stats"]["last_buy_date"] = today + save_positions(data) + return data["stats"]["buys_today"] < MAX_BUYS_PER_DAY + + +def cmd_buy(mint, amount_sol=None): + """Buy a token.""" + if amount_sol is None: + amount_sol = MAX_BUY_SOL + + if not TRADING_ENABLED: + print(f"TRADING DISABLED. Would buy {amount_sol} SOL of {mint}") + print("Set TRADING_ENABLED=true in .env to enable") + log_trade({ + "date": datetime.now(timezone.utc).isoformat(), + "action": "buy_simulated", + "mint": mint, + "amount_sol": amount_sol, + "reason": "trading_disabled" + }) + return False + + signing_key, wallet_address = get_keypair() + print(f"Wallet: {wallet_address}") + + # Check balance + balance = get_sol_balance(wallet_address) + print(f"SOL Balance: {balance}") + if balance < amount_sol + 0.01: + logger.warning(f"Insufficient balance: {balance} < {amount_sol + 0.01}") + return False + + # Check daily limit + if not check_daily_limit(): + logger.warning(f"Daily buy limit reached ({MAX_BUYS_PER_DAY})") + return False + + # Determine route + on_pump_fun = is_pump_fun_token(mint) + print(f"Token on pump.fun bonding curve: {on_pump_fun}") + + result = None + route_used = None + + if on_pump_fun: + print(">> Trying pump.fun direct buy...") + result = pump_fun_buy(mint, amount_sol, wallet_address, signing_key) + route_used = "pump_fun" + + if not result.get("success"): + logger.warning(f"pump.fun failed: {result.get('error')}") + print(">> Falling back to Jupiter...") + amount_lamports = int(amount_sol * 1e9) + result = jupiter_swap(WSOL_MINT, mint, amount_lamports, wallet_address, signing_key) + route_used = "jupiter" + else: + print(">> Using Jupiter swap...") + amount_lamports = int(amount_sol * 1e9) + result = jupiter_swap(WSOL_MINT, mint, amount_lamports, wallet_address, signing_key) + route_used = "jupiter" + + if not result.get("success"): + logger.warning(f"Jupiter failed: {result.get('error')}") + print(">> Jupiter failed. Trade not executed.") + + if result and result.get("success"): + sig = result.get("signature", "unknown") + logger.info(f"BUY SUCCESS: {mint[:20]} via {route_used} | TX: {sig[:20]}") + print(f"SUCCESS! TX: {sig}") + print(f"Route: {route_used}") + + # Update positions (file-locked) + data = load_positions() + data["positions"].append({ + "mint": mint, + "entry_sol": amount_sol, + "entry_date": datetime.now(timezone.utc).isoformat(), + "entry_tx": sig, + "route": route_used, + "status": "open" + }) + data["stats"]["total_buys"] += 1 + data["stats"]["total_sol_spent"] += amount_sol + data["stats"]["buys_today"] += 1 + data["stats"]["last_buy_date"] = datetime.now(timezone.utc).strftime('%Y-%m-%d') + save_positions(data) + + log_trade({ + "date": datetime.now(timezone.utc).isoformat(), + "action": "buy", + "mint": mint, + "amount_sol": amount_sol, + "signature": sig, + "route": route_used + }) + return True + else: + error_msg = result.get('error', 'unknown error') if result else 'no result' + logger.error(f"BUY FAILED: {mint[:20]} | {error_msg}") + log_trade({ + "date": datetime.now(timezone.utc).isoformat(), + "action": "buy_failed", + "mint": mint, + "amount_sol": amount_sol, + "error": error_msg + }) + return False + + +def cmd_sell(mint, pct=100): + """Sell a token position.""" + if not TRADING_ENABLED: + print(f"TRADING DISABLED. Would sell {pct}% of {mint}") + log_trade({ + "date": datetime.now(timezone.utc).isoformat(), + "action": "sell_simulated", + "mint": mint, + "pct": pct, + "reason": "trading_disabled" + }) + return False + + signing_key, wallet_address = get_keypair() + + # Get token balance — need both uiAmount (human) and raw amount (for Jupiter) + token_balance = get_token_balance(wallet_address, mint) + if token_balance <= 0: + logger.warning(f"No tokens to sell for {mint}") + return False + + # Fix N1: Get raw atomic amount for Jupiter (not uiAmount) + raw_balance = get_token_balance_raw(wallet_address, mint) + sell_amount = int(raw_balance * (pct / 100)) + print(f"Selling {pct}% of {token_balance} tokens (raw: {sell_amount})") + + result = jupiter_swap(mint, WSOL_MINT, sell_amount, wallet_address, signing_key) + + if result and result.get("success"): + sig = result.get("signature", "unknown") + sol_received = result.get("out_amount", 0) / 1e9 + logger.info(f"SELL SUCCESS: {mint[:20]} | {sol_received:.4f} SOL | TX: {sig[:20]}") + print(f"SOLD! TX: {sig}") + print(f"SOL received: {sol_received}") + + # Update positions (file-locked) + data = load_positions() + for pos in data["positions"]: + if pos["mint"] == mint and pos["status"] == "open": + if pct >= 100: + pos["status"] = "closed" + pos["exit_tx"] = sig + pos["exit_date"] = datetime.now(timezone.utc).isoformat() + pos["exit_sol"] = sol_received + break + data["stats"]["total_sells"] += 1 + data["stats"]["total_sol_received"] += sol_received + save_positions(data) + + log_trade({ + "date": datetime.now(timezone.utc).isoformat(), + "action": "sell", + "mint": mint, + "pct": pct, + "sol_received": sol_received, + "signature": sig + }) + return True + else: + error_msg = result.get('error') if result else 'no result' + logger.error(f"SELL FAILED: {mint[:20]} | {error_msg}") + return False + + +# ─── Fix #9: Automated Stop-Loss / Take-Profit ─── + +def check_positions(): + """Check all open positions for stop-loss or take-profit triggers. + Called by monitor_wallets.py daemon every 60s cycle. + Returns list of actions taken. + + Fix: Saves non-sell changes (zero_balance, price_fail_count) BEFORE executing + sells. Each cmd_sell() does its own load/modify/save cycle, so saving stale + data after cmd_sell would overwrite its changes (RMW race). + """ + data = load_positions() + open_positions = [p for p in data["positions"] if p["status"] == "open"] + + if not open_positions: + return [] + + _, wallet_address = get_keypair() + actions = [] + pending_sells = [] # (mint, pct, action_type, pnl_pct) — executed AFTER saving data + + for pos in open_positions: + mint = pos["mint"] + entry_sol = pos["entry_sol"] + + try: + token_bal = get_token_balance(wallet_address, mint) + if token_bal <= 0: + logger.info(f"Position {mint[:16]}: zero balance, marking closed") + pos["status"] = "closed" + pos["exit_date"] = datetime.now(timezone.utc).isoformat() + pos["exit_sol"] = 0 + pos["exit_reason"] = "zero_balance" + actions.append({"mint": mint, "action": "closed_zero_balance"}) + continue + + price = get_token_price_sol(mint) + if price <= 0: + # Fix N5: Track consecutive price failures — force close after 5 failures + pos.setdefault("price_fail_count", 0) + pos["price_fail_count"] = pos.get("price_fail_count", 0) + 1 + if pos["price_fail_count"] >= 5: + logger.warning(f"Position {mint[:16]}: price unavailable for 5+ cycles, force closing") + pos["status"] = "closed" + pos["exit_date"] = datetime.now(timezone.utc).isoformat() + pos["exit_sol"] = 0 + pos["exit_reason"] = "price_unavailable_force_close" + actions.append({"mint": mint, "action": "force_close_no_price"}) + else: + logger.warning(f"Position {mint[:16]}: price unavailable ({pos['price_fail_count']}/5)") + continue + + # Price available — reset consecutive failure counter + if pos.get("price_fail_count", 0) > 0: + pos["price_fail_count"] = 0 + + current_value = token_bal * price + pnl_pct = ((current_value - entry_sol) / entry_sol * 100) if entry_sol > 0 else 0 + + # Stop-loss check + if pnl_pct <= STOP_LOSS_PCT: + logger.warning(f"STOP-LOSS triggered for {mint[:16]}: {pnl_pct:.1f}% (threshold: {STOP_LOSS_PCT}%)") + pending_sells.append((mint, 100, "stop_loss", pnl_pct)) + + # Take-profit check + elif pnl_pct >= TAKE_PROFIT_PCT: + logger.info(f"TAKE-PROFIT triggered for {mint[:16]}: {pnl_pct:.1f}% (threshold: {TAKE_PROFIT_PCT}%)") + pending_sells.append((mint, 50, "take_profit_50pct", pnl_pct)) + + except Exception as e: + logger.error(f"Position check error for {mint[:16]}: {e}") + + # Save non-sell changes first (zero_balance, price_fail_count, force_close). + # This MUST happen before cmd_sell calls, which do their own load/modify/save. + # Previously, saving stale data AFTER cmd_sell overwrote sell changes (RMW race). + save_positions(data) + + # Execute pending sells — each cmd_sell() does its own atomic load/modify/save + for mint, pct, action_type, pnl_pct in pending_sells: + success = cmd_sell(mint, pct) + actions.append({ + "mint": mint, + "action": action_type, + "pnl_pct": round(pnl_pct, 1), + "sold": success + }) + return actions + + +def cmd_balance(): + """Show wallet balance and holdings.""" + _, wallet_address = get_keypair() + print(f"Wallet: {wallet_address}") + + sol = get_sol_balance(wallet_address) + print(f"SOL: {sol:.4f}") + + result = rpc_call("getTokenAccountsByOwner", [ + wallet_address, + {"programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"}, + {"encoding": "jsonParsed"} + ]) + + if result: + accounts = result.get("value", []) + holdings = [] + for acc in accounts: + info = acc.get("account", {}).get("data", {}).get("parsed", {}).get("info", {}) + amount = info.get("tokenAmount", {}) + ui_amount = float(amount.get("uiAmount", 0) or 0) + if ui_amount > 0: + holdings.append({ + "mint": info.get("mint", ""), + "amount": amount.get("uiAmountString", "0"), + }) + if holdings: + print(f"\nToken Holdings ({len(holdings)}):") + for h in holdings: + print(f" {h['mint'][:12]}... : {h['amount']}") + else: + print("\nNo token holdings") + + +def cmd_positions(): + """Show open positions.""" + data = load_positions() + positions = [p for p in data["positions"] if p["status"] == "open"] + + if not positions: + print("No open positions") + return + + _, wallet_address = get_keypair() + print(f"Open Positions ({len(positions)}):") + print() + + for p in positions: + mint = p["mint"] + entry_sol = p["entry_sol"] + entry_date = p["entry_date"][:10] + + token_bal = get_token_balance(wallet_address, mint) + price = get_token_price_sol(mint) + current_value = token_bal * price if price > 0 else 0 + pnl = current_value - entry_sol + pnl_pct = (pnl / entry_sol * 100) if entry_sol > 0 else 0 + + status = "+" if pnl >= 0 else "" + print(f" {mint[:16]}...") + print(f" Entry: {entry_sol:.2f} SOL on {entry_date}") + print(f" Current: {current_value:.4f} SOL ({status}{pnl_pct:.1f}%)") + print(f" SL: {STOP_LOSS_PCT}% | TP: {TAKE_PROFIT_PCT}%") + print() + + +def cmd_pnl(): + """Generate PNL summary for daily report.""" + data = load_positions() + _, wallet_address = get_keypair() + sol_balance = get_sol_balance(wallet_address) + + total_spent = data["stats"]["total_sol_spent"] + total_received = data["stats"]["total_sol_received"] + total_buys = data["stats"]["total_buys"] + + open_positions = [p for p in data["positions"] if p["status"] == "open"] + unrealized_value = 0 + position_details = [] + + for p in open_positions: + token_bal = get_token_balance(wallet_address, p["mint"]) + price = get_token_price_sol(p["mint"]) + current_value = token_bal * price if price > 0 else 0 + pnl = current_value - p["entry_sol"] + pnl_pct = (pnl / p["entry_sol"] * 100) if p["entry_sol"] > 0 else 0 + unrealized_value += current_value + position_details.append({ + "mint": p["mint"], + "entry_sol": p["entry_sol"], + "current_value_sol": round(current_value, 4), + "pnl_sol": round(pnl, 4), + "pnl_pct": round(pnl_pct, 1), + "entry_date": p["entry_date"][:10] + }) + + closed = [p for p in data["positions"] if p["status"] == "closed"] + realized_pnl = sum(p.get("exit_sol", 0) - p["entry_sol"] for p in closed) + + summary = { + "date": datetime.now(timezone.utc).isoformat(), + "wallet": wallet_address, + "sol_balance": sol_balance, + "total_buys": total_buys, + "total_sol_deployed": total_spent, + "total_sol_returned": total_received, + "realized_pnl_sol": round(realized_pnl, 4), + "unrealized_value_sol": round(unrealized_value, 4), + "open_positions": len(open_positions), + "closed_positions": len(closed), + "position_details": position_details + } + + print(json.dumps(summary, indent=2)) + return summary + + +# ─── Main ─── + +if __name__ == "__main__": + cmd = sys.argv[1] if len(sys.argv) > 1 else "help" + + if cmd == "buy": + mint = sys.argv[2] if len(sys.argv) > 2 else None + amount = float(sys.argv[3]) if len(sys.argv) > 3 else None + if not mint: + print("Usage: trade_executor.py buy [amount_sol]") + sys.exit(1) + cmd_buy(mint, amount) + + elif cmd == "sell": + mint = sys.argv[2] if len(sys.argv) > 2 else None + pct = int(sys.argv[3]) if len(sys.argv) > 3 else 100 + if not mint: + print("Usage: trade_executor.py sell [pct]") + sys.exit(1) + cmd_sell(mint, pct) + + elif cmd == "balance": + cmd_balance() + + elif cmd == "positions": + cmd_positions() + + elif cmd == "pnl": + cmd_pnl() + + elif cmd == "check": + actions = check_positions() + if actions: + print(f"Actions taken: {json.dumps(actions, indent=2)}") + else: + print("No SL/TP triggers") + + else: + print("Trade Executor — Autonomous Solana token buyer") + print() + print("Commands:") + print(" buy [sol] Buy token (default: 1 SOL)") + print(" sell [pct] Sell token (default: 100%)") + print(" balance Show wallet balance") + print(" positions Show open positions") + print(" pnl PNL summary for daily report") + print(" check Check SL/TP for all positions") + print() + print(f"Wallet: {get_keypair()[1]}") + print(f"Trading: {'ENABLED' if TRADING_ENABLED else 'DISABLED'}") + print(f"Max buy: {MAX_BUY_SOL} SOL") + print(f"Max daily: {MAX_BUYS_PER_DAY}") + print(f"Stop-loss: {STOP_LOSS_PCT}% | Take-profit: {TAKE_PROFIT_PCT}%") diff --git a/vps_setup.sh b/vps_setup.sh new file mode 100755 index 0000000..e93ac7a --- /dev/null +++ b/vps_setup.sh @@ -0,0 +1,309 @@ +#!/bin/bash +# VPS Setup Script — Run this on your Vultr VPS to deploy the full system +# Usage: curl -sSL | bash +# Or: scp this file to VPS and run: bash vps_setup.sh +# +# After running, you need to: +# 1. Create /opt/cute-panel/.env with your keys +# 2. Start the daemons: /opt/cute-panel/sniper_daemon.sh start +# 3. Enable trading: edit .env, set TRADING_ENABLED=true + +set -euo pipefail + +echo "════════════════════════════════════════" +echo " Crypto Intelligence System — VPS Setup" +echo "════════════════════════════════════════" +echo "" + +INSTALL_DIR="/opt/cute-panel" +REPO_URL="https://github.com/KatriaDopex/Cute-Panel.git" +BRANCH="claude/crypto-intelligence-system-8oO0s" + +# ─── Step 1: System packages ─── +echo ">> Installing system packages..." +apt-get update -qq +apt-get install -y -qq python3 python3-pip git curl cron jq + +# ─── Step 2: Python packages ─── +echo ">> Installing Python packages..." +pip3 install base58 pynacl --break-system-packages 2>/dev/null || pip3 install base58 pynacl + +# ─── Step 3: Clone repo ─── +echo ">> Cloning repository..." +if [ -d "$INSTALL_DIR" ]; then + echo " Directory exists, pulling latest..." + cd "$INSTALL_DIR" + git fetch origin "$BRANCH" + git checkout "$BRANCH" + git pull origin "$BRANCH" +else + git clone -b "$BRANCH" "$REPO_URL" "$INSTALL_DIR" + cd "$INSTALL_DIR" +fi + +# ─── Step 4: Create .env if not exists ─── +if [ ! -f "$INSTALL_DIR/.env" ]; then + echo ">> Creating .env template..." + cat > "$INSTALL_DIR/.env" << 'ENVEOF' +# Crypto Intelligence System — Environment Variables +# FILL IN YOUR KEYS BELOW + +# Grok API (for X search) +XAI_API_KEY=PASTE_YOUR_GROK_API_KEY_HERE + +# Helius RPC (for Solana on-chain data) +HELIUS_RPC_URL=PASTE_YOUR_HELIUS_RPC_URL_HERE + +# Solana wallet private key (base58) +SOL_PRIVATE_KEY=PASTE_YOUR_PRIVATE_KEY_HERE + +# Trading settings +MAX_BUY_SOL=1 +MAX_BUYS_PER_DAY=10 +TRADING_ENABLED=false +ENVEOF + echo "" + echo " *** IMPORTANT: Edit /opt/cute-panel/.env with your actual keys! ***" + echo " Run: nano /opt/cute-panel/.env" + echo "" +else + echo ">> .env already exists, keeping it" +fi + +# ─── Step 5: Set permissions ─── +echo ">> Setting permissions..." +chmod +x "$INSTALL_DIR"/*.sh "$INSTALL_DIR"/*.py 2>/dev/null || true + +# ─── Step 6: Create directories ─── +mkdir -p "$INSTALL_DIR/logs" "$INSTALL_DIR/.pids" "$INSTALL_DIR/dd_reports" +mkdir -p "$INSTALL_DIR/memory" + +# ─── Step 7: Install Claude Code CLI (for daily reports) ─── +echo ">> Installing Claude Code CLI..." +if ! command -v claude &> /dev/null; then + npm install -g @anthropic-ai/claude-code 2>/dev/null || { + # Install Node.js first if not present + if ! command -v node &> /dev/null; then + curl -fsSL https://deb.nodesource.com/setup_22.x | bash - + apt-get install -y -qq nodejs + fi + npm install -g @anthropic-ai/claude-code + } +fi + +# ─── Step 8: Create auto-deploy script ─── +echo ">> Creating auto-deploy script..." +cat > "$INSTALL_DIR/auto_deploy.sh" << 'DEPLOYEOF' +#!/bin/bash +# Auto-deploy: pull latest code from GitHub, start/restart daemons +cd /opt/cute-panel || exit 1 + +# Fetch latest +git fetch origin claude/crypto-intelligence-system-8oO0s 2>/dev/null + +LOCAL=$(git rev-parse HEAD) +REMOTE=$(git rev-parse origin/claude/crypto-intelligence-system-8oO0s) + +if [ "$LOCAL" != "$REMOTE" ]; then + echo "[$(date)] New code detected, deploying..." + git pull origin claude/crypto-intelligence-system-8oO0s + chmod +x *.sh *.py 2>/dev/null || true + + # Syntax check before restart (prevent broken code from taking down daemons) + SYNTAX_OK=true + for pyfile in signal_bus.py scan_x_alpha.py monitor_wallets.py trade_executor.py scan_trending_wallets.py scan_early_buyers.py scan_trending_new.py alpha_wallet_scanner.py cross_reference.py realtime_scanner.py; do + if [ -f "$pyfile" ]; then + if ! python3 -c "import py_compile; py_compile.compile('$pyfile', doraise=True)" 2>/dev/null; then + echo "[$(date)] SYNTAX ERROR in $pyfile — aborting deploy!" + SYNTAX_OK=false + fi + fi + done + + if [ "$SYNTAX_OK" = true ]; then + systemctl restart crypto-wallet-monitor 2>/dev/null + systemctl restart crypto-x-scanner 2>/dev/null + systemctl restart crypto-trending-scanner 2>/dev/null + echo "[$(date)] Deploy complete. All 3 daemons restarted." + + # Check for pending early buyer scan trigger + if [ -f "scan_trigger.json" ]; then + echo "[$(date)] Scan trigger detected, launching early buyer scan in background..." + nohup bash run_full_scan.sh >> /tmp/scan_bg.log 2>&1 & + echo "[$(date)] Scan started (PID: $!)." + rm -f scan_trigger.json + fi + else + echo "[$(date)] Deploy ABORTED due to syntax errors. Daemons NOT restarted." + git checkout -- . 2>/dev/null # Revert broken code + fi +else + echo "[$(date)] Up to date." +fi + +# Ensure daemons are enabled and running (auto-start on first deploy) +if ! systemctl is-enabled crypto-wallet-monitor &>/dev/null; then + echo "[$(date)] Enabling crypto-wallet-monitor..." + systemctl enable --now crypto-wallet-monitor 2>/dev/null +fi +if ! systemctl is-enabled crypto-x-scanner &>/dev/null; then + echo "[$(date)] Enabling crypto-x-scanner..." + systemctl enable --now crypto-x-scanner 2>/dev/null +fi +if ! systemctl is-enabled crypto-trending-scanner &>/dev/null; then + echo "[$(date)] Enabling crypto-trending-scanner..." + systemctl enable --now crypto-trending-scanner 2>/dev/null +fi + +# Restart if dead +for svc in crypto-wallet-monitor crypto-x-scanner crypto-trending-scanner crypto-realtime-scanner; do + if ! systemctl is-active "$svc" &>/dev/null; then + echo "[$(date)] $svc dead, restarting..." + systemctl restart "$svc" + fi +done +DEPLOYEOF +chmod +x "$INSTALL_DIR/auto_deploy.sh" + +# ─── Step 9: Set up cron jobs ─── +echo ">> Setting up cron jobs..." +cat > /etc/cron.d/crypto_intel << 'CRONEOF' +SHELL=/bin/bash +TZ=Europe/Warsaw + +# Auto-deploy from GitHub every 5 minutes +*/5 * * * * root /opt/cute-panel/auto_deploy.sh >> /opt/cute-panel/logs/auto_deploy.log 2>&1 + +# Daily morning report at 8 AM Poland time (would-have-been-bought coins + system status) +0 8 * * * root cd /opt/cute-panel && python3 daily_morning_report.py >> /opt/cute-panel/logs/morning_report.log 2>&1 + +# Alpha pipeline: twice daily (trending scan → alpha wallets → cross-reference) +# 14:00 CET = US market open + Asia evening peak +0 14 * * * root bash /opt/cute-panel/run_alpha_pipeline.sh >> /opt/cute-panel/logs/alpha_pipeline.log 2>&1 +# 02:00 CET = US evening + Asia morning peak +0 2 * * * root bash /opt/cute-panel/run_alpha_pipeline.sh >> /opt/cute-panel/logs/alpha_pipeline.log 2>&1 + +# NOTE: auto_deploy.sh above already handles restart-if-dead for all 3 systemd services +CRONEOF + +# ─── Step 10: Create systemd service for daemons ─── +echo ">> Creating systemd services..." + +cat > /etc/systemd/system/crypto-wallet-monitor.service << 'SVCEOF' +[Unit] +Description=Crypto Alpha Wallet Monitor +After=network.target + +[Service] +Type=simple +WorkingDirectory=/opt/cute-panel +ExecStart=/usr/bin/python3 /opt/cute-panel/monitor_wallets.py daemon +Restart=always +RestartSec=10 +EnvironmentFile=/opt/cute-panel/.env + +[Install] +WantedBy=multi-user.target +SVCEOF + +cat > /etc/systemd/system/crypto-x-scanner.service << 'SVCEOF' +[Unit] +Description=Crypto X Alpha Scanner +After=network.target + +[Service] +Type=simple +WorkingDirectory=/opt/cute-panel +ExecStart=/usr/bin/python3 /opt/cute-panel/scan_x_alpha.py daemon +Restart=always +RestartSec=30 +EnvironmentFile=/opt/cute-panel/.env + +[Install] +WantedBy=multi-user.target +SVCEOF + +cat > /etc/systemd/system/crypto-trending-scanner.service << 'SVCEOF' +[Unit] +Description=Crypto Trending Token Scanner (hourly DexScreener + early buyer pipeline) +After=network.target + +[Service] +Type=simple +WorkingDirectory=/opt/cute-panel +ExecStart=/usr/bin/python3 /opt/cute-panel/scan_trending_wallets.py daemon +Restart=always +RestartSec=60 +EnvironmentFile=/opt/cute-panel/.env + +[Install] +WantedBy=multi-user.target +SVCEOF + +cat > /etc/systemd/system/crypto-realtime-scanner.service << 'SVCEOF' +[Unit] +Description=Real-Time Token Scanner (60s loop — DexScreener + GeckoTerminal) +After=network.target + +[Service] +Type=simple +WorkingDirectory=/opt/cute-panel +ExecStart=/usr/bin/python3 /opt/cute-panel/realtime_scanner.py loop +Restart=always +RestartSec=10 +EnvironmentFile=/opt/cute-panel/.env + +[Install] +WantedBy=multi-user.target +SVCEOF + +systemctl daemon-reload + +echo "" +echo "════════════════════════════════════════" +echo " SETUP COMPLETE!" +echo "════════════════════════════════════════" +echo "" +echo "Next steps:" +echo "" +echo "1. Edit your keys:" +echo " nano /opt/cute-panel/.env" +echo " (paste your XAI_API_KEY, HELIUS_RPC_URL, SOL_PRIVATE_KEY)" +echo "" +echo "2. Start the monitoring daemons:" +echo " systemctl enable --now crypto-wallet-monitor" +echo " systemctl enable --now crypto-x-scanner" +echo " systemctl enable --now crypto-trending-scanner" +echo " systemctl enable --now crypto-realtime-scanner" +echo "" +echo "3. Check daemon status:" +echo " systemctl status crypto-wallet-monitor" +echo " systemctl status crypto-x-scanner" +echo " systemctl status crypto-trending-scanner" +echo " systemctl status crypto-realtime-scanner" +echo "" +echo "4. View logs:" +echo " journalctl -u crypto-wallet-monitor -f" +echo " journalctl -u crypto-x-scanner -f" +echo " journalctl -u crypto-trending-scanner -f" +echo " journalctl -u crypto-realtime-scanner -f" +echo " tail -f /opt/cute-panel/logs/auto_deploy.log" +echo "" +echo "5. When ready to trade, edit .env:" +echo " Set TRADING_ENABLED=true" +echo " Fund wallet: 4QVAFHofNg8FSwxwZNtMDFmiujQFKEjVKaGp7uxxXqPU" +echo "" +echo "6. AUTO-DEPLOY is ON: VPS pulls from GitHub every 5 min" +echo " Any changes pushed to GitHub auto-deploy + daemons restart" +echo " Works from laptop or phone (Claude Code app)" +echo "" +echo "7. Daily reports run automatically at 8 AM Poland time" +echo " Check: tail -f /opt/cute-panel/logs/intel_cron.log" +echo "" +echo "8. Manual commands:" +echo " python3 /opt/cute-panel/trade_executor.py balance" +echo " python3 /opt/cute-panel/trade_executor.py positions" +echo " python3 /opt/cute-panel/trade_executor.py pnl" +echo " python3 /opt/cute-panel/scan_early_wallets.py" +echo " bash /opt/cute-panel/on_chain_dd.sh token " +echo "" diff --git a/wallet_tracker.py b/wallet_tracker.py new file mode 100644 index 0000000..344dfe3 --- /dev/null +++ b/wallet_tracker.py @@ -0,0 +1,343 @@ +#!/usr/bin/env python3 +""" +Wallet Tracker — Monitors alpha wallets for new token buys via Helius RPC. + +Designed for GitHub Actions (no VPS needed). Runs every 15 minutes. +Uses raw RPC (getSignaturesForAddress + getTransaction) instead of +Helius Enhanced API (which is blocked on free tier / proxy). + +State: memory/wallet_tracker_state.json (last seen signature per wallet) + +Usage: + python3 wallet_tracker.py # Single scan + python3 wallet_tracker.py --dry-run # Dry run (no side effects) +""" + +import json +import os +import sys +import time +from datetime import datetime, timezone +from urllib.request import Request, urlopen + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) + +# Load env +env_path = os.path.join(SCRIPT_DIR, '.env') +if os.path.exists(env_path): + with open(env_path) as f: + for line in f: + line = line.strip() + if '=' in line and not line.startswith('#'): + key, val = line.split('=', 1) + os.environ[key] = val + +HELIUS_RPC = os.environ.get('HELIUS_RPC_URL', '') + +SMART_WALLETS = os.path.join(SCRIPT_DIR, 'memory', 'smart_wallets.json') +STATE_FILE = os.path.join(SCRIPT_DIR, 'memory', 'wallet_tracker_state.json') +ALERTS_LOG = os.path.join(SCRIPT_DIR, 'memory', 'wallet_tracker_alerts.jsonl') + +# Mints to ignore (stables, wrapped SOL) +IGNORE_MINTS = { + 'So11111111111111111111111111111111111111112', # Wrapped SOL + 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', # USDC + 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB', # USDT +} + +# Rate limiting +RPC_DELAY = 0.3 # seconds between RPC calls + +# Wallet filter thresholds +MIN_RELIABILITY = 6 # manual wallets +MIN_ALPHA_SCORE = 40 # auto-discovered wallets + +DRY_RUN = '--dry-run' in sys.argv + + +def rpc_call(method, params): + """Make a Solana RPC call via Helius.""" + if not HELIUS_RPC: + return None + try: + payload = json.dumps({ + 'jsonrpc': '2.0', 'id': 1, + 'method': method, 'params': params, + }).encode() + req = Request(HELIUS_RPC, data=payload, headers={'Content-Type': 'application/json'}) + with urlopen(req, timeout=15) as resp: + data = json.loads(resp.read()) + if 'error' in data: + print(f" RPC error ({method}): {data['error']}") + return None + return data.get('result') + except Exception as e: + print(f" RPC exception ({method}): {e}") + return None + + +def load_state(): + """Load last-seen signatures per wallet.""" + if os.path.exists(STATE_FILE): + with open(STATE_FILE) as f: + return json.load(f) + return {} + + +def save_state(state): + """Save wallet tracker state.""" + os.makedirs(os.path.dirname(STATE_FILE), exist_ok=True) + with open(STATE_FILE, 'w') as f: + json.dump(state, f, indent=2) + + +def log_alert(alert): + """Append alert to JSONL log.""" + os.makedirs(os.path.dirname(ALERTS_LOG), exist_ok=True) + with open(ALERTS_LOG, 'a') as f: + f.write(json.dumps(alert) + '\n') + + +def get_eligible_wallets(): + """Load Solana wallets eligible for tracking.""" + if not os.path.exists(SMART_WALLETS): + print("No smart_wallets.json found") + return [] + + with open(SMART_WALLETS) as f: + data = json.load(f) + + wallets = [] + for w in data.get('wallets', []): + if w.get('chain') != 'solana': + continue + addr = w.get('address', 'unknown') + if addr == 'unknown': + continue + if not w.get('status', '').startswith('active'): + continue + + reliability = w.get('reliability_score') or 0 + alpha_score = w.get('alpha_score') or 0 + + if reliability >= MIN_RELIABILITY or alpha_score >= MIN_ALPHA_SCORE: + wallets.append({ + 'address': addr, + 'label': w.get('label', addr[:16]), + }) + + return wallets + + +def parse_token_buys(tx, wallet_address): + """Parse a transaction for token buys by the wallet. + Returns list of {mint, token_change, sol_spent} for buys. + """ + meta = tx.get('meta', {}) + if meta.get('err'): + return [] + + pre_balances = meta.get('preTokenBalances', []) + post_balances = meta.get('postTokenBalances', []) + + # Build token balance diffs for this wallet + token_diffs = {} # mint -> (pre, post) + + for b in pre_balances: + if b.get('owner') == wallet_address: + mint = b.get('mint', '') + amount = float(b.get('uiTokenAmount', {}).get('uiAmount', 0) or 0) + if mint and mint not in IGNORE_MINTS: + token_diffs.setdefault(mint, [0, 0]) + token_diffs[mint][0] = amount + + for b in post_balances: + if b.get('owner') == wallet_address: + mint = b.get('mint', '') + amount = float(b.get('uiTokenAmount', {}).get('uiAmount', 0) or 0) + if mint and mint not in IGNORE_MINTS: + token_diffs.setdefault(mint, [0, 0]) + token_diffs[mint][1] = amount + + buys = [] + for mint, (pre, post) in token_diffs.items(): + diff = post - pre + if diff > 0: + # Token balance increased = BUY + # Estimate SOL spent from native balance change + sol_spent = 0 + account_keys = tx.get('transaction', {}).get('message', {}).get('accountKeys', []) + for i, key in enumerate(account_keys): + pubkey = key.get('pubkey', '') if isinstance(key, dict) else key + if pubkey == wallet_address: + pre_sol = (meta.get('preBalances', [0] * (i + 1))[i]) / 1e9 + post_sol = (meta.get('postBalances', [0] * (i + 1))[i]) / 1e9 + sol_spent = max(0, pre_sol - post_sol) + break + + buys.append({ + 'mint': mint, + 'token_change': diff, + 'sol_spent': round(sol_spent, 4), + }) + + return buys + + +def get_token_info(mint): + """Get token info from DexScreener.""" + try: + url = f"https://api.dexscreener.com/tokens/v1/solana/{mint}" + req = Request(url, headers={'Accept': 'application/json', 'User-Agent': 'Mozilla/5.0'}) + with urlopen(req, timeout=10) as resp: + data = json.loads(resp.read()) + if data and isinstance(data, list) and len(data) > 0: + p = data[0] + return { + 'symbol': p.get('baseToken', {}).get('symbol', mint[:8]), + 'name': p.get('baseToken', {}).get('name', ''), + 'mc': p.get('marketCap', 0), + 'price': float(p.get('priceUsd', 0) or 0), + 'liquidity': (p.get('liquidity') or {}).get('usd', 0), + 'volume_24h': p.get('volume', {}).get('h24', 0), + 'price_change_24h': p.get('priceChange', {}).get('h24', 0), + 'url': p.get('url', ''), + } + except Exception as e: + print(f" [DexScreener] Error for {mint[:20]}: {e}") + return None + + +def check_wallet(address, label, last_sig): + """Check a wallet for new token buys since last scan. + Returns (buys, new_last_sig). + """ + time.sleep(RPC_DELAY) + sigs_result = rpc_call('getSignaturesForAddress', [address, {'limit': 5}]) + if not sigs_result: + return [], last_sig + + if not sigs_result: + return [], last_sig + + newest_sig = sigs_result[0]['signature'] + + # No new activity + if newest_sig == last_sig: + return [], last_sig + + # Find new signatures (everything before last_sig) + new_sigs = [] + for s in sigs_result: + if s['signature'] == last_sig: + break + if not s.get('err'): + new_sigs.append(s) + + if not new_sigs: + return [], newest_sig + + # Parse each new transaction for token buys + all_buys = [] + for sig_info in new_sigs: + sig = sig_info['signature'] + block_time = sig_info.get('blockTime', 0) + + time.sleep(RPC_DELAY) + tx = rpc_call('getTransaction', [sig, {'encoding': 'jsonParsed', 'maxSupportedTransactionVersion': 0}]) + if not tx: + continue + + buys = parse_token_buys(tx, address) + for buy in buys: + buy['signature'] = sig + buy['block_time'] = block_time + buy['wallet'] = address + buy['wallet_label'] = label + all_buys.append(buy) + + return all_buys, newest_sig + + +def run_scan(): + """Run a single wallet tracking scan.""" + now = datetime.now(timezone.utc) + print(f"[{now.strftime('%Y-%m-%d %H:%M:%S UTC')}] Wallet Tracker starting...") + + if not HELIUS_RPC: + print("ERROR: HELIUS_RPC_URL not set") + return [] + + wallets = get_eligible_wallets() + if not wallets: + print("No eligible wallets to track") + return [] + + print(f"Tracking {len(wallets)} wallets...") + state = load_state() + all_buys = [] + wallets_with_activity = 0 + + for i, w in enumerate(wallets): + addr = w['address'] + label = w['label'] + last_sig = state.get(addr, '') + + buys, new_sig = check_wallet(addr, label, last_sig) + state[addr] = new_sig + + if buys: + wallets_with_activity += 1 + all_buys.extend(buys) + for buy in buys: + print(f" BUY: {label} bought {buy['mint'][:20]}... ({buy['sol_spent']:.2f} SOL)") + + save_state(state) + + # Process and alert on buys + if all_buys: + print(f"\n{len(all_buys)} new buy(s) from {wallets_with_activity} wallet(s)") + + # Deduplicate by mint (multiple wallets may buy same token) + seen_mints = {} + for buy in all_buys: + mint = buy['mint'] + if mint not in seen_mints: + seen_mints[mint] = [] + seen_mints[mint].append(buy) + + for mint, buys in seen_mints.items(): + # Get token info once per mint + time.sleep(0.5) + token_info = get_token_info(mint) + sym = token_info['symbol'] if token_info else mint[:12] + + if len(buys) > 1: + # Multiple wallets bought same token = stronger signal + wallet_names = list(set(b['wallet_label'] for b in buys)) + print(f" MULTI-WALLET: {len(wallet_names)} wallets bought ${sym}") + + # Log each buy + for buy in buys: + alert = { + 'timestamp': now.isoformat(), + 'wallet': buy['wallet'], + 'wallet_label': buy['wallet_label'], + 'mint': mint, + 'symbol': sym, + 'sol_spent': buy['sol_spent'], + 'token_info': token_info, + 'signature': buy['signature'], + 'block_time': buy['block_time'], + } + log_alert(alert) + else: + print("No new buys detected") + + print(f"Scan complete. {len(all_buys)} buys from {len(wallets)} wallets.") + return all_buys + + +if __name__ == '__main__': + buys = run_scan() + sys.exit(0 if buys is not None else 1)