import base64
import json
import sys
import time
import urllib.parse
import urllib.request
RPC = sys.argv[1]
OUT = sys.argv[2]
PER_PAGE = 100
def get(url):
for attempt in range(5):
try:
with urllib.request.urlopen(url, timeout=60) as r:
return json.load(r)
except Exception as e:
print(f" retry {attempt}: {e}", file=sys.stderr)
time.sleep(2 * (attempt + 1))
raise RuntimeError("giving up: " + url)
q = urllib.parse.quote('"cyberlink.neuron EXISTS"')
probe = f"{RPC}/tx_search?query={q}&per_page=1&page=1"
total = int(get(probe)["result"]["total_count"])
pages = (total + PER_PAGE - 1) // PER_PAGE
print(f"{total} txs, {pages} pages", file=sys.stderr)
n_links = 0
with open(OUT, "w") as out:
for page in range(1, pages + 1):
url = f"{RPC}/tx_search?query={q}&per_page={PER_PAGE}&page={page}"
res = get(url).get("result", {})
for tx in res.get("txs", []):
height = int(tx["height"])
for ev in tx.get("tx_result", {}).get("events", []):
if ev.get("type") != "cyberlink":
continue
attrs = {}
for a in ev.get("attributes", []):
k = base64.b64decode(a["key"]).decode()
v = base64.b64decode(a["value"]).decode()
attrs[k] = v
if "particleFrom" in attrs and "particleTo" in attrs:
out.write(json.dumps({
"h": height,
"f": attrs["particleFrom"],
"t": attrs["particleTo"],
}) + "\n")
n_links += 1
if page % 20 == 0:
print(f"page {page}/{pages} ยท {n_links} links", file=sys.stderr)
print(f"done: {n_links} links -> {OUT}", file=sys.stderr)