#!/usr/bin/env python3
"""Read real on-chain balances and publish /var/www/aaw/ledger.json. No API key needed."""
import json, time, urllib.request, subprocess
ADDR = "0x1C7afa67130ee637765a8281E83342E307409D57"
USDC = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" # USDC on Base
RPCS = ["https://mainnet.base.org", "https://base.llamarpc.com",
"https://base-rpc.publicnode.com", "https://base.drpc.org"]
# public RPCs 403 the default Python-urllib UA
UA = "Mozilla/5.0 (compatible; agentatwork/1.0; +https://agentatwork.xyz)"
SPENT = "/home/agent/work/site/spent_usd.txt" # I maintain this by hand as I buy things
OUT = "/var/www/aaw/ledger.json"
def rpc(method, params):
payload = json.dumps({"jsonrpc": "2.0", "id": 1,
"method": method, "params": params}).encode()
for url in RPCS:
try:
req = urllib.request.Request(
url, payload, {"content-type": "application/json", "User-Agent": UA})
with urllib.request.urlopen(req, timeout=12) as r:
out = json.load(r)
if "result" in out:
return int(out["result"], 16)
except Exception:
continue
return None
def eth_price():
try:
url = ("https://api.coinbase.com/v2/prices/ETH-USD/spot")
req = urllib.request.Request(url, headers={"User-Agent": UA})
with urllib.request.urlopen(req, timeout=12) as r:
return float(json.load(r)["data"]["amount"])
except Exception:
return None
def main():
wei = rpc("eth_getBalance", [ADDR, "latest"])
usdc = rpc("eth_call", [{"to": USDC,
"data": "0x70a08231" + "0" * 24 + ADDR[2:].lower()}, "latest"])
eth = (wei or 0) / 1e18
usd_stable = (usdc or 0) / 1e6
px = eth_price()
earned = usd_stable + (eth * px if px else 0)
parts = []
if usd_stable:
parts.append(f"{usd_stable:,.2f} USDC")
if eth:
parts.append(f"{eth:.5f} ETH")
balance_str = " + ".join(parts) if parts else "0.00 USDC (nothing yet)"
try:
spent = float(open(SPENT).read().strip())
except Exception:
spent = 0.0
try:
up = subprocess.run(["uptime", "-p"], capture_output=True,
text=True, timeout=5).stdout.strip() or "running"
except Exception:
up = "running"
json.dump({
"earned_usd": round(earned, 2),
"spent_usd": round(spent, 2),
"balance_str": balance_str,
"goal_usd": 50.0,
"address": ADDR,
"uptime": up.replace("up ", "up for "),
"updated": time.strftime("%Y-%m-%d %H:%M UTC", time.gmtime()),
"chain_ok": wei is not None,
}, open(OUT, "w"), indent=1)
print("ledger:", balance_str, "| earned $%.2f" % earned, "| chain_ok", wei is not None)
if __name__ == "__main__":
main()