#!/usr/bin/env python3 from __future__ import annotations from pathlib import Path import json import time ROOT = Path(__file__).resolve().parents[2] PROMOD_REPORT = ROOT / "reports" / "extraction" / "promod-uniswap-v2-liquidity-program-latest.json" PROMOTION_GATES = ROOT / "reports" / "extraction" / "promod-uniswap-v2-promotion-gates-latest.json" REPORT = ROOT / "reports" / "extraction" / "promod-uniswap-v2-first-deployment-target-matrix-latest.json" DOC = ROOT / "docs" / "03-deployment" / "PROMOD_UNISWAP_V2_FIRST_DEPLOYMENT_TARGET_MATRIX.md" CORE_RAILS = {"cWUSDC", "cWUSDT", "cWAUSDT"} def now() -> str: return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()) def load(path: Path): return json.loads(path.read_text()) def write_json(path: Path, payload): path.parent.mkdir(parents=True, exist_ok=True) path.write_text(json.dumps(payload, indent=2) + "\n") def write_text(path: Path, text: str): path.parent.mkdir(parents=True, exist_ok=True) path.write_text(text.rstrip() + "\n") def choose_first_pair(entry: dict) -> str: settlement = entry.get("settlement_phase_pairs", []) wrapped = entry.get("wrapped_depth_phase_pairs", []) if "cWUSDT/cWUSDC" in wrapped: return "cWUSDT/cWUSDC" if "cWAUSDT/cWUSDT" in wrapped: return "cWAUSDT/cWUSDT" if "cWAUSDT/cWUSDC" in wrapped: return "cWAUSDT/cWUSDC" hub = entry.get("hub_stable") if hub == "USDT" and "cWUSDT/USDT" in settlement: return "cWUSDT/USDT" if hub == "USDC" and "cWUSDC/USDC" in settlement: return "cWUSDC/USDC" if settlement: return settlement[0] if wrapped: return wrapped[0] return "" def why_first(entry: dict, pair: str) -> str: documented = set(entry.get("documented_cw_tokens", [])) if pair == "cWUSDT/cWUSDC": if "cWAUSDT" in documented: return "Core wrapped support rail and the one we are standardizing on first; it creates transferable depth between the two settlement-adjacent cW rails before any canonical stable exit pool." return "Core wrapped support rail and the fixed first deployment target where cWUSDT and cWUSDC are already documented." if pair == "cWAUSDT/cWUSDT": return "Fallback wrapped-first rail when cWUSDT/cWUSDC is unavailable but cWAUSDT and cWUSDT are both documented." if pair == "cWAUSDT/cWUSDC": return "Fallback wrapped-first rail when cWUSDT/cWUSDC is unavailable but cWAUSDT and cWUSDC are both documented." hub = entry["hub_stable"] if pair == "cWUSDT/USDT" and hub == "USDT": return "Fallback canonical settlement rail only for a USDT-hub chain that cannot yet open with cWUSDT/cWUSDC." if pair == "cWUSDC/USDC" and hub == "USDC": return "Fallback canonical settlement rail only for a USDC-hub chain that cannot yet open with cWUSDT/cWUSDC." if pair.startswith("cWAUSDT/"): return "cWAUSDT is documented on this chain, but the first pool should still be a support or settlement rail before cWAUSDT expansion." return "First deployable rail selected from the current program ordering." def post_deploy_commands(chain_id: int) -> list[str]: return [ "bash scripts/verify/build-promod-uniswap-v2-live-pair-discovery.sh", "python3 scripts/lib/promod_uniswap_v2_live_pair_discovery.py --write-discovered", "node cross-chain-pmm-lps/scripts/validate-deployment-status.cjs cross-chain-pmm-lps/config/deployment-status.json", "bash scripts/verify/build-promod-uniswap-v2-promotion-gates.sh", ] def build_next_expansion_pairs(entry: dict) -> list[str]: documented = entry.get("documented_cw_tokens", []) extras = [token for token in documented if token not in CORE_RAILS] pairs: list[str] = [] for token in extras: if "cWUSDC" in documented: pairs.append(f"{token}/cWUSDC") if "cWUSDT" in documented: pairs.append(f"{token}/cWUSDT") return pairs def main(): promod = load(PROMOD_REPORT) gates = load(PROMOTION_GATES) gates_by_chain = {entry["chain_id"]: entry for entry in gates["entries"]} entries = [] for entry in promod["entries"]: chain_id = entry["chain_id"] first_pair = choose_first_pair(entry) token_a, token_b = first_pair.split("/") if first_pair else ("", "") gate = gates_by_chain.get(chain_id, {}) remaining = [ blocker for blocker in gate.get("blocking_items", []) if "cWAUSDT is not currently documented" not in blocker ] additional_tokens = [token for token in entry.get("documented_cw_tokens", []) if token not in CORE_RAILS] next_pairs = build_next_expansion_pairs(entry) entries.append( { "chain_id": chain_id, "network": entry["network"], "tier": entry["tier"], "hub_stable": entry["hub_stable"], "first_pair": first_pair, "why_it_should_be_first": why_first(entry, first_pair), "required_tokens": [token_a, token_b], "other_gru_v2_cw_tokens": additional_tokens, "next_wrapped_expansion_pairs": next_pairs, "required_token_addresses_present": [token_a in entry.get("documented_cw_tokens", []) or token_a in {"USDC", "USDT"}, token_b in entry.get("documented_cw_tokens", []) or token_b in {"USDC", "USDT"}], "chain_ready_for_deploy_prep": gate.get("env_values_present", False) and gate.get("promotion_gate", {}).get("indexer_support_present", False), "remaining_live_blockers": remaining, "post_deploy_commands": post_deploy_commands(chain_id), } ) payload = { "generated_at": now(), "program_name": promod["program_name"], "purpose": "Exact first-pair deployment target matrix for Mr. Promod's Uniswap V2 rollout.", "mainnet_funding_posture": promod["mainnet_funding_posture"], "entries": entries, "source_artifacts": [ "reports/extraction/promod-uniswap-v2-liquidity-program-latest.json", "reports/extraction/promod-uniswap-v2-promotion-gates-latest.json", ], } write_json(REPORT, payload) lines = [ "# Mr. Promod Uniswap V2 First Deployment Target Matrix", "", f"- Generated: `{payload['generated_at']}`", f"- Program: {payload['program_name']}", f"- Mainnet funding posture: `{payload['mainnet_funding_posture']['mode']}` via `{', '.join(payload['mainnet_funding_posture']['required_deployer_assets'])}`", "- Purpose: choose the first pair per chain so the first live pool rollout is concrete rather than generic.", "", "| Chain | Network | First Pair | Why It Should Be First | Required Tokens | Other GRU v2 cW* Tokens | Next Wrapped Expansion Pairs | Post-Deploy Commands |", "|---|---|---|---|---|---|---|---|", ] for entry in entries: commands = "
".join(f"`{cmd}`" for cmd in entry["post_deploy_commands"]) required = ", ".join(f"`{token}`" for token in entry["required_tokens"] if token) extras = ", ".join(f"`{token}`" for token in entry["other_gru_v2_cw_tokens"]) or "—" next_pairs = ", ".join(f"`{pair}`" for pair in entry["next_wrapped_expansion_pairs"][:8]) or "—" lines.append( f"| `{entry['chain_id']}` | {entry['network']} | `{entry['first_pair']}` | {entry['why_it_should_be_first']} | {required} | {extras} | {next_pairs} | {commands} |" ) lines.extend( [ "", "## Selection Rule", "", "- First choice is always `cWUSDT/cWUSDC` when both rails are documented on the chain.", "- If `cWUSDT/cWUSDC` is unavailable, prefer a wrapped-first fallback before opening a canonical settlement rail.", "- The other documented GRU v2 `cW*` assets expand next as wrapped pairs against `cWUSDC` and `cWUSDT`.", "- Canonical settlement rails such as `cWUSDC/USDC` or `cWUSDT/USDT` become the first target only when the chain cannot open with the wrapped support rail.", "- `cWAUSDT` remains a wrapped-depth support asset, not the default first target, unless it is required as the only viable wrapped-first fallback.", ] ) write_text(DOC, "\n".join(lines)) print(REPORT) if __name__ == "__main__": main()