From 5aaf46b7a0b78b217993ebd496fd574e37327908 Mon Sep 17 00:00:00 2001 From: apenzk Date: Mon, 5 Jan 2026 09:32:48 +0100 Subject: [PATCH 1/8] feat: Query verification status and only display verified source code Update explorer to query node's bytecode verification endpoint and only display source code when verification succeeds. Changes: - Add getModuleVerificationStatus API client function - Add useGetModuleVerificationStatus React hook for querying verification status - Update Code component to query verification before displaying source - Only display source code if verification status is true (verified_success) - Handle errors: 404 (no source), 503 (verification disabled), false (verification failure) - Update ViewCode and Contract components to pass address/moduleName to Code component - Add SERVICE_UNAVAILABLE error type for 503 responses Display logic: - Loading: shows "Verifying source code..." message - Verified (true): displays source code with syntax highlighting - Not verified (false/error): does not display source code --- .gitignore | 3 + src/api/client.ts | 39 +++++++ .../hooks/useGetModuleVerificationStatus.ts | 40 +++++++ src/pages/Account/Components/CodeSnippet.tsx | 102 ++++++++++++++---- .../Account/Tabs/ModulesTab/Contract.tsx | 6 +- .../Account/Tabs/ModulesTab/ViewCode.tsx | 2 +- 6 files changed, 169 insertions(+), 23 deletions(-) create mode 100644 src/api/hooks/useGetModuleVerificationStatus.ts diff --git a/.gitignore b/.gitignore index 25b593ecb..0f3e0c9da 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,9 @@ # IDEs and editors /.idea /.vscode +/.claude +/.cursor +/.taskmaster # misc .DS_Store diff --git a/src/api/client.ts b/src/api/client.ts index 8b2a5f0fb..e57a5f6a5 100644 --- a/src/api/client.ts +++ b/src/api/client.ts @@ -3,6 +3,7 @@ export enum ResponseErrorType { INVALID_INPUT = "Invalid Input", UNHANDLED = "Unhandled", TOO_MANY_REQUESTS = "Too Many Requests", + SERVICE_UNAVAILABLE = "Service Unavailable", } export type ResponseError = {type: ResponseErrorType; message?: string}; @@ -16,6 +17,9 @@ export async function withResponseError(promise: Promise): Promise { if (error.status === 404) { throw {type: ResponseErrorType.NOT_FOUND}; } + if (error.status === 503) { + throw {type: ResponseErrorType.SERVICE_UNAVAILABLE}; + } } if ( error.message @@ -33,3 +37,38 @@ export async function withResponseError(promise: Promise): Promise { }; }); } + +export interface ModuleVerificationStatusResponse { + verified: boolean; +} + +/** Fetch module verification status. Throws NOT_FOUND (404) or SERVICE_UNAVAILABLE (503). */ +export async function getModuleVerificationStatus( + nodeUrl: string, + address: string, + moduleName: string, +): Promise { + const url = `${nodeUrl}/v1/accounts/${address}/modules/${moduleName}/verification_status`; + + const response = await fetch(url, { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }); + + if (!response.ok) { + if (response.status === 404) { + throw {type: ResponseErrorType.NOT_FOUND}; + } + if (response.status === 503) { + throw {type: ResponseErrorType.SERVICE_UNAVAILABLE}; + } + throw { + type: ResponseErrorType.UNHANDLED, + message: `HTTP error! status: ${response.status}`, + }; + } + + return await response.json(); +} diff --git a/src/api/hooks/useGetModuleVerificationStatus.ts b/src/api/hooks/useGetModuleVerificationStatus.ts new file mode 100644 index 000000000..ce6c4f889 --- /dev/null +++ b/src/api/hooks/useGetModuleVerificationStatus.ts @@ -0,0 +1,40 @@ +import {useQuery, UseQueryResult} from "@tanstack/react-query"; +import { + getModuleVerificationStatus, + ModuleVerificationStatusResponse, + ResponseError, + ResponseErrorType, +} from "../client"; +import {useGlobalState} from "../../global-config/GlobalConfig"; + +/** Hook to query module bytecode verification status. */ +export function useGetModuleVerificationStatus( + address: string, + moduleName: string, + options?: {enabled?: boolean}, +): UseQueryResult { + const [state] = useGlobalState(); + + return useQuery({ + queryKey: [ + "moduleVerificationStatus", + {address, moduleName}, + state.network_value, + ], + queryFn: () => + getModuleVerificationStatus(state.network_value, address, moduleName), + refetchOnWindowFocus: false, + retry: (failureCount, error) => { + // Don't retry for expected error types + if ( + error.type === ResponseErrorType.NOT_FOUND || + error.type === ResponseErrorType.SERVICE_UNAVAILABLE + ) { + return false; + } + return failureCount < 2; + }, + ...options, + }); +} + diff --git a/src/pages/Account/Components/CodeSnippet.tsx b/src/pages/Account/Components/CodeSnippet.tsx index 328141334..e256cf655 100644 --- a/src/pages/Account/Components/CodeSnippet.tsx +++ b/src/pages/Account/Components/CodeSnippet.tsx @@ -1,4 +1,12 @@ -import {Box, Button, Modal, Stack, Typography, useTheme} from "@mui/material"; +import { + Box, + Button, + CircularProgress, + Modal, + Stack, + Typography, + useTheme, +} from "@mui/material"; import {ContentCopy, OpenInFull} from "@mui/icons-material"; import SyntaxHighlighter from "react-syntax-highlighter"; import {getPublicFunctionLineNumber, transformCode} from "../../../utils"; @@ -18,6 +26,8 @@ import { } from "../../../themes/colors/aptosColorPalette"; import {useParams} from "react-router-dom"; import {useLogEventWithBasic} from "../hooks/useLogEventWithBasic"; +import {useGetModuleVerificationStatus} from "../../../api/hooks/useGetModuleVerificationStatus"; +import {ResponseErrorType} from "../../../api/client"; function useStartingLineNumber(sourceCode?: string) { const functionToHighlight = useParams().selectedFnName; @@ -105,15 +115,36 @@ function ExpandCode({sourceCode}: {sourceCode: string | undefined}) { ); } -export function Code({bytecode}: {bytecode: string}) { +/** Displays source code only if bytecode verification succeeds. */ +export function Code({ + bytecode, + address, + moduleName, +}: { + bytecode: string; + address?: string; + moduleName?: string; +}) { const {selectedModuleName} = useParams(); const logEvent = useLogEventWithBasic(); + const theme = useTheme(); + + // Use the module name from props or from URL params + const moduleNameToVerify = moduleName || selectedModuleName || ""; + + // Query verification status + const { + data: verificationStatus, + isLoading: isVerificationLoading, + error: verificationError, + } = useGetModuleVerificationStatus(address || "", moduleNameToVerify, { + enabled: !!address && !!moduleNameToVerify, + }); const TOOLTIP_TIME = 2000; // 2s const sourceCode = bytecode === "0x" ? undefined : transformCode(bytecode); - const theme = useTheme(); const [tooltipOpen, setTooltipOpen] = useState(false); async function copyCode() { @@ -136,6 +167,36 @@ export function Code({bytecode}: {bytecode: string}) { } }); + // Check if code should be shown: + // - If verification is disabled (SERVICE_UNAVAILABLE) or loading, don't show code + // - If verified = true, show code + // - If verified = false or NOT_FOUND, don't show code + const isVerified = verificationStatus?.verified === true; + const shouldShowCode = sourceCode && isVerified; + + // Determine the message to show when code is not displayed + const getNoCodeMessage = () => { + if (isVerificationLoading) { + return null; // Will show loading spinner + } + if (verificationError) { + if (verificationError.type === ResponseErrorType.SERVICE_UNAVAILABLE) { + return "Source code is not available because verification is not enabled on this node."; + } + if (verificationError.type === ResponseErrorType.NOT_FOUND) { + return "Source code is not available."; + } + return "Unable to verify source code."; + } + if (!sourceCode) { + return "Unfortunately, the source code cannot be shown because the package publisher has chosen not to make it available."; + } + if (verificationStatus?.verified === false) { + return "Source code is not available because it does not match the deployed bytecode."; + } + return "Source code is not available."; + }; + return ( Code - - {sourceCode && ( + {shouldShowCode && ( )} - {sourceCode && ( - - The source code is plain text uploaded by the deployer, which can be - different from the actual bytecode. - - )} - {!sourceCode ? ( - - Unfortunately, the source code cannot be shown because the package - publisher has chosen not to make it available + + Verifying source code... - ) : ( + ) : shouldShowCode ? ( + ) : ( + + {getNoCodeMessage()} + )} ); diff --git a/src/pages/Account/Tabs/ModulesTab/Contract.tsx b/src/pages/Account/Tabs/ModulesTab/Contract.tsx index 8d2d06d14..0bb138a7d 100644 --- a/src/pages/Account/Tabs/ModulesTab/Contract.tsx +++ b/src/pages/Account/Tabs/ModulesTab/Contract.tsx @@ -158,7 +158,11 @@ function Contract({ {module && fn && selectedModule && ( <> - + )} diff --git a/src/pages/Account/Tabs/ModulesTab/ViewCode.tsx b/src/pages/Account/Tabs/ModulesTab/ViewCode.tsx index 165ed7c07..84fbb4883 100644 --- a/src/pages/Account/Tabs/ModulesTab/ViewCode.tsx +++ b/src/pages/Account/Tabs/ModulesTab/ViewCode.tsx @@ -191,7 +191,7 @@ function ModuleContent({address, moduleName, bytecode}: ModuleContentProps) { > - + From 7a693c672e5b35eca6bc1c811af3d37e708cb0d2 Mon Sep 17 00:00:00 2001 From: apenzk Date: Mon, 5 Jan 2026 15:41:18 +0100 Subject: [PATCH 2/8] display code always but show a warning --- src/pages/Account/Components/CodeSnippet.tsx | 60 ++++++++++++-------- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/src/pages/Account/Components/CodeSnippet.tsx b/src/pages/Account/Components/CodeSnippet.tsx index e256cf655..98831e09c 100644 --- a/src/pages/Account/Components/CodeSnippet.tsx +++ b/src/pages/Account/Components/CodeSnippet.tsx @@ -1,4 +1,5 @@ import { + Alert, Box, Button, CircularProgress, @@ -115,7 +116,7 @@ function ExpandCode({sourceCode}: {sourceCode: string | undefined}) { ); } -/** Displays source code only if bytecode verification succeeds. */ +/** Displays source code with a warning if bytecode verification fails. */ export function Code({ bytecode, address, @@ -168,11 +169,13 @@ export function Code({ }); // Check if code should be shown: - // - If verification is disabled (SERVICE_UNAVAILABLE) or loading, don't show code - // - If verified = true, show code - // - If verified = false or NOT_FOUND, don't show code + // - Show code if sourceCode exists (unless SERVICE_UNAVAILABLE or NOT_FOUND) + // - Show warning if verified = false const isVerified = verificationStatus?.verified === true; - const shouldShowCode = sourceCode && isVerified; + const hasVerificationFailure = verificationStatus?.verified === false; + const shouldShowCode = sourceCode && + verificationError?.type !== ResponseErrorType.SERVICE_UNAVAILABLE && + verificationError?.type !== ResponseErrorType.NOT_FOUND; // Determine the message to show when code is not displayed const getNoCodeMessage = () => { @@ -267,27 +270,34 @@ export function Code({ Verifying source code... ) : shouldShowCode ? ( - - + {hasVerificationFailure && ( + + The deployer provided source code but it does not match the deployed bytecode. The displayed code may not accurately represent what is actually running on-chain. + + )} + - {sourceCode} - - + + {sourceCode} + + + ) : ( Date: Mon, 5 Jan 2026 15:45:27 +0100 Subject: [PATCH 3/8] fix(explorer): update local network URL to standard port 8080 --- src/constants.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/constants.tsx b/src/constants.tsx index e021debdc..9caab0245 100644 --- a/src/constants.tsx +++ b/src/constants.tsx @@ -18,7 +18,7 @@ export const bardockTestnetUrl = testnet: "", "bardock testnet": bardockTestnetUrl, devnet: "", - local: "http://localhost:30731", + local: "http://127.0.0.1:8080", mevmdevnet: "", custom: "", }; From bcdf6c5826d670342b55b1cbcfc1f2e3f9b3ef1f Mon Sep 17 00:00:00 2001 From: apenzk Date: Mon, 5 Jan 2026 16:51:29 +0100 Subject: [PATCH 4/8] change code display behavior --- src/pages/Account/Components/CodeSnippet.tsx | 44 ++++++-------------- 1 file changed, 13 insertions(+), 31 deletions(-) diff --git a/src/pages/Account/Components/CodeSnippet.tsx b/src/pages/Account/Components/CodeSnippet.tsx index 98831e09c..8aa08e35c 100644 --- a/src/pages/Account/Components/CodeSnippet.tsx +++ b/src/pages/Account/Components/CodeSnippet.tsx @@ -168,37 +168,12 @@ export function Code({ } }); - // Check if code should be shown: - // - Show code if sourceCode exists (unless SERVICE_UNAVAILABLE or NOT_FOUND) - // - Show warning if verified = false + // Always show code if sourceCode exists, with warnings when appropriate const isVerified = verificationStatus?.verified === true; const hasVerificationFailure = verificationStatus?.verified === false; - const shouldShowCode = sourceCode && - verificationError?.type !== ResponseErrorType.SERVICE_UNAVAILABLE && - verificationError?.type !== ResponseErrorType.NOT_FOUND; - - // Determine the message to show when code is not displayed - const getNoCodeMessage = () => { - if (isVerificationLoading) { - return null; // Will show loading spinner - } - if (verificationError) { - if (verificationError.type === ResponseErrorType.SERVICE_UNAVAILABLE) { - return "Source code is not available because verification is not enabled on this node."; - } - if (verificationError.type === ResponseErrorType.NOT_FOUND) { - return "Source code is not available."; - } - return "Unable to verify source code."; - } - if (!sourceCode) { - return "Unfortunately, the source code cannot be shown because the package publisher has chosen not to make it available."; - } - if (verificationStatus?.verified === false) { - return "Source code is not available because it does not match the deployed bytecode."; - } - return "Source code is not available."; - }; + const hasVerificationDisabled = verificationError?.type === ResponseErrorType.SERVICE_UNAVAILABLE; + const hasVerificationUnavailable = verificationError?.type === ResponseErrorType.NOT_FOUND; + const shouldShowCode = !!sourceCode; return ( @@ -219,7 +194,7 @@ export function Code({ Code - {shouldShowCode && ( + {sourceCode && ( )} + {(hasVerificationDisabled || hasVerificationUnavailable) && ( + + Source code verification is not available on this node. The displayed code was provided by the deployer and may not match the deployed bytecode. + + )} - {getNoCodeMessage()} + + The source code cannot be shown because the package publisher has chosen not to make it available. + )} From e50466197a7cc56bca3e26b703a32885ab3a9079 Mon Sep 17 00:00:00 2001 From: apenzk Date: Wed, 14 Jan 2026 13:08:19 +0100 Subject: [PATCH 5/8] Handle HTTP 422 compilation errors with distinct warning --- src/api/client.ts | 13 ++++++++++++- src/api/hooks/useGetModuleVerificationStatus.ts | 3 ++- src/pages/Account/Components/CodeSnippet.tsx | 10 ++++++++-- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/api/client.ts b/src/api/client.ts index e57a5f6a5..b4df30485 100644 --- a/src/api/client.ts +++ b/src/api/client.ts @@ -4,6 +4,7 @@ export enum ResponseErrorType { UNHANDLED = "Unhandled", TOO_MANY_REQUESTS = "Too Many Requests", SERVICE_UNAVAILABLE = "Service Unavailable", + COMPILATION_ERROR = "Compilation Error", } export type ResponseError = {type: ResponseErrorType; message?: string}; @@ -42,7 +43,12 @@ export interface ModuleVerificationStatusResponse { verified: boolean; } -/** Fetch module verification status. Throws NOT_FOUND (404) or SERVICE_UNAVAILABLE (503). */ +/** Fetch module verification status. + * Throws: + * - NOT_FOUND (404) - no source code available + * - SERVICE_UNAVAILABLE (503) - verification disabled on node + * - COMPILATION_ERROR (422) - cannot verify (e.g., unsupported dependencies) + */ export async function getModuleVerificationStatus( nodeUrl: string, address: string, @@ -61,6 +67,11 @@ export async function getModuleVerificationStatus( if (response.status === 404) { throw {type: ResponseErrorType.NOT_FOUND}; } + if (response.status === 422) { + // Compilation error - can't verify, but not suspicious + const errorData = await response.json().catch(() => ({})); + throw {type: ResponseErrorType.COMPILATION_ERROR, message: errorData.message}; + } if (response.status === 503) { throw {type: ResponseErrorType.SERVICE_UNAVAILABLE}; } diff --git a/src/api/hooks/useGetModuleVerificationStatus.ts b/src/api/hooks/useGetModuleVerificationStatus.ts index ce6c4f889..5e47c347d 100644 --- a/src/api/hooks/useGetModuleVerificationStatus.ts +++ b/src/api/hooks/useGetModuleVerificationStatus.ts @@ -28,7 +28,8 @@ export function useGetModuleVerificationStatus( // Don't retry for expected error types if ( error.type === ResponseErrorType.NOT_FOUND || - error.type === ResponseErrorType.SERVICE_UNAVAILABLE + error.type === ResponseErrorType.SERVICE_UNAVAILABLE || + error.type === ResponseErrorType.COMPILATION_ERROR ) { return false; } diff --git a/src/pages/Account/Components/CodeSnippet.tsx b/src/pages/Account/Components/CodeSnippet.tsx index 8aa08e35c..0f1fbe0e1 100644 --- a/src/pages/Account/Components/CodeSnippet.tsx +++ b/src/pages/Account/Components/CodeSnippet.tsx @@ -173,6 +173,7 @@ export function Code({ const hasVerificationFailure = verificationStatus?.verified === false; const hasVerificationDisabled = verificationError?.type === ResponseErrorType.SERVICE_UNAVAILABLE; const hasVerificationUnavailable = verificationError?.type === ResponseErrorType.NOT_FOUND; + const hasCompilationError = verificationError?.type === ResponseErrorType.COMPILATION_ERROR; const shouldShowCode = !!sourceCode; return ( @@ -247,12 +248,17 @@ export function Code({ ) : shouldShowCode ? ( {hasVerificationFailure && ( - + The deployer provided source code but it does not match the deployed bytecode. The displayed code may not accurately represent what is actually running on-chain. )} - {(hasVerificationDisabled || hasVerificationUnavailable) && ( + {hasCompilationError && ( + This contract cannot be verified because it uses dependencies that are not part of the standard Aptos framework. The displayed code was provided by the deployer and may not match the deployed bytecode. + + )} + {(hasVerificationDisabled || hasVerificationUnavailable) && ( + Source code verification is not available on this node. The displayed code was provided by the deployer and may not match the deployed bytecode. )} From 324c5ff89225fb5e1c663da0d05f04529ce65fb4 Mon Sep 17 00:00:00 2001 From: apenzk Date: Wed, 14 Jan 2026 13:17:47 +0100 Subject: [PATCH 6/8] Add success alert when source code verification passes --- src/pages/Account/Components/CodeSnippet.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/pages/Account/Components/CodeSnippet.tsx b/src/pages/Account/Components/CodeSnippet.tsx index 0f1fbe0e1..2d247cb20 100644 --- a/src/pages/Account/Components/CodeSnippet.tsx +++ b/src/pages/Account/Components/CodeSnippet.tsx @@ -247,6 +247,11 @@ export function Code({ ) : shouldShowCode ? ( + {isVerified && ( + + Source code verified: the displayed code matches the deployed bytecode. + + )} {hasVerificationFailure && ( The deployer provided source code but it does not match the deployed bytecode. The displayed code may not accurately represent what is actually running on-chain. From e535e168a3e49f6ef6df543da3cf7c6100fd8459 Mon Sep 17 00:00:00 2001 From: apenzk Date: Wed, 14 Jan 2026 13:19:33 +0100 Subject: [PATCH 7/8] Fix indentation in networks object --- src/constants.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/constants.tsx b/src/constants.tsx index 9caab0245..2a1c0d45b 100644 --- a/src/constants.tsx +++ b/src/constants.tsx @@ -13,15 +13,15 @@ export const bardockTestnetUrl = import.meta.env.MOVEMENT_TESTNET_URL || `https://testnet.movementnetwork.xyz/v1`; - export const networks = { - mainnet: mainnetUrl, - testnet: "", - "bardock testnet": bardockTestnetUrl, +export const networks = { + mainnet: mainnetUrl, + testnet: "", + "bardock testnet": bardockTestnetUrl, devnet: "", - local: "http://127.0.0.1:8080", - mevmdevnet: "", - custom: "", - }; + local: "http://127.0.0.1:8080", + mevmdevnet: "", + custom: "", +}; export const availableNetworks = ["mainnet", "bardock testnet"]; From 5ab5c34d6e24dd254f6d4e7034a7a39ae776392a Mon Sep 17 00:00:00 2001 From: apenzk Date: Wed, 21 Jan 2026 12:43:32 +0100 Subject: [PATCH 8/8] verification: send upgrade_number, get from package, drop ledger_version - getModuleVerificationStatus and useGetModuleVerificationStatus accept upgradeNumber - API called with ?upgrade_number= when set - Contract and ViewCode pass upgrade_number from selected package to Code/verification hook - CodeSnippet accepts upgradeNumber and forwards to useGetModuleVerificationStatus --- src/api/client.ts | 10 +++++--- .../hooks/useGetModuleVerificationStatus.ts | 16 ++++++++---- src/pages/Account/Components/CodeSnippet.tsx | 5 +++- .../Account/Tabs/ModulesTab/Contract.tsx | 6 +++++ .../Account/Tabs/ModulesTab/ViewCode.tsx | 25 ++++++++++++++++--- 5 files changed, 48 insertions(+), 14 deletions(-) diff --git a/src/api/client.ts b/src/api/client.ts index b4df30485..8d9949feb 100644 --- a/src/api/client.ts +++ b/src/api/client.ts @@ -43,9 +43,9 @@ export interface ModuleVerificationStatusResponse { verified: boolean; } -/** Fetch module verification status. +/** Fetch module verification status for a specific contract version (upgrade_number). * Throws: - * - NOT_FOUND (404) - no source code available + * - NOT_FOUND (404) - no source code available, or contract upgraded (refresh page) * - SERVICE_UNAVAILABLE (503) - verification disabled on node * - COMPILATION_ERROR (422) - cannot verify (e.g., unsupported dependencies) */ @@ -53,9 +53,11 @@ export async function getModuleVerificationStatus( nodeUrl: string, address: string, moduleName: string, + upgradeNumber?: number, ): Promise { - const url = `${nodeUrl}/v1/accounts/${address}/modules/${moduleName}/verification_status`; - + const params = upgradeNumber != null ? `?upgrade_number=${upgradeNumber}` : ""; + const url = `${nodeUrl}/v1/accounts/${address}/modules/${moduleName}/verification_status${params}`; + const response = await fetch(url, { method: "GET", headers: { diff --git a/src/api/hooks/useGetModuleVerificationStatus.ts b/src/api/hooks/useGetModuleVerificationStatus.ts index 5e47c347d..4b2792be1 100644 --- a/src/api/hooks/useGetModuleVerificationStatus.ts +++ b/src/api/hooks/useGetModuleVerificationStatus.ts @@ -7,22 +7,28 @@ import { } from "../client"; import {useGlobalState} from "../../global-config/GlobalConfig"; -/** Hook to query module bytecode verification status. */ +/** Hook to query module bytecode verification status for a contract version (upgrade_number). */ export function useGetModuleVerificationStatus( address: string, moduleName: string, - options?: {enabled?: boolean}, + options?: {enabled?: boolean; upgradeNumber?: number}, ): UseQueryResult { const [state] = useGlobalState(); + const {upgradeNumber, ...rest} = options ?? {}; return useQuery({ queryKey: [ "moduleVerificationStatus", - {address, moduleName}, + {address, moduleName, upgradeNumber}, state.network_value, ], queryFn: () => - getModuleVerificationStatus(state.network_value, address, moduleName), + getModuleVerificationStatus( + state.network_value, + address, + moduleName, + upgradeNumber, + ), refetchOnWindowFocus: false, retry: (failureCount, error) => { // Don't retry for expected error types @@ -35,7 +41,7 @@ export function useGetModuleVerificationStatus( } return failureCount < 2; }, - ...options, + ...rest, }); } diff --git a/src/pages/Account/Components/CodeSnippet.tsx b/src/pages/Account/Components/CodeSnippet.tsx index 2d247cb20..2befee7f3 100644 --- a/src/pages/Account/Components/CodeSnippet.tsx +++ b/src/pages/Account/Components/CodeSnippet.tsx @@ -121,10 +121,12 @@ export function Code({ bytecode, address, moduleName, + upgradeNumber, }: { bytecode: string; address?: string; moduleName?: string; + upgradeNumber?: number; }) { const {selectedModuleName} = useParams(); const logEvent = useLogEventWithBasic(); @@ -133,13 +135,14 @@ export function Code({ // Use the module name from props or from URL params const moduleNameToVerify = moduleName || selectedModuleName || ""; - // Query verification status + // Query verification for this contract version (upgrade_number) const { data: verificationStatus, isLoading: isVerificationLoading, error: verificationError, } = useGetModuleVerificationStatus(address || "", moduleNameToVerify, { enabled: !!address && !!moduleNameToVerify, + upgradeNumber, }); const TOOLTIP_TIME = 2000; // 2s diff --git a/src/pages/Account/Tabs/ModulesTab/Contract.tsx b/src/pages/Account/Tabs/ModulesTab/Contract.tsx index 0bb138a7d..e3d87426b 100644 --- a/src/pages/Account/Tabs/ModulesTab/Contract.tsx +++ b/src/pages/Account/Tabs/ModulesTab/Contract.tsx @@ -72,6 +72,11 @@ function Contract({ const {data, isLoading, error} = useGetAccountModules(address); const {selectedModuleName, selectedFnName} = useParams(); const sortedPackages: PackageMetadata[] = useGetAccountPackages(address); + const selectedPackage = sortedPackages.find((p) => + p.modules.some((m) => m.name === selectedModuleName), + ); + const upgradeNumber = + selectedPackage != null ? Number(selectedPackage.upgrade_number) : undefined; const selectedModule = sortedPackages .flatMap((pkg) => pkg.modules) .find((module) => module.name === selectedModuleName); @@ -162,6 +167,7 @@ function Contract({ bytecode={selectedModule?.source} address={address} moduleName={selectedModuleName} + upgradeNumber={upgradeNumber} /> )} diff --git a/src/pages/Account/Tabs/ModulesTab/ViewCode.tsx b/src/pages/Account/Tabs/ModulesTab/ViewCode.tsx index 84fbb4883..a1a38bdf9 100644 --- a/src/pages/Account/Tabs/ModulesTab/ViewCode.tsx +++ b/src/pages/Account/Tabs/ModulesTab/ViewCode.tsx @@ -39,14 +39,20 @@ interface ModuleContentProps { address: string; moduleName: string; bytecode: string; + upgradeNumber?: number; } function ViewCode({address, isObject}: {address: string; isObject: boolean}) { const sortedPackages: PackageMetadata[] = useGetAccountPackages(address); - const navigate = useNavigate(); - const selectedModuleName = useParams().selectedModuleName ?? ""; + + const selectedPackage = sortedPackages.find((p) => + p.modules.some((m) => m.name === selectedModuleName), + ); + const upgradeNumber = + selectedPackage != null ? Number(selectedPackage.upgrade_number) : undefined; + useEffect(() => { if ( !selectedModuleName && @@ -98,6 +104,7 @@ function ViewCode({address, isObject}: {address: string; isObject: boolean}) { address={address} moduleName={selectedModuleName} bytecode={selectedModule.source} + upgradeNumber={upgradeNumber} /> )} @@ -179,7 +186,12 @@ function ModuleSidebar({ ); } -function ModuleContent({address, moduleName, bytecode}: ModuleContentProps) { +function ModuleContent({ + address, + moduleName, + bytecode, + upgradeNumber, +}: ModuleContentProps) { const theme = useTheme(); return ( - +