From e2d5f31883db8a80350a6bd0cce0cef42e946064 Mon Sep 17 00:00:00 2001 From: danielporterda Date: Mon, 15 Jun 2026 12:04:18 -0400 Subject: [PATCH] Add Wallet Gateway source updater --- .../wallet_gateway_openrpc.py | 104 ++++++++++++++++++ scripts/update_generated_reference_sources.py | 22 +++- ...test_update_generated_reference_sources.py | 93 +++++++++++++++- 3 files changed, 215 insertions(+), 4 deletions(-) create mode 100644 scripts/generated_reference_sources/wallet_gateway_openrpc.py diff --git a/scripts/generated_reference_sources/wallet_gateway_openrpc.py b/scripts/generated_reference_sources/wallet_gateway_openrpc.py new file mode 100644 index 00000000..578ede54 --- /dev/null +++ b/scripts/generated_reference_sources/wallet_gateway_openrpc.py @@ -0,0 +1,104 @@ +from __future__ import annotations + +from dataclasses import dataclass +from pathlib import Path +from typing import Required, TypedDict + +import generate_wallet_gateway_openrpc_reference as wallet_gateway_openrpc_generator + +from generated_reference_sources.common import SourceUpdate, load_json, write_json + + +REPO_ROOT = Path(__file__).resolve().parents[2] +SOURCE_KEY = "wallet-gateway-openrpc" +SOURCE_LABEL = "Wallet Gateway OpenRPC" +DEFAULT_SOURCE_CONFIG = ( + REPO_ROOT / "config" / "x2mdx" / "wallet-gateway-openrpc" / "source-artifacts.json" +) + + +class WalletGatewayOpenRpcSpecConfig(TypedDict, total=False): + spec_id: str + display_name: str + source_path: str + + +class WalletGatewayOpenRpcSourceConfigPayload(TypedDict, total=False): + source: str + release_repo: Required[str] + remote: str + tag_prefix: Required[str] + min_version: str + publish_version: Required[str] + specs: list[WalletGatewayOpenRpcSpecConfig] + + +@dataclass(frozen=True) +class WalletGatewayOpenRpcSourceConfig: + raw: WalletGatewayOpenRpcSourceConfigPayload + release_repo: str + tag_prefix: str + min_version: str + publish_version: str + + +def parse_source_config(path: Path) -> WalletGatewayOpenRpcSourceConfig: + raw_json = load_json(path) + release_repo = raw_json.get("release_repo") + tag_prefix = raw_json.get("tag_prefix") + min_version = raw_json.get("min_version") or "0.0.0" + publish_version = raw_json.get("publish_version") + if not isinstance(release_repo, str) or not release_repo: + raise ValueError("Wallet Gateway OpenRPC source config must define release_repo") + if not isinstance(tag_prefix, str) or not tag_prefix: + raise ValueError("Wallet Gateway OpenRPC source config must define tag_prefix") + if not isinstance(min_version, str): + raise ValueError("Wallet Gateway OpenRPC min_version must be a string") + if not isinstance(publish_version, str) or not publish_version: + raise ValueError(f"{path} must define non-empty publish_version") + raw: WalletGatewayOpenRpcSourceConfigPayload = {} + raw.update(raw_json) + return WalletGatewayOpenRpcSourceConfig( + raw=raw, + release_repo=release_repo, + tag_prefix=tag_prefix, + min_version=min_version, + publish_version=publish_version, + ) + + +def latest_version(source_config: WalletGatewayOpenRpcSourceConfig) -> str: + versions = wallet_gateway_openrpc_generator.stable_release_versions( + release_repo=source_config.release_repo, + tag_prefix=source_config.tag_prefix, + min_version=source_config.min_version, + max_version=None, + include_versions=None, + ) + if not versions: + raise ValueError("No Wallet Gateway OpenRPC releases selected") + return versions[-1] + + +def update_source( + *, + source_config_path: Path, + dry_run: bool, +) -> SourceUpdate | None: + source_config = parse_source_config(source_config_path) + current_version = latest_version(source_config) + if source_config.publish_version == current_version: + return None + + update = SourceUpdate( + source=SOURCE_LABEL, + path=source_config_path, + field="publish_version", + previous=source_config.publish_version, + current=current_version, + ) + if not dry_run: + updated_config = dict(source_config.raw) + updated_config["publish_version"] = current_version + write_json(source_config_path, updated_config) + return update diff --git a/scripts/update_generated_reference_sources.py b/scripts/update_generated_reference_sources.py index 45cee1cf..62ffbec6 100644 --- a/scripts/update_generated_reference_sources.py +++ b/scripts/update_generated_reference_sources.py @@ -6,12 +6,13 @@ import sys from pathlib import Path -from generated_reference_sources import splice_openapi +from generated_reference_sources import splice_openapi, wallet_gateway_openrpc from generated_reference_sources.common import SourceUpdate SOURCE_SPLICE_OPENAPI = splice_openapi.SOURCE_KEY -ALL_SOURCES = (SOURCE_SPLICE_OPENAPI,) +SOURCE_WALLET_GATEWAY_OPENRPC = wallet_gateway_openrpc.SOURCE_KEY +ALL_SOURCES = (SOURCE_SPLICE_OPENAPI, SOURCE_WALLET_GATEWAY_OPENRPC) def parse_args() -> argparse.Namespace: @@ -24,6 +25,15 @@ def parse_args() -> argparse.Namespace: default=splice_openapi.DEFAULT_SOURCE_CONFIG, help=f"Splice OpenAPI source-artifacts config. Default: {splice_openapi.DEFAULT_SOURCE_CONFIG}", ) + parser.add_argument( + "--wallet-gateway-openrpc-source-config", + type=Path, + default=wallet_gateway_openrpc.DEFAULT_SOURCE_CONFIG, + help=( + "Wallet Gateway OpenRPC source-artifacts config. " + f"Default: {wallet_gateway_openrpc.DEFAULT_SOURCE_CONFIG}" + ), + ) parser.add_argument( "--source", action="append", @@ -62,6 +72,14 @@ def main() -> int: ) if update is not None: updates.append(update) + if SOURCE_WALLET_GATEWAY_OPENRPC in sources: + update = wallet_gateway_openrpc.update_source( + source_config_path=args.wallet_gateway_openrpc_source_config.resolve(), + dry_run=args.dry_run or args.check, + ) + if update is not None: + updates.append(update) + if not updates: print("Generated reference source pins are up to date.") return 0 diff --git a/tests/test_update_generated_reference_sources.py b/tests/test_update_generated_reference_sources.py index 745bbeaf..87b65536 100644 --- a/tests/test_update_generated_reference_sources.py +++ b/tests/test_update_generated_reference_sources.py @@ -42,6 +42,25 @@ def write_source_config(path: Path, *, publish_version: str) -> None: ) +def write_wallet_gateway_source_config(path: Path, *, publish_version: str) -> None: + path.write_text( + json.dumps( + { + "source": "test", + "release_repo": "hyperledger-labs/splice-wallet-kernel", + "remote": "https://github.com/hyperledger-labs/splice-wallet-kernel.git", + "tag_prefix": "@canton-network/wallet-gateway-remote@", + "min_version": "0.24.0", + "publish_version": publish_version, + "specs": [], + }, + indent=2, + ) + + "\n", + encoding="utf-8", + ) + + def test_update_splice_openapi_source_updates_stale_publish_version(tmp_path: Path) -> None: module = load_script_module() source_config_path = tmp_path / "source-artifacts.json" @@ -105,6 +124,75 @@ def test_update_splice_openapi_source_dry_run_does_not_write(tmp_path: Path) -> assert json.loads(source_config_path.read_text(encoding="utf-8"))["publish_version"] == "0.5.18" +def test_update_wallet_gateway_openrpc_source_updates_stale_publish_version(tmp_path: Path) -> None: + module = load_script_module() + source_config_path = tmp_path / "source-artifacts.json" + write_wallet_gateway_source_config(source_config_path, publish_version="0.25.0") + module.wallet_gateway_openrpc.wallet_gateway_openrpc_generator.stable_release_versions = ( + lambda **_kwargs: [ + "0.25.0", + "1.4.0", + ] + ) + + update = module.wallet_gateway_openrpc.update_source( + source_config_path=source_config_path, + dry_run=False, + ) + + assert update == module.SourceUpdate( + source="Wallet Gateway OpenRPC", + path=source_config_path, + field="publish_version", + previous="0.25.0", + current="1.4.0", + ) + assert json.loads(source_config_path.read_text(encoding="utf-8"))["publish_version"] == "1.4.0" + + +def test_update_wallet_gateway_openrpc_source_noops_when_current(tmp_path: Path) -> None: + module = load_script_module() + source_config_path = tmp_path / "source-artifacts.json" + write_wallet_gateway_source_config(source_config_path, publish_version="1.4.0") + module.wallet_gateway_openrpc.wallet_gateway_openrpc_generator.stable_release_versions = ( + lambda **_kwargs: [ + "0.25.0", + "1.4.0", + ] + ) + + assert ( + module.wallet_gateway_openrpc.update_source( + source_config_path=source_config_path, + dry_run=False, + ) + is None + ) + assert json.loads(source_config_path.read_text(encoding="utf-8"))["publish_version"] == "1.4.0" + + +def test_update_wallet_gateway_openrpc_source_dry_run_does_not_write(tmp_path: Path) -> None: + module = load_script_module() + source_config_path = tmp_path / "source-artifacts.json" + write_wallet_gateway_source_config(source_config_path, publish_version="0.25.0") + module.wallet_gateway_openrpc.wallet_gateway_openrpc_generator.stable_release_versions = ( + lambda **_kwargs: [ + "0.25.0", + "1.4.0", + ] + ) + + update = module.wallet_gateway_openrpc.update_source( + source_config_path=source_config_path, + dry_run=True, + ) + + assert update is not None + assert update.previous == "0.25.0" + assert update.current == "1.4.0" + assert json.loads(source_config_path.read_text(encoding="utf-8"))["publish_version"] == "0.25.0" + + def test_requested_sources_defaults_to_all_sources() -> None: module = load_script_module() @@ -120,9 +208,10 @@ def test_requested_sources_preserves_order_and_deduplicates() -> None: (), { "sources": [ + "wallet-gateway-openrpc", "splice-openapi", - "splice-openapi", + "wallet-gateway-openrpc", ] }, )() - ) == ("splice-openapi",) + ) == ("wallet-gateway-openrpc", "splice-openapi")