"""v3kit.py (A1.21): launch-kit label for every v3 pool with cap $100k+ at +5 min (A1.14 method: keccak of the create tx's "to" bytecode),
then extend Swap/Mint/Burn data to 48 h for kit pools with cap $150k to $2M at +5 min. Writes /root/fwa1/v3/kit.json and more rows in v3ext.db."""
import json, sqlite3, time, urllib.request, pickle
from Crypto.Hash import keccak
src = open("/root/fwa1/v3pull.py").read().split("\n")
K = json.load(open("/opt/common/drpc_paid.json"))["robinhood"]
exec(next(l for l in src if l.startswith("U =")))
PM = "0x73991a25c818bf1f1128deaab1492d45638de0d3"
def post(body):
    for i in range(6):
        try:
            rq = urllib.request.Request(U, json.dumps(body).encode(), {"Content-Type": "application/json", "User-Agent": "Mozilla/5.0"})
            return json.load(urllib.request.urlopen(rq, timeout=120))
        except Exception as e:
            err = e; time.sleep(2 * (i + 1))
    raise err
M = sqlite3.connect("file:/root/fwa1/v3/v3a1.db?mode=ro", uri=True)
P, W = pickle.load(open("/root/fwa1/v3/an.pkl", "rb"))
mc5 = {p["pool"]: p["feats"][300]["mc"] for p in P if p["feats"][300]["mc"] and p["feats"][300]["mc"] >= 1e5}
meta = {r[0]: r for r in M.execute("SELECT pool, creator_tx, cb FROM meta")}
pools = [p for p in mc5 if p in meta and meta[p][1]]
to = {}
for i in range(0, len(pools), 50):
    g = pools[i:i + 50]
    r = post([{"jsonrpc": "2.0", "id": k, "method": "eth_getTransactionByHash", "params": [meta[p][1]]} for k, p in enumerate(g)])
    for x in r:
        res = x.get("result") or {}
        to[g[x["id"]]] = ((res.get("to") or "").lower(), (res.get("from") or "").lower())
    time.sleep(0.2)
addrs = sorted({t for t, f in to.values() if t})
code = {}
for i in range(0, len(addrs), 50):
    g = addrs[i:i + 50]
    r = post([{"jsonrpc": "2.0", "id": k, "method": "eth_getCode", "params": [a, "latest"]} for k, a in enumerate(g)])
    for x in r:
        c = x.get("result") or "0x"; b = bytes.fromhex(c[2:])
        h = keccak.new(digest_bits=256); h.update(b); code[g[x["id"]]] = (h.hexdigest()[:12], len(b))
    time.sleep(0.2)
KIT = {}
for p in pools:
    t, f = to.get(p, ("", ""))
    hsh, n = code.get(t, ("", 0))
    lab = "A" if hsh == "0e81be52d5cf" else "B" if hsh == "89885b75fd29" else "PM" if t == PM else "other"
    KIT[p] = dict(kit=lab, to=t, sender=f, hash=hsh, bytes=n)
json.dump(KIT, open("/root/fwa1/v3/kit.json", "w"))
import collections
print("labels", collections.Counter(v["kit"] for v in KIT.values()))
print("top other hashes", collections.Counter((v["hash"], v["bytes"]) for v in KIT.values() if v["kit"] == "other").most_common(6), flush=True)
# extend to 48 h for kit pools, cap $150k-$2M at +5 min
T_SWAP = "0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67"
T_MINT = "0x7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde"
T_BURN = "0x0c396cd989a39f4459b5fa1aed6a9a8dcdbc45908acfd67e028cd568da98982c"
SPB = 0.101283; W12 = int(12 * 3600 / SPB); W48 = int(48 * 3600 / SPB); CH = 50000
head = int(post({"jsonrpc": "2.0", "id": 1, "method": "eth_blockNumber", "params": []})["result"], 16)
D = sqlite3.connect("/root/fwa1/v3/v3ext.db", timeout=120)
done = {tuple(r) for r in D.execute("SELECT pool, fb FROM done")}
jobs = []
for p, v in KIT.items():
    if v["kit"] not in ("A", "B") or not (1.5e5 <= mc5[p] < 2e6): continue
    cb = meta[p][2]
    for f in range(cb + W12 + 1, min(cb + W48, head) + 1, CH):
        if (p, f) not in done: jobs.append((p, f, min(f + CH - 1, cb + W48, head)))
print("48 h jobs", len(jobs), flush=True)
for i in range(0, len(jobs), 20):
    g = jobs[i:i + 20]
    res = post([{"jsonrpc": "2.0", "id": k, "method": "eth_getLogs", "params": [{"address": p, "fromBlock": hex(f), "toBlock": hex(t), "topics": [[T_SWAP, T_MINT, T_BURN]]}]} for k, (p, f, t) in enumerate(g)])
    for r in (res if isinstance(res, list) else []):
        p, f, t = g[r["id"]]
        if "result" not in r: continue
        for l in r["result"]:
            b, li = int(l["blockNumber"], 16), int(l["logIndex"], 16)
            if l["topics"][0] == T_SWAP:
                D.execute("INSERT OR IGNORE INTO sw VALUES(?,?,?,?,?,?,?,?,?)", (p, b, li, l["transactionHash"], "0x" + l["topics"][1][26:], "0x" + l["topics"][2][26:], l["data"][2:66], l["data"][66:130], l["data"][130:194]))
            else:
                D.execute("INSERT OR IGNORE INTO lp VALUES(?,?,?,?,?)", (p, b, li, "m" if l["topics"][0] == T_MINT else "b", l["data"]))
        D.execute("INSERT OR IGNORE INTO done VALUES(?,?)", (p, f))
    D.commit(); time.sleep(0.3)
print("done 48h", flush=True)
