diff --git a/package.json b/package.json index 58cac9ae..22ec2e25 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "@tanstack/react-query": "^5.59.0", "@tanstack/react-query-devtools": "^5.59.0", "@trezor/connect-plugin-stellar": "^9.0.6", - "@trezor/connect-web": "^9.5.0", + "@trezor/connect-web": "^9.5.1", "@typescript-eslint/eslint-plugin": "^7.13.1", "bignumber.js": "^9.1.2", "dompurify": "^3.1.7", diff --git a/src/app/(sidebar)/smart-contracts/contract-explorer/components/ContractInfo.tsx b/src/app/(sidebar)/smart-contracts/contract-explorer/components/ContractInfo.tsx index e99b16f0..601ade7c 100644 --- a/src/app/(sidebar)/smart-contracts/contract-explorer/components/ContractInfo.tsx +++ b/src/app/(sidebar)/smart-contracts/contract-explorer/components/ContractInfo.tsx @@ -244,6 +244,7 @@ export const ContractInfo = ({ { const isXdrInit = useIsXdrInit(); + const queryClient = useQueryClient(); const { data: wasmData, @@ -37,6 +48,41 @@ export const ContractSpec = ({ isActive: Boolean(isActive && rpcUrl && wasmHash), }); + const { + data: wasmBinary, + error: wasmBinaryError, + isLoading: isWasmBinaryLoading, + isFetching: isWasmBinaryFetching, + refetch: fetchWasmBinary, + } = useSEContractWasmBinary({ wasmHash, networkId }); + + const resetWasmBlob = useCallback(() => { + queryClient.resetQueries({ + queryKey: ["useSEContractWasmBinary", networkId, wasmHash], + }); + }, [networkId, queryClient, wasmHash]); + + useEffect(() => { + if (wasmBinary) { + downloadFile({ + value: wasmBinary, + fileType: "application/octet-stream", + fileName: wasmHash, + fileExtension: "wasm", + }); + } + }, [wasmBinary, wasmHash]); + + useEffect(() => { + if (wasmBinaryError) { + // Automatically clear error message after 5 sec + delayedAction({ + action: resetWasmBlob, + delay: 5000, + }); + } + }, [resetWasmBlob, wasmBinaryError]); + if (!wasmHash) { return ( @@ -63,7 +109,26 @@ export const ContractSpec = ({ } if (wasmError) { - return ; + const errorString = wasmError.toString(); + let networkMessage = null; + + if (errorString.toLowerCase().includes("network error")) { + networkMessage = ( + + There may be an issue with the RPC server. You can change it in the + network settings in the upper right corner. + + ); + } + + return ( + + <> + + {networkMessage} + + + ); } const formatSpec = () => { @@ -90,6 +155,43 @@ export const ContractSpec = ({ }; return ( - + + + + + + + <> + {wasmBinaryError ? ( + + ) : null} + + + ); }; diff --git a/src/components/CodeEditor/index.tsx b/src/components/CodeEditor/index.tsx index 2d1fd0b4..486c1045 100644 --- a/src/components/CodeEditor/index.tsx +++ b/src/components/CodeEditor/index.tsx @@ -1,14 +1,26 @@ import { useEffect, useRef, useState } from "react"; import { Button, CopyText, Icon } from "@stellar/design-system"; import MonacoEditor, { useMonaco } from "@monaco-editor/react"; + import { useStore } from "@/store/useStore"; import { Box } from "@/components/layout/Box"; +import { downloadFile } from "@/helpers/downloadFile"; import "./styles.scss"; -type CodeEditorProps = { title: string; value: string; language: "json" }; +type CodeEditorProps = { + title: string; + value: string; + language: "json"; + fileName?: string; +}; -export const CodeEditor = ({ title, value, language }: CodeEditorProps) => { +export const CodeEditor = ({ + title, + value, + language, + fileName, +}: CodeEditorProps) => { const { theme } = useStore(); const monaco = useMonaco(); const headerEl = useRef(null); @@ -37,6 +49,27 @@ export const CodeEditor = ({ title, value, language }: CodeEditorProps) => { {/* Actions */} + <> + {fileName ? ( + + ) : null} + +