diff --git a/media/tools.svg b/media/tools.svg new file mode 100644 index 0000000..f1cd568 --- /dev/null +++ b/media/tools.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/package.json b/package.json index c0dcbb5..b154772 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "sui-simulator-vscode", "displayName": "sui-simulator-vscode", "description": "", - "version": "0.0.1", + "version": "0.2.0", "engines": { "vscode": "^1.87.0" }, @@ -12,6 +12,26 @@ "activationEvents": [], "main": "./dist/extension.js", "contributes": { + "viewsContainers": { + "activitybar": [ + { + "id": "sui-simulator-sidebar-view", + "title": "Sui Simulator", + "icon": "media/tools.svg" + } + ] + }, + "views": { + "sui-simulator-sidebar-view": [ + { + "type": "webview", + "id": "sui-simulator-sidebar", + "name": "Sui Simulator", + "icon": "media/tools.svg", + "contextualTitle": "Sui Simulator" + } + ] + }, "commands": [ { "command": "sui-simulator-vscode.helloWorld", @@ -75,4 +95,4 @@ "webpack-cli": "^5.1.4", "webpack-dev-server": "^5.0.4" } -} +} \ No newline at end of file diff --git a/src/SidebarProvider.ts b/src/SidebarProvider.ts new file mode 100644 index 0000000..e0d6fe8 --- /dev/null +++ b/src/SidebarProvider.ts @@ -0,0 +1,79 @@ +import * as vscode from "vscode"; +import { build, executeCommand, publish } from "./suiCommand"; +import { join } from "path"; + +export class SidebarProvider implements vscode.WebviewViewProvider { + constructor(private readonly _extensionContext: vscode.ExtensionContext) { } + + public resolveWebviewView(webviewView: vscode.WebviewView, context: vscode.WebviewViewResolveContext, token: vscode.CancellationToken) { + + webviewView.webview.options = { + // Allow scripts in the webview + enableScripts: true, + + localResourceRoots: [this._extensionContext.extensionUri], + }; + + webviewView.webview.html = this._getHtmlForWebview(webviewView.webview); + + webviewView.webview.onDidReceiveMessage((message) => { + const { command, requestId, payload } = message; + + switch (command) { + case "SUI_TERMINAL": + executeCommand(payload.command, payload.suiPath); + break; + + case "BUILD": + build(payload.packagePath, payload.suiPath); + break; + + case "PUBLISH": + publish(payload.packagePath, payload.suiPath); + break; + + case "SAVE_ALIASES": + this._extensionContext.workspaceState.update(payload.address, { + aliases: payload.aliases + }).then(() => { + vscode.window.showInformationMessage("Aliases saved successfully!"); + }); + + // use value as undefined to remove the key + // context.workspaceState.update("", undefined); + + default: + vscode.window.showInformationMessage(`Unknown command: ${command}`); + } + }); + } + + private _getHtmlForWebview(webview: vscode.Webview) { + const jsFile = "webview.js"; + const localServerUrl = "http://localhost:9999"; + + let scriptUrl = null; + let cssUrl = null; + + const isProduction = this._extensionContext.extensionMode === vscode.ExtensionMode.Production; + if (isProduction) { + scriptUrl = webview.asWebviewUri(vscode.Uri.file(join(this._extensionContext.extensionPath, 'dist', jsFile))).toString(); + } else { + scriptUrl = `${localServerUrl}/${jsFile}`; + } + + return ` + + + + + ${isProduction ? `` : ''} + + +
+ + + + `; + } +} \ No newline at end of file diff --git a/src/enums/index.ts b/src/enums/index.ts new file mode 100644 index 0000000..99fb10b --- /dev/null +++ b/src/enums/index.ts @@ -0,0 +1,20 @@ +export enum MoveCallStatus { + BEGIN, + FINISH, + ERROR, +}; + +export enum MoveCallActionType { + SET_MNEMONICS = "SET_MNEMONICS", + SET_PACKAGE_ID = "SET_PACKAGE_ID", + SET_MODULES = "SET_MODULES", + SET_ERROR = "SET_ERROR", + SET_CURRENT_MODULE = "SET_CURRENT_MODULE", + SET_FUNCTIONS = "SET_FUNCTIONS", + SET_CURRENT_FUNCTION = "SET_CURRENT_FUNCTION", + RESET_ARGS = "RESET_ARGS", + RESET_ARGS_USER_INPUT = "RESET_ARGS_USER_INPUT", + ADD_ARG = "ADD_ARG", + SET_VALUE_TO_ARG = "SET_VALUE_TO_ARG", + SET_RESPONSE = "SET_RESPONSE", +}; \ No newline at end of file diff --git a/src/extension.ts b/src/extension.ts index fff25c5..b70fa69 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -4,6 +4,7 @@ import * as vscode from 'vscode'; import { join } from 'path'; import { MessageHandlerData } from '@estruyf/vscode'; import { build, publish, executeCommand } from './suiCommand'; +import { SidebarProvider } from './SidebarProvider'; // This method is called when your extension is activated // Your extension is activated the very first time the command is executed @@ -22,6 +23,14 @@ export function activate(context: vscode.ExtensionContext) { vscode.window.showInformationMessage('Hello World from sui-simulator-vscode!'); }); + const sidebarProvider = new SidebarProvider(context); + context.subscriptions.push( + vscode.window.registerWebviewViewProvider( + "sui-simulator-sidebar", + sidebarProvider + ) + ); + context.subscriptions.push(disposable); context.subscriptions.push(vscode.commands.registerCommand("sui-simulator-vscode.webView", () => { @@ -64,15 +73,15 @@ export function activate(context: vscode.ExtensionContext) { break; case "SUI_TERMINAL": - executeCommand(payload.command); + executeCommand(payload.command, payload.suiPath); break; case "BUILD": - build(payload.path); + build(payload.packagePath, payload.suiPath); break; case "PUBLISH": - publish(payload.path); + publish(payload.packagePath, payload.suiPath); break; case "SAVE_ALIASES": diff --git a/src/suiCommand.ts b/src/suiCommand.ts index 38f8ae4..973844f 100644 --- a/src/suiCommand.ts +++ b/src/suiCommand.ts @@ -1,19 +1,29 @@ import * as vscode from 'vscode'; -export const build = (path: string) => { +const handleSuiPathEmpty = (suiPath: string) => { + if (!suiPath) { + return "sui"; + } + return suiPath; +} + +export const build = (path: string, suiPath: string) => { + suiPath = handleSuiPathEmpty(suiPath); const terminal = vscode.window.createTerminal("Sui Simulator"); - terminal.sendText(`sui move build -p ${path}`); + terminal.sendText(`${suiPath} move build -p ${path}`); terminal.show(); }; -export const publish = (path: string) => { +export const publish = (path: string, suiPath: string) => { + suiPath = handleSuiPathEmpty(suiPath); const terminal = vscode.window.createTerminal("Sui Simulator"); - terminal.sendText(`sui client publish --gas-budget 100000000 ${path}`); + terminal.sendText(`${suiPath} client publish --gas-budget 100000000 ${path}`); terminal.show(); }; -export const executeCommand = (command: string) => { +export const executeCommand = (command: string, suiPath: string) => { + suiPath = handleSuiPathEmpty(suiPath); const terminal = vscode.window.createTerminal("Sui Simulator"); - terminal.sendText(command); + terminal.sendText(`${suiPath} ${command}`); terminal.show(); }; \ No newline at end of file diff --git a/src/types/index.ts b/src/types/index.ts new file mode 100644 index 0000000..42d384d --- /dev/null +++ b/src/types/index.ts @@ -0,0 +1,23 @@ +import { SuiMoveNormalizedFunction } from "@mysten/sui.js/client"; +import { MoveCallStatus } from "../enums"; + +export interface ActionType { + type: string, + payload: any +}; + +export interface MoveCallState { + mnemonics: string, + status: MoveCallStatus, + packageId: string, + modules: string[], + currentModule: string, + functions: { + [key: string]: SuiMoveNormalizedFunction; + }, + currentFunction: string; + args: string[], + argsUserInput: string[], + error: string, + response: string, +} \ No newline at end of file diff --git a/src/webview/App.tsx b/src/webview/App.tsx index a949b2f..cfd3e0d 100644 --- a/src/webview/App.tsx +++ b/src/webview/App.tsx @@ -1,13 +1,109 @@ -import React, { useEffect, useState } from "react"; +import React, { useReducer, useState } from "react"; import "./style.css"; import { useSuiClient, useSuiClientContext } from "@mysten/dapp-kit"; -import { DEFAULT_ED25519_DERIVATION_PATH, Ed25519Keypair } from "@mysten/sui.js/keypairs/ed25519"; -import { TransactionArgument, TransactionBlock } from "@mysten/sui.js/transactions"; import { Input } from "./components/Input"; import { Button } from "./components/Button"; import { Aliases } from './components/Aliases'; import { sendMessage } from "./utils/wv_communicate_ext"; -import { getDetailPackage } from "./utils/suiPackage"; +import { ActionType, MoveCallState } from "../types"; +import { MoveCallActionType, MoveCallStatus } from "../enums"; +import { MoveCall } from "./features/moveCall/v2"; + +const initialState: MoveCallState = { + mnemonics: "mouse hood crucial soup report axis awful point stairs guess scrap winter", + status: MoveCallStatus.BEGIN, + packageId: "", + modules: [], + currentModule: "", + functions: {}, + currentFunction: "", + args: [], + argsUserInput: [], + error: "", + response: "", +}; + +const reducer = (state: MoveCallState, action: ActionType): MoveCallState => { + const { type, payload } = action; + switch (type) { + case MoveCallActionType.SET_MNEMONICS: + return { + ...state, + mnemonics: payload, + }; + case MoveCallActionType.SET_PACKAGE_ID: + return { + ...state, + packageId: payload, + }; + case MoveCallActionType.SET_MODULES: + return { + ...state, + modules: payload, + }; + + case MoveCallActionType.SET_CURRENT_MODULE: + return { + ...state, + currentModule: payload, + }; + + case MoveCallActionType.SET_FUNCTIONS: + return { + ...state, + functions: payload, + }; + + case MoveCallActionType.SET_ERROR: + return { + ...state, + status: MoveCallStatus.ERROR, + error: payload, + }; + + case MoveCallActionType.SET_CURRENT_FUNCTION: + return { + ...state, + currentFunction: payload, + }; + + case MoveCallActionType.RESET_ARGS: + return { + ...state, + args: [], + }; + + case MoveCallActionType.RESET_ARGS_USER_INPUT: + return { + ...state, + argsUserInput: [], + }; + + case MoveCallActionType.ADD_ARG: + return { + ...state, + args: [...state.args, payload], + }; + + case MoveCallActionType.SET_VALUE_TO_ARG: + const argsUserInput = [...state.argsUserInput]; + argsUserInput[payload.index] = payload.value; + return { + ...state, + argsUserInput, + }; + + case MoveCallActionType.SET_RESPONSE: + return { + ...state, + status: MoveCallStatus.FINISH, + response: payload, + }; + + default: + throw new Error(`Unhandled action type: ${type}`); + } +}; export interface IAppProps { } @@ -15,183 +111,44 @@ export const App: React.FunctionComponent = ({ }: React.PropsWithChil const suiClient = useSuiClient(); const { network, selectNetwork } = useSuiClientContext(); - const [mnemonics, setMnemonics] = useState("mouse hood crucial soup report axis awful point stairs guess scrap winter"); - - const [packageId, setPackageId] = useState("0xcab68c8cd7e80f3dd06466da6b2c083d1fd50ab3e9be8e32395c19b53021c064"); - const [module, setModule] = useState("counter"); - const [functionName, setFunctionName] = useState("create"); - const [args, setArgs] = useState([]); - - const [error, setError] = useState(""); - const [isError, setIsError] = useState(false); - const [response, setResponse] = useState(""); + const [state, dispatch] = useReducer(reducer, initialState); const [buildPath, setBuildPath] = useState(""); const [publishPath, setPublishPath] = useState(""); - - let keypair: Ed25519Keypair | null = null; + const [suiPath, setSuiPath] = useState(""); const handleNetworkChange = (e: React.ChangeEvent) => { selectNetwork(e.target.value); }; - const handleAddArgs = () => { - setArgs((prevArgs) => [...prevArgs, { - index: null, - kind: "Input", - value: null, - type: null - }]); - }; - - const handleDeleteArgs = (index: number) => { - setArgs((prevArgs) => prevArgs.filter((_, i) => i !== index)); - }; - - const handleMnemonicsChange = (e: React.ChangeEvent) => { - setMnemonics(e.target.value); - }; - - const handleCall = async () => { - try { - keypair = Ed25519Keypair.deriveKeypair( - mnemonics, - DEFAULT_ED25519_DERIVATION_PATH, - ); - const privateKey = keypair.getSecretKey(); - const publicKey = keypair.getPublicKey(); - const address = publicKey.toSuiAddress(); - - const txb = new TransactionBlock(); - txb.setSender(address); - txb.setGasOwner(address); - txb.setGasPrice(10000); - - // add arguments to the transaction - for (const arg of args) { - if (arg.type === "object") { - txb.object(arg.value); - } else { - txb.pure(arg.value); - } - } - - txb.moveCall({ - arguments: args, - target: `${packageId}::${module}::${functionName}` - }); - - const txBytes = await txb.build({ client: suiClient }); - - const serializedSignature = (await keypair.signTransactionBlock(txBytes)) - .signature; - - const response = await suiClient.executeTransactionBlock({ - transactionBlock: txBytes, - signature: [serializedSignature], - options: { - showEffects: true, - showObjectChanges: true, - showBalanceChanges: true, - showEvents: true, - showInput: true, - showRawInput: true, - }, - }); - - setIsError(false); - - const executionStatus = response.effects?.status; - if (executionStatus?.status === "failure") { - setError(executionStatus?.error); - } else { - setResponse(JSON.stringify(response.digest)); - } - return response; - } catch (err: any) { - setIsError(true); - setError(err.message); - return err; - } - }; - - useEffect(() => { - getDetailPackage(suiClient, "0xcab68c8cd7e80f3dd06466da6b2c083d1fd50ab3e9be8e32395c19b53021c064").then((data) => { - const modules = Object.keys(data as {}); - - if (data) { - for (const module of modules) { - const { exposedFunctions } = data[module]; - - } - } - }).catch(err => console.log(err)); - }, []); - return ( <>

Sui Simulator


+

+ Setup Sui +

+ setSuiPath(e.target.value)} />

Network


-

Buikd

- setBuildPath(e.target.value)} /> -

Publish

- setPublishPath(e.target.value)} /> -
-

Call

-
- Mnemonics: - -
-
- Package: - setPackageId(e.target.value)} /> -
-
- Module: - setModule(e.target.value)} /> -
-
- Function: - setFunctionName(e.target.value)} /> -
-

Args

- {args.map((arg, index) => { - return <> { - const newArgs = [...args]; - newArgs[index] = { - ...newArgs[index], - index, - value: e.target.value, - type: e.target.value.startsWith("0x") ? "object" : "pure" - }; - setArgs((newArgs)); - }} /> - - ; - } - - )} - - - {!isError ?

Result: {response}

:

Error: {error}

} + + +
diff --git a/src/webview/features/moveCall/v1/index.tsx b/src/webview/features/moveCall/v1/index.tsx new file mode 100644 index 0000000..c5f0817 --- /dev/null +++ b/src/webview/features/moveCall/v1/index.tsx @@ -0,0 +1,151 @@ +import React, { useState } from 'react'; +import { Button } from '../../../components/Button'; +import { Input } from '../../../components/Input'; +import { DEFAULT_ED25519_DERIVATION_PATH, Ed25519Keypair } from '@mysten/sui.js/keypairs/ed25519'; +import { TransactionArgument, TransactionBlock } from '@mysten/sui.js/transactions'; +import { useSuiClient } from '@mysten/dapp-kit'; + +export default function index() { + const suiClient = useSuiClient(); + + const [mnemonics, setMnemonics] = useState("mouse hood crucial soup report axis awful point stairs guess scrap winter"); + + const [packageId, setPackageId] = useState("0xcab68c8cd7e80f3dd06466da6b2c083d1fd50ab3e9be8e32395c19b53021c064"); + const [module, setModule] = useState("counter"); + const [functionName, setFunctionName] = useState("create"); + const [args, setArgs] = useState([]); + + const [error, setError] = useState(""); + const [isError, setIsError] = useState(false); + const [response, setResponse] = useState(""); + + let keypair: Ed25519Keypair | null = null; + + const handleAddArgs = () => { + setArgs((prevArgs) => [...prevArgs, { + index: null, + kind: "Input", + value: null, + type: null + }]); + }; + + const handleDeleteArgs = (index: number) => { + setArgs((prevArgs) => prevArgs.filter((_, i) => i !== index)); + }; + + const handleMnemonicsChange = (e: React.ChangeEvent) => { + setMnemonics(e.target.value); + }; + + const handleCall = async () => { + try { + keypair = Ed25519Keypair.deriveKeypair( + mnemonics, + DEFAULT_ED25519_DERIVATION_PATH, + ); + const privateKey = keypair.getSecretKey(); + const publicKey = keypair.getPublicKey(); + const address = publicKey.toSuiAddress(); + + const txb = new TransactionBlock(); + txb.setSender(address); + txb.setGasOwner(address); + txb.setGasPrice(10000); + + // add arguments to the transaction + for (const arg of args) { + if (arg.type === "object") { + txb.object(arg.value); + } else { + txb.pure(arg.value); + } + } + + txb.moveCall({ + arguments: args, + target: `${packageId}::${module}::${functionName}` + }); + + const txBytes = await txb.build({ client: suiClient }); + + const serializedSignature = (await keypair.signTransactionBlock(txBytes)) + .signature; + + const response = await suiClient.executeTransactionBlock({ + transactionBlock: txBytes, + signature: [serializedSignature], + options: { + showEffects: true, + showObjectChanges: true, + showBalanceChanges: true, + showEvents: true, + showInput: true, + showRawInput: true, + }, + }); + + setIsError(false); + + const executionStatus = response.effects?.status; + if (executionStatus?.status === "failure") { + setError(executionStatus?.error); + } else { + setResponse(JSON.stringify(response.digest)); + } + return response; + } catch (err: any) { + setIsError(true); + setError(err.message); + return err; + } + }; + + return ( + <> +

Call

+
+ Mnemonics: + +
+
+ Package: + setPackageId(e.target.value)} /> +
+
+ Module: + setModule(e.target.value)} /> +
+
+ Function: + setFunctionName(e.target.value)} /> +
+

Args

+ {args.map((arg, index) => { + return <> { + const newArgs = [...args]; + newArgs[index] = { + ...newArgs[index], + index, + value: e.target.value, + type: e.target.value.startsWith("0x") ? "object" : "pure" + }; + setArgs((newArgs)); + }} /> + + ; + } + + )} + + + {!isError ?

Result: {response}

:

Error: {error}

} + + ); +}; diff --git a/src/webview/features/moveCall/v2/index.tsx b/src/webview/features/moveCall/v2/index.tsx new file mode 100644 index 0000000..c8e9ab6 --- /dev/null +++ b/src/webview/features/moveCall/v2/index.tsx @@ -0,0 +1,218 @@ +import React, { useEffect } from 'react'; +import { MoveCallState } from '../../../../types'; +import { Input } from '../../../components/Input'; +import { MoveCallActionType, MoveCallStatus } from '../../../../enums'; +import { useSuiClient } from '@mysten/dapp-kit'; +import { Button } from '../../../components/Button'; +import { DEFAULT_ED25519_DERIVATION_PATH, Ed25519Keypair } from '@mysten/sui.js/keypairs/ed25519'; +import { TransactionBlock } from '@mysten/sui.js/transactions'; + +export interface IMoveCallProps { + state: MoveCallState; + dispatch: React.Dispatch; +} + +export const MoveCall = ({ state, dispatch }: IMoveCallProps) => { + const suiClient = useSuiClient(); + + const { mnemonics, packageId, args, argsUserInput, currentFunction, currentModule, error, functions, modules, response, status } = state; + + const handleMnemonicsChange = (e: React.ChangeEvent) => { + dispatch({ type: MoveCallActionType.SET_MNEMONICS, payload: e.target.value }); + }; + + const handlePackageIdChange = (e: React.ChangeEvent) => { + dispatch({ type: MoveCallActionType.SET_PACKAGE_ID, payload: e.target.value }); + }; + + const handleChooseModule = async (e: React.ChangeEvent) => { + if (e.target.value) { + dispatch({ type: MoveCallActionType.SET_CURRENT_MODULE, payload: e.target.value }); + + try { + const module = await suiClient.getNormalizedMoveModule({ package: packageId, module: e.target.value }); + const { exposedFunctions } = module; + dispatch({ type: MoveCallActionType.SET_FUNCTIONS, payload: exposedFunctions }); + } catch (err: any) { + dispatch({ type: MoveCallActionType.SET_ERROR, payload: err.message }); + } + } + }; + + const handleChooseFunction = async (e: React.ChangeEvent) => { + if (e.target.value) { + dispatch({ type: MoveCallActionType.SET_CURRENT_FUNCTION, payload: e.target.value }); + dispatch({ type: MoveCallActionType.RESET_ARGS }); + dispatch({ type: MoveCallActionType.RESET_ARGS_USER_INPUT }); + + const fn = functions[e.target.value]; + const { parameters } = fn; + for (const param of parameters) { + // handle typescript error by this way is suck => refactor later + if (typeof param === 'object') { + if ('MutableReference' in param) { + if (typeof param.MutableReference === "object" && 'Struct' in param.MutableReference) { + let { Struct: { + address, module, name + } } = param.MutableReference; + if (name !== "TxContext") { + dispatch({ type: MoveCallActionType.ADD_ARG, payload: `${address}::${module}::${name}` }); + } + } + } else if ('Reference' in param) { + + } else if ('Vector' in param) { + + } else if ('Struct' in param) { + + } else if ('TypeParameter' in param) { + + } + } + else { + dispatch({ type: MoveCallActionType.ADD_ARG, payload: param }); + } + }; + } + }; + + const handleSetValueToArg = (index: number, value: string) => { + dispatch({ + type: MoveCallActionType.SET_VALUE_TO_ARG, + payload: { index, value }, + }); + }; + + useEffect(() => { + async function getModules() { + try { + const modules = await suiClient.getNormalizedMoveModulesByPackage({ package: packageId }); + dispatch({ type: MoveCallActionType.SET_MODULES, payload: modules }); + } catch (err: any) { + dispatch({ type: MoveCallActionType.SET_ERROR, payload: err.message }); + } + } + + if (packageId) { + getModules(); + } + }, [packageId]); + + const modulesName = Object.keys(modules as {}); + const functionsName = Object.keys(functions as {}); + + let keypair: Ed25519Keypair | null = null; + + const handleCall = async () => { + try { + keypair = Ed25519Keypair.deriveKeypair( + mnemonics, + DEFAULT_ED25519_DERIVATION_PATH, + ); + const privateKey = keypair.getSecretKey(); + const publicKey = keypair.getPublicKey(); + const address = publicKey.toSuiAddress(); + + const txb = new TransactionBlock(); + txb.setSender(address); + txb.setGasOwner(address); + txb.setGasPrice(10000); + + const argsFinal = argsUserInput.map((ele) => { + if (ele.startsWith("0x")) { + return txb.object(ele); + } else { + return txb.pure(ele); + } + }); + + txb.moveCall({ + arguments: argsFinal, + target: `${packageId}::${currentModule}::${currentFunction}` + }); + + const txBytes = await txb.build({ client: suiClient }); + + const serializedSignature = (await keypair.signTransactionBlock(txBytes)) + .signature; + + const response = await suiClient.executeTransactionBlock({ + transactionBlock: txBytes, + signature: [serializedSignature], + options: { + showEffects: true, + showObjectChanges: true, + showBalanceChanges: true, + showEvents: true, + showInput: true, + showRawInput: true, + }, + }); + + const executionStatus = response.effects?.status; + if (executionStatus?.status === "failure") { + dispatch({ type: MoveCallActionType.SET_ERROR, payload: executionStatus?.error }); + } else { + dispatch({ type: MoveCallActionType.SET_RESPONSE, payload: JSON.stringify(response.digest) }); + } + return response; + } catch (err: any) { + dispatch({ type: MoveCallActionType.SET_ERROR, payload: err.message }); + return err; + } + }; + + return ( + <> +

Call

+
+ Mnemonics: + +
+
+ Package: + +
+
+ {modulesName.length > 0 && <> + Module: + + } +
+
+ + {currentModule.length > 0 && <> + Function: + + } +
+ {currentFunction.length > 0 && <> +

Args

+ {args.map((arg, index) => { + return
+ handleSetValueToArg(index, e.target.value)} /> + {/* value need to set like above if not will have bug when choose between functions */} +
; + })} + } + + + {status === MoveCallStatus.FINISH &&

Result: ${response}

} + {status === MoveCallStatus.ERROR &&

Error: ${error}

} + + ); +}; diff --git a/src/webview/style.css b/src/webview/style.css index 48ec0d8..3944a4c 100644 --- a/src/webview/style.css +++ b/src/webview/style.css @@ -1,17 +1,3 @@ h1 { font-family: var(--vscode-editor-font-family); -} - -.app { - margin: 15px auto; - max-width: 80rem; -} - -.app__actions { - display: flex; - gap: 1rem; -} - -.app__error { - color: var(--vscode-editorError-foreground); } \ No newline at end of file diff --git a/src/webview/utils/suiPackage.ts b/src/webview/utils/suiPackage.ts deleted file mode 100644 index 09b730f..0000000 --- a/src/webview/utils/suiPackage.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { SuiClient } from "@mysten/sui.js/client"; - -export const getDetailPackage = async ( - suiClient: SuiClient, - packageId: string -) => { - try { - const data = await suiClient.getNormalizedMoveModulesByPackage({ - package: packageId, - }); - return data; - } catch (err) {} -};