#!/usr/bin/env python3
"""Clustly settle-rate row — jill's ask (2026-09-29): of the 24 live listings,
how many agentWallets show >=1 confirmed on-chain receive, amounts publishable.

Method (stranger-replayable):
  1. GET clustly.ai/v1/listings -> collect distinct agentWallet (Solana).
  2. Per wallet, Solana mainnet RPC (api.mainnet-beta.solana.com):
     a. getBalance(owner)                    -> SOL lamports
     b. getSignaturesForAddress(owner, 20)   -> owner-account tx count
     c. getTokenAccountsByOwner(owner, USDC mint) -> ATA + uiAmount
     d. getSignaturesForAddress(ATA, 20)     -> token-account tx count
  A wallet "has receive evidence" iff its USDC ATA exists with tx history
  or balance > 0, or the owner account shows any confirmed signatures.
Stdlib only. Prints the row + writes JSON next to this file.
"""
import json, time, urllib.request, sys, os

RPC = "https://api.mainnet-beta.solana.com"
USDC_MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
HERE = os.path.dirname(os.path.abspath(__file__))

def rpc(method, params, retries=3):
    body = json.dumps({"jsonrpc": "2.0", "id": 1, "method": method, "params": params}).encode()
    for i in range(retries):
        try:
            req = urllib.request.Request(RPC, data=body,
                headers={"Content-Type": "application/json", "User-Agent": "ARION-brain/1.0"})
            d = json.load(urllib.request.urlopen(req, timeout=25))
            if "error" in d:
                return {"error": d["error"]}
            return d.get("result")
        except Exception as e:
            if i == retries - 1:
                return {"error": str(e)}
            time.sleep(2)

def main():
    req = urllib.request.Request("https://clustly.ai/v1/listings",
                                 headers={"User-Agent": "ARION-brain/1.0"})
    d = json.load(urllib.request.urlopen(req, timeout=25))
    items = d if isinstance(d, list) else d.get("items", d.get("listings", []))
    wallets = {}
    for l in items:
        wallets.setdefault(l.get("agentWallet"), set()).add(l.get("agentName"))
    print("listings=%d distinct_wallets=%d" % (len(items), len(wallets)))

    rows = []
    for w in sorted(wallets):
        names = sorted(wallets[w])
        bal = rpc("getBalance", [w])
        sol = (bal or {}).get("value", 0) / 1e9 if isinstance(bal, dict) else 0
        sigs = rpc("getSignaturesForAddress", [w, {"limit": 20}])
        n_owner_sigs = len(sigs) if isinstance(sigs, list) else 0
        tok = rpc("getTokenAccountsByOwner",
                  [w, {"mint": USDC_MINT}, {"encoding": "jsonParsed"}])
        atas = tok.get("value", []) if isinstance(tok, dict) else []
        usdc_bal = 0.0
        ata_addr = None
        ata_sigs = 0
        first_sig = None
        if atas:
            a = atas[0]
            ata_addr = a.get("pubkey")
            try:
                usdc_bal = float(a["account"]["data"]["parsed"]["info"]
                                 ["tokenAmount"]["uiAmount"] or 0)
            except Exception:
                pass
            s2 = rpc("getSignaturesForAddress", [ata_addr, {"limit": 20}])
            if isinstance(s2, list):
                ata_sigs = len(s2)
                if s2:
                    first_sig = s2[-1].get("signature")
        has_recv = (usdc_bal > 0) or ata_sigs > 0 or n_owner_sigs > 0
        rows.append({
            "wallet": w, "agents": names, "sol": round(sol, 6),
            "owner_sigs_sampled": n_owner_sigs, "usdc_ata": ata_addr,
            "usdc_balance": usdc_bal, "ata_sigs_sampled": ata_sigs,
            "sample_tx": first_sig, "has_onchain_activity": has_recv,
        })
        print("%s | %s | sol=%.6f owner_sigs=%d usdc=%s ata_sigs=%d active=%s"
              % (w[:12], names[0], sol, n_owner_sigs, usdc_bal, ata_sigs, has_recv))
        time.sleep(0.4)

    active = [r for r in rows if r["has_onchain_activity"]]
    out = {"checked_at": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
           "listings": len(items), "wallets": len(wallets),
           "wallets_with_onchain_activity": len(active), "rows": rows}
    path = os.path.join(HERE, "clustly_settle_rate_20260929.json")
    json.dump(out, open(path, "w"), indent=1)
    print("\nSETTLE-ROW: %d/%d wallets show >=1 confirmed-chain signature; "
          "%d/%d hold nonzero USDC" % (len(active), len(wallets),
          sum(1 for r in rows if r["usdc_balance"] > 0), len(wallets)))
    print("wrote", path)

if __name__ == "__main__":
    main()
