solwatch 0.1.6

Real-data Solana memecoin auditor — rug/freeze/bundle scanner with a 0-100 risk score, plain-English flags, and a live dashboard. Sister tool to Hoodwatch.
Documentation
//! Solana mainnet constants + endpoint config. All endpoints are public and
//! tokenless; override via env for a paid RPC (Helius etc.) when rate limits bite.

pub const CHAIN: &str = "solana";

pub fn rpc_url() -> String {
    if let Ok(u) = std::env::var("SOLWATCH_RPC_URL") {
        return u;
    }
    // A Helius key (free tier) removes the public endpoint's method blocks —
    // used automatically when present, never required.
    if let Ok(k) = std::env::var("HELIUS_API_KEY") {
        if !k.trim().is_empty() {
            return format!("https://mainnet.helius-rpc.com/?api-key={}", k.trim());
        }
    }
    "https://api.mainnet-beta.solana.com".to_string()
}

/// Global RPC concurrency (a public endpoint throttles bursts hard).
pub fn rpc_concurrency() -> usize {
    std::env::var("SOLWATCH_RPC_CONCURRENCY")
        .ok()
        .and_then(|s| s.parse().ok())
        .filter(|n| *n >= 1 && *n <= 64)
        .unwrap_or(4)
}

pub fn jupiter_base() -> String {
    std::env::var("SOLWATCH_JUPITER").unwrap_or_else(|_| "https://lite-api.jup.ag".to_string())
}

/// The audit's "view this in Rokha" link, or None.
///
/// There is deliberately NO fabricated default. An earlier version emitted
/// `https://rokha.ai/?app=solwatch&token=<mint>` — **that route does not
/// exist**, so every audit advertised a dead link. The real shareable surface
/// is the rig's product page (`rokha.ai/@<handle>/<rig-slug>`), which only
/// exists once its owner mints the link — an owner-specific fact this binary
/// cannot know. So the owner supplies it:
///
/// ```text
/// SOLWATCH_ROKHA_URL=https://rokha.ai/@you/solwatch-audit
/// ```
///
/// Unset (the default) => the field is omitted entirely. Never advertise a URL
/// we have not been told is real.
pub fn rokha_link() -> Option<String> {
    std::env::var("SOLWATCH_ROKHA_URL")
        .ok()
        .map(|s| s.trim().to_string())
        .filter(|s| !s.is_empty())
}

pub const DEXSCREENER_BASE: &str = "https://api.dexscreener.com";
pub const DEXSCREENER_CHAIN: &str = "solana";

// Core program ids.
pub const SYSTEM_PROGRAM: &str = "11111111111111111111111111111111";
pub const SPL_TOKEN: &str = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
pub const TOKEN_2022: &str = "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb";
pub const METAPLEX_METADATA: &str = "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s";
pub const ASSOCIATED_TOKEN: &str = "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL";
pub const PUMPFUN_PROGRAM: &str = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P";

/// Burn / dead destinations excluded from holder math.
pub const INCINERATOR: &str = "1nc1nerator11111111111111111111111111111111";

/// Token-locker / vesting program owners: a top holder whose owner account is
/// owned by one of these is a LOCK (team vesting, escrow), not a whale —
/// excluded from concentration math and never clustered.
pub fn locker_program_labels() -> Vec<(&'static str, &'static str)> {
    vec![
        (
            "strmRqUCoQUgGUan5YhzUZa6KqdzwX5L6FpUxfmKg5m",
            "Streamflow lock",
        ),
        (
            "LocpQgucEQHbqNABEYvBvwoxCPsSbG91A1QaQhQQqjn",
            "Jupiter Lock",
        ),
        (
            "TokenVestA6qNSLDGRc4KzMRWfPXGqmDFj2CJYhKRWH",
            "Bonfida token vesting",
        ),
        (
            "CChTq6PthWEHaGSa2cbKDBw3JfaYspbC24oZQYZ1kFa5",
            "Bonfida vesting (legacy)",
        ),
    ]
}

/// Jito tip accounts (static, 8). A launch-window transaction paying one of
/// these is a Jito-bundled transaction — the atomic-coordination fingerprint.
pub const JITO_TIP_ACCOUNTS: [&str; 8] = [
    "96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5",
    "HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe",
    "Cw8CFyM9FkoMi7K7Crf6HNQqf4uEMzpKw6QNghXLvLkY",
    "ADaUMid9yfUytqMBgopwjb2DTLSokTSzL1zt6iGPaS49",
    "DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh",
    "ADuUkR4vqLUMWXxW9gh6D6L8pMSawimctcNZ5pGwDcEt",
    "DttWaMuVvTiduZRnguLF7jNxTgiMBZ1hyAumKUiL2KRL",
    "3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jT",
];

/// Jito bundle-proof API (per-transaction bundle lookup). Third-party — every
/// use degrades gracefully to the tip heuristic when unreachable.
pub const JITO_BUNDLES_API: &str = "https://bundles.jito.wtf/api/v1/bundles/transaction";

