diff --git a/apps/remix-ide/src/app/files/fileManager.ts b/apps/remix-ide/src/app/files/fileManager.ts index 263d583093..df40820b27 100644 --- a/apps/remix-ide/src/app/files/fileManager.ts +++ b/apps/remix-ide/src/app/files/fileManager.ts @@ -19,7 +19,7 @@ const profile = { icon: 'assets/img/fileManager.webp', permission: true, version: packageJson.version, - methods: ['closeAllFiles', 'closeFile', 'file', 'exists', 'open', 'writeFile', 'readFile', 'copyFile', 'copyDir', 'rename', 'mkdir', 'readdir', 'remove', 'getCurrentFile', 'getFile', 'getFolder', 'setFile', 'switchFile', 'refresh', 'getProviderOf', 'getProviderByName', 'getPathFromUrl', 'getUrlFromPath', 'saveCurrentFile', 'setBatchFiles', 'findInFile'], + methods: ['closeAllFiles', 'closeFile', 'file', 'exists', 'open', 'writeFile', 'readFile', 'copyFile', 'copyDir', 'rename', 'mkdir', 'readdir', 'dirList', 'fileList', 'remove', 'getCurrentFile', 'getFile', 'getFolder', 'setFile', 'switchFile', 'refresh', 'getProviderOf', 'getProviderByName', 'getPathFromUrl', 'getUrlFromPath', 'saveCurrentFile', 'setBatchFiles'], kind: 'file-system' } const errorMsg = { @@ -396,14 +396,6 @@ class FileManager extends Plugin { } } - - async findInFile(query) { - const browserProvider = this.getProvider('browser') - await browserProvider.copyFolderToJson('/.workspaces/default_workspace', ({ path, content }) => { - console.log(path, content) - }) - } - init() { this._deps = { config: this._components.registry.get('config').api, @@ -712,7 +704,14 @@ class FileManager extends Plugin { return collectList(path) } - isRemixDActive() { + async fileList (dirPath) { + const paths: any = await this.readdir(dirPath) + for( const path in paths) + if(paths[path].isDirectory) delete paths[path] + return Object.keys(paths) + } + + isRemixDActive () { return this.appManager.isActive('remixd') } diff --git a/libs/remix-core-plugin/src/lib/compiler-artefacts.ts b/libs/remix-core-plugin/src/lib/compiler-artefacts.ts index 1198a012db..d35fa36141 100644 --- a/libs/remix-core-plugin/src/lib/compiler-artefacts.ts +++ b/libs/remix-core-plugin/src/lib/compiler-artefacts.ts @@ -4,7 +4,7 @@ import { CompilerAbstract } from '@remix-project/remix-solidity' const profile = { name: 'compilerArtefacts', - methods: ['get', 'addResolvedContract', 'getCompilerAbstract', 'getAllContractDatas', 'getLastCompilationResult'], + methods: ['get', 'addResolvedContract', 'getCompilerAbstract', 'getAllContractDatas', 'getLastCompilationResult', 'getArtefactsByContractName'], events: [], version: '0.0.1' } @@ -72,6 +72,53 @@ export class CompilerArtefacts extends Plugin { return contractsData } + async getArtefactsFromFE (path, contractName) { + const dirList = await this.call('fileManager', 'dirList', path) + if(dirList && dirList.length) { + if(dirList.includes(path + '/artifacts')) { + const fileList = await this.call('fileManager', 'fileList', path + '/artifacts') + const artefactsFilePaths = fileList.filter(filePath => { + const filenameArr = filePath.split('/') + const filename = filenameArr[filenameArr.length - 1] + if (filename === `${contractName}.json` || filename === `${contractName}_metadata.json`) return true + }) + if (artefactsFilePaths && artefactsFilePaths.length) { + const content = await this.call('fileManager', 'readFile', artefactsFilePaths[1]) + const artifacts = JSON.parse(content) + return { abi: artifacts.abi, bytecode: artifacts.data.bytecode.object } + } else { + for (const dirPath of dirList) { + const result = await this.getArtefactsFromFE (dirPath, contractName) + if (result) return result + } + } + } else { + for (const dirPath of dirList) { + const result = await this.getArtefactsFromFE (dirPath, contractName) + if (result) return result + } + } + } else return + } + + async getArtefactsByContractName (contractName) { + const contractsDataByFilename = this.getAllContractDatas() + const contractsData = Object.values(contractsDataByFilename) + if (contractsData && contractsData.length) { + const index = contractsData.findIndex((contractsObj) => Object.keys(contractsObj).includes(contractName)) + if (index !== -1) return { abi: contractsData[index][contractName].abi, bytecode: contractsData[index][contractName].evm.bytecode.object } + else { + const result = await this.getArtefactsFromFE ('contracts', contractName) + if (result) return result + else throw new Error(`Could not find artifacts for ${contractName}. Compile contract to generate artifacts.`) + } + } else { + const result = await this.getArtefactsFromFE ('contracts', contractName) + if (result) return result + else throw new Error(`Could not find artifacts for ${contractName}. Compile contract to generate artifacts.`) + } + } + getCompilerAbstract (file) { return this.compilersArtefactsPerFile[file] } diff --git a/libs/remix-ui/workspace/src/lib/actions/index.ts b/libs/remix-ui/workspace/src/lib/actions/index.ts index ae248d6fa8..12f178348c 100644 --- a/libs/remix-ui/workspace/src/lib/actions/index.ts +++ b/libs/remix-ui/workspace/src/lib/actions/index.ts @@ -256,6 +256,17 @@ export const runScript = async (path: string) => { }) } +export const runScriptWithMocha = async (path: string) => { + const provider = plugin.fileManager.currentFileProvider() + provider.get(path, (error, content: string) => { + if (error) { + return dispatch(displayPopUp(error)) + } + if (content) content = content + '\n' + 'mocha.run()' + plugin.call('scriptRunner', 'execute', content) + }) +} + export const emitContextMenuEvent = async (cmd: customAction) => { await plugin.call(cmd.id, cmd.name, cmd) } diff --git a/libs/remix-ui/workspace/src/lib/components/file-explorer-context-menu.tsx b/libs/remix-ui/workspace/src/lib/components/file-explorer-context-menu.tsx index 5e6518c2de..b9bad4b170 100644 --- a/libs/remix-ui/workspace/src/lib/components/file-explorer-context-menu.tsx +++ b/libs/remix-ui/workspace/src/lib/components/file-explorer-context-menu.tsx @@ -12,7 +12,7 @@ declare global { const _paq = window._paq = window._paq || [] //eslint-disable-line export const FileExplorerContextMenu = (props: FileExplorerContextMenuProps) => { - const { actions, createNewFile, createNewFolder, deletePath, renamePath, hideContextMenu, pushChangesToGist, publishFileToGist, publishFolderToGist, copy, paste, runScript, emit, pageX, pageY, path, type, focus, ...otherProps } = props + const { actions, createNewFile, createNewFolder, deletePath, renamePath, hideContextMenu, pushChangesToGist, publishFileToGist, publishFolderToGist, copy, paste, runScript, runScriptWithMocha, emit, pageX, pageY, path, type, focus, ...otherProps } = props const contextMenuRef = useRef(null) useEffect(() => { contextMenuRef.current.focus() @@ -98,6 +98,10 @@ export const FileExplorerContextMenu = (props: FileExplorerContextMenuProps) => _paq.push(['trackEvent', 'fileExplorer', 'runScript']) runScript(path) break + case 'Run with Mocha': + _paq.push(['trackEvent', 'fileExplorer', 'runScriptWithMocha']) + runScriptWithMocha(path) + break case 'Copy': copy(path, type) break diff --git a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx index 5ae7de8d05..d5c0fa8f75 100644 --- a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx +++ b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx @@ -221,6 +221,14 @@ export const FileExplorer = (props: FileExplorerProps) => { } } + const runScriptWithMocha = async (path: string) => { + try { + props.dispatchRunScriptWithMocha(path) + } catch (error) { + props.toast('Run script with Mocha failed') + } + } + const emitContextMenuEvent = (cmd: customAction) => { try { props.dispatchEmitContextMenuEvent(cmd) @@ -454,6 +462,7 @@ export const FileExplorer = (props: FileExplorerProps) => { deletePath={deletePath} renamePath={editModeOn} runScript={runScript} + runScriptWithMocha={runScriptWithMocha} copy={handleCopyClick} paste={handlePasteClick} emit={emitContextMenuEvent} diff --git a/libs/remix-ui/workspace/src/lib/contexts/index.ts b/libs/remix-ui/workspace/src/lib/contexts/index.ts index 1aedce98b5..20c9b46633 100644 --- a/libs/remix-ui/workspace/src/lib/contexts/index.ts +++ b/libs/remix-ui/workspace/src/lib/contexts/index.ts @@ -25,6 +25,7 @@ export const FileSystemContext = createContext<{ dispatchCopyFile: (src: string, dest: string) => Promise, dispatchCopyFolder: (src: string, dest: string) => Promise, dispatchRunScript: (path: string) => Promise, + dispatchRunScriptWithMocha: (path: string) => Promise, dispatchEmitContextMenuEvent: (cmd: customAction) => Promise, dispatchHandleClickFile: (path: string, type: 'file' | 'folder' | 'gist') => Promise dispatchHandleExpandPath: (paths: string[]) => Promise diff --git a/libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx b/libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx index 904ed7cade..330270cf5e 100644 --- a/libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx +++ b/libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx @@ -5,7 +5,7 @@ import { Toaster } from '@remix-ui/toaster' // eslint-disable-line // eslint-disable-next-line @typescript-eslint/no-unused-vars import { FileSystemContext } from '../contexts' import { browserReducer, browserInitialState } from '../reducers/workspace' -import { initWorkspace, fetchDirectory, removeInputField, deleteWorkspace, clearPopUp, publishToGist, createNewFile, setFocusElement, createNewFolder, deletePath, renamePath, copyFile, copyFolder, runScript, emitContextMenuEvent, handleClickFile, handleExpandPath, addInputField, createWorkspace, fetchWorkspaceDirectory, renameWorkspace, switchToWorkspace, uploadFile } from '../actions' +import { initWorkspace, fetchDirectory, removeInputField, deleteWorkspace, clearPopUp, publishToGist, createNewFile, setFocusElement, createNewFolder, deletePath, renamePath, copyFile, copyFolder, runScript, runScriptWithMocha, emitContextMenuEvent, handleClickFile, handleExpandPath, addInputField, createWorkspace, fetchWorkspaceDirectory, renameWorkspace, switchToWorkspace, uploadFile } from '../actions' import { Modal, WorkspaceProps } from '../types' // eslint-disable-next-line @typescript-eslint/no-unused-vars import { Workspace } from '../remix-ui-workspace' @@ -103,6 +103,10 @@ export const FileSystemProvider = (props: WorkspaceProps) => { await runScript(path) } + const dispatchRunScriptWithMocha = async (path: string) => { + await runScriptWithMocha(path) + } + const dispatchEmitContextMenuEvent = async (cmd: customAction) => { await emitContextMenuEvent(cmd) } @@ -212,6 +216,7 @@ export const FileSystemProvider = (props: WorkspaceProps) => { dispatchCopyFile, dispatchCopyFolder, dispatchRunScript, + dispatchRunScriptWithMocha, dispatchEmitContextMenuEvent, dispatchHandleClickFile, dispatchHandleExpandPath diff --git a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx index a51224f86c..a5a84e1e1f 100644 --- a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx +++ b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx @@ -198,6 +198,7 @@ export function Workspace () { dispatchCopyFolder={global.dispatchCopyFolder} dispatchPublishToGist={global.dispatchPublishToGist} dispatchRunScript={global.dispatchRunScript} + dispatchRunScriptWithMocha={global.dispatchRunScriptWithMocha} dispatchEmitContextMenuEvent={global.dispatchEmitContextMenuEvent} dispatchHandleClickFile={global.dispatchHandleClickFile} dispatchSetFocusElement={global.dispatchSetFocusElement} @@ -233,6 +234,7 @@ export function Workspace () { dispatchCopyFolder={global.dispatchCopyFolder} dispatchPublishToGist={global.dispatchPublishToGist} dispatchRunScript={global.dispatchRunScript} + dispatchRunScriptWithMocha={global.dispatchRunScriptWithMocha} dispatchEmitContextMenuEvent={global.dispatchEmitContextMenuEvent} dispatchHandleClickFile={global.dispatchHandleClickFile} dispatchSetFocusElement={global.dispatchSetFocusElement} diff --git a/libs/remix-ui/workspace/src/lib/types/index.ts b/libs/remix-ui/workspace/src/lib/types/index.ts index bf4b24d661..5db5bd0a99 100644 --- a/libs/remix-ui/workspace/src/lib/types/index.ts +++ b/libs/remix-ui/workspace/src/lib/types/index.ts @@ -78,6 +78,7 @@ export interface FileExplorerProps { dispatchCopyFile: (src: string, dest: string) => Promise, dispatchCopyFolder: (src: string, dest: string) => Promise, dispatchRunScript: (path: string) => Promise, + dispatchRunScriptWithMocha: (path: string) => Promise, dispatchPublishToGist: (path?: string, type?: string) => Promise, dispatchEmitContextMenuEvent: (cmd: customAction) => Promise, dispatchHandleClickFile: (path: string, type: 'file' | 'folder' | 'gist') => Promise, @@ -108,6 +109,7 @@ export interface FileExplorerContextMenuProps { publishFolderToGist?: (path?: string, type?: string) => void, publishFileToGist?: (path?: string, type?: string) => void, runScript?: (path: string) => void, + runScriptWithMocha?: (path: string) => void, emit?: (cmd: customAction) => void, pageX: number, pageY: number, diff --git a/libs/remix-ui/workspace/src/lib/utils/index.ts b/libs/remix-ui/workspace/src/lib/utils/index.ts index 0dd70b14bc..f2558c1b2c 100644 --- a/libs/remix-ui/workspace/src/lib/utils/index.ts +++ b/libs/remix-ui/workspace/src/lib/utils/index.ts @@ -30,6 +30,12 @@ export const contextMenuActions: MenuItems = [{ extension: ['.js'], multiselect: false, label: '' +}, { + id: 'runWithMocha', + name: 'Run with Mocha', + extension: ['.js'], + multiselect: false, + label: '' }, { id: 'pushChangesToGist', name: 'Push changes to gist',