From d059274c13fa78dc64478c4aca5cdf2ed06e14d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Corentin=20M=C3=A9hat?= Date: Tue, 9 Jun 2026 13:51:33 -0400 Subject: [PATCH 1/2] Add historical voting data from TzKT to protocol popups Fetch voting epoch data (ballot counts, result) for each protocol that passed through on-chain governance. Attach as a "voting" key in protocols.json and display in the map popup. --- docs/index.html | 14 +++++++-- scripts/update_gpx.py | 72 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 3 deletions(-) diff --git a/docs/index.html b/docs/index.html index c05476a..3eaaffc 100644 --- a/docs/index.html +++ b/docs/index.html @@ -74,12 +74,20 @@ var date = d.activationDate ? d.activationDate.split("T")[0] : "N/A"; var network = d.mainnet ? "Mainnet" : "Testnet only"; - marker.bindPopup( + var popupHtml = "" + esc(String(d.number).padStart(3, "0") + " " + d.name) + "
" + "Hash: " + esc(hashTrunc) + "
" + "Activated: " + esc(date) + "
" + - "Network: " + esc(network) - ); + "Network: " + esc(network); + + if (d.voting) { + popupHtml += "
Voted: Epoch " + esc(String(d.voting.epoch)) + + " \u2014 " + esc(d.voting.result) + + "
Ballots: " + d.voting.yayBallots + " yay, " + + d.voting.nayBallots + " nay, " + d.voting.passBallots + " pass"; + } + + marker.bindPopup(popupHtml); trailCoords.push([d.lat, d.lon]); }); diff --git a/scripts/update_gpx.py b/scripts/update_gpx.py index 3c23ee6..5d9d8cc 100644 --- a/scripts/update_gpx.py +++ b/scripts/update_gpx.py @@ -286,6 +286,63 @@ def build_protocols_json(scraped, tzkt_data, gpx_coords, testnet_info=None): return result +def fetch_voting_epochs(): + """Fetch historical voting epoch data from TzKT. Returns dict keyed by proposal hash.""" + try: + resp = requests.get( + f"{TZKT_API}/voting/epochs", + params={"limit": 100, "sort.desc": "id"}, + timeout=30, + ) + resp.raise_for_status() + raw = resp.json() + except (requests.RequestException, ValueError) as exc: + print(f" WARNING: TzKT voting API unreachable ({exc}).", file=sys.stderr) + return {} + + if not isinstance(raw, list): + return {} + + epochs = {} + for epoch in raw: + if not isinstance(epoch, dict): + continue + proposals = epoch.get("proposals") + if not proposals or not isinstance(proposals, list): + continue + for proposal in proposals: + if not isinstance(proposal, dict): + continue + prop_hash = proposal.get("hash") + if not prop_hash: + continue + status = epoch.get("status") or "unknown" + periods = epoch.get("periods") + # Extract ballot data from the last period (promotion vote). + yay = 0 + nay = 0 + pas = 0 + if isinstance(periods, list): + for period in reversed(periods): + if not isinstance(period, dict): + continue + if period.get("kind") in ("promotion", "exploration"): + yay = period.get("yayBallots") or 0 + nay = period.get("nayBallots") or 0 + pas = period.get("passBallots") or 0 + break + + epochs[prop_hash] = { + "epoch": epoch.get("index"), + "result": status, + "yayBallots": yay, + "nayBallots": nay, + "passBallots": pas, + } + + return epochs + + def write_protocols_json(protocols_data): """Write protocols.json and protocol-count.json.""" with open(PROTOCOLS_JSON_PATH, "w", encoding="utf-8") as f: @@ -398,6 +455,21 @@ def main(): gpx_coords = gpx_coords_for_protocols(scraped, final_text) protocols_data = build_protocols_json(scraped, tzkt_data, gpx_coords, testnet_info) + + # Enrich with historical voting data. + print("Fetching voting epoch data from TzKT...") + voting_epochs = fetch_voting_epochs() + if voting_epochs: + matched = 0 + for proto in protocols_data.values(): + proto_hash = proto.get("hash") + if proto_hash and proto_hash in voting_epochs: + proto["voting"] = voting_epochs[proto_hash] + matched += 1 + print(f" Matched voting data for {matched} protocols.") + else: + print(" No voting data available.") + write_protocols_json(protocols_data) From 6964d5a94be2a34edc253458ab91b5d46cd436b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Corentin=20M=C3=A9hat?= Date: Tue, 9 Jun 2026 15:37:02 -0400 Subject: [PATCH 2/2] Remove Copolycube attribution from GPX creator string --- scripts/update_gpx.py | 2 +- tezos.gpx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/update_gpx.py b/scripts/update_gpx.py index 5d9d8cc..e40b324 100644 --- a/scripts/update_gpx.py +++ b/scripts/update_gpx.py @@ -140,7 +140,7 @@ def sort_key(wpt_block): def write_gpx(existing_text, wpt_blocks): """Write the GPX file with sorted waypoints, preserving header/footer.""" header = '\n' - header += '\n' + header += '\n' footer = "\n" sorted_blocks = sorted(wpt_blocks, key=sort_key) diff --git a/tezos.gpx b/tezos.gpx index 91e9525..44dda27 100644 --- a/tezos.gpx +++ b/tezos.gpx @@ -1,5 +1,5 @@ - + Athens, Greece Capital of Greece