#!/usr/bin/env python3
"""The other half of the question.

The liveness probe measures supply: 1,482 of 1,551 hosts answer a stranger with
a valid payment demand. That is a shop with the lights on. It is not a sale.

Every seller in the Bazaar publishes the address they want to be paid at, and
Base is public, so the demand side is measurable too: count USDC Transfer logs
*into* the 1,032 Base payee addresses over the last 24 hours.

The honest caveat, stated before the number rather than after it: a USDC
transfer into a seller's address is not proof of an x402 sale. It could be the
operator topping up, an exchange withdrawal, or unrelated business. What makes
it evidence is the *size distribution* -- listings ask a median of one cent, so
if the incoming transfers cluster at cent-scale they are being paid for what
they advertise, and if they cluster at hundreds of dollars they are something
else wearing the same address. I report the distribution rather than a verdict.
"""
import json, sys, time, collections
sys.path.insert(0, "/home/agent")
from wstatus import rpc, USDC

TRANSFER = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
CHUNK = 1000
BLOCKS_24H = 43200  # Base targets 2s blocks


def pad(a):
    return "0x" + "0" * 24 + a[2:]


def main():
    raw = json.load(open("/home/agent/x402survey/raw.json"))
    pay = collections.Counter()
    for r in raw:
        for a in r.get("accepts", []) or []:
            p = str(a.get("payTo", "")).lower()
            if p.startswith("0x") and len(p) == 42 and a.get("network") == "eip155:8453":
                pay[p] += 1
    addrs = list(pay)
    topics = [TRANSFER, None, [pad(a) for a in addrs]]
    head = int(rpc("eth_blockNumber", []), 16)
    start = head - BLOCKS_24H
    print(f"{len(addrs)} Base payees; blocks {start}..{head}", flush=True)

    recv = collections.Counter()     # address -> number of incoming transfers
    total = collections.Counter()    # address -> total atoms received
    amounts = []
    senders = collections.Counter()
    lo = start
    while lo < head:
        hi = min(lo + CHUNK, head)
        for attempt in range(4):
            try:
                logs = rpc("eth_getLogs", [{"address": USDC, "topics": topics,
                                            "fromBlock": hex(lo), "toBlock": hex(hi)}])
                break
            except Exception as e:
                if attempt == 3:
                    print(f"  chunk {lo} FAILED {str(e)[:80]}", flush=True)
                    logs = []
                else:
                    time.sleep(2 + attempt * 3)
        for L in logs:
            to = "0x" + L["topics"][2][-40:]
            frm = "0x" + L["topics"][1][-40:]
            try:
                v = int(L["data"], 16)
            except Exception:
                continue
            recv[to] += 1
            total[to] += v
            senders[frm] += 1
            amounts.append(v)
        lo = hi
        if (lo - start) % 10000 == 0:
            print(f"  {lo-start}/{BLOCKS_24H} blocks, {len(amounts)} transfers", flush=True)

    amounts.sort()
    out = {
        "payees_listed": len(addrs),
        "payees_paid_24h": len(recv),
        "transfers_24h": len(amounts),
        "unique_senders": len(senders),
        "usdc_total_24h": sum(amounts) / 1e6,
        "blocks": [start, head],
        "amount_pctiles_usdc": {
            p: (amounts[int(len(amounts) * p / 100)] / 1e6 if amounts else None)
            for p in (10, 25, 50, 75, 90, 99)
        } if amounts else {},
        "amount_max_usdc": amounts[-1] / 1e6 if amounts else None,
        "under_1_cent": sum(1 for a in amounts if a < 10000),
        "under_1_dollar": sum(1 for a in amounts if a < 1000000),
        "top_payees": [
            {"addr": a, "transfers": n, "usdc": total[a] / 1e6, "listings": pay[a]}
            for a, n in recv.most_common(15)
        ],
        "top_senders": [{"addr": a, "transfers": n} for a, n in senders.most_common(10)],
        # Ranking payees by transfer count answers "who is busiest", which is not
        # the question a would-be seller has. That question is "what does a
        # typical seller take home in a day", and it needs every payee, ranked by
        # money rather than by traffic.
        "all_payees": sorted(
            ({"addr": a, "transfers": recv[a], "usdc": total[a] / 1e6,
              "listings": pay[a]} for a in recv),
            key=lambda x: -x["usdc"]),
    }
    json.dump(out, open("/home/agent/x402survey/demand.json", "w"), indent=1)
    print(json.dumps({k: v for k, v in out.items()
                      if k not in ("top_payees", "top_senders")}, indent=1))


if __name__ == "__main__":
    main()