/// Known CEX / bridge hot wallets — cluster STOP-NODES. Two wallets funded by
/// an exchange withdrawal wallet are NOT the same person; unioning through one
/// of these would merge half of Solana. Rendered as `cex` nodes, never unioned.
pub fn cex_hot_wallets() -> Vec<(&'static str, &'static str)> {
    vec![
        ("5tzFkiKscXHK5ZXCGbXZxdw7gTjjD1mBwuoFbhUvuAi9", "Binance"),
        ("2ojv9BAiHUrvsm9gxDe7fJSzbNZSJcxZvf8dqmWGHG8S", "Binance"),
        ("9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM", "Binance"),
        ("AC5RDfQFmDS1deWZos921JfqscXdByf8BKHs5ACWjtW2", "Bybit"),
        ("42brAgAVNzMBP7aaktPvAmBSPEkehnFQejiZc53EpJFd", "Bybit"),
        ("H8sMJSCQxfKiFTCfDR3DUMLPwcRbM61LGFJ8N4dK3WjS", "Coinbase"),
        ("2AQdpHJ2JpcEgPiATUXjQxA8QmafFegfQwSLWSprPicm", "Coinbase"),
        (
            "GJRs4FwHtemZ5ZE9x3FNvJ8TMwitKTh21yxdRPqn7npE",
            "Coinbase Hot",
        ),
        ("5VCwKtCXgCJ6kit5FybXjvriW3xELsFDhYrPSqtJNmcD", "OKX"),
        ("9un5wqE3q4oCjyrDkwsdD48KteCJitQX5978Vh7KKxHo", "OKX 2"),
        ("FWznbcNXWQuHTawe9RxvQ2LdCENssh12dsznf4RiouN5", "Kraken"),
        ("BmFdpraQhkiDQE6SnfG5omcA1VwzqfXrwtNYBwWTymy6", "Kucoin"),
        ("ASTyfSima4LLAdDgoFGkgqoKowG1LZFDr9fAQrg7iaJZ", "MEXC"),
        ("5PAhQiYdLBd6SVdjzBQDxUAEFyDdF5ExNPQfcscnPRj5", "Gate.io"),
        ("u6PJ8DtQuPFnfmwHbGFULQ4u4EgjDiyYKjVEsynXq2w", "Gate.io 2"),
    ]
}

/// Programs that own AMM pools / bonding curves / vault authorities. A top
/// holder whose OWNER account is owned by one of these is a liquidity pool,
/// not a person — excluded from concentration math (and labeled).
pub fn pool_program_labels() -> Vec<(&'static str, &'static str)> {
    vec![
        (
            "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
            "pump.fun bonding curve",
        ),
        (
            "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA",
            "PumpSwap pool",
        ),
        (
            "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8",
            "Raydium AMM v4",
        ),
        (
            "CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK",
            "Raydium CLMM",
        ),
        (
            "CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C",
            "Raydium CPMM",
        ),
        (
            "LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj",
            "Raydium LaunchLab",
        ),
        (
            "whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc",
            "Orca Whirlpool",
        ),
        ("9W959DqEETiGZocYWCQPaJ6sBmUzgfxXfqGeTEdp3aQP", "Orca v2"),
        (
            "Eo7WjKq67rjJQSZxS6z3YkapzY3eMj6Xy8X5EQVn5UaB",
            "Meteora DAMM",
        ),
        (
            "LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo",
            "Meteora DLMM",
        ),
        (
            "cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG",
            "Meteora DAMM v2",
        ),
        ("dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN", "Meteora DBC"),
        (
            "srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX",
            "OpenBook/Serum",
        ),
        ("PhoeNiXZ8ByJGLkxNfZRnkUfjvmuYqLR89jjFHGqdXY", "Phoenix"),
        ("opnb2LAfJYbRMAHHvqjCwQxanZn7ReEHp1k81EohpZb", "OpenBook v2"),
        ("SSwpkEEcbUqx4vtoEByFjSkhKdCT862DNVb52nZg1UZ", "Saber"),
        ("MERLuDFBMmsHnsBPZw2sDQZHvXFMwp8EdjudcU2HKky", "Mercurial"),
        ("stkitrT1Uoy18Dk1fTrgPw8W6MVzoCfYoAFT4MLsmhq", "Sanctum"),
        (
            "5ocnV1qiCgaQR8Jb8xWnVbApfaygJ8tNoZfgPwsgx9kx",
            "Sanctum Infinity",
        ),
        ("HEvSKofvBgfaexv23kMabbYqxasxU3mQ4ibBMEmJWHny", "Bonkswap"),
        (
            "BSwp6bEBihVLdqJRKGgzjcGLHkcTuzmSo1TQkHepzH8p",
            "Bonk launchpad",
        ),
        (
            "boop8hVGQGqehUK2iVEMEnMrL5RbjywRzHKBmBE7ry4",
            "Boop launchpad",
        ),
        ("MoonCVVNZFSYkqNXP6bxHLPL6QQJiMagDL3qcqUQTrG", "Moonshot"),
    ]
}