"""sellrouter.py (ppfeeds #2346/#2348): sell sim for H3000 WETH pools via the pool's OWN router (the only sender the hook accepts).
Router calldata (sel b3938887, copied from real sells): (c0=WETH, c1=token, fee, ts, hooks, zeroForOne=0, amountIn, minOut, recipientWord, deadline).
Usage: sellrouter.py OUT.db  (pools+amounts from /tmp/sc.db copy of sellcross.db)"""
import sys, json, sqlite3, time, collections
sys.path.insert(0, "/opt/sw"); sys.path.insert(0, "/opt/sw/sellsim")
import rpcfall
from sellprobe import k, pad, h, W, probe_balance, probe_allow
WETH = "0x0bd7d308f8e1639fab988df18a8011f41eacad73"
def rpc(m, p): return rpcfall.post({"jsonrpc": "2.0", "id": 1, "method": m, "params": p}, timeout=20, tries=3)
def data(tok, hooks, amt, minout, rword):
    ws = [WETH, tok, 3000, 60, hooks, 0, amt, minout, rword, 0xffffffff]
    return "0xb3938887" + "".join(pad(x).hex() for x in ws)
def sim(router, tok, hooks, amt, tag, rword):
    b = probe_balance(tok); a = probe_allow(tok, W, router)
    if not b or not a: return dict(err="probe_fail bal=%s allow=%s" % (bool(b), bool(a)))
    ov = {tok: {"stateDiff": {b[1]: h(pad(amt)), a[1]: h(pad(1 << 200))}}, W: {"balance": "0x" + "f" * 20},
          router: {"stateDiff": {h(k(pad(W) + pad(4))): h(pad(1))}}}   # router caller-whitelist mapping at slot 4 (buyers via router are whitelisted: 45/45 sampled)
    out = {}
    r = rpc("eth_call", [{"from": W, "to": router, "data": data(tok, hooks, amt, 0, rword)}, tag, ov])
    if "result" in r: out["ok"] = 1
    elif "error" in r: out["ok"] = 0; out["revert"] = str(r["error"].get("data", r["error"].get("message")))[:140]; return out
    else: out["err"] = str(r)[:100]; return out
    r2 = rpc("eth_call", [{"from": W, "to": router, "data": data(tok, hooks, amt, 1 << 120, rword)}, tag, ov])
    d = r2.get("error", {}).get("data", "")
    if isinstance(d, str) and len(d) >= 138: out["out_eth"] = int(d[-64:], 16) / 1e18
    return out
def routers():
    src = sqlite3.connect("/tmp/sc.db"); tok = {r[0]: r[1] for r in src.execute("select pool,token from cross where quote='weth'")}
    cnt = collections.defaultdict(collections.Counter)
    for l in open("/opt/sw/v4tape/swaps.jsonl"):
        try: s = json.loads(l)
        except Exception: continue
        p = s["pool_id"]
        if p not in tok: continue
        a = s["amount0"] if tok[p] < WETH else s["amount1"]
        if a < 0 and s["sender"] != "0x8876789976decbfcbbbe364623c63652db8c0904": cnt[p][s["sender"]] += 1
    return {p: c.most_common(1)[0][0] for p, c in cnt.items()}
if __name__ == "__main__":
    src = sqlite3.connect("/tmp/sc.db"); o = sqlite3.connect(sys.argv[1]); R = routers()
    o.execute("create table if not exists r(pool,token,hooks,router,level,cap_usd,amount_in,mode,ok,out_eth,revert,err,t,primary key(pool,level))")
    rw = sys.argv[2] if len(sys.argv) > 2 else "router"
    for pool, tok, hk, lv, cap, amt, blk in src.execute("select pool,token,hooks,level,cap_usd,amount_in,block from cross where quote='weth' and cap_usd<1e9").fetchall():
        if pool not in R: continue
        router = R[pool]; rword = int(router, 16) if rw == "router" else int(W, 16)
        amt = int(amt); mode = "hist_at_block"
        r = sim(router, tok, hk, amt, hex(blk), rword)
        if r.get("err") or "missing trie" in r.get("revert", "") or r.get("revert") == "0x":
            r2 = sim(router, tok, hk, amt, "latest", rword)
            if r2.get("ok") is not None: r = r2; mode = "latest"
        o.execute("insert or replace into r values(?,?,?,?,?,?,?,?,?,?,?,?,?)", (pool, tok, hk, router, lv, cap, str(amt), mode, r.get("ok"), r.get("out_eth"), r.get("revert"), r.get("err"), time.time()))
        o.commit(); print(pool[:10], lv, mode, r, flush=True)
