From ed058c6040341290dd830a1b8e9e891544997d8c Mon Sep 17 00:00:00 2001 From: Pam Selle Date: Tue, 8 Sep 2026 11:02:21 -0400 Subject: [PATCH 1/6] fix: fall back to wasm hash in contract history when unpublished MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A contract's version history (/v1/contracts/{name}) includes every on-chain wasm transition, not just published ones — wasm_name/ wasm_version/wasm_channel are null for transitions that never resolved to a published wasm (e.g. predate the registry, or were never published). The Contract History list assumed these were always present and linked every entry to /wasms/{name}/v/{version}, which broke (or rendered nothing useful) for contracts with unpublished history — see stellar-registry/tansu on testnet. Minimal-surface fix on the UI side only: when a version entry has no published wasm_name, render its wasm_hash as plain text instead of a link. Entries that do resolve to a published wasm keep linking to the registry wasm page as before. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01BFkp8Uduc8SWRMmeUS9c1E --- app/lib/types.ts | 13 ++++++++++--- app/routes/contractDetails.tsx | 31 ++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/app/lib/types.ts b/app/lib/types.ts index 4f32b64..8656c55 100644 --- a/app/lib/types.ts +++ b/app/lib/types.ts @@ -100,10 +100,17 @@ export interface Contract { is_stellar_asset_contract: boolean } +// wasm_name/wasm_version/wasm_channel are null when this on-chain wasm +// transition never resolved to a published wasm (uploaded but not +// published, or predates the registry). wasm_hash can ALSO be null — not +// every transition's executable is backed by a wasm hash at all (e.g. an +// upgrade to an `ExternalRef` executable, seen in production); the UI +// needs a fallback below the "hash, unlinked" case too. interface ContractVersion { - wasm_name: string - wasm_version: string - wasm_channel?: string + wasm_hash: string | null + wasm_name: string | null + wasm_version: string | null + wasm_channel: string | null version_index: number kind: string } diff --git a/app/routes/contractDetails.tsx b/app/routes/contractDetails.tsx index 79c6425..defdcf2 100644 --- a/app/routes/contractDetails.tsx +++ b/app/routes/contractDetails.tsx @@ -135,20 +135,29 @@ export default function ContractDetail({ loaderData }: Route.ComponentProps) {
    {contractVersions.map((version) => { - const versionWasmName = prefixName( - version.wasm_name!, - version.wasm_channel, - ) - const versionLabel = `${versionWasmName}@v${version.wasm_version}` + const isPublished = !!version.wasm_name + const versionWasmName = isPublished + ? prefixName( + version.wasm_name!, + version.wasm_channel ?? undefined, + ) + : undefined + const versionLabel = isPublished + ? `${versionWasmName}@v${version.wasm_version}` + : (version.wasm_hash ?? "non-wasm executable") return ( -
  1. +
  2. {version.version_index}:  - - {versionLabel} - {" "} + {isPublished ? ( + + {versionLabel} + + ) : ( + versionLabel + )}{" "} {version.kind}
  3. ) From 9b481e06db180d4b1c9a07f68cf5801c78c117f0 Mon Sep 17 00:00:00 2001 From: Pam Selle Date: Tue, 8 Sep 2026 13:15:09 -0400 Subject: [PATCH 2/6] style: truncate Contract History rows to one line, full text on hover Long wasm hashes (or the fallback labels) could wrap the version list onto multiple lines per entry. Truncate each row with an ellipsis and expose the full ':