From f80b39e0f82ee4bcbeb2d3fd66570958aac0c700 Mon Sep 17 00:00:00 2001 From: filip mertens Date: Fri, 14 May 2021 10:49:05 +0200 Subject: [PATCH 01/56] added customactions rm event --- apps/remix-ide/src/app/panels/file-panel.js | 16 ++++++++++++++-- .../src/lib/file-explorer-context-menu.tsx | 3 ++- .../file-explorer/src/lib/file-explorer.tsx | 5 +++-- .../file-explorer/src/lib/types/index.ts | 4 +++- package.json | 15 +++++++-------- 5 files changed, 29 insertions(+), 14 deletions(-) diff --git a/apps/remix-ide/src/app/panels/file-panel.js b/apps/remix-ide/src/app/panels/file-panel.js index 991108285c..38720d4ca2 100644 --- a/apps/remix-ide/src/app/panels/file-panel.js +++ b/apps/remix-ide/src/app/panels/file-panel.js @@ -34,7 +34,7 @@ const modalDialogCustom = require('../ui/modal-dialog-custom') const profile = { name: 'filePanel', displayName: 'File explorers', - methods: ['createNewFile', 'uploadFile', 'getCurrentWorkspace', 'getWorkspaces', 'createWorkspace'], + methods: ['createNewFile', 'uploadFile', 'getCurrentWorkspace', 'getWorkspaces', 'createWorkspace', 'registerContextMenuItem'], events: ['setWorkspace', 'renameWorkspace', 'deleteWorkspace'], icon: 'assets/img/fileManager.webp', description: ' - ', @@ -64,6 +64,7 @@ module.exports = class Filepanel extends ViewPlugin { this.request = {} this.workspaces = [] this.initialWorkspace = null + this.appManager = appManager } render () { @@ -102,11 +103,19 @@ module.exports = class Filepanel extends ViewPlugin { if (!item) throw new Error('Invalid register context menu argument') if (!item.name || !item.id) throw new Error('Item name and id is mandatory') if (!item.type && !item.path && !item.extension && !item.pattern) throw new Error('Invalid file matching criteria provided') - + if (this.registeredMenuItems.filter((o) => { + return o.id === item.id & o.name === item.name + }).length) throw new Error(`Action ${item.name} already exists on ${item.id}`) this.registeredMenuItems = [...this.registeredMenuItems, item] this.renderComponent() } + removePluginActions (plugin) { + this.registeredMenuItems = this.registeredMenuItems.filter((item) => { + return item.id !== plugin.name + }) + } + async getCurrentWorkspace () { return await this.request.getCurrentWorkspace() } @@ -173,6 +182,9 @@ module.exports = class Filepanel extends ViewPlugin { } this.getWorkspaces() }) + + const self = this + this.appManager.on('manager', 'pluginDeactivated', self.removePluginActions.bind(this)) } async createNewFile () { diff --git a/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx b/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx index 3e6b308a35..5011ea574a 100644 --- a/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx +++ b/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx @@ -2,6 +2,7 @@ import React, { useRef, useEffect } from 'react' // eslint-disable-line import { FileExplorerContextMenuProps } from './types' import './css/file-explorer-context-menu.css' +import { customAction } from '@remixproject/plugin-api/lib/file-system/file-panel' export const FileExplorerContextMenu = (props: FileExplorerContextMenuProps) => { const { actions, createNewFile, createNewFolder, deletePath, renamePath, hideContextMenu, publishToGist, runScript, emit, pageX, pageY, path, type, ...otherProps } = props @@ -56,7 +57,7 @@ export const FileExplorerContextMenu = (props: FileExplorerContextMenuProps) => runScript(path) break default: - emit && emit(item.id, path) + emit && emit({ ...item, path: [path] } as customAction) break } hideContextMenu() diff --git a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx index fc8c89450a..8b70ff2075 100644 --- a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx +++ b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx @@ -11,6 +11,7 @@ import { fileSystemReducer, fileSystemInitialState } from './reducers/fileSystem import { fetchDirectory, init, resolveDirectory, addInputField, removeInputField } from './actions/fileSystem' import * as helper from '../../../../../apps/remix-ide/src/lib/helper' import QueryParams from '../../../../../apps/remix-ide/src/lib/query-params' +import { customAction } from '@remixproject/plugin-api/lib/file-system/file-panel' import './css/file-explorer.css' @@ -526,8 +527,8 @@ export const FileExplorer = (props: FileExplorerProps) => { }) } - const emitContextMenuEvent = (id: string, path: string) => { - plugin.emit(id, path) + const emitContextMenuEvent = (cmd: customAction) => { + plugin.call(cmd.id, cmd.name, cmd) } const handleHideModal = () => { diff --git a/libs/remix-ui/file-explorer/src/lib/types/index.ts b/libs/remix-ui/file-explorer/src/lib/types/index.ts index 17d6975414..6c29d2197d 100644 --- a/libs/remix-ui/file-explorer/src/lib/types/index.ts +++ b/libs/remix-ui/file-explorer/src/lib/types/index.ts @@ -1,3 +1,5 @@ +import { customAction } from '@remixproject/plugin-api/lib/file-system/file-panel' + /* eslint-disable-next-line */ export interface FileExplorerProps { name: string, @@ -37,7 +39,7 @@ export interface FileExplorerContextMenuProps { hideContextMenu: () => void, publishToGist?: () => void, runScript?: (path: string) => void, - emit?: (id: string, path: string) => void, + emit?: (cmd: customAction) => void, pageX: number, pageY: number, path: string, diff --git a/package.json b/package.json index 0e3b262c5e..432c273219 100644 --- a/package.json +++ b/package.json @@ -134,13 +134,13 @@ "@ethereumjs/common": "^2.2.0", "@ethereumjs/tx": "^3.1.3", "@ethereumjs/vm": "^5.3.2", - "@remixproject/engine": "^0.3.11", - "@remixproject/engine-web": "^0.3.11", - "@remixproject/plugin": "^0.3.11", - "@remixproject/plugin-api": "^0.3.11", - "@remixproject/plugin-utils": "^0.3.11", - "@remixproject/plugin-webview": "^0.3.11", - "@remixproject/plugin-ws": "^0.3.11", + "@remixproject/engine": "^0.3.14", + "@remixproject/engine-web": "^0.3.14", + "@remixproject/plugin": "^0.3.14", + "@remixproject/plugin-api": "^0.3.14", + "@remixproject/plugin-utils": "^0.3.14", + "@remixproject/plugin-webview": "^0.3.14", + "@remixproject/plugin-ws": "^0.3.14", "ansi-gray": "^0.1.1", "async": "^2.6.2", "axios": ">=0.21.1", @@ -161,7 +161,6 @@ "jszip": "^3.6.0", "lodash": "^4.17.21", "latest-version": "^5.1.0", - "lodash": "^4.17.21", "merge": "^1.2.0", "npm-install-version": "^6.0.2", "react": "16.13.1", From ec958e06614408052fe64c50c59b0e2b35a2d655 Mon Sep 17 00:00:00 2001 From: filip mertens Date: Mon, 17 May 2021 15:20:47 +0200 Subject: [PATCH 02/56] remove items that are not sticky --- apps/remix-ide/src/app/panels/file-panel.js | 4 +- .../file-explorer/src/lib/file-explorer.tsx | 93 +++++++++---------- 2 files changed, 49 insertions(+), 48 deletions(-) diff --git a/apps/remix-ide/src/app/panels/file-panel.js b/apps/remix-ide/src/app/panels/file-panel.js index 38720d4ca2..5c3096ff23 100644 --- a/apps/remix-ide/src/app/panels/file-panel.js +++ b/apps/remix-ide/src/app/panels/file-panel.js @@ -73,6 +73,7 @@ module.exports = class Filepanel extends ViewPlugin { } renderComponent () { + console.log("render", this.registeredMenuItems) ReactDOM.render( { - return item.id !== plugin.name + return item.id !== plugin.name || item.sticky === true }) + this.renderComponent() } async getCurrentWorkspace () { diff --git a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx index 8b70ff2075..9f16fc11c3 100644 --- a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx +++ b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx @@ -17,6 +17,50 @@ import './css/file-explorer.css' const queryParams = new QueryParams() +const initialActions = [{ + id: 'newFile', + name: 'New File', + type: ['folder'], + path: [], + extension: [], + pattern: [] +}, { + id: 'newFolder', + name: 'New Folder', + type: ['folder'], + path: [], + extension: [], + pattern: [] +}, { + id: 'rename', + name: 'Rename', + type: ['file', 'folder'], + path: [], + extension: [], + pattern: [] +}, { + id: 'delete', + name: 'Delete', + type: ['file', 'folder'], + path: [], + extension: [], + pattern: [] +}, { + id: 'pushChangesToGist', + name: 'Push changes to gist', + type: [], + path: [], + extension: [], + pattern: ['^browser/gists/([0-9]|[a-z])*$'] +}, { + id: 'run', + name: 'Run', + type: [], + path: [], + extension: ['.js'], + pattern: [] +}] + export const FileExplorer = (props: FileExplorerProps) => { const { name, registry, plugin, focusRoot, contextMenuItems, displayInput, externalUploads } = props const [state, setState] = useState({ @@ -29,49 +73,7 @@ export const FileExplorer = (props: FileExplorerProps) => { fileManager: null, ctrlKey: false, newFileName: '', - actions: [{ - id: 'newFile', - name: 'New File', - type: ['folder'], - path: [], - extension: [], - pattern: [] - }, { - id: 'newFolder', - name: 'New Folder', - type: ['folder'], - path: [], - extension: [], - pattern: [] - }, { - id: 'rename', - name: 'Rename', - type: ['file', 'folder'], - path: [], - extension: [], - pattern: [] - }, { - id: 'delete', - name: 'Delete', - type: ['file', 'folder'], - path: [], - extension: [], - pattern: [] - }, { - id: 'pushChangesToGist', - name: 'Push changes to gist', - type: [], - path: [], - extension: [], - pattern: ['^browser/gists/([0-9]|[a-z])*$'] - }, { - id: 'run', - name: 'Run', - type: [], - path: [], - extension: ['.js'], - pattern: [] - }], + actions: initialActions, focusContext: { element: null, x: null, @@ -173,10 +175,7 @@ export const FileExplorer = (props: FileExplorerProps) => { useEffect(() => { if (contextMenuItems) { setState(prevState => { - // filter duplicate items - const items = contextMenuItems.filter(({ name }) => prevState.actions.findIndex(action => action.name === name) === -1) - - return { ...prevState, actions: [...prevState.actions, ...items] } + return { ...prevState, actions: [...initialActions, ...contextMenuItems] } }) } }, [contextMenuItems]) From e113244c3f8bef9f64dce4a446f619bb375fe856 Mon Sep 17 00:00:00 2001 From: filip mertens Date: Fri, 21 May 2021 13:13:48 +0200 Subject: [PATCH 03/56] rm console --- apps/remix-ide/src/app/panels/file-panel.js | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/remix-ide/src/app/panels/file-panel.js b/apps/remix-ide/src/app/panels/file-panel.js index 8a35fcb48c..677267ed70 100644 --- a/apps/remix-ide/src/app/panels/file-panel.js +++ b/apps/remix-ide/src/app/panels/file-panel.js @@ -73,7 +73,6 @@ module.exports = class Filepanel extends ViewPlugin { } renderComponent () { - console.log("render", this.registeredMenuItems) ReactDOM.render( Date: Mon, 21 Jun 2021 15:26:11 +0200 Subject: [PATCH 04/56] log with error input name --- libs/remix-lib/src/execution/txExecution.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/libs/remix-lib/src/execution/txExecution.ts b/libs/remix-lib/src/execution/txExecution.ts index 639151c781..e87db02eb1 100644 --- a/libs/remix-lib/src/execution/txExecution.ts +++ b/libs/remix-lib/src/execution/txExecution.ts @@ -92,7 +92,7 @@ export function checkVMError (execResult, abi) { const returnDataHex = returnData.slice(0, 4).toString('hex') let customError if (abi) { - let decodedCustomErrorInputs + let decodedCustomErrorInputsClean for (const item of abi) { if (item.type === 'error') { // ethers doesn't crash anymore if "error" type is specified, but it doesn't extract the errors. see: @@ -104,16 +104,22 @@ export function checkVMError (execResult, abi) { if (!sign) continue if (returnDataHex === sign.replace('0x', '')) { customError = item.name - decodedCustomErrorInputs = fn.decodeFunctionData(fn.getFunction(item.name), returnData) + let functionDesc = fn.getFunction(item.name) + let decodedCustomErrorInputs = fn.decodeFunctionData(functionDesc, returnData) + decodedCustomErrorInputsClean = {} + for (const input of functionDesc.inputs) { + const v = decodedCustomErrorInputs[input.name] + decodedCustomErrorInputsClean[input.name] = v.toString ? v.toString() : v + } break } } } - if (decodedCustomErrorInputs) { + if (decodedCustomErrorInputsClean) { msg = '\tThe transaction has been reverted to the initial state.\nError provided by the contract:' msg += `\n${customError}` msg += '\nParameters:' - msg += `\n${decodedCustomErrorInputs}` + msg += `\n${JSON.stringify(decodedCustomErrorInputsClean, null, ' ')}` } } if (!customError) { From 2457c0cfe260b02c980bd1008cef3ee0231a80c6 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 21 Jun 2021 18:03:22 +0200 Subject: [PATCH 05/56] add natspec info to error report --- .../src/tests/transactionExecution.spec.ts | 13 +++++++++++-- apps/remix-ide/src/app/ui/universal-dapp-ui.js | 8 +++++--- apps/remix-ide/src/blockchain/blockchain.js | 5 +++-- libs/remix-lib/src/execution/txExecution.ts | 14 ++++++++++++-- 4 files changed, 31 insertions(+), 9 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/transactionExecution.spec.ts b/apps/remix-ide-e2e/src/tests/transactionExecution.spec.ts index e1d5ebb82f..d000d5e206 100644 --- a/apps/remix-ide-e2e/src/tests/transactionExecution.spec.ts +++ b/apps/remix-ide-e2e/src/tests/transactionExecution.spec.ts @@ -148,9 +148,14 @@ module.exports = { .click('.instance:nth-of-type(3) > div > button') .clickFunction('g - transact (not payable)') .journalLastChildIncludes('Error provided by the contract:') - .journalLastChildIncludes('CustomError') + .journalLastChildIncludes('CustomError: error description') .journalLastChildIncludes('Parameters:') - .journalLastChildIncludes('2,3,error_string_2') + .journalLastChildIncludes('"value": "2",') + .journalLastChildIncludes('"value": "3",') + .journalLastChildIncludes('"value": "error_string_2",') + .journalLastChildIncludes('"documentation": "param1"') + .journalLastChildIncludes('"documentation": "param2"') + .journalLastChildIncludes('"documentation": "param3"') .journalLastChildIncludes('Debug the transaction to get more information.') }, @@ -256,6 +261,10 @@ contract C { pragma solidity ^0.8.4; + /// error description + /// @param a param1 + /// @param b param2 + /// @param c param3 error CustomError(uint a, uint b, string c); contract C { function f() public pure { diff --git a/apps/remix-ide/src/app/ui/universal-dapp-ui.js b/apps/remix-ide/src/app/ui/universal-dapp-ui.js index 17fe7058c8..217217503f 100644 --- a/apps/remix-ide/src/app/ui/universal-dapp-ui.js +++ b/apps/remix-ide/src/app/ui/universal-dapp-ui.js @@ -44,14 +44,14 @@ UniversalDAppUI.prototype.renderInstance = function (contract, address, contract noInstances.parentNode.removeChild(noInstances) } const abi = txHelper.sortAbiFunction(contract.abi) - return this.renderInstanceFromABI(abi, address, contractName) + return this.renderInstanceFromABI(abi, address, contractName, contract) } // TODO this function was named before "appendChild". // this will render an instance: contract name, contract address, and all the public functions // basically this has to be called for the "atAddress" (line 393) and when a contract creation succeed // this returns a DOM element -UniversalDAppUI.prototype.renderInstanceFromABI = function (contractABI, address, contractName) { +UniversalDAppUI.prototype.renderInstanceFromABI = function (contractABI, address, contractName, contract) { const self = this address = (address.slice(0, 2) === '0x' ? '' : '0x') + address.toString('hex') address = ethJSUtil.toChecksumAddress(address) @@ -117,7 +117,8 @@ UniversalDAppUI.prototype.renderInstanceFromABI = function (contractABI, address funABI: funABI, address: address, contractABI: contractABI, - contractName: contractName + contractName: contractName, + contract })) }) @@ -255,6 +256,7 @@ UniversalDAppUI.prototype.runTransaction = function (lookupOnly, args, valArr, i args.contractName, args.contractABI, args.funABI, + args.contract, inputsValues, args.address, params, diff --git a/apps/remix-ide/src/blockchain/blockchain.js b/apps/remix-ide/src/blockchain/blockchain.js index f3dc841646..2b156e2a9b 100644 --- a/apps/remix-ide/src/blockchain/blockchain.js +++ b/apps/remix-ide/src/blockchain/blockchain.js @@ -249,7 +249,7 @@ class Blockchain { return txlistener } - runOrCallContractMethod (contractName, contractAbi, funABI, value, address, callType, lookupOnly, logMsg, logCallback, outputCb, confirmationCb, continueCb, promptCb) { + runOrCallContractMethod (contractName, contractAbi, funABI, contract, value, address, callType, lookupOnly, logMsg, logCallback, outputCb, confirmationCb, continueCb, promptCb) { // contractsDetails is used to resolve libraries txFormat.buildData(contractName, contractAbi, {}, false, funABI, callType, (error, data) => { if (error) { @@ -265,6 +265,7 @@ class Blockchain { if (data) { data.contractName = contractName data.contractABI = contractAbi + data.contract = contract } const useCall = funABI.stateMutability === 'view' || funABI.stateMutability === 'pure' this.runTx({ to: address, data, useCall }, confirmationCb, continueCb, promptCb, (error, txResult, _address, returnValue) => { @@ -490,7 +491,7 @@ class Blockchain { if (execResult) { // if it's not the VM, we don't have return value. We only have the transaction, and it does not contain the return value. returnValue = execResult ? execResult.returnValue : toBuffer(addHexPrefix(txResult.result) || '0x0000000000000000000000000000000000000000000000000000000000000000') - const vmError = txExecution.checkVMError(execResult, args.data.contractABI) + const vmError = txExecution.checkVMError(execResult, args.data.contractABI, args.data.contract) if (vmError.error) { return cb(vmError.message) } diff --git a/libs/remix-lib/src/execution/txExecution.ts b/libs/remix-lib/src/execution/txExecution.ts index e87db02eb1..035726c35e 100644 --- a/libs/remix-lib/src/execution/txExecution.ts +++ b/libs/remix-lib/src/execution/txExecution.ts @@ -57,7 +57,7 @@ export function callFunction (from, to, data, value, gasLimit, funAbi, txRunner, * @param {Object} execResult - execution result given by the VM * @return {Object} - { error: true/false, message: DOMNode } */ -export function checkVMError (execResult, abi) { +export function checkVMError (execResult, abi, contract) { const errorCode = { OUT_OF_GAS: 'out of gas', STACK_UNDERFLOW: 'stack underflow', @@ -107,9 +107,19 @@ export function checkVMError (execResult, abi) { let functionDesc = fn.getFunction(item.name) let decodedCustomErrorInputs = fn.decodeFunctionData(functionDesc, returnData) decodedCustomErrorInputsClean = {} + let devdoc = {} + if (contract && fn.functions && Object.keys(fn.functions).length) { + const functionSignature = Object.keys(fn.functions)[0] + devdoc = contract.object.devdoc.errors[functionSignature][0] || {} + let userdoc = contract.object.userdoc.errors[functionSignature][0] || {} + if (userdoc) customError += ' : ' + (userdoc as any).notice + } for (const input of functionDesc.inputs) { const v = decodedCustomErrorInputs[input.name] - decodedCustomErrorInputsClean[input.name] = v.toString ? v.toString() : v + decodedCustomErrorInputsClean[input.name] = { + value: v.toString ? v.toString() : v, + documentation: (devdoc as any).params[input.name] + } } break } From 945874072d4f664045b59dd66198ea027dc14c2f Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 21 Jun 2021 18:13:35 +0200 Subject: [PATCH 06/56] linting --- libs/remix-lib/src/execution/txExecution.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/remix-lib/src/execution/txExecution.ts b/libs/remix-lib/src/execution/txExecution.ts index 035726c35e..bf6441e133 100644 --- a/libs/remix-lib/src/execution/txExecution.ts +++ b/libs/remix-lib/src/execution/txExecution.ts @@ -104,14 +104,14 @@ export function checkVMError (execResult, abi, contract) { if (!sign) continue if (returnDataHex === sign.replace('0x', '')) { customError = item.name - let functionDesc = fn.getFunction(item.name) - let decodedCustomErrorInputs = fn.decodeFunctionData(functionDesc, returnData) + const functionDesc = fn.getFunction(item.name) + const decodedCustomErrorInputs = fn.decodeFunctionData(functionDesc, returnData) decodedCustomErrorInputsClean = {} let devdoc = {} if (contract && fn.functions && Object.keys(fn.functions).length) { const functionSignature = Object.keys(fn.functions)[0] devdoc = contract.object.devdoc.errors[functionSignature][0] || {} - let userdoc = contract.object.userdoc.errors[functionSignature][0] || {} + const userdoc = contract.object.userdoc.errors[functionSignature][0] || {} if (userdoc) customError += ' : ' + (userdoc as any).notice } for (const input of functionDesc.inputs) { From 6986cd5b529bfb19ec06ef1272e34d0650fde8d0 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 22 Jun 2021 08:25:04 +0200 Subject: [PATCH 07/56] e2e test --- apps/remix-ide-e2e/src/tests/transactionExecution.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/remix-ide-e2e/src/tests/transactionExecution.spec.ts b/apps/remix-ide-e2e/src/tests/transactionExecution.spec.ts index d000d5e206..f67a954706 100644 --- a/apps/remix-ide-e2e/src/tests/transactionExecution.spec.ts +++ b/apps/remix-ide-e2e/src/tests/transactionExecution.spec.ts @@ -148,7 +148,7 @@ module.exports = { .click('.instance:nth-of-type(3) > div > button') .clickFunction('g - transact (not payable)') .journalLastChildIncludes('Error provided by the contract:') - .journalLastChildIncludes('CustomError: error description') + .journalLastChildIncludes('CustomError : error description') .journalLastChildIncludes('Parameters:') .journalLastChildIncludes('"value": "2",') .journalLastChildIncludes('"value": "3",') From 75dc083a5517387498773c0ca6f2d53f18628bff Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 29 Jun 2021 10:10:45 +0200 Subject: [PATCH 08/56] add comment --- libs/remix-lib/src/execution/txExecution.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libs/remix-lib/src/execution/txExecution.ts b/libs/remix-lib/src/execution/txExecution.ts index bf6441e133..792175a48c 100644 --- a/libs/remix-lib/src/execution/txExecution.ts +++ b/libs/remix-lib/src/execution/txExecution.ts @@ -105,20 +105,24 @@ export function checkVMError (execResult, abi, contract) { if (returnDataHex === sign.replace('0x', '')) { customError = item.name const functionDesc = fn.getFunction(item.name) + // decoding error parameters const decodedCustomErrorInputs = fn.decodeFunctionData(functionDesc, returnData) decodedCustomErrorInputsClean = {} let devdoc = {} + // "contract" reprensents the compilation result containing the NATSPEC documentation if (contract && fn.functions && Object.keys(fn.functions).length) { const functionSignature = Object.keys(fn.functions)[0] + // we check in the 'devdoc' if there's a developer documentation for this error devdoc = contract.object.devdoc.errors[functionSignature][0] || {} + // we check in the 'userdoc' if there's an user documentation for this error const userdoc = contract.object.userdoc.errors[functionSignature][0] || {} - if (userdoc) customError += ' : ' + (userdoc as any).notice + if (userdoc) customError += ' : ' + (userdoc as any).notice // we append the user doc if any } for (const input of functionDesc.inputs) { const v = decodedCustomErrorInputs[input.name] decodedCustomErrorInputsClean[input.name] = { value: v.toString ? v.toString() : v, - documentation: (devdoc as any).params[input.name] + documentation: (devdoc as any).params[input.name] // we add the developer documentation for this input parameter if any } } break From b9060bda40ea26912ee68be3cb01708ef9afdfd8 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 29 Jun 2021 12:13:44 +0200 Subject: [PATCH 09/56] fix e2e --- .../remix-ide-e2e/src/tests/transactionExecution.spec.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/transactionExecution.spec.ts b/apps/remix-ide-e2e/src/tests/transactionExecution.spec.ts index f67a954706..d06c1c1c9d 100644 --- a/apps/remix-ide-e2e/src/tests/transactionExecution.spec.ts +++ b/apps/remix-ide-e2e/src/tests/transactionExecution.spec.ts @@ -168,9 +168,14 @@ module.exports = { .click('.instance:nth-of-type(2) > div > button') .clickFunction('g - transact (not payable)') .journalLastChildIncludes('Error provided by the contract:') - .journalLastChildIncludes('CustomError') + .journalLastChildIncludes('CustomError : error description') .journalLastChildIncludes('Parameters:') - .journalLastChildIncludes('2,3,error_string_2') + .journalLastChildIncludes('"value": "2",') + .journalLastChildIncludes('"value": "3",') + .journalLastChildIncludes('"value": "error_string_2",') + .journalLastChildIncludes('"documentation": "param1"') + .journalLastChildIncludes('"documentation": "param2"') + .journalLastChildIncludes('"documentation": "param3"') .journalLastChildIncludes('Debug the transaction to get more information.') .end() } From fcadbfd9f94846634e835d9f37dee89d168f4c21 Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 17 Jun 2021 14:15:08 +0200 Subject: [PATCH 10/56] make sure non zero are highlighted --- .../src/lib/vm-debugger/dropdown-panel.tsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/dropdown-panel.tsx b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/dropdown-panel.tsx index 4ba9b16c12..0ce016fda4 100644 --- a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/dropdown-panel.tsx +++ b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/dropdown-panel.tsx @@ -34,10 +34,19 @@ export const DropdownPanel = (props: DropdownPanelProps) => { return ret } const formatSelfDefault = (key: string | number, data: ExtractData) => { + let value + if (typeof(data.self) === 'string') { + let regex = /^(0+)(.*)/g + let split = regex.exec(data.self.replace('0x', '')) + if (split && split[1] && split[2]) { + split[1] = data.self.indexOf('0x') === 0 ? '0x' + split[1] : split[1] + value = ({split[1]}{split[2]}) + } + } else value = data.self return (
- +
) } From d3969a68a40b880d5860e8d13f0c5598ce95ed0e Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 17 Jun 2021 14:40:48 +0200 Subject: [PATCH 11/56] use monospace for memory and stack --- .../debugger-ui/src/lib/vm-debugger/dropdown-panel.tsx | 6 +++--- .../debugger-ui/src/lib/vm-debugger/memory-panel.tsx | 2 +- .../debugger-ui/src/lib/vm-debugger/stack-panel.tsx | 2 +- libs/remix-ui/debugger-ui/src/types/index.ts | 4 +++- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/dropdown-panel.tsx b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/dropdown-panel.tsx index 0ce016fda4..3abd08fcbb 100644 --- a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/dropdown-panel.tsx +++ b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/dropdown-panel.tsx @@ -7,7 +7,7 @@ import './styles/dropdown-panel.css' export const DropdownPanel = (props: DropdownPanelProps) => { const [calldataObj, dispatch] = useReducer(reducer, initialState) - const { dropdownName, dropdownMessage, calldata, header, loading, extractFunc, formatSelfFunc, registerEvent, triggerEvent, loadMoreEvent, loadMoreCompletedEvent } = props + const { dropdownName, dropdownMessage, calldata, header, loading, extractFunc, formatSelfFunc, registerEvent, triggerEvent, loadMoreEvent, loadMoreCompletedEvent, headStyle, bodyStyle } = props const extractDataDefault: ExtractFunc = (item, parent?) => { const ret: ExtractData = {} @@ -193,14 +193,14 @@ export const DropdownPanel = (props: DropdownPanelProps) => { return (
-
+
{dropdownName}
{header}
-
+
{ state.data && diff --git a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/memory-panel.tsx b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/memory-panel.tsx index b772369ec6..75358e9c07 100644 --- a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/memory-panel.tsx +++ b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/memory-panel.tsx @@ -3,7 +3,7 @@ import DropdownPanel from './dropdown-panel' // eslint-disable-line export const MemoryPanel = ({ calldata }) => { return ( - + ) } diff --git a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/stack-panel.tsx b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/stack-panel.tsx index fcb86b2699..1824a55477 100644 --- a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/stack-panel.tsx +++ b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/stack-panel.tsx @@ -4,7 +4,7 @@ import DropdownPanel from './dropdown-panel' // eslint-disable-line export const StackPanel = ({ calldata }) => { return (
- +
) } diff --git a/libs/remix-ui/debugger-ui/src/types/index.ts b/libs/remix-ui/debugger-ui/src/types/index.ts index 45a26384dc..b968815242 100644 --- a/libs/remix-ui/debugger-ui/src/types/index.ts +++ b/libs/remix-ui/debugger-ui/src/types/index.ts @@ -27,7 +27,9 @@ export interface DropdownPanelProps { registerEvent?: Function, triggerEvent?: Function, loadMoreEvent?: string, - loadMoreCompletedEvent?: string + loadMoreCompletedEvent?: string, + bodyStyle?: React.CSSProperties + headStyle?: React.CSSProperties } export type FormatSelfFunc = (key: string | number, data: ExtractData) => JSX.Element From 86af2594dac7e13995be5f41e813065ba1bf879b Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 17 Jun 2021 16:01:31 +0200 Subject: [PATCH 12/56] use hexHighlight --- .../src/lib/vm-debugger/dropdown-panel.tsx | 22 ++++++++++--------- .../src/lib/vm-debugger/memory-panel.tsx | 2 +- .../src/lib/vm-debugger/stack-panel.tsx | 2 +- .../src/lib/vm-debugger/step-detail.tsx | 2 +- libs/remix-ui/debugger-ui/src/types/index.ts | 5 +++-- 5 files changed, 18 insertions(+), 15 deletions(-) diff --git a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/dropdown-panel.tsx b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/dropdown-panel.tsx index 3abd08fcbb..4b196b9796 100644 --- a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/dropdown-panel.tsx +++ b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/dropdown-panel.tsx @@ -7,7 +7,7 @@ import './styles/dropdown-panel.css' export const DropdownPanel = (props: DropdownPanelProps) => { const [calldataObj, dispatch] = useReducer(reducer, initialState) - const { dropdownName, dropdownMessage, calldata, header, loading, extractFunc, formatSelfFunc, registerEvent, triggerEvent, loadMoreEvent, loadMoreCompletedEvent, headStyle, bodyStyle } = props + const { dropdownName, dropdownMessage, calldata, header, loading, extractFunc, formatSelfFunc, registerEvent, triggerEvent, loadMoreEvent, loadMoreCompletedEvent, headStyle, bodyStyle, hexHighlight } = props const extractDataDefault: ExtractFunc = (item, parent?) => { const ret: ExtractData = {} @@ -34,15 +34,17 @@ export const DropdownPanel = (props: DropdownPanelProps) => { return ret } const formatSelfDefault = (key: string | number, data: ExtractData) => { - let value - if (typeof(data.self) === 'string') { - let regex = /^(0+)(.*)/g - let split = regex.exec(data.self.replace('0x', '')) - if (split && split[1] && split[2]) { - split[1] = data.self.indexOf('0x') === 0 ? '0x' + split[1] : split[1] - value = ({split[1]}{split[2]}) - } - } else value = data.self + let value + if (hexHighlight && typeof(data.self) === 'string') { + const isHex = data.self.startsWith('0x') || hexHighlight + if (isHex) { + let regex = /^(0+)(.*)/g + let split = regex.exec(data.self.replace('0x', '')) + if (split && split[1]) { + value = (0x{split[1]}{ split[2] && {split[2]} }) + } else value = (0x{data.self.replace('0x', '')}) + } else value = {data.self} + } else value = {data.self} return (
diff --git a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/memory-panel.tsx b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/memory-panel.tsx index 75358e9c07..8e6cd8b3be 100644 --- a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/memory-panel.tsx +++ b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/memory-panel.tsx @@ -3,7 +3,7 @@ import DropdownPanel from './dropdown-panel' // eslint-disable-line export const MemoryPanel = ({ calldata }) => { return ( - + ) } diff --git a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/stack-panel.tsx b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/stack-panel.tsx index 1824a55477..0864ec035f 100644 --- a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/stack-panel.tsx +++ b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/stack-panel.tsx @@ -4,7 +4,7 @@ import DropdownPanel from './dropdown-panel' // eslint-disable-line export const StackPanel = ({ calldata }) => { return (
- +
) } diff --git a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/step-detail.tsx b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/step-detail.tsx index 15d17a7792..f4669baebc 100644 --- a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/step-detail.tsx +++ b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/step-detail.tsx @@ -4,7 +4,7 @@ import DropdownPanel from './dropdown-panel' // eslint-disable-line export const StepDetail = ({ stepDetail }) => { return (
- +
) } diff --git a/libs/remix-ui/debugger-ui/src/types/index.ts b/libs/remix-ui/debugger-ui/src/types/index.ts index b968815242..9d13aab883 100644 --- a/libs/remix-ui/debugger-ui/src/types/index.ts +++ b/libs/remix-ui/debugger-ui/src/types/index.ts @@ -28,8 +28,9 @@ export interface DropdownPanelProps { triggerEvent?: Function, loadMoreEvent?: string, loadMoreCompletedEvent?: string, - bodyStyle?: React.CSSProperties - headStyle?: React.CSSProperties + bodyStyle?: React.CSSProperties, + headStyle?: React.CSSProperties, + hexHighlight?: boolean // highlight non zero value of hex value } export type FormatSelfFunc = (key: string | number, data: ExtractData) => JSX.Element From a3424ad2a9078c5cfb8929da4ff611cadd86c1ef Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 17 Jun 2021 22:37:23 +0200 Subject: [PATCH 13/56] linting --- .../src/lib/vm-debugger/dropdown-panel.tsx | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/dropdown-panel.tsx b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/dropdown-panel.tsx index 4b196b9796..207e99ea74 100644 --- a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/dropdown-panel.tsx +++ b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/dropdown-panel.tsx @@ -34,16 +34,16 @@ export const DropdownPanel = (props: DropdownPanelProps) => { return ret } const formatSelfDefault = (key: string | number, data: ExtractData) => { - let value - if (hexHighlight && typeof(data.self) === 'string') { - const isHex = data.self.startsWith('0x') || hexHighlight - if (isHex) { - let regex = /^(0+)(.*)/g - let split = regex.exec(data.self.replace('0x', '')) - if (split && split[1]) { - value = (0x{split[1]}{ split[2] && {split[2]} }) - } else value = (0x{data.self.replace('0x', '')}) - } else value = {data.self} + let value + if (hexHighlight && typeof (data.self) === 'string') { + const isHex = data.self.startsWith('0x') || hexHighlight + if (isHex) { + const regex = /^(0+)(.*)/g + const split = regex.exec(data.self.replace('0x', '')) + if (split && split[1]) { + value = (0x{split[1]}{ split[2] && {split[2]} }) + } else value = (0x{data.self.replace('0x', '')}) + } else value = {data.self} } else value = {data.self} return (
From a9c77582b935e313edda98a6379ef5ef95eb784a Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 17 Jun 2021 17:12:05 +0200 Subject: [PATCH 14/56] use a better code comparison --- libs/remix-lib/src/util.ts | 6 ++++-- package-lock.json | 5 +++++ package.json | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/libs/remix-lib/src/util.ts b/libs/remix-lib/src/util.ts index cc70e786e8..f14e48174a 100644 --- a/libs/remix-lib/src/util.ts +++ b/libs/remix-lib/src/util.ts @@ -1,5 +1,6 @@ 'use strict' import { BN, bufferToHex, keccak, setLengthLeft, toBuffer, addHexPrefix } from 'ethereumjs-util' +import stringSimilarity from 'string-similarity' /* contains misc util: @TODO should be splitted @@ -222,8 +223,9 @@ export function compareByteCode (code1, code2) { code2 = this.extractSwarmHash(code2) code2 = this.extractcborMetadata(code2) - if (code1 && code2 && code1.indexOf(code2) === 0) { - return true + if (code1 && code2) { + const compare = stringSimilarity.compareTwoStrings(code1, code2) + return compare > 0.5 } return false } diff --git a/package-lock.json b/package-lock.json index fa010f1b61..9e028132b2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36072,6 +36072,11 @@ } } }, + "string-similarity": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/string-similarity/-/string-similarity-4.0.4.tgz", + "integrity": "sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ==" + }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", diff --git a/package.json b/package.json index 895639bd6c..07ab9d39e1 100644 --- a/package.json +++ b/package.json @@ -172,6 +172,7 @@ "react-dom": "16.13.1", "selenium": "^2.20.0", "signale": "^1.4.0", + "string-similarity": "^4.0.4", "time-stamp": "^2.2.0", "tslib": "^2.3.0", "web3": "1.2.4", From a59cd8b97745e6959cc3b7508b2b10dbf5b78d72 Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 17 Jun 2021 17:12:19 +0200 Subject: [PATCH 15/56] manage immutable --- libs/remix-debug/src/solidity-decoder/decodeInfo.ts | 11 +++++++---- libs/remix-debug/src/solidity-decoder/stateDecoder.ts | 4 ++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/libs/remix-debug/src/solidity-decoder/decodeInfo.ts b/libs/remix-debug/src/solidity-decoder/decodeInfo.ts index 5384b1af86..d506e5ca3e 100644 --- a/libs/remix-debug/src/solidity-decoder/decodeInfo.ts +++ b/libs/remix-debug/src/solidity-decoder/decodeInfo.ts @@ -336,7 +336,9 @@ function computeOffsets (types, stateDefinitions, contractName, location) { console.log('unable to retrieve decode info of ' + variable.typeDescriptions.typeString) return null } - if (!variable.constant && storagelocation.offset + type.storageBytes > 32) { + const immutable = variable.mutability === 'immutable' + const hasStorageSlots = !immutable && !variable.constant + if (hasStorageSlots && storagelocation.offset + type.storageBytes > 32) { storagelocation.slot++ storagelocation.offset = 0 } @@ -344,12 +346,13 @@ function computeOffsets (types, stateDefinitions, contractName, location) { name: variable.name, type: type, constant: variable.constant, + immutable, storagelocation: { - offset: variable.constant ? 0 : storagelocation.offset, - slot: variable.constant ? 0 : storagelocation.slot + offset: !hasStorageSlots ? 0 : storagelocation.offset, + slot: !hasStorageSlots ? 0 : storagelocation.slot } }) - if (!variable.constant) { + if (hasStorageSlots) { if (type.storageSlots === 1 && storagelocation.offset + type.storageBytes <= 32) { storagelocation.offset += type.storageBytes } else { diff --git a/libs/remix-debug/src/solidity-decoder/stateDecoder.ts b/libs/remix-debug/src/solidity-decoder/stateDecoder.ts index 0e27ac740c..b7908da3c3 100644 --- a/libs/remix-debug/src/solidity-decoder/stateDecoder.ts +++ b/libs/remix-debug/src/solidity-decoder/stateDecoder.ts @@ -15,9 +15,13 @@ export async function decodeState (stateVars, storageResolver) { try { const decoded = await stateVar.type.decodeFromStorage(stateVar.storagelocation, storageResolver) decoded.constant = stateVar.constant + decoded.immutable = stateVar.immutable if (decoded.constant) { decoded.value = '' } + if (decoded.immutable) { + decoded.value = '' + } ret[stateVar.name] = decoded } catch (e) { console.log(e) From b20ab527f92772000561a9db784e11c5af7de68b Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 18 Jun 2021 14:10:43 +0200 Subject: [PATCH 16/56] fix e2e --- apps/remix-ide-e2e/src/tests/ballot.test.ts | 9 ++++++--- apps/remix-ide-e2e/src/tests/debugger.spec.ts | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/ballot.test.ts b/apps/remix-ide-e2e/src/tests/ballot.test.ts index b44b17746e..aa6d507120 100644 --- a/apps/remix-ide-e2e/src/tests/ballot.test.ts +++ b/apps/remix-ide-e2e/src/tests/ballot.test.ts @@ -121,7 +121,8 @@ const stateCheck = { chairperson: { value: '0xCA35B7D915458EF540ADE6068DFE2F44E8FA733C', type: 'address', - constant: false + constant: false, + immutable: false }, voters: { value: { @@ -148,7 +149,8 @@ const stateCheck = { } }, type: 'mapping(address => struct Ballot.Voter)', - constant: false + constant: false, + immutable: false }, proposals: { value: [ @@ -168,7 +170,8 @@ const stateCheck = { ], length: '0x1', type: 'struct Ballot.Proposal[]', - constant: false + constant: false, + immutable: false } } diff --git a/apps/remix-ide-e2e/src/tests/debugger.spec.ts b/apps/remix-ide-e2e/src/tests/debugger.spec.ts index 78406a7b8d..0baeee65b3 100644 --- a/apps/remix-ide-e2e/src/tests/debugger.spec.ts +++ b/apps/remix-ide-e2e/src/tests/debugger.spec.ts @@ -228,7 +228,7 @@ module.exports = { .waitForElementVisible('*[data-id="solidityLocals"]', 60000) .pause(10000) .checkVariableDebug('soliditylocals', { num: { value: '2', type: 'uint256' } }) - .checkVariableDebug('soliditystate', { number: { value: '0', type: 'uint256', constant: false } }) + .checkVariableDebug('soliditystate', { number: { value: '0', type: 'uint256', constant: false, immutable: false } }) .end() } } From 18f1e83cb97da0fcee05742ee8eb64fc36f86acc Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 24 Jun 2021 09:59:46 +0200 Subject: [PATCH 17/56] change comparison treshold --- libs/remix-lib/src/util.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/remix-lib/src/util.ts b/libs/remix-lib/src/util.ts index f14e48174a..58f5d875dd 100644 --- a/libs/remix-lib/src/util.ts +++ b/libs/remix-lib/src/util.ts @@ -225,8 +225,9 @@ export function compareByteCode (code1, code2) { if (code1 && code2) { const compare = stringSimilarity.compareTwoStrings(code1, code2) - return compare > 0.5 + return compare > 0.93 } + return false } /* util extracted out from remix-ide. @TODO split this file, cause it mix real util fn with solidity related stuff ... */ From 738f8292a751b817b3aa75387b4dfe9c8075e56f Mon Sep 17 00:00:00 2001 From: David Zagi Date: Wed, 30 Jun 2021 08:17:02 +0100 Subject: [PATCH 18/56] feat: task configuration and creating of setting-tab in react (#1171) initial project setup and creation of setting tab in react Fixes https://github.com/ethereum/remix-project/issues/1159 --- .../src/tests/generalSettings.test.ts | 17 +- apps/remix-ide-e2e/src/tests/runAndDeploy.ts | 2 + apps/remix-ide/src/app/tabs/settings-tab.js | 221 ++---------------- .../copy-to-clipboard/copy-to-clipboard.tsx | 1 + libs/remix-ui/settings/.babelrc | 4 + libs/remix-ui/settings/.eslintrc | 19 ++ libs/remix-ui/settings/README.md | 7 + libs/remix-ui/settings/src/index.ts | 1 + libs/remix-ui/settings/src/lib/constants.ts | 12 + .../settings/src/lib/remix-ui-settings.css | 0 .../settings/src/lib/remix-ui-settings.tsx | 166 +++++++++++++ .../settings/src/lib/settingsAction.ts | 52 +++++ .../settings/src/lib/settingsReducer.ts | 103 ++++++++ libs/remix-ui/settings/tsconfig.json | 16 ++ libs/remix-ui/settings/tsconfig.lib.json | 13 ++ nx.json | 6 + package.json | 2 +- tsconfig.json | 4 +- workspace.json | 18 +- 19 files changed, 452 insertions(+), 212 deletions(-) create mode 100644 libs/remix-ui/settings/.babelrc create mode 100644 libs/remix-ui/settings/.eslintrc create mode 100644 libs/remix-ui/settings/README.md create mode 100644 libs/remix-ui/settings/src/index.ts create mode 100644 libs/remix-ui/settings/src/lib/constants.ts create mode 100644 libs/remix-ui/settings/src/lib/remix-ui-settings.css create mode 100644 libs/remix-ui/settings/src/lib/remix-ui-settings.tsx create mode 100644 libs/remix-ui/settings/src/lib/settingsAction.ts create mode 100644 libs/remix-ui/settings/src/lib/settingsReducer.ts create mode 100644 libs/remix-ui/settings/tsconfig.json create mode 100644 libs/remix-ui/settings/tsconfig.lib.json diff --git a/apps/remix-ide-e2e/src/tests/generalSettings.test.ts b/apps/remix-ide-e2e/src/tests/generalSettings.test.ts index 9c605afec0..b79d2e5054 100644 --- a/apps/remix-ide-e2e/src/tests/generalSettings.test.ts +++ b/apps/remix-ide-e2e/src/tests/generalSettings.test.ts @@ -18,6 +18,7 @@ module.exports = { 'Should activate `generate contract metadata`': function (browser) { browser.waitForElementVisible('*[data-id="remixIdeSidePanel"]', 5000) .waitForElementVisible('*[data-id="settingsTabGenerateContractMetadataLabel"]', 5000) + .verify.elementPresent('[data-id="settingsTabGenerateContractMetadata"]:checked') .click('*[data-id="verticalIconsFileExplorerIcons"]') .click('[data-id="treeViewLitreeViewItemcontracts"]') .openFile('contracts/3_Ballot.sol') @@ -39,22 +40,26 @@ module.exports = { .click('*[data-id="verticalIconsKindsettings"]') .setValue('*[data-id="settingsTabGistAccessToken"]', '**********') .click('*[data-id="settingsTabSaveGistToken"]') - .waitForElementVisible('*[data-shared="tooltipPopup"]:nth-last-of-type(1)', 5000) - .assert.containsText('*[data-shared="tooltipPopup"]:nth-last-of-type(1)', 'Access token has been saved') + .waitForElementVisible('*[data-shared="tooltipPopup"]', 5000) + .assert.containsText('*[data-shared="tooltipPopup"]', 'Access token has been saved') + .pause(3000) }, 'Should copy github access token to clipboard': function (browser: NightwatchBrowser) { browser.waitForElementVisible('*[data-id="verticalIconsKindsettings"]', 5000) .click('*[data-id="copyToClipboardCopyIcon"]') - .waitForElementVisible('*[data-shared="tooltipPopup"]:nth-last-of-type(1)', 5000) - .assert.containsText('*[data-shared="tooltipPopup"]:nth-last-of-type(1)', 'Copied value to clipboard.') + .waitForElementVisible('*[data-shared="tooltipPopup"]', 5000) + // .waitForElementVisible('*[data-shared="tooltipPopup"]:nth-last-of-type(1) , 5000) + // .assert.containsText('*[data-shared="tooltipPopup"]', 'Copied value to clipboard.') + // .assert.containsText('*[data-shared="tooltipPopup"]:nth-last-of-type(1)', 'Copied value to clipboard.') }, 'Should remove github access token': function (browser: NightwatchBrowser) { browser.waitForElementVisible('*[data-id="verticalIconsKindsettings"]', 5000) + .pause(1000) .click('*[data-id="settingsTabRemoveGistToken"]') - .waitForElementVisible('*[data-shared="tooltipPopup"]:nth-last-of-type(1)', 5000) - .assert.containsText('*[data-shared="tooltipPopup"]:nth-last-of-type(1)', 'Access token removed') + .waitForElementVisible('*[data-shared="tooltipPopup"]', 5000) + .assert.containsText('*[data-shared="tooltipPopup"]', 'Access token removed') .assert.containsText('*[data-id="settingsTabGistAccessToken"]', '') }, diff --git a/apps/remix-ide-e2e/src/tests/runAndDeploy.ts b/apps/remix-ide-e2e/src/tests/runAndDeploy.ts index 20455df8b3..a138bc77d1 100644 --- a/apps/remix-ide-e2e/src/tests/runAndDeploy.ts +++ b/apps/remix-ide-e2e/src/tests/runAndDeploy.ts @@ -32,6 +32,8 @@ module.exports = { 'Should sign message using account key': function (browser: NightwatchBrowser) { browser.waitForElementPresent('*[data-id="settingsRemixRunSignMsg"]') + .click('select[id="selectExEnvOptions"] option[value="vm-berlin"]') + .pause(2000) .click('*[data-id="settingsRemixRunSignMsg"]') .pause(2000) .waitForElementPresent('*[data-id="modalDialogCustomPromptText"]') diff --git a/apps/remix-ide/src/app/tabs/settings-tab.js b/apps/remix-ide/src/app/tabs/settings-tab.js index 3ef4d2953d..8c3889a02b 100644 --- a/apps/remix-ide/src/app/tabs/settings-tab.js +++ b/apps/remix-ide/src/app/tabs/settings-tab.js @@ -1,12 +1,10 @@ +import React from 'react' // eslint-disable-line import { ViewPlugin } from '@remixproject/engine-web' +import ReactDOM from 'react-dom' import * as packageJson from '../../../../../package.json' -const yo = require('yo-yo') +import { RemixUiSettings } from '@remix-ui/settings' //eslint-disable-line const globalRegistry = require('../../global/registry') -const tooltip = require('../ui/tooltip') -const copyToClipboard = require('../ui/copy-to-clipboard') const EventManager = require('../../lib/events') -const css = require('./styles/settings-tab-styles') -const _paq = window._paq = window._paq || [] const profile = { name: 'settings', @@ -51,210 +49,27 @@ module.exports = class SettingsTab extends ViewPlugin { textWrapLabel: null } /* eslint-enable */ this.event = new EventManager() + this.element = document.createElement('div') + this.element.setAttribute('id', 'settingsTab') } - createThemeCheckies () { - const themes = this._deps.themeModule.getThemes() - const onswitchTheme = (event, name) => { - this._deps.themeModule.switchTheme(name) - } - if (themes) { - return yo`
- ${themes.map((aTheme) => { - const el = yo`
- { onswitchTheme(event, aTheme.name) }} class="align-middle custom-control-input" name="theme" id="${aTheme.name}" data-id="settingsTabTheme${aTheme.name}"> - -
` - if (this._deps.themeModule.active === aTheme.name) el.querySelector('input').setAttribute('checked', 'checked') - return el - })} -
` - } + onActivation () { + this.renderComponent() } render () { - const self = this - if (self._view.el) return self._view.el - - // Gist settings - const token = this.config.get('settings/gist-access-token') - const gistAccessToken = yo`` - if (token) gistAccessToken.value = token - const removeToken = () => { self.config.set('settings/gist-access-token', ''); gistAccessToken.value = ''; tooltip('Access token removed') } - const saveToken = () => { - this.config.set('settings/gist-access-token', gistAccessToken.value) - tooltip('Access token has been saved. RELOAD the page to apply it.') - } - const gistAddToken = yo` saveToken()} value="Save" type="button">` - const gistRemoveToken = yo`` - this._view.gistToken = yo` -
- ${gistAccessToken} -
- ${copyToClipboard(() => gistAccessToken.value)}${gistAddToken}${gistRemoveToken} -
-

- - Please reload Remix after having saved the token. -

-
- ` - this._view.optionVM = yo`` - this._view.optionVMLabel = yo`` - if (this.config.get('settings/always-use-vm') === undefined) this.config.set('settings/always-use-vm', true) - if (this.config.get('settings/always-use-vm')) this._view.optionVM.setAttribute('checked', '') - elementStateChanged(self._view.optionVMLabel, !this.config.get('settings/always-use-vm')) - - this._view.textWrap = yo`` - this._view.textWrapLabel = yo`` - if (this.config.get('settings/text-wrap')) this._view.textWrap.setAttribute('checked', '') - elementStateChanged(self._view.textWrapLabel, !this.config.get('settings/text-wrap')) - - const warnText = `Transaction sent over Web3 will use the web3.personal API - be sure the endpoint is opened before enabling it. - This mode allows to provide the passphrase in the Remix interface without having to unlock the account. - Although this is very convenient, you should completely trust the backend you are connected to (Geth, Parity, ...). - Remix never persist any passphrase.`.split('\n').map(s => s.trim()).join(' ') - - this._view.personal = yo`` - this._view.warnPersonalMode = yo`` - this._view.personalLabel = yo`` - if (this.config.get('settings/personal-mode')) this._view.personal.setAttribute('checked', '') - elementStateChanged(self._view.personalLabel, !this.config.get('settings/personal-mode')) - - this._view.useMatomoAnalytics = yo`` - this._view.useMatomoAnalyticsLabel = yo` - - ` - if (this.config.get('settings/matomo-analytics')) { - this._view.useMatomoAnalytics.setAttribute('checked', '') - _paq.push(['forgetUserOptOut']) - // @TODO remove next line when https://github.com/matomo-org/matomo/commit/9e10a150585522ca30ecdd275007a882a70c6df5 is used - document.cookie = 'mtm_consent_removed=; expires=Thu, 01 Jan 1970 00:00:01 GMT;' - } else { - _paq.push(['optUserOut']) - } - elementStateChanged(self._view.useMatomoAnalyticsLabel, !this.config.get('settings/matomo-analytics')) - - this._view.generateContractMetadata = yo`` - this._view.generateContractMetadataLabel = yo`` - if (this.config.get('settings/generate-contract-metadata') === undefined) this.config.set('settings/generate-contract-metadata', true) - if (this.config.get('settings/generate-contract-metadata')) this._view.generateContractMetadata.setAttribute('checked', '') - elementStateChanged(self._view.generateContractMetadataLabel, !this.config.get('settings/generate-contract-metadata')) - - this._view.pluginInput = yo`` - - this._view.themes = this._deps.themeModule.getThemes() - this._view.themesCheckBoxes = this.createThemeCheckies() - - this._view.config.general = yo` -
-
-
General settings
-
- ${this._view.generateContractMetadata} - ${this._view.generateContractMetadataLabel} -
-
- ${this._view.optionVM} - ${this._view.optionVMLabel} -
-
- ${this._view.textWrap} - ${this._view.textWrapLabel} -
-
- ${this._view.personal} - ${this._view.personalLabel} -
-
- ${this._view.useMatomoAnalytics} - ${this._view.useMatomoAnalyticsLabel} -
-
-
- ` - this._view.gistToken = yo` -
-
-
Github Access Token
-

Manage the access token used to publish to Gist and retrieve Github contents.

-

Go to github token page (link below) to create a new token and save it in Remix. Make sure this token has only 'create gist' permission.

-

https://github.com/settings/tokens

-
${this._view.gistToken}
-
-
` - this._view.config.themes = yo` -
-
-
Themes
- ${this._view.themesCheckBoxes} -
-
` - this._view.el = yo` -
- ${this._view.config.general} - ${this._view.gistToken} - ${this._view.config.themes} -
` - - function onchangeGenerateContractMetadata (event) { - const isChecked = self.config.get('settings/generate-contract-metadata') - - self.config.set('settings/generate-contract-metadata', !isChecked) - elementStateChanged(self._view.generateContractMetadataLabel, isChecked) - } - - function onchangeOption (event) { - const isChecked = self.config.get('settings/always-use-vm') - - self.config.set('settings/always-use-vm', !isChecked) - elementStateChanged(self._view.optionVMLabel, isChecked) - } - - function textWrapEvent (event) { - const isChecked = self.config.get('settings/text-wrap') - - self.config.set('settings/text-wrap', !isChecked) - elementStateChanged(self._view.textWrapLabel, isChecked) - self.editor.resize(!isChecked) - } - - function onchangePersonal (event) { - const isChecked = self.config.get('settings/personal-mode') - - self.config.set('settings/personal-mode', !isChecked) - elementStateChanged(self._view.personalLabel, isChecked) - } - - function onchangeMatomoAnalytics (event) { - const isChecked = self.config.get('settings/matomo-analytics') - - self.config.set('settings/matomo-analytics', !isChecked) - elementStateChanged(self._view.useMatomoAnalyticsLabel, isChecked) - if (event.target.checked) { - _paq.push(['forgetUserOptOut']) - // @TODO remove next line when https://github.com/matomo-org/matomo/commit/9e10a150585522ca30ecdd275007a882a70c6df5 is used - document.cookie = 'mtm_consent_removed=; expires=Thu, 01 Jan 1970 00:00:01 GMT;' - } else { - _paq.push(['optUserOut']) - } - } - - function elementStateChanged (el, isChanged) { - if (isChanged) { - el.classList.remove('text-dark') - el.classList.add('text-secondary') - } else { - el.classList.add('text-dark') - el.classList.remove('text-secondary') - } - } + return this.element + } - this._deps.themeModule.switchTheme() - return this._view.el + renderComponent () { + ReactDOM.render( + , + this.element + ) } getGithubAccessToken () { diff --git a/libs/remix-ui/clipboard/src/lib/copy-to-clipboard/copy-to-clipboard.tsx b/libs/remix-ui/clipboard/src/lib/copy-to-clipboard/copy-to-clipboard.tsx index 2bea5aed07..fbfdc6dfba 100644 --- a/libs/remix-ui/clipboard/src/lib/copy-to-clipboard/copy-to-clipboard.tsx +++ b/libs/remix-ui/clipboard/src/lib/copy-to-clipboard/copy-to-clipboard.tsx @@ -6,6 +6,7 @@ import './copy-to-clipboard.css' export const CopyToClipboard = ({ content, tip='Copy', icon='fa-copy', ...otherProps }) => { const [message, setMessage] = useState(tip) + const handleClick = (event) => { if (content && content !== '') { // module `copy` keeps last copied thing in the memory, so don't show tooltip if nothing is copied, because nothing was added to memory try { diff --git a/libs/remix-ui/settings/.babelrc b/libs/remix-ui/settings/.babelrc new file mode 100644 index 0000000000..09d67939cc --- /dev/null +++ b/libs/remix-ui/settings/.babelrc @@ -0,0 +1,4 @@ +{ + "presets": ["@nrwl/react/babel"], + "plugins": [] +} diff --git a/libs/remix-ui/settings/.eslintrc b/libs/remix-ui/settings/.eslintrc new file mode 100644 index 0000000000..dae5c6feeb --- /dev/null +++ b/libs/remix-ui/settings/.eslintrc @@ -0,0 +1,19 @@ +{ + "env": { + "browser": true, + "es6": true + }, + "extends": "../../../.eslintrc", + "globals": { + "Atomics": "readonly", + "SharedArrayBuffer": "readonly" + }, + "parserOptions": { + "ecmaVersion": 11, + "sourceType": "module" + }, + "rules": { + "no-unused-vars": "off", + "@typescript-eslint/no-unused-vars": "error" + } +} diff --git a/libs/remix-ui/settings/README.md b/libs/remix-ui/settings/README.md new file mode 100644 index 0000000000..d4a8337744 --- /dev/null +++ b/libs/remix-ui/settings/README.md @@ -0,0 +1,7 @@ +# remix-ui-settings + +This library was generated with [Nx](https://nx.dev). + +## Running unit tests + +Run `nx test remix-ui-settings` to execute the unit tests via [Jest](https://jestjs.io). diff --git a/libs/remix-ui/settings/src/index.ts b/libs/remix-ui/settings/src/index.ts new file mode 100644 index 0000000000..432ac58185 --- /dev/null +++ b/libs/remix-ui/settings/src/index.ts @@ -0,0 +1 @@ +export * from './lib/remix-ui-settings' diff --git a/libs/remix-ui/settings/src/lib/constants.ts b/libs/remix-ui/settings/src/lib/constants.ts new file mode 100644 index 0000000000..4d6d2a06de --- /dev/null +++ b/libs/remix-ui/settings/src/lib/constants.ts @@ -0,0 +1,12 @@ +export const generateContractMetadataText = 'Generate contract metadata. Generate a JSON file in the contract folder. Allows to specify library addresses the contract depends on. If nothing is specified, Remix deploys libraries automatically.' +export const textSecondary = 'text-secondary' +export const textDark = 'text-dark' +export const warnText = 'Be sure the endpoint is opened before enabling it. \nThis mode allows a user to provide a passphrase in the Remix interface without having to unlock the account. Although this is very convenient, you should completely trust the backend you are connected to (Geth, Parity, ...). Remix never persists any passphrase'.split('\n').map(s => s.trim()).join(' ') +export const gitAccessTokenTitle = 'Github Access Token' +export const gitAccessTokenText = 'Manage the access token used to publish to Gist and retrieve Github contents.' +export const gitAccessTokenText2 = 'Go to github token page (link below) to create a new token and save it in Remix. Make sure this token has only \'create gist\' permission.' +export const gitAccessTokenLink = 'https://github.com/settings/tokens' +export const ethereunVMText = 'Always use Ethereum VM at load' +export const wordWrapText = 'Word wrap in editor' +export const enablePersonalModeText = ' Enable Personal Mode for web3 provider. Transaction sent over Web3 will use the web3.personal API.\n' +export const matomoAnalytics = 'Enable Matomo Analytics. We do not collect personally identifiable information (PII). The info is used to improve the site’s UX & UI. See more about ' diff --git a/libs/remix-ui/settings/src/lib/remix-ui-settings.css b/libs/remix-ui/settings/src/lib/remix-ui-settings.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/libs/remix-ui/settings/src/lib/remix-ui-settings.tsx b/libs/remix-ui/settings/src/lib/remix-ui-settings.tsx new file mode 100644 index 0000000000..ef8c3ed6c5 --- /dev/null +++ b/libs/remix-ui/settings/src/lib/remix-ui-settings.tsx @@ -0,0 +1,166 @@ +import React, { useState, useReducer, useEffect, useCallback } from 'react' // eslint-disable-line +import { CopyToClipboard } from '@remix-ui/clipboard' // eslint-disable-line + +import { enablePersonalModeText, ethereunVMText, generateContractMetadataText, gitAccessTokenLink, gitAccessTokenText, gitAccessTokenText2, gitAccessTokenTitle, matomoAnalytics, textDark, textSecondary, warnText, wordWrapText } from './constants' + +import './remix-ui-settings.css' +import { etherumVM, generateContractMetadat, personal, textWrapEventAction, useMatomoAnalytics, saveTokenToast, removeTokenToast } from './settingsAction' +import { initialState, toastInitialState, toastReducer, settingReducer } from './settingsReducer' +import { Toaster } from '@remix-ui/toaster'// eslint-disable-line + +/* eslint-disable-next-line */ +export interface RemixUiSettingsProps { + config: any, + editor: any, + _deps: any +} + +export const RemixUiSettings = (props: RemixUiSettingsProps) => { + const [, dispatch] = useReducer(settingReducer, initialState) + const [state, dispatchToast] = useReducer(toastReducer, toastInitialState) + const [tokenValue, setTokenValue] = useState('') + const [themeName, setThemeName] = useState('') + + useEffect(() => { + const token = props.config.get('settings/gist-access-token') + if (token === undefined) { + props.config.set('settings/generate-contract-metadata', true) + dispatch({ type: 'contractMetadata', payload: { name: 'contractMetadata', isChecked: true, textClass: textDark } }) + } + if (token) { + setTokenValue(token) + } + }, [themeName, state.message]) + + const onchangeGenerateContractMetadata = (event) => { + generateContractMetadat(props, event, dispatch) + } + + const onchangeOption = (event) => { + etherumVM(props, event, dispatch) + } + + const textWrapEvent = (event) => { + textWrapEventAction(props, event, dispatch) + } + + const onchangePersonal = event => { + personal(props, event, dispatch) + } + + const onchangeMatomoAnalytics = event => { + useMatomoAnalytics(props, event, dispatch) + } + + const onswitchTheme = (event, name) => { + props._deps.themeModule.switchTheme(name) + setThemeName(name) + } + + const getTextClass = (key) => { + if (props.config.get(key)) { + return textDark + } else { + return textSecondary + } + } + + const generalConfig = () => ( +
+
+
General settings
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ ) + + const saveToken = () => { + saveTokenToast(props, dispatchToast, tokenValue) + } + + const removeToken = () => { + setTokenValue('') + removeTokenToast(props, dispatchToast) + } + + const handleSaveTokenState = useCallback( + (event) => { + setTokenValue(event.target.value) + }, + [tokenValue] + ) + + const gistToken = () => ( +
+
+
{ gitAccessTokenTitle }
+

{ gitAccessTokenText }

+

{ gitAccessTokenText2 }

+

{ gitAccessTokenLink }

+
+
+ +
+ + saveToken()} value="Save" type="button" disabled={tokenValue === ''}> + +
+
+
+
+ ) + + const themes = () => { + const themes = props._deps.themeModule.getThemes() + if (themes) { + return themes.map((aTheme, index) => ( +
+ { onswitchTheme(event, aTheme.name) }} className="align-middle custom-control-input" name='theme' id={aTheme.name} data-id={`settingsTabTheme${aTheme.name}`} checked = {props._deps.themeModule.active === aTheme.name ? true : null}/> + +
+ ) + ) + } + } + + return ( +
+ {state.message ? : null} + {generalConfig()} + {gistToken()} +
+
+
Themes
+
+ {themes()} +
+
+
+
+ ) +} diff --git a/libs/remix-ui/settings/src/lib/settingsAction.ts b/libs/remix-ui/settings/src/lib/settingsAction.ts new file mode 100644 index 0000000000..055c84449b --- /dev/null +++ b/libs/remix-ui/settings/src/lib/settingsAction.ts @@ -0,0 +1,52 @@ +import { textDark, textSecondary } from './constants' + +declare global { + interface Window { + _paq: any + } +} + +const _paq = window._paq = window._paq || [] //eslint-disable-line + +export const generateContractMetadat = (element, event, dispatch) => { + element.config.set('settings/generate-contract-metadata', event.target.checked) + dispatch({ type: 'contractMetadata', payload: { name: event.target.name, isChecked: event.target.checked, textClass: event.target.checked ? textDark : textSecondary } }) +} + +export const etherumVM = (element, event, dispatch) => { + element.config.set('settings/always-use-vm', event.target.checked) + dispatch({ type: 'ethereumVM', payload: { name: event.target.name, isChecked: event.target.checked, textClass: event.target.checked ? textDark : textSecondary } }) +} + +export const textWrapEventAction = (element, event, dispatch) => { + element.config.set('settings/text-wrap', event.target.checked) + element.editor.resize(event.target.checked) + dispatch({ type: 'textWrap', payload: { name: event.target.name, isChecked: event.target.checked, textClass: event.target.checked ? textDark : textSecondary } }) +} + +export const personal = (element, event, dispatch) => { + element.config.set('settings/personal-mode', event.target.checked) + dispatch({ type: 'personal', payload: { name: event.target.name, isChecked: event.target.checked, textClass: event.target.checked ? textDark : textSecondary } }) +} + +export const useMatomoAnalytics = (element, event, dispatch) => { + element.config.set('settings/matomo-analytics', event.target.checked) + dispatch({ type: 'useMatomoAnalytics', payload: { name: event.target.name, isChecked: event.target.checked, textClass: event.target.checked ? textDark : textSecondary } }) + if (event.target.checked) { + _paq.push(['forgetUserOptOut']) + // @TODO remove next line when https://github.com/matomo-org/matomo/commit/9e10a150585522ca30ecdd275007a882a70c6df5 is used + document.cookie = 'mtm_consent_removed=; expires=Thu, 01 Jan 1970 00:00:01 GMT;' + } else { + _paq.push(['optUserOut']) + } +} + +export const saveTokenToast = (props, dispatch, tokenValue) => { + props.config.set('settings/gist-access-token', tokenValue) + dispatch({ type: 'save', payload: { message: 'Access token has been saved' } }) +} + +export const removeTokenToast = (props, dispatch) => { + props.config.set('settings/gist-access-token', '') + dispatch({ type: 'removed', payload: { message: 'Access token removed' } }) +} diff --git a/libs/remix-ui/settings/src/lib/settingsReducer.ts b/libs/remix-ui/settings/src/lib/settingsReducer.ts new file mode 100644 index 0000000000..daf6453959 --- /dev/null +++ b/libs/remix-ui/settings/src/lib/settingsReducer.ts @@ -0,0 +1,103 @@ +import { textSecondary } from './constants' + +export const initialState = { + elementState: [ + { + name: 'contractMetadata', + isChecked: false, + textClass: textSecondary + }, + { + name: 'ethereumVM', + isChecked: false, + textClass: textSecondary + }, + { + name: 'textWrap', + isChecked: false, + textClass: textSecondary + }, + { + name: 'personal', + isChecked: false, + textClass: textSecondary + }, + { + name: 'useMatomoAnalytics', + isChecked: false, + textClass: textSecondary + } + ] +} + +export const settingReducer = (state, action) => { + switch (action.type) { + case 'contractMetadata': + state.elementState.map(element => { + if (element.name === 'contractMetadata') { + element.isChecked = action.payload.isChecked + element.textClass = action.payload.textClass + } + }) + return { + ...state + } + case 'ethereumVM': + state.elementState.map(element => { + if (element.name === 'ethereumVM') { + element.isChecked = action.payload.isChecked + element.textClass = action.payload.textClass + } + }) + return { + ...state + } + case 'textWrap': + state.elementState.map(element => { + if (element.name === 'textWrap') { + element.isChecked = action.payload.isChecked + element.textClass = action.payload.textClass + } + }) + return { + ...state + } + case 'personal': + state.elementState.map(element => { + if (element.name === 'personal') { + element.isChecked = action.payload.isChecked + element.textClass = action.payload.textClass + } + }) + return { + ...state + } + case 'useMatomoAnalytics': + state.elementState.map(element => { + if (element.name === 'useMatomoAnalytics') { + element.isChecked = action.payload.isChecked + element.textClass = action.payload.textClass + } + }) + return { + ...state + } + default: + return initialState + } +} + +export const toastInitialState = { + message: '' +} + +export const toastReducer = (state, action) => { + switch (action.type) { + case 'save' : + return { ...state, message: action.payload.message } + case 'removed' : + return { ...state, message: action.payload.message } + default : + return { ...state, message: '' } + } +} diff --git a/libs/remix-ui/settings/tsconfig.json b/libs/remix-ui/settings/tsconfig.json new file mode 100644 index 0000000000..6b65264565 --- /dev/null +++ b/libs/remix-ui/settings/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "jsx": "react", + "allowJs": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + } + ] +} diff --git a/libs/remix-ui/settings/tsconfig.lib.json b/libs/remix-ui/settings/tsconfig.lib.json new file mode 100644 index 0000000000..b560bc4dec --- /dev/null +++ b/libs/remix-ui/settings/tsconfig.lib.json @@ -0,0 +1,13 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": ["node"] + }, + "files": [ + "../../../node_modules/@nrwl/react/typings/cssmodule.d.ts", + "../../../node_modules/@nrwl/react/typings/image.d.ts" + ], + "exclude": ["**/*.spec.ts", "**/*.spec.tsx"], + "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] +} diff --git a/nx.json b/nx.json index a63c015d64..64d8dcaeaf 100644 --- a/nx.json +++ b/nx.json @@ -96,11 +96,17 @@ "remix-ui-workspace": { "tags": [] }, + "remix-ui-settings": { + "tags": [] + }, "remix-ui-static-analyser": { "tags": [] }, "remix-ui-checkbox": { "tags": [] + }, + "remix-ui-settings": { + "tags": [] } } } diff --git a/package.json b/package.json index 07ab9d39e1..e238787d68 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "workspace-schematic": "nx workspace-schematic", "dep-graph": "nx dep-graph", "help": "nx help", - "lint:libs": "nx run-many --target=lint --projects=remix-analyzer,remix-astwalker,remix-debug,remix-lib,remix-simulator,remix-solidity,remix-tests,remix-url-resolver,remixd,remix-ui-tree-view,remix-ui-modal-dialog,remix-ui-toaster,remix-ui-file-explorer,remix-ui-debugger-ui,remix-ui-workspace,remix-ui-static-analyser,remix-ui-checkbox", + "lint:libs": "nx run-many --target=lint --projects=remix-analyzer,remix-astwalker,remix-debug,remix-lib,remix-simulator,remix-solidity,remix-tests,remix-url-resolver,remixd,remix-ui-tree-view,remix-ui-modal-dialog,remix-ui-toaster,remix-ui-file-explorer,remix-ui-debugger-ui,remix-ui-workspace,remix-ui-static-analyser,remix-ui-checkbox,remix-ui-settings", "build:libs": "nx run-many --target=build --parallel=false --with-deps=true --projects=remix-analyzer,remix-astwalker,remix-debug,remix-lib,remix-simulator,remix-solidity,remix-tests,remix-url-resolver,remixd", "test:libs": "nx run-many --target=test --projects=remix-analyzer,remix-astwalker,remix-debug,remix-lib,remix-simulator,remix-solidity,remix-tests,remix-url-resolver,remixd", "publish:libs": "npm run build:libs && lerna publish --skip-git && npm run bumpVersion:libs", diff --git a/tsconfig.json b/tsconfig.json index 75db5bc6ff..573a63975e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -39,8 +39,10 @@ "@remix-ui/toaster": ["libs/remix-ui/toaster/src/index.ts"], "@remix-ui/file-explorer": ["libs/remix-ui/file-explorer/src/index.ts"], "@remix-ui/workspace": ["libs/remix-ui/workspace/src/index.ts"], + "@remix-ui/settings": ["libs/remix-ui/settings/src/index.ts"], "@remix-ui/static-analyser": ["libs/remix-ui/static-analyser/src/index.ts"], - "@remix-ui/checkbox": ["libs/remix-ui/checkbox/src/index.ts"] + "@remix-ui/checkbox": ["libs/remix-ui/checkbox/src/index.ts"], + "@remix-ui/settings": ["libs/remix-ui/settings/src/index.ts"] } }, "exclude": ["node_modules", "tmp"] diff --git a/workspace.json b/workspace.json index 5d2bf912c0..04da7184e5 100644 --- a/workspace.json +++ b/workspace.json @@ -726,6 +726,22 @@ } } }, + "remix-ui-settings": { + "root": "libs/remix-ui/settings", + "sourceRoot": "libs/remix-ui/settings/src", + "projectType": "library", + "schematics": {}, + "architect": { + "lint": { + "builder": "@nrwl/linter:lint", + "options": { + "linter": "eslint", + "tsConfig": ["libs/remix-ui/settings/tsconfig.lib.json"], + "exclude": ["**/node_modules/**", "!libs/remix-ui/settings/**/*"] + } + } + } + }, "remix-ui-static-analyser": { "root": "libs/remix-ui/static-analyser", "sourceRoot": "libs/remix-ui/static-analyser/src", @@ -828,4 +844,4 @@ } }, "defaultProject": "remix-ide" -} +} \ No newline at end of file From 9d0d8064a2ec111a65de492feca6ccf86ecf23e6 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 25 Jun 2021 10:36:26 +0200 Subject: [PATCH 19/56] don't set a current fork if injected or web3 is used --- apps/remix-ide/src/blockchain/execution-context.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/apps/remix-ide/src/blockchain/execution-context.js b/apps/remix-ide/src/blockchain/execution-context.js index 352a689df3..0e1debeb2b 100644 --- a/apps/remix-ide/src/blockchain/execution-context.js +++ b/apps/remix-ide/src/blockchain/execution-context.js @@ -21,8 +21,7 @@ export class ExecutionContext { this.executionContext = null this.blockGasLimitDefault = 4300000 this.blockGasLimit = this.blockGasLimitDefault - this.defaultFork = 'berlin' - this.currentFork = this.defaultFork + this.currentFork = ' - ' this.mainNetGenesisHash = '0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3' this.customNetWorks = {} this.blocks = {} @@ -125,18 +124,17 @@ export class ExecutionContext { executionContextChange (value, endPointUrl, confirmCb, infoCb, cb) { const context = value.context - const fork = value.fork || this.defaultFork if (!cb) cb = () => {} if (!confirmCb) confirmCb = () => {} if (!infoCb) infoCb = () => {} if (context === 'vm') { this.executionContext = context - this.currentFork = fork + this.currentFork = value.fork this.event.trigger('contextChanged', ['vm']) return cb() } - this.currentFork = this.defaultFork // in the case of injected and web3, we default to the last fork. + this.currentFork = ' - ' if (context === 'injected') { if (injectedProvider === undefined) { From 8bb34084afed48221e31dbc78620806a076e679c Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 25 Jun 2021 10:42:41 +0200 Subject: [PATCH 20/56] remove uneeded default value --- libs/remix-simulator/src/vm-context.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libs/remix-simulator/src/vm-context.ts b/libs/remix-simulator/src/vm-context.ts index e0a3aef849..a7e766c6ba 100644 --- a/libs/remix-simulator/src/vm-context.ts +++ b/libs/remix-simulator/src/vm-context.ts @@ -91,7 +91,6 @@ export class VMContext { blocks latestBlockNumber txs - defaultFork currentVm web3vm logsManager @@ -100,8 +99,7 @@ export class VMContext { constructor (fork?) { this.blockGasLimitDefault = 4300000 this.blockGasLimit = this.blockGasLimitDefault - this.defaultFork = fork || 'berlin' - this.currentFork = this.defaultFork + this.currentFork = fork this.currentVm = this.createVm(this.currentFork) this.blocks = {} this.latestBlockNumber = 0 From e31cd263298fa9fbb52cabbf49071491b62f2b51 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 25 Jun 2021 10:43:00 +0200 Subject: [PATCH 21/56] add London to Solidity EVM version --- libs/remix-solidity/src/compiler/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/remix-solidity/src/compiler/types.ts b/libs/remix-solidity/src/compiler/types.ts index e10e99e52f..75091f366b 100644 --- a/libs/remix-solidity/src/compiler/types.ts +++ b/libs/remix-solidity/src/compiler/types.ts @@ -150,7 +150,7 @@ export interface CompilerInputOptions { language?: Language } -export type EVMVersion = 'homestead' | 'tangerineWhistle' | 'spuriousDragon' | 'byzantium' | 'constantinople' | 'petersburg' | 'istanbul' | 'muirGlacier' | 'berlin' | null +export type EVMVersion = 'homestead' | 'tangerineWhistle' | 'spuriousDragon' | 'byzantium' | 'constantinople' | 'petersburg' | 'istanbul' | 'muirGlacier' | 'berlin' | 'london' | null export type Language = 'Solidity' | 'Yul' From a5755a96b305c341d7139fb4abf69d993ce233a2 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 25 Jun 2021 12:36:52 +0200 Subject: [PATCH 22/56] allow debugging various fork --- apps/debugger/src/app/debugger-api.ts | 3 +- .../src/blockchain/execution-context.js | 22 ++-- libs/remix-debug/src/Ethdebugger.ts | 4 +- libs/remix-debug/src/debugger/debugger.ts | 3 +- libs/remix-debug/src/trace/traceManager.ts | 12 +- libs/remix-lib/src/execution/forkAt.ts | 121 ++++++++++++++++++ libs/remix-lib/src/index.ts | 4 +- .../debugger-ui/src/lib/debugger-ui.tsx | 3 +- 8 files changed, 153 insertions(+), 19 deletions(-) create mode 100644 libs/remix-lib/src/execution/forkAt.ts diff --git a/apps/debugger/src/app/debugger-api.ts b/apps/debugger/src/app/debugger-api.ts index e1b66a3d48..0f99518e78 100644 --- a/apps/debugger/src/app/debugger-api.ts +++ b/apps/debugger/src/app/debugger-api.ts @@ -111,8 +111,7 @@ export const DebuggerApiMixin = (Base) => class extends Base { } return null }, - debugWithGeneratedSources: false, - fork: 'berlin' + debugWithGeneratedSources: false }) return await debug.debugger.traceManager.getTrace(hash) } diff --git a/apps/remix-ide/src/blockchain/execution-context.js b/apps/remix-ide/src/blockchain/execution-context.js index 0e1debeb2b..b6a988e915 100644 --- a/apps/remix-ide/src/blockchain/execution-context.js +++ b/apps/remix-ide/src/blockchain/execution-context.js @@ -1,6 +1,7 @@ /* global ethereum */ 'use strict' import Web3 from 'web3' +import { execution } from '@remix-project/remix-lib' import EventManager from '../lib/events' let web3 @@ -21,7 +22,7 @@ export class ExecutionContext { this.executionContext = null this.blockGasLimitDefault = 4300000 this.blockGasLimit = this.blockGasLimitDefault - this.currentFork = ' - ' + this.currentFork = 'berlin' this.mainNetGenesisHash = '0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3' this.customNetWorks = {} this.blocks = {} @@ -134,8 +135,6 @@ export class ExecutionContext { return cb() } - this.currentFork = ' - ' - if (context === 'injected') { if (injectedProvider === undefined) { infoCb('No injected Web3 provider found. Make sure your provider (e.g. MetaMask) is active and running (when recently activated you may have to reload the page).') @@ -144,7 +143,7 @@ export class ExecutionContext { this.askPermission() this.executionContext = context web3.setProvider(injectedProvider) - this._updateBlockGasLimit() + this._updateChainContext() this.event.trigger('contextChanged', ['injected']) return cb() } @@ -171,12 +170,19 @@ export class ExecutionContext { this.listenOnLastBlockId = null } - _updateBlockGasLimit () { + _updateChainContext () { if (this.getProvider() !== 'vm') { - web3.eth.getBlock('latest', (err, block) => { + web3.eth.getBlock('latest', async (err, block) => { if (!err) { // we can't use the blockGasLimit cause the next blocks could have a lower limit : https://github.com/ethereum/remix/issues/506 this.blockGasLimit = (block && block.gasLimit) ? Math.floor(block.gasLimit - (5 * block.gasLimit) / 1024) : this.blockGasLimitDefault + try { + this.currentFork = execution.forkAt(await web3.eth.net.getId(), block.number) + } catch (e) { + this.currentFork = 'berlin' + console.log(`unable to detect fork, defaulting to ${this.currentFork}..`) + console.error(e) + } } else { this.blockGasLimit = this.blockGasLimitDefault } @@ -186,7 +192,7 @@ export class ExecutionContext { listenOnLastBlock () { this.listenOnLastBlockId = setInterval(() => { - this._updateBlockGasLimit() + this._updateChainContext() }, 15000) } @@ -200,7 +206,7 @@ export class ExecutionContext { web3.eth.net.isListening((err, isConnected) => { if (!err && isConnected === true) { this.executionContext = context - this._updateBlockGasLimit() + this._updateChainContext() this.event.trigger('contextChanged', [context]) this.event.trigger('web3EndpointChanged') cb() diff --git a/libs/remix-debug/src/Ethdebugger.ts b/libs/remix-debug/src/Ethdebugger.ts index 4c023c6028..3c492e1812 100644 --- a/libs/remix-debug/src/Ethdebugger.ts +++ b/libs/remix-debug/src/Ethdebugger.ts @@ -41,7 +41,7 @@ export class Ethdebugger { this.opts = opts this.event = new EventManager() - this.traceManager = new TraceManager({ web3: this.web3, fork: this.opts.fork }) + this.traceManager = new TraceManager({ web3: this.web3 }) this.codeManager = new CodeManager(this.traceManager) this.solidityProxy = new SolidityProxy({ getCurrentCalledAddressAt: this.traceManager.getCurrentCalledAddressAt.bind(this.traceManager), getCode: this.codeManager.getCode.bind(this.codeManager) }) this.storageResolver = null @@ -55,7 +55,7 @@ export class Ethdebugger { } setManagers () { - this.traceManager = new TraceManager({ web3: this.web3, fork: this.opts.fork }) + this.traceManager = new TraceManager({ web3: this.web3 }) this.codeManager = new CodeManager(this.traceManager) this.solidityProxy = new SolidityProxy({ getCurrentCalledAddressAt: this.traceManager.getCurrentCalledAddressAt.bind(this.traceManager), getCode: this.codeManager.getCode.bind(this.codeManager) }) this.storageResolver = null diff --git a/libs/remix-debug/src/debugger/debugger.ts b/libs/remix-debug/src/debugger/debugger.ts index 76d28746bd..11395026b3 100644 --- a/libs/remix-debug/src/debugger/debugger.ts +++ b/libs/remix-debug/src/debugger/debugger.ts @@ -26,8 +26,7 @@ export class Debugger { this.debugger = new Ethdebugger({ web3: options.web3, debugWithGeneratedSources: options.debugWithGeneratedSources, - compilationResult: this.compilationResult, - fork: options.fork + compilationResult: this.compilationResult }) const { traceManager, callTree, solidityProxy } = this.debugger diff --git a/libs/remix-debug/src/trace/traceManager.ts b/libs/remix-debug/src/trace/traceManager.ts index d3f3861e0f..8e78782922 100644 --- a/libs/remix-debug/src/trace/traceManager.ts +++ b/libs/remix-debug/src/trace/traceManager.ts @@ -1,9 +1,9 @@ 'use strict' +import { util, execution } from '@remix-project/remix-lib' import { TraceAnalyser } from './traceAnalyser' import { TraceCache } from './traceCache' import { TraceStepManager } from './traceStepManager' import { isCreateInstruction } from './traceHelper' -import { util } from '@remix-project/remix-lib' export class TraceManager { web3 @@ -17,7 +17,6 @@ export class TraceManager { constructor (options) { this.web3 = options.web3 - this.fork = options.fork this.isLoading = false this.trace = null this.traceCache = new TraceCache() @@ -37,6 +36,15 @@ export class TraceManager { if (result['structLogs'].length > 0) { this.trace = result['structLogs'] + try { + const networkId = await this.web3.eth.net.getId() + this.fork = execution.forkAt(networkId, tx.blockNumber) + } catch (e) { + this.fork = 'berlin' + console.log(`unable to detect fork, defaulting to ${this.fork}..`) + console.error(e) + } + this.traceAnalyser.analyse(result['structLogs'], tx) this.isLoading = false return true diff --git a/libs/remix-lib/src/execution/forkAt.ts b/libs/remix-lib/src/execution/forkAt.ts new file mode 100644 index 0000000000..5c4316f868 --- /dev/null +++ b/libs/remix-lib/src/execution/forkAt.ts @@ -0,0 +1,121 @@ +'use strict' + +/** + * returns the fork name for the @argument networkId and @argument blockNumber + * + * @param {Object} networkId - network Id (1 for VM, 3 for Ropsten, 4 for Rinkeby, 5 for Goerli) + * @param {Object} blockNumber - block number + * @return {String} - fork name (Berlin, Istanbul, ...) + */ +export function forkAt (networkId, blockNumber) { + if (forks[networkId]) { + let currentForkName = forks[networkId][0].name + for (const fork of forks[networkId]) { + if (blockNumber >= fork.number) { + currentForkName = fork.name + } + } + return currentForkName + } + return 'berlin' +} + +// see https://github.com/ethereum/go-ethereum/blob/master/params/config.go +const forks = { + 1: [ + { + number: 4370000, + name: 'byzantium' + }, + { + number: 7280000, + name: 'constantinople' + }, + { + number: 7280000, + name: 'petersburg' + }, + { + number: 9069000, + name: 'istanbul' + }, + { + number: 9200000, + name: 'muirglacier' + }, + { + number: 12244000, + name: 'berlin' + } + ], + 3: [ + { + number: 1700000, + name: 'byzantium' + }, + { + number: 4230000, + name: 'constantinople' + }, + { + number: 4939394, + name: 'petersburg' + }, + { + number: 6485846, + name: 'istanbul' + }, + { + number: 7117117, + name: 'muirglacier' + }, + { + number: 9812189, + name: 'berlin' + }, + { + number: 10499401, + name: 'london' + } + ], + 4: [ + { + number: 1035301, + name: 'byzantium' + }, + { + number: 3660663, + name: 'constantinople' + }, + { + number: 4321234, + name: 'petersburg' + }, + { + number: 5435345, + name: 'istanbul' + }, + { + number: 8290928, + name: 'berlin' + }, + { + number: 8897988, + name: 'london' + } + ], + 5: [ + { + number: 1561651, + name: 'istanbul' + }, + { + number: 4460644, + name: 'berlin' + }, + { + number: 5062605, + name: 'london' + } + ] +} diff --git a/libs/remix-lib/src/index.ts b/libs/remix-lib/src/index.ts index ae3864a8c9..d3d37231f1 100644 --- a/libs/remix-lib/src/index.ts +++ b/libs/remix-lib/src/index.ts @@ -13,6 +13,7 @@ import * as txFormat from './execution/txFormat' import { TxListener } from './execution/txListener' import { TxRunner } from './execution/txRunner' import { LogsManager } from './execution/logsManager' +import { forkAt } from './execution/forkAt' import * as typeConversion from './execution/typeConversion' import { TxRunnerVM } from './execution/txRunnerVM' import { TxRunnerWeb3 } from './execution/txRunnerWeb3' @@ -45,7 +46,8 @@ function modules () { TxRunnerWeb3: TxRunnerWeb3, TxRunnerVM: TxRunnerVM, typeConversion: typeConversion, - LogsManager + LogsManager, + forkAt } } } diff --git a/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx b/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx index 78ec2de174..af3648aa90 100644 --- a/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx +++ b/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx @@ -208,8 +208,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => { } return null }, - debugWithGeneratedSources: state.opt.debugWithGeneratedSources, - fork: 'berlin' + debugWithGeneratedSources: state.opt.debugWithGeneratedSources }) debuggerInstance.debug(blockNumber, txNumber, tx, () => { From caff3b595d3cd457bcdf04b2571271f316e3b040 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 28 Jun 2021 17:39:19 +0200 Subject: [PATCH 23/56] remix-simulator default to last fork --- libs/remix-simulator/src/vm-context.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/remix-simulator/src/vm-context.ts b/libs/remix-simulator/src/vm-context.ts index a7e766c6ba..363e9ab50e 100644 --- a/libs/remix-simulator/src/vm-context.ts +++ b/libs/remix-simulator/src/vm-context.ts @@ -99,7 +99,7 @@ export class VMContext { constructor (fork?) { this.blockGasLimitDefault = 4300000 this.blockGasLimit = this.blockGasLimitDefault - this.currentFork = fork + this.currentFork = fork || 'berlin' this.currentVm = this.createVm(this.currentFork) this.blocks = {} this.latestBlockNumber = 0 From 47bbf64b2fb6c09b14671e28823e82c9e4d06b13 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 30 Jun 2021 11:28:40 +0200 Subject: [PATCH 24/56] Make sure current fork is set before continuing (#1340) --- .../src/blockchain/execution-context.js | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/apps/remix-ide/src/blockchain/execution-context.js b/apps/remix-ide/src/blockchain/execution-context.js index b6a988e915..f29d0ec0d4 100644 --- a/apps/remix-ide/src/blockchain/execution-context.js +++ b/apps/remix-ide/src/blockchain/execution-context.js @@ -123,7 +123,7 @@ export class ExecutionContext { this.executionContextChange(context, endPointUrl, confirmCb, infoCb, null) } - executionContextChange (value, endPointUrl, confirmCb, infoCb, cb) { + async executionContextChange (value, endPointUrl, confirmCb, infoCb, cb) { const context = value.context if (!cb) cb = () => {} if (!confirmCb) confirmCb = () => {} @@ -143,7 +143,7 @@ export class ExecutionContext { this.askPermission() this.executionContext = context web3.setProvider(injectedProvider) - this._updateChainContext() + await this._updateChainContext() this.event.trigger('contextChanged', ['injected']) return cb() } @@ -170,23 +170,23 @@ export class ExecutionContext { this.listenOnLastBlockId = null } - _updateChainContext () { + async _updateChainContext () { if (this.getProvider() !== 'vm') { - web3.eth.getBlock('latest', async (err, block) => { - if (!err) { - // we can't use the blockGasLimit cause the next blocks could have a lower limit : https://github.com/ethereum/remix/issues/506 - this.blockGasLimit = (block && block.gasLimit) ? Math.floor(block.gasLimit - (5 * block.gasLimit) / 1024) : this.blockGasLimitDefault - try { - this.currentFork = execution.forkAt(await web3.eth.net.getId(), block.number) - } catch (e) { - this.currentFork = 'berlin' - console.log(`unable to detect fork, defaulting to ${this.currentFork}..`) - console.error(e) - } - } else { - this.blockGasLimit = this.blockGasLimitDefault + try { + const block = await web3.eth.getBlock('latest') + // we can't use the blockGasLimit cause the next blocks could have a lower limit : https://github.com/ethereum/remix/issues/506 + this.blockGasLimit = (block && block.gasLimit) ? Math.floor(block.gasLimit - (5 * block.gasLimit) / 1024) : this.blockGasLimitDefault + try { + this.currentFork = execution.forkAt(await web3.eth.net.getId(), block.number) + } catch (e) { + this.currentFork = 'berlin' + console.log(`unable to detect fork, defaulting to ${this.currentFork}..`) + console.error(e) } - }) + } catch (e) { + console.error(e) + this.blockGasLimit = this.blockGasLimitDefault + } } } From baa3fc843297c92c8a1b5126c34d4f8093b30476 Mon Sep 17 00:00:00 2001 From: aniket-engg Date: Tue, 22 Jun 2021 15:39:57 +0530 Subject: [PATCH 25/56] fix hardhat modal reappearing --- apps/remix-ide/src/app/tabs/hardhat-provider.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/remix-ide/src/app/tabs/hardhat-provider.js b/apps/remix-ide/src/app/tabs/hardhat-provider.js index 037117fa85..88fe3b7c85 100644 --- a/apps/remix-ide/src/app/tabs/hardhat-provider.js +++ b/apps/remix-ide/src/app/tabs/hardhat-provider.js @@ -39,12 +39,17 @@ export default class HardhatProvider extends Plugin { sendAsync (data) { return new Promise((resolve, reject) => { - if (!this.provider) { + if (!this.provider || data.method === 'net_listening') { modalDialogCustom.prompt('Hardhat node request', this.hardhatProviderDialogBody(), 'http://127.0.0.1:8545', (target) => { this.provider = new Web3.providers.HttpProvider(target) this.sendAsyncInternal(data, resolve, reject) }, () => { - this.sendAsyncInternal(data, resolve, reject) + if (data.method === 'net_listening') resolve({ jsonrpc: '2.0', result: 'canceled', id: data.id }) + else { + this.blockchain.changeExecutionContext('vm') + this.provider = this.blockchain.getCurrentProvider() + reject(new Error('Connection canceled')) + } }) } else { this.sendAsyncInternal(data, resolve, reject) @@ -62,8 +67,7 @@ export default class HardhatProvider extends Plugin { resolve(message) }) } else { - const result = data.method === 'net_listening' ? 'canceled' : [] - resolve({ jsonrpc: '2.0', result: result, id: data.id }) + resolve({ jsonrpc: '2.0', result: [], id: data.id }) } } } From 94910717816b82024628ca28a981c8fe722118cc Mon Sep 17 00:00:00 2001 From: aniket-engg Date: Tue, 22 Jun 2021 16:04:45 +0530 Subject: [PATCH 26/56] specific error on tooltip --- apps/remix-ide/src/app/tabs/hardhat-provider.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/remix-ide/src/app/tabs/hardhat-provider.js b/apps/remix-ide/src/app/tabs/hardhat-provider.js index 88fe3b7c85..8c2cd0ae05 100644 --- a/apps/remix-ide/src/app/tabs/hardhat-provider.js +++ b/apps/remix-ide/src/app/tabs/hardhat-provider.js @@ -59,6 +59,9 @@ export default class HardhatProvider extends Plugin { sendAsyncInternal (data, resolve, reject) { if (this.provider) { + // Check the case where current environment is VM on UI and it still sends RPC requests + // This will be displayed on UI tooltip as 'cannot get account list: Environment Updated !!' + if (this.blockchain.getProvider() !== 'Hardhat Provider' && data.method !== 'net_listening') return reject(new Error('Environment Updated !!')) this.provider[this.provider.sendAsync ? 'sendAsync' : 'send'](data, (error, message) => { if (error) { this.provider = null From b1a0286707378f5efb50e1165919be9446570ae9 Mon Sep 17 00:00:00 2001 From: aniket-engg Date: Tue, 22 Jun 2021 19:02:01 +0530 Subject: [PATCH 27/56] comments --- apps/remix-ide/src/app/tabs/hardhat-provider.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/remix-ide/src/app/tabs/hardhat-provider.js b/apps/remix-ide/src/app/tabs/hardhat-provider.js index 8c2cd0ae05..0676d199d3 100644 --- a/apps/remix-ide/src/app/tabs/hardhat-provider.js +++ b/apps/remix-ide/src/app/tabs/hardhat-provider.js @@ -39,13 +39,17 @@ export default class HardhatProvider extends Plugin { sendAsync (data) { return new Promise((resolve, reject) => { + // If provider is not set, allow to open modal only when provider is trying to connect if (!this.provider || data.method === 'net_listening') { modalDialogCustom.prompt('Hardhat node request', this.hardhatProviderDialogBody(), 'http://127.0.0.1:8545', (target) => { this.provider = new Web3.providers.HttpProvider(target) this.sendAsyncInternal(data, resolve, reject) }, () => { + // If 'cancel' is clicked while trying to connect, handle it in custom manner if (data.method === 'net_listening') resolve({ jsonrpc: '2.0', result: 'canceled', id: data.id }) else { + // When node is abruptly stopped, modal will appear + // On which clicking on 'Cancel' will set the Envrionment to VM this.blockchain.changeExecutionContext('vm') this.provider = this.blockchain.getCurrentProvider() reject(new Error('Connection canceled')) From 552324df22ef9fd31811f21a38c4117496f06365 Mon Sep 17 00:00:00 2001 From: aniket-engg Date: Tue, 22 Jun 2021 19:20:13 +0530 Subject: [PATCH 28/56] added info in modal --- apps/remix-ide/src/app/tabs/hardhat-provider.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/remix-ide/src/app/tabs/hardhat-provider.js b/apps/remix-ide/src/app/tabs/hardhat-provider.js index 0676d199d3..ec43d72ffc 100644 --- a/apps/remix-ide/src/app/tabs/hardhat-provider.js +++ b/apps/remix-ide/src/app/tabs/hardhat-provider.js @@ -32,12 +32,16 @@ export default class HardhatProvider extends Plugin {
For more info, visit: Hardhat Documentation

+ Note: Click on 'Cancel' if node is stopped. +

Hardhat JSON-RPC Endpoint
` } sendAsync (data) { + console.log('data in sendAsync-->', data) + console.log('provider in sendAsync-->', this.provider) return new Promise((resolve, reject) => { // If provider is not set, allow to open modal only when provider is trying to connect if (!this.provider || data.method === 'net_listening') { From 47117eda63fbe2be7325086ce825fc0c8f89b1d3 Mon Sep 17 00:00:00 2001 From: aniket-engg Date: Tue, 22 Jun 2021 19:22:01 +0530 Subject: [PATCH 29/56] consoles removed --- apps/remix-ide/src/app/tabs/hardhat-provider.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/remix-ide/src/app/tabs/hardhat-provider.js b/apps/remix-ide/src/app/tabs/hardhat-provider.js index ec43d72ffc..43fc613624 100644 --- a/apps/remix-ide/src/app/tabs/hardhat-provider.js +++ b/apps/remix-ide/src/app/tabs/hardhat-provider.js @@ -40,8 +40,6 @@ export default class HardhatProvider extends Plugin { } sendAsync (data) { - console.log('data in sendAsync-->', data) - console.log('provider in sendAsync-->', this.provider) return new Promise((resolve, reject) => { // If provider is not set, allow to open modal only when provider is trying to connect if (!this.provider || data.method === 'net_listening') { From c24b7e5926653c3ca7542aab97ee5dc0007a40d4 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 28 Jun 2021 16:29:16 +0200 Subject: [PATCH 30/56] temporarily block provider --- .../src/app/tabs/hardhat-provider.js | 22 +++++++++---------- apps/remix-ide/src/remixAppManager.js | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/apps/remix-ide/src/app/tabs/hardhat-provider.js b/apps/remix-ide/src/app/tabs/hardhat-provider.js index 43fc613624..fa99969d20 100644 --- a/apps/remix-ide/src/app/tabs/hardhat-provider.js +++ b/apps/remix-ide/src/app/tabs/hardhat-provider.js @@ -1,6 +1,7 @@ import * as packageJson from '../../../../../package.json' import { Plugin } from '@remixproject/engine' import Web3 from 'web3' +import toaster from '../ui/tooltip' const yo = require('yo-yo') const modalDialogCustom = require('../ui/modal-dialog-custom') @@ -17,11 +18,13 @@ export default class HardhatProvider extends Plugin { constructor (blockchain) { super(profile) this.provider = null + this.blocked = false // used to block any call when trying to recover after a failed connection. this.blockchain = blockchain } onDeactivation () { this.provider = null + this.blocked = false } hardhatProviderDialogBody () { @@ -41,21 +44,14 @@ export default class HardhatProvider extends Plugin { sendAsync (data) { return new Promise((resolve, reject) => { + if (this.blocked) return reject(new Error('provider temporarily blocked')) // If provider is not set, allow to open modal only when provider is trying to connect - if (!this.provider || data.method === 'net_listening') { + if (!this.provider) { modalDialogCustom.prompt('Hardhat node request', this.hardhatProviderDialogBody(), 'http://127.0.0.1:8545', (target) => { this.provider = new Web3.providers.HttpProvider(target) this.sendAsyncInternal(data, resolve, reject) }, () => { - // If 'cancel' is clicked while trying to connect, handle it in custom manner - if (data.method === 'net_listening') resolve({ jsonrpc: '2.0', result: 'canceled', id: data.id }) - else { - // When node is abruptly stopped, modal will appear - // On which clicking on 'Cancel' will set the Envrionment to VM - this.blockchain.changeExecutionContext('vm') - this.provider = this.blockchain.getCurrentProvider() - reject(new Error('Connection canceled')) - } + this.sendAsyncInternal(data, resolve, reject) }) } else { this.sendAsyncInternal(data, resolve, reject) @@ -68,9 +64,13 @@ export default class HardhatProvider extends Plugin { // Check the case where current environment is VM on UI and it still sends RPC requests // This will be displayed on UI tooltip as 'cannot get account list: Environment Updated !!' if (this.blockchain.getProvider() !== 'Hardhat Provider' && data.method !== 'net_listening') return reject(new Error('Environment Updated !!')) - this.provider[this.provider.sendAsync ? 'sendAsync' : 'send'](data, (error, message) => { + this.provider[this.provider.sendAsync ? 'sendAsync' : 'send'](data, async (error, message) => { if (error) { + this.blocked = true + modalDialogCustom.alert('Hardhat', `Error while connecting to the hardhat provider: ${error.message}`) + await this.call('udapp', 'setEnvironmentMode', 'vm') this.provider = null + setTimeout(_ => this.blocked = false, 1000) return reject(error) } resolve(message) diff --git a/apps/remix-ide/src/remixAppManager.js b/apps/remix-ide/src/remixAppManager.js index 26f684e432..45bc5a7421 100644 --- a/apps/remix-ide/src/remixAppManager.js +++ b/apps/remix-ide/src/remixAppManager.js @@ -14,7 +14,7 @@ const requiredModules = [ // services + layout views + system views const dependentModules = ['git', 'hardhat'] // module which shouldn't be manually activated (e.g git is activated by remixd) export function isNative (name) { - const nativePlugins = ['vyper', 'workshops', 'debugger', 'remixd', 'menuicons', 'solidity'] + const nativePlugins = ['vyper', 'workshops', 'debugger', 'remixd', 'menuicons', 'solidity', 'hardhat-provider'] return nativePlugins.includes(name) || requiredModules.includes(name) } From b4fde6a4364b86779449861de46c0d94357c52d9 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 29 Jun 2021 15:47:21 +0200 Subject: [PATCH 31/56] linting --- apps/remix-ide/src/app/tabs/hardhat-provider.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/remix-ide/src/app/tabs/hardhat-provider.js b/apps/remix-ide/src/app/tabs/hardhat-provider.js index fa99969d20..afcd72276a 100644 --- a/apps/remix-ide/src/app/tabs/hardhat-provider.js +++ b/apps/remix-ide/src/app/tabs/hardhat-provider.js @@ -1,7 +1,6 @@ import * as packageJson from '../../../../../package.json' import { Plugin } from '@remixproject/engine' import Web3 from 'web3' -import toaster from '../ui/tooltip' const yo = require('yo-yo') const modalDialogCustom = require('../ui/modal-dialog-custom') @@ -70,7 +69,7 @@ export default class HardhatProvider extends Plugin { modalDialogCustom.alert('Hardhat', `Error while connecting to the hardhat provider: ${error.message}`) await this.call('udapp', 'setEnvironmentMode', 'vm') this.provider = null - setTimeout(_ => this.blocked = false, 1000) + setTimeout(_ => { this.blocked = false }, 1000) return reject(error) } resolve(message) From cc35bf1cbd46ffb14ad5ec40dc2bb6a68e777b9e Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 29 Jun 2021 16:41:54 +0200 Subject: [PATCH 32/56] label & comment --- apps/remix-ide/src/app/tabs/hardhat-provider.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/remix-ide/src/app/tabs/hardhat-provider.js b/apps/remix-ide/src/app/tabs/hardhat-provider.js index afcd72276a..06d9459426 100644 --- a/apps/remix-ide/src/app/tabs/hardhat-provider.js +++ b/apps/remix-ide/src/app/tabs/hardhat-provider.js @@ -43,7 +43,7 @@ export default class HardhatProvider extends Plugin { sendAsync (data) { return new Promise((resolve, reject) => { - if (this.blocked) return reject(new Error('provider temporarily blocked')) + if (this.blocked) return reject(new Error('provider unable to connect')) // If provider is not set, allow to open modal only when provider is trying to connect if (!this.provider) { modalDialogCustom.prompt('Hardhat node request', this.hardhatProviderDialogBody(), 'http://127.0.0.1:8545', (target) => { @@ -66,10 +66,10 @@ export default class HardhatProvider extends Plugin { this.provider[this.provider.sendAsync ? 'sendAsync' : 'send'](data, async (error, message) => { if (error) { this.blocked = true - modalDialogCustom.alert('Hardhat', `Error while connecting to the hardhat provider: ${error.message}`) + modalDialogCustom.alert('Hardhat Provider', `Error while connecting to the hardhat provider: ${error.message}`) await this.call('udapp', 'setEnvironmentMode', 'vm') this.provider = null - setTimeout(_ => { this.blocked = false }, 1000) + setTimeout(_ => { this.blocked = false }, 1000) // we wait 1 second for letting remix to switch to vm return reject(error) } resolve(message) From 5631491b63f7a103b1dc9c10c4a7f04faa6186be Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Wed, 30 Jun 2021 12:03:24 +0530 Subject: [PATCH 33/56] Update hardhat-provider.js --- apps/remix-ide/src/app/tabs/hardhat-provider.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/remix-ide/src/app/tabs/hardhat-provider.js b/apps/remix-ide/src/app/tabs/hardhat-provider.js index 06d9459426..805bc37e08 100644 --- a/apps/remix-ide/src/app/tabs/hardhat-provider.js +++ b/apps/remix-ide/src/app/tabs/hardhat-provider.js @@ -34,8 +34,6 @@ export default class HardhatProvider extends Plugin {
For more info, visit: Hardhat Documentation

- Note: Click on 'Cancel' if node is stopped. -

Hardhat JSON-RPC Endpoint
` @@ -75,7 +73,8 @@ export default class HardhatProvider extends Plugin { resolve(message) }) } else { - resolve({ jsonrpc: '2.0', result: [], id: data.id }) + const result = data.method === 'net_listening' ? 'canceled' : [] + resolve({ jsonrpc: '2.0', result: result, id: data.id }) } } } From 444893180aeef64ac66d11881536dfcf4925248e Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 22 Jun 2021 14:27:13 +0200 Subject: [PATCH 34/56] improve loading opcodes --- .../debugger-ui/src/reducers/assembly-items.ts | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/libs/remix-ui/debugger-ui/src/reducers/assembly-items.ts b/libs/remix-ui/debugger-ui/src/reducers/assembly-items.ts index 4038cce2d9..35d428c667 100644 --- a/libs/remix-ui/debugger-ui/src/reducers/assembly-items.ts +++ b/libs/remix-ui/debugger-ui/src/reducers/assembly-items.ts @@ -20,6 +20,14 @@ export const initialState = { hasError: null } +const reducedOpcode = (opCodes) => { + const length = 50 + let bottom = opCodes.index - 10 + bottom = bottom < 0 ? 0 : bottom + const top = bottom + length + return { top, bottom, display: opCodes.code.slice(bottom, top) } +} + export const reducer = (state = initialState, action: Action) => { switch (action.type) { case 'FETCH_OPCODES_REQUEST': { @@ -34,16 +42,12 @@ export const reducer = (state = initialState, action: Action) => { const opCodes = action.payload.address === state.opCodes.address ? { ...state.opCodes, index: action.payload.index } : deepEqual(action.payload.code, state.opCodes.code) ? state.opCodes : action.payload - const top = opCodes.index - 3 > 0 ? opCodes.index - 3 : 0 - const bottom = opCodes.index + 4 < opCodes.code.length ? opCodes.index + 4 : opCodes.code.length - const display = opCodes.code.slice(top, bottom) + const reduced = reducedOpcode(opCodes) return { opCodes, - display, - index: display.findIndex(code => code === opCodes.code[opCodes.index]), - top, - bottom, + display: reduced.display, + index: reduced.display.findIndex(code => code === opCodes.code[opCodes.index]), isRequesting: false, isSuccessful: true, hasError: null From 84e0d3315f2066069099db5fa8c2745efddfb47a Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 23 Jun 2021 11:05:37 +0200 Subject: [PATCH 35/56] highlight the next opcode to be executed --- libs/remix-debug/src/code/codeManager.ts | 4 +- libs/remix-debug/src/debugger/VmDebugger.ts | 4 +- .../src/lib/vm-debugger/assembly-items.tsx | 56 ++++++++++++++++--- .../src/reducers/assembly-items.ts | 14 +++-- 4 files changed, 62 insertions(+), 16 deletions(-) diff --git a/libs/remix-debug/src/code/codeManager.ts b/libs/remix-debug/src/code/codeManager.ts index fff30cba15..b0f61a0a24 100644 --- a/libs/remix-debug/src/code/codeManager.ts +++ b/libs/remix-debug/src/code/codeManager.ts @@ -147,13 +147,15 @@ export class CodeManager { private retrieveIndexAndTrigger (codeMananger, address, step, code) { let result + let next try { result = codeMananger.getInstructionIndex(address, step) + next = codeMananger.getInstructionIndex(address, step + 1) } catch (error) { return console.log(error) } try { - codeMananger.event.trigger('changed', [code, address, result]) + codeMananger.event.trigger('changed', [code, address, result, next]) } catch (e) { console.log('dispatching event failed', e) } diff --git a/libs/remix-debug/src/debugger/VmDebugger.ts b/libs/remix-debug/src/debugger/VmDebugger.ts index 2a90d0ed2c..47ea75ea4b 100644 --- a/libs/remix-debug/src/debugger/VmDebugger.ts +++ b/libs/remix-debug/src/debugger/VmDebugger.ts @@ -59,8 +59,8 @@ export class VmDebuggerLogic { } listenToCodeManagerEvents () { - this._codeManager.event.register('changed', (code, address, index) => { - this.event.trigger('codeManagerChanged', [code, address, index]) + this._codeManager.event.register('changed', (code, address, index, nextIndex) => { + this.event.trigger('codeManagerChanged', [code, address, index, nextIndex]) }) } diff --git a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx index 67f9821960..debabf4ce1 100644 --- a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx +++ b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx @@ -4,24 +4,28 @@ import './styles/assembly-items.css' export const AssemblyItems = ({ registerEvent }) => { const [assemblyItems, dispatch] = useReducer(reducer, initialState) + const [absoluteSelectedIndex, setAbsoluteSelectedIndex] = useState(0) const [selectedItem, setSelectedItem] = useState(0) + const [nextSelectedItem, setNextSelectedItem] = useState(1) const refs = useRef({}) const asmItemsRef = useRef(null) useEffect(() => { - registerEvent && registerEvent('codeManagerChanged', (code, address, index) => { - dispatch({ type: 'FETCH_OPCODES_SUCCESS', payload: { code, address, index } }) + registerEvent && registerEvent('codeManagerChanged', (code, address, index, nextIndex) => { + dispatch({ type: 'FETCH_OPCODES_SUCCESS', payload: { code, address, index, nextIndex } }) }) }, []) useEffect(() => { - if (selectedItem !== assemblyItems.index) { + console.log('useEffect', assemblyItems.index) + if (absoluteSelectedIndex !== assemblyItems.index) { + clearItems() indexChanged(assemblyItems.index) + nextIndexChanged(assemblyItems.nextIndex) } - }, [assemblyItems.index]) + }, [assemblyItems.opCodes.index]) - const indexChanged = (index: number) => { - if (index < 0) return + const clearItems = () => { let currentItem = refs.current[selectedItem] ? refs.current[selectedItem] : null if (currentItem) { @@ -30,15 +34,49 @@ export const AssemblyItems = ({ registerEvent }) => { if (currentItem.firstChild) { currentItem.firstChild.removeAttribute('style') } - const codeView = asmItemsRef.current + } - currentItem = codeView.children[index] + currentItem = refs.current[nextSelectedItem] ? refs.current[nextSelectedItem] : null + + if (currentItem) { + currentItem.removeAttribute('selected') + currentItem.removeAttribute('style') + if (currentItem.firstChild) { + currentItem.firstChild.removeAttribute('style') + } + } + } + + const indexChanged = (index: number) => { + console.log("index " + index) + if (index < 0) return + + const codeView = asmItemsRef.current + + const currentItem = codeView.children[index] + if (currentItem) { currentItem.style.setProperty('border-color', 'var(--primary)') currentItem.style.setProperty('border-style', 'solid') currentItem.setAttribute('selected', 'selected') codeView.scrollTop = currentItem.offsetTop - parseInt(codeView.offsetTop) - setSelectedItem(index) } + + setSelectedItem(index) + setAbsoluteSelectedIndex(assemblyItems.opCodes.index) + } + + const nextIndexChanged = (index: number) => { + if (index < 0) return + + const codeView = asmItemsRef.current + + const currentItem = codeView.children[index] + if (currentItem) { + currentItem.style.setProperty('border-color', 'var(--secondary)') + currentItem.style.setProperty('border-style', 'dotted') + currentItem.setAttribute('selected', 'selected') + } + setNextSelectedItem(index) } return ( diff --git a/libs/remix-ui/debugger-ui/src/reducers/assembly-items.ts b/libs/remix-ui/debugger-ui/src/reducers/assembly-items.ts index 35d428c667..ff6fe23b40 100644 --- a/libs/remix-ui/debugger-ui/src/reducers/assembly-items.ts +++ b/libs/remix-ui/debugger-ui/src/reducers/assembly-items.ts @@ -13,6 +13,7 @@ export const initialState = { }, display: [], index: 0, + nextIndex: -1, top: 0, bottom: 0, isRequesting: false, @@ -21,11 +22,15 @@ export const initialState = { } const reducedOpcode = (opCodes) => { - const length = 50 + const length = 100 let bottom = opCodes.index - 10 bottom = bottom < 0 ? 0 : bottom const top = bottom + length - return { top, bottom, display: opCodes.code.slice(bottom, top) } + return { + index: opCodes.index - bottom, + nextIndex:opCodes.nextIndex - bottom, + display: opCodes.code.slice(bottom, top) + } } export const reducer = (state = initialState, action: Action) => { @@ -40,14 +45,15 @@ export const reducer = (state = initialState, action: Action) => { } case 'FETCH_OPCODES_SUCCESS': { const opCodes = action.payload.address === state.opCodes.address ? { - ...state.opCodes, index: action.payload.index + ...state.opCodes, index: action.payload.index, nextIndex: action.payload.nextIndex } : deepEqual(action.payload.code, state.opCodes.code) ? state.opCodes : action.payload const reduced = reducedOpcode(opCodes) return { opCodes, display: reduced.display, - index: reduced.display.findIndex(code => code === opCodes.code[opCodes.index]), + index: reduced.index, + nextIndex: reduced.nextIndex, isRequesting: false, isSuccessful: true, hasError: null From 3ef6c2a9b80ae8db7a5e8f382f59d24728544dbc Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 23 Jun 2021 11:13:26 +0200 Subject: [PATCH 36/56] linting --- .../debugger-ui/src/lib/vm-debugger/assembly-items.tsx | 10 +++++----- .../debugger-ui/src/reducers/assembly-items.ts | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx index debabf4ce1..248e4be9cc 100644 --- a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx +++ b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx @@ -48,9 +48,9 @@ export const AssemblyItems = ({ registerEvent }) => { } const indexChanged = (index: number) => { - console.log("index " + index) + console.log('index ' + index) if (index < 0) return - + const codeView = asmItemsRef.current const currentItem = codeView.children[index] @@ -60,21 +60,21 @@ export const AssemblyItems = ({ registerEvent }) => { currentItem.setAttribute('selected', 'selected') codeView.scrollTop = currentItem.offsetTop - parseInt(codeView.offsetTop) } - + setSelectedItem(index) setAbsoluteSelectedIndex(assemblyItems.opCodes.index) } const nextIndexChanged = (index: number) => { if (index < 0) return - + const codeView = asmItemsRef.current const currentItem = codeView.children[index] if (currentItem) { currentItem.style.setProperty('border-color', 'var(--secondary)') currentItem.style.setProperty('border-style', 'dotted') - currentItem.setAttribute('selected', 'selected') + currentItem.setAttribute('selected', 'selected') } setNextSelectedItem(index) } diff --git a/libs/remix-ui/debugger-ui/src/reducers/assembly-items.ts b/libs/remix-ui/debugger-ui/src/reducers/assembly-items.ts index ff6fe23b40..bc9ea96580 100644 --- a/libs/remix-ui/debugger-ui/src/reducers/assembly-items.ts +++ b/libs/remix-ui/debugger-ui/src/reducers/assembly-items.ts @@ -26,10 +26,10 @@ const reducedOpcode = (opCodes) => { let bottom = opCodes.index - 10 bottom = bottom < 0 ? 0 : bottom const top = bottom + length - return { + return { index: opCodes.index - bottom, - nextIndex:opCodes.nextIndex - bottom, - display: opCodes.code.slice(bottom, top) + nextIndex: opCodes.nextIndex - bottom, + display: opCodes.code.slice(bottom, top) } } From 59e8169a8abe24d935a903e587a59b024f8bb7c2 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 23 Jun 2021 11:18:27 +0200 Subject: [PATCH 37/56] add css style --- libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx b/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx index af3648aa90..7adc8a9312 100644 --- a/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx +++ b/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx @@ -274,7 +274,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => {

Debugger Configuration

-
+
{ setState(prevState => { return { ...prevState, opt: { debugWithGeneratedSources: checked } } From 0fd5334f473f7afa545169b29916901fda71c05b Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 23 Jun 2021 23:11:37 +0200 Subject: [PATCH 38/56] keep track of stop/revert/return indexes and outofgad indexes --- libs/remix-debug/src/code/codeManager.ts | 30 ++++++-- libs/remix-debug/src/debugger/VmDebugger.ts | 4 +- libs/remix-debug/src/trace/traceAnalyser.ts | 11 +++ libs/remix-debug/src/trace/traceCache.ts | 14 +++- libs/remix-debug/src/trace/traceManager.ts | 8 +++ .../src/web3Provider/web3VmProvider.ts | 2 +- .../src/lib/vm-debugger/assembly-items.tsx | 69 ++++++++++++++++++- .../src/reducers/assembly-items.ts | 14 ++-- 8 files changed, 136 insertions(+), 16 deletions(-) diff --git a/libs/remix-debug/src/code/codeManager.ts b/libs/remix-debug/src/code/codeManager.ts index b0f61a0a24..fb04f64945 100644 --- a/libs/remix-debug/src/code/codeManager.ts +++ b/libs/remix-debug/src/code/codeManager.ts @@ -145,17 +145,37 @@ export class CodeManager { }) } - private retrieveIndexAndTrigger (codeMananger, address, step, code) { + private async retrieveIndexAndTrigger (codeMananger, address, step, code) { let result let next + let returnInstructionIndexes = [] + let outOfGasInstructionIndexes = [] + try { result = codeMananger.getInstructionIndex(address, step) next = codeMananger.getInstructionIndex(address, step + 1) - } catch (error) { - return console.log(error) - } + + let values = this.traceManager.getAllStopIndexes() + values = values.filter((value) => value.address === address) + if (values) { + for (const value of values) { + returnInstructionIndexes.push({ instructionIndex: this.getInstructionIndex(address, value.index), address }) + } + } + + values = this.traceManager.getAllOutofGasIndexes() + values = values.filter((value) => value.address === address) + if (values) { + for (const value of values) { + outOfGasInstructionIndexes.push({ instructionIndex: this.getInstructionIndex(address, value.index), address }) + } + } + + } catch (error) { + return console.log(error) + } try { - codeMananger.event.trigger('changed', [code, address, result, next]) + codeMananger.event.trigger('changed', [code, address, result, next, returnInstructionIndexes, outOfGasInstructionIndexes]) } catch (e) { console.log('dispatching event failed', e) } diff --git a/libs/remix-debug/src/debugger/VmDebugger.ts b/libs/remix-debug/src/debugger/VmDebugger.ts index 47ea75ea4b..72a131cfd6 100644 --- a/libs/remix-debug/src/debugger/VmDebugger.ts +++ b/libs/remix-debug/src/debugger/VmDebugger.ts @@ -59,8 +59,8 @@ export class VmDebuggerLogic { } listenToCodeManagerEvents () { - this._codeManager.event.register('changed', (code, address, index, nextIndex) => { - this.event.trigger('codeManagerChanged', [code, address, index, nextIndex]) + this._codeManager.event.register('changed', (code, address, index, nextIndex, returnInstructionIndexes, outOfGasInstructionIndexes) => { + this.event.trigger('codeManagerChanged', [code, address, index, nextIndex, returnInstructionIndexes, outOfGasInstructionIndexes]) }) } diff --git a/libs/remix-debug/src/trace/traceAnalyser.ts b/libs/remix-debug/src/trace/traceAnalyser.ts index ae8957b5ac..ba66f2dbb1 100644 --- a/libs/remix-debug/src/trace/traceAnalyser.ts +++ b/libs/remix-debug/src/trace/traceAnalyser.ts @@ -49,6 +49,17 @@ export class TraceAnalyser { this.traceCache.pushReturnValue(index, returnParamsObj) } + if (traceHelper.isReturnInstruction(step) || traceHelper.isStopInstruction(step) || traceHelper.isRevertInstruction(step)) { + this.traceCache.pushStopIndex(index, this.traceCache.currentCall.call.address) + } + + try { + if (parseInt(step.gas) - parseInt(step.gasCost) <= 0 || step.error === 'OutOfGas') { + this.traceCache.pushOutOfGasIndex(index, this.traceCache.currentCall.call.address) + } + } catch (e) { + console.error(e) + } } buildCalldata (index, step, tx, newContext) { diff --git a/libs/remix-debug/src/trace/traceCache.ts b/libs/remix-debug/src/trace/traceCache.ts index 7c2d381ccc..411e8e617c 100644 --- a/libs/remix-debug/src/trace/traceCache.ts +++ b/libs/remix-debug/src/trace/traceCache.ts @@ -5,6 +5,8 @@ const { sha3_256 } = util export class TraceCache { returnValues + stopIndexes + outofgasIndexes currentCall callsTree callsData @@ -24,6 +26,8 @@ export class TraceCache { // ...Changes contains index in the vmtrace of the corresponding changes this.returnValues = {} + this.stopIndexes = [] + this.outofgasIndexes = [] this.currentCall = null this.callsTree = null this.callsData = {} @@ -59,7 +63,7 @@ export class TraceCache { this.currentCall.call.reverted = reverted } var parent = this.currentCall.parent - this.currentCall = parent ? { call: parent.call, parent: parent.parent } : null + if (parent) this.currentCall = { call: parent.call, parent: parent.parent } return } const call = { @@ -78,6 +82,14 @@ export class TraceCache { this.currentCall = { call: call, parent: this.currentCall } } + pushOutOfGasIndex (index, address) { + this.outofgasIndexes.push({ index, address }) + } + + pushStopIndex (index, address) { + this.stopIndexes.push({ index, address }) + } + pushReturnValue (step, value) { this.returnValues[step] = value } diff --git a/libs/remix-debug/src/trace/traceManager.ts b/libs/remix-debug/src/trace/traceManager.ts index 8e78782922..848b3c57aa 100644 --- a/libs/remix-debug/src/trace/traceManager.ts +++ b/libs/remix-debug/src/trace/traceManager.ts @@ -209,6 +209,14 @@ export class TraceManager { return this.trace[stepIndex].pc } + getAllStopIndexes () { + return this.traceCache.stopIndexes + } + + getAllOutofGasIndexes () { + return this.traceCache.outofgasIndexes + } + getReturnValue (stepIndex) { try { this.checkRequestedStep(stepIndex) diff --git a/libs/remix-lib/src/web3Provider/web3VmProvider.ts b/libs/remix-lib/src/web3Provider/web3VmProvider.ts index 59b0e7e909..b5d8ea4732 100644 --- a/libs/remix-lib/src/web3Provider/web3VmProvider.ts +++ b/libs/remix-lib/src/web3Provider/web3VmProvider.ts @@ -138,7 +138,7 @@ export class Web3VmProvider { async txProcessed (data) { const lastOp = this.vmTraces[this.processingHash].structLogs[this.processingIndex - 1] if (lastOp) { - lastOp.error = lastOp.op !== 'RETURN' && lastOp.op !== 'STOP' && lastOp.op !== 'thisDESTRUCT' + lastOp.error = lastOp.op !== 'RETURN' && lastOp.op !== 'STOP' && lastOp.op !== 'DESTRUCT' } this.vmTraces[this.processingHash].gas = '0x' + data.gasUsed.toString(16) diff --git a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx index 248e4be9cc..de9c37e1bc 100644 --- a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx +++ b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx @@ -7,12 +7,14 @@ export const AssemblyItems = ({ registerEvent }) => { const [absoluteSelectedIndex, setAbsoluteSelectedIndex] = useState(0) const [selectedItem, setSelectedItem] = useState(0) const [nextSelectedItem, setNextSelectedItem] = useState(1) + const [returnInstructionIndexes, setReturnInstructionIndexes] = useState([]) + const [outOfGasInstructionIndexes, setOutOfGasInstructionIndexes] = useState([]) const refs = useRef({}) const asmItemsRef = useRef(null) useEffect(() => { - registerEvent && registerEvent('codeManagerChanged', (code, address, index, nextIndex) => { - dispatch({ type: 'FETCH_OPCODES_SUCCESS', payload: { code, address, index, nextIndex } }) + registerEvent && registerEvent('codeManagerChanged', (code, address, index, nextIndex, returnInstructionIndexes, outOfGasInstructionIndexes) => { + dispatch({ type: 'FETCH_OPCODES_SUCCESS', payload: { code, address, index, nextIndex, returnInstructionIndexes, outOfGasInstructionIndexes } }) }) }, []) @@ -22,6 +24,8 @@ export const AssemblyItems = ({ registerEvent }) => { clearItems() indexChanged(assemblyItems.index) nextIndexChanged(assemblyItems.nextIndex) + returnIndexes(assemblyItems.returnInstructionIndexes) + outOfGasIndexes(assemblyItems.outOfGasInstructionIndexes) } }, [assemblyItems.opCodes.index]) @@ -45,10 +49,37 @@ export const AssemblyItems = ({ registerEvent }) => { currentItem.firstChild.removeAttribute('style') } } + + returnInstructionIndexes.map((index) => { + if (index < 0) return + + currentItem = refs.current[index] ? refs.current[index] : null + + if (currentItem) { + currentItem.removeAttribute('selected') + currentItem.removeAttribute('style') + if (currentItem.firstChild) { + currentItem.firstChild.removeAttribute('style') + } + } + }) + + outOfGasInstructionIndexes.map((index) => { + if (index < 0) return + + currentItem = refs.current[index] ? refs.current[index] : null + + if (currentItem) { + currentItem.removeAttribute('selected') + currentItem.removeAttribute('style') + if (currentItem.firstChild) { + currentItem.firstChild.removeAttribute('style') + } + } + }) } const indexChanged = (index: number) => { - console.log('index ' + index) if (index < 0) return const codeView = asmItemsRef.current @@ -79,6 +110,38 @@ export const AssemblyItems = ({ registerEvent }) => { setNextSelectedItem(index) } + const returnIndexes = (indexes) => { + indexes.map((index) => { + if (index < 0) return + + const codeView = asmItemsRef.current + + const currentItem = codeView.children[index] + if (currentItem) { + currentItem.style.setProperty('border-color', 'var(--warning)') + currentItem.style.setProperty('border-style', 'dotted') + currentItem.setAttribute('selected', 'selected') + } + }) + setReturnInstructionIndexes(indexes) + } + + const outOfGasIndexes = (indexes) => { + indexes.map((index) => { + if (index < 0) return + + const codeView = asmItemsRef.current + + const currentItem = codeView.children[index] + if (currentItem) { + currentItem.style.setProperty('border-color', 'var(--danger)') + currentItem.style.setProperty('border-style', 'dotted') + currentItem.setAttribute('selected', 'selected') + } + }) + setOutOfGasInstructionIndexes(indexes) + } + return (
diff --git a/libs/remix-ui/debugger-ui/src/reducers/assembly-items.ts b/libs/remix-ui/debugger-ui/src/reducers/assembly-items.ts index bc9ea96580..d5a936bc95 100644 --- a/libs/remix-ui/debugger-ui/src/reducers/assembly-items.ts +++ b/libs/remix-ui/debugger-ui/src/reducers/assembly-items.ts @@ -14,6 +14,8 @@ export const initialState = { display: [], index: 0, nextIndex: -1, + returnInstructionIndexes: [], + outOfGasInstructionIndexes: [], top: 0, bottom: 0, isRequesting: false, @@ -21,7 +23,7 @@ export const initialState = { hasError: null } -const reducedOpcode = (opCodes) => { +const reducedOpcode = (opCodes, payload) => { const length = 100 let bottom = opCodes.index - 10 bottom = bottom < 0 ? 0 : bottom @@ -29,7 +31,9 @@ const reducedOpcode = (opCodes) => { return { index: opCodes.index - bottom, nextIndex: opCodes.nextIndex - bottom, - display: opCodes.code.slice(bottom, top) + display: opCodes.code.slice(bottom, top), + returnInstructionIndexes: payload.returnInstructionIndexes.map((index) => index.instructionIndex - bottom ), + outOfGasInstructionIndexes: payload.outOfGasInstructionIndexes.map((index) => index.instructionIndex - bottom ) } } @@ -48,7 +52,7 @@ export const reducer = (state = initialState, action: Action) => { ...state.opCodes, index: action.payload.index, nextIndex: action.payload.nextIndex } : deepEqual(action.payload.code, state.opCodes.code) ? state.opCodes : action.payload - const reduced = reducedOpcode(opCodes) + const reduced = reducedOpcode(opCodes, action.payload) return { opCodes, display: reduced.display, @@ -56,7 +60,9 @@ export const reducer = (state = initialState, action: Action) => { nextIndex: reduced.nextIndex, isRequesting: false, isSuccessful: true, - hasError: null + hasError: null, + returnInstructionIndexes: reduced.returnInstructionIndexes, + outOfGasInstructionIndexes: reduced.outOfGasInstructionIndexes } } case 'FETCH_OPCODES_ERROR': { From c0bd3883050dc575cb7735df5dad6e057f9830e9 Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 24 Jun 2021 09:01:55 +0200 Subject: [PATCH 39/56] linting --- libs/remix-debug/src/code/codeManager.ts | 11 +++++------ libs/remix-debug/src/trace/traceAnalyser.ts | 4 ++-- .../debugger-ui/src/reducers/assembly-items.ts | 4 ++-- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/libs/remix-debug/src/code/codeManager.ts b/libs/remix-debug/src/code/codeManager.ts index fb04f64945..207f3e0510 100644 --- a/libs/remix-debug/src/code/codeManager.ts +++ b/libs/remix-debug/src/code/codeManager.ts @@ -148,8 +148,8 @@ export class CodeManager { private async retrieveIndexAndTrigger (codeMananger, address, step, code) { let result let next - let returnInstructionIndexes = [] - let outOfGasInstructionIndexes = [] + const returnInstructionIndexes = [] + const outOfGasInstructionIndexes = [] try { result = codeMananger.getInstructionIndex(address, step) @@ -170,10 +170,9 @@ export class CodeManager { outOfGasInstructionIndexes.push({ instructionIndex: this.getInstructionIndex(address, value.index), address }) } } - - } catch (error) { - return console.log(error) - } + } catch (error) { + return console.log(error) + } try { codeMananger.event.trigger('changed', [code, address, result, next, returnInstructionIndexes, outOfGasInstructionIndexes]) } catch (e) { diff --git a/libs/remix-debug/src/trace/traceAnalyser.ts b/libs/remix-debug/src/trace/traceAnalyser.ts index ba66f2dbb1..74651b228d 100644 --- a/libs/remix-debug/src/trace/traceAnalyser.ts +++ b/libs/remix-debug/src/trace/traceAnalyser.ts @@ -52,14 +52,14 @@ export class TraceAnalyser { if (traceHelper.isReturnInstruction(step) || traceHelper.isStopInstruction(step) || traceHelper.isRevertInstruction(step)) { this.traceCache.pushStopIndex(index, this.traceCache.currentCall.call.address) } - + try { if (parseInt(step.gas) - parseInt(step.gasCost) <= 0 || step.error === 'OutOfGas') { this.traceCache.pushOutOfGasIndex(index, this.traceCache.currentCall.call.address) } } catch (e) { console.error(e) - } + } } buildCalldata (index, step, tx, newContext) { diff --git a/libs/remix-ui/debugger-ui/src/reducers/assembly-items.ts b/libs/remix-ui/debugger-ui/src/reducers/assembly-items.ts index d5a936bc95..18622bfa68 100644 --- a/libs/remix-ui/debugger-ui/src/reducers/assembly-items.ts +++ b/libs/remix-ui/debugger-ui/src/reducers/assembly-items.ts @@ -32,8 +32,8 @@ const reducedOpcode = (opCodes, payload) => { index: opCodes.index - bottom, nextIndex: opCodes.nextIndex - bottom, display: opCodes.code.slice(bottom, top), - returnInstructionIndexes: payload.returnInstructionIndexes.map((index) => index.instructionIndex - bottom ), - outOfGasInstructionIndexes: payload.outOfGasInstructionIndexes.map((index) => index.instructionIndex - bottom ) + returnInstructionIndexes: payload.returnInstructionIndexes.map((index) => index.instructionIndex - bottom), + outOfGasInstructionIndexes: payload.outOfGasInstructionIndexes.map((index) => index.instructionIndex - bottom) } } From b78ff327ccbb83bf1d7f91a9bd8e3498318b9690 Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 24 Jun 2021 14:37:50 +0200 Subject: [PATCH 40/56] remove unneeded loop --- libs/remix-debug/src/code/codeManager.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libs/remix-debug/src/code/codeManager.ts b/libs/remix-debug/src/code/codeManager.ts index 207f3e0510..390c988eed 100644 --- a/libs/remix-debug/src/code/codeManager.ts +++ b/libs/remix-debug/src/code/codeManager.ts @@ -156,18 +156,20 @@ export class CodeManager { next = codeMananger.getInstructionIndex(address, step + 1) let values = this.traceManager.getAllStopIndexes() - values = values.filter((value) => value.address === address) if (values) { for (const value of values) { - returnInstructionIndexes.push({ instructionIndex: this.getInstructionIndex(address, value.index), address }) + if (value.address === address) { + returnInstructionIndexes.push({ instructionIndex: this.getInstructionIndex(address, value.index), address }) + } } } values = this.traceManager.getAllOutofGasIndexes() - values = values.filter((value) => value.address === address) if (values) { for (const value of values) { - outOfGasInstructionIndexes.push({ instructionIndex: this.getInstructionIndex(address, value.index), address }) + if (value.address === address) { + outOfGasInstructionIndexes.push({ instructionIndex: this.getInstructionIndex(address, value.index), address }) + } } } } catch (error) { From f8989c663f95fb293a9b46e8ff95021162167a34 Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 24 Jun 2021 14:38:25 +0200 Subject: [PATCH 41/56] remove console.log --- libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx index de9c37e1bc..3f1a4c5235 100644 --- a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx +++ b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx @@ -19,7 +19,6 @@ export const AssemblyItems = ({ registerEvent }) => { }, []) useEffect(() => { - console.log('useEffect', assemblyItems.index) if (absoluteSelectedIndex !== assemblyItems.index) { clearItems() indexChanged(assemblyItems.index) From 3959e1bb5768be091cb59aafae0b815a28d6e3ee Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 24 Jun 2021 14:42:14 +0200 Subject: [PATCH 42/56] refactor --- .../src/lib/vm-debugger/assembly-items.tsx | 41 ++++--------------- 1 file changed, 8 insertions(+), 33 deletions(-) diff --git a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx index 3f1a4c5235..af6c061e6c 100644 --- a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx +++ b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx @@ -28,19 +28,7 @@ export const AssemblyItems = ({ registerEvent }) => { } }, [assemblyItems.opCodes.index]) - const clearItems = () => { - let currentItem = refs.current[selectedItem] ? refs.current[selectedItem] : null - - if (currentItem) { - currentItem.removeAttribute('selected') - currentItem.removeAttribute('style') - if (currentItem.firstChild) { - currentItem.firstChild.removeAttribute('style') - } - } - - currentItem = refs.current[nextSelectedItem] ? refs.current[nextSelectedItem] : null - + let clearItem = (currentItem) => { if (currentItem) { currentItem.removeAttribute('selected') currentItem.removeAttribute('style') @@ -48,33 +36,20 @@ export const AssemblyItems = ({ registerEvent }) => { currentItem.firstChild.removeAttribute('style') } } + } + const clearItems = () => { + clearItem(refs.current[selectedItem] ? refs.current[selectedItem] : null) + clearItem(refs.current[nextSelectedItem] ? refs.current[nextSelectedItem] : null) + returnInstructionIndexes.map((index) => { if (index < 0) return - - currentItem = refs.current[index] ? refs.current[index] : null - - if (currentItem) { - currentItem.removeAttribute('selected') - currentItem.removeAttribute('style') - if (currentItem.firstChild) { - currentItem.firstChild.removeAttribute('style') - } - } + clearItem(refs.current[index] ? refs.current[index] : null) }) outOfGasInstructionIndexes.map((index) => { if (index < 0) return - - currentItem = refs.current[index] ? refs.current[index] : null - - if (currentItem) { - currentItem.removeAttribute('selected') - currentItem.removeAttribute('style') - if (currentItem.firstChild) { - currentItem.firstChild.removeAttribute('style') - } - } + clearItem(refs.current[index] ? refs.current[index] : null) }) } From 5086d96cecc9d8dd03f36e3b5737cd94329938b1 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 29 Jun 2021 15:07:20 +0200 Subject: [PATCH 43/56] linting --- libs/remix-debug/src/code/codeManager.ts | 4 ++-- .../debugger-ui/src/lib/vm-debugger/assembly-items.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/remix-debug/src/code/codeManager.ts b/libs/remix-debug/src/code/codeManager.ts index 390c988eed..f0b38ea3d9 100644 --- a/libs/remix-debug/src/code/codeManager.ts +++ b/libs/remix-debug/src/code/codeManager.ts @@ -159,7 +159,7 @@ export class CodeManager { if (values) { for (const value of values) { if (value.address === address) { - returnInstructionIndexes.push({ instructionIndex: this.getInstructionIndex(address, value.index), address }) + returnInstructionIndexes.push({ instructionIndex: this.getInstructionIndex(address, value.index), address }) } } } @@ -168,7 +168,7 @@ export class CodeManager { if (values) { for (const value of values) { if (value.address === address) { - outOfGasInstructionIndexes.push({ instructionIndex: this.getInstructionIndex(address, value.index), address }) + outOfGasInstructionIndexes.push({ instructionIndex: this.getInstructionIndex(address, value.index), address }) } } } diff --git a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx index af6c061e6c..8b0ed07d9c 100644 --- a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx +++ b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx @@ -28,7 +28,7 @@ export const AssemblyItems = ({ registerEvent }) => { } }, [assemblyItems.opCodes.index]) - let clearItem = (currentItem) => { + const clearItem = (currentItem) => { if (currentItem) { currentItem.removeAttribute('selected') currentItem.removeAttribute('style') @@ -41,7 +41,7 @@ export const AssemblyItems = ({ registerEvent }) => { const clearItems = () => { clearItem(refs.current[selectedItem] ? refs.current[selectedItem] : null) clearItem(refs.current[nextSelectedItem] ? refs.current[nextSelectedItem] : null) - + returnInstructionIndexes.map((index) => { if (index < 0) return clearItem(refs.current[index] ? refs.current[index] : null) From 857d47591878a97c01aa1a3ca655eb495a1ebb69 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 30 Jun 2021 16:52:09 +0200 Subject: [PATCH 44/56] change font style --- .../debugger-ui/src/lib/vm-debugger/assembly-items.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx index 8b0ed07d9c..1606ce8491 100644 --- a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx +++ b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx @@ -60,8 +60,8 @@ export const AssemblyItems = ({ registerEvent }) => { const currentItem = codeView.children[index] if (currentItem) { - currentItem.style.setProperty('border-color', 'var(--primary)') - currentItem.style.setProperty('border-style', 'solid') + currentItem.style.setProperty('background-color', 'var(--primary)') + currentItem.style.setProperty('color', 'var(--light)') currentItem.setAttribute('selected', 'selected') codeView.scrollTop = currentItem.offsetTop - parseInt(codeView.offsetTop) } From dcefec4a7deb02ef07d05677aa7a778159dc4b7d Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 30 Jun 2021 21:38:46 +0200 Subject: [PATCH 45/56] fix e2e --- apps/remix-ide-e2e/src/tests/pluginManager.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/remix-ide-e2e/src/tests/pluginManager.spec.ts b/apps/remix-ide-e2e/src/tests/pluginManager.spec.ts index bd2884e4e5..f87bf1269e 100644 --- a/apps/remix-ide-e2e/src/tests/pluginManager.spec.ts +++ b/apps/remix-ide-e2e/src/tests/pluginManager.spec.ts @@ -5,7 +5,7 @@ import init from '../helpers/init' const testData = { pluginName: 'remixIde', pluginDisplayName: 'Remix IDE', - pluginUrl: 'https://zokrates-remix-plugin.netlify.app/' + pluginUrl: 'https://zokrates.github.io/zokrates-remix-plugin/' } module.exports = { From 3658c29a6d52cc3d77c2e1defd6d4efcc4671729 Mon Sep 17 00:00:00 2001 From: tizah Date: Thu, 1 Jul 2021 13:13:58 +0100 Subject: [PATCH 46/56] fixing editor issue --- libs/remix-ui/settings/src/lib/remix-ui-settings.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/remix-ui/settings/src/lib/remix-ui-settings.tsx b/libs/remix-ui/settings/src/lib/remix-ui-settings.tsx index ef8c3ed6c5..7af4eb4da2 100644 --- a/libs/remix-ui/settings/src/lib/remix-ui-settings.tsx +++ b/libs/remix-ui/settings/src/lib/remix-ui-settings.tsx @@ -22,6 +22,7 @@ export const RemixUiSettings = (props: RemixUiSettingsProps) => { const [themeName, setThemeName] = useState('') useEffect(() => { + props._deps.themeModule.switchTheme() const token = props.config.get('settings/gist-access-token') if (token === undefined) { props.config.set('settings/generate-contract-metadata', true) @@ -140,7 +141,7 @@ export const RemixUiSettings = (props: RemixUiSettingsProps) => { if (themes) { return themes.map((aTheme, index) => (
- { onswitchTheme(event, aTheme.name) }} className="align-middle custom-control-input" name='theme' id={aTheme.name} data-id={`settingsTabTheme${aTheme.name}`} checked = {props._deps.themeModule.active === aTheme.name ? true : null}/> + { onswitchTheme(event, aTheme.name) }} className="align-middle custom-control-input" name='theme' id={aTheme.name} data-id={`settingsTabTheme${aTheme.name}`} checked = {props._deps.themeModule.active === aTheme.name }/>
) From cc695fa9dcc771a2e83eef734db8433df844135c Mon Sep 17 00:00:00 2001 From: filip mertens Date: Fri, 14 May 2021 10:49:05 +0200 Subject: [PATCH 47/56] added customactions rm event --- apps/remix-ide/src/app/panels/file-panel.js | 16 ++++++++++++++-- .../src/lib/file-explorer-context-menu.tsx | 3 ++- .../file-explorer/src/lib/file-explorer.tsx | 5 +++-- .../file-explorer/src/lib/types/index.ts | 4 +++- package.json | 3 +-- 5 files changed, 23 insertions(+), 8 deletions(-) diff --git a/apps/remix-ide/src/app/panels/file-panel.js b/apps/remix-ide/src/app/panels/file-panel.js index 82177860d3..09d697acea 100644 --- a/apps/remix-ide/src/app/panels/file-panel.js +++ b/apps/remix-ide/src/app/panels/file-panel.js @@ -34,7 +34,7 @@ const modalDialogCustom = require('../ui/modal-dialog-custom') const profile = { name: 'filePanel', displayName: 'File explorers', - methods: ['createNewFile', 'uploadFile', 'getCurrentWorkspace', 'getWorkspaces', 'createWorkspace', 'setWorkspace'], + methods: ['createNewFile', 'uploadFile', 'getCurrentWorkspace', 'getWorkspaces', 'createWorkspace', 'registerContextMenuItem', 'setWorkspace'], events: ['setWorkspace', 'renameWorkspace', 'deleteWorkspace', 'createWorkspace'], icon: 'assets/img/fileManager.webp', description: ' - ', @@ -63,6 +63,7 @@ module.exports = class Filepanel extends ViewPlugin { this.request = {} this.workspaces = [] this.initialWorkspace = null + this.appManager = appManager } render () { @@ -101,11 +102,19 @@ module.exports = class Filepanel extends ViewPlugin { if (!item) throw new Error('Invalid register context menu argument') if (!item.name || !item.id) throw new Error('Item name and id is mandatory') if (!item.type && !item.path && !item.extension && !item.pattern) throw new Error('Invalid file matching criteria provided') - + if (this.registeredMenuItems.filter((o) => { + return o.id === item.id & o.name === item.name + }).length) throw new Error(`Action ${item.name} already exists on ${item.id}`) this.registeredMenuItems = [...this.registeredMenuItems, item] this.renderComponent() } + removePluginActions (plugin) { + this.registeredMenuItems = this.registeredMenuItems.filter((item) => { + return item.id !== plugin.name + }) + } + async getCurrentWorkspace () { return await this.request.getCurrentWorkspace() } @@ -185,6 +194,9 @@ module.exports = class Filepanel extends ViewPlugin { } }) }) + + const self = this + this.appManager.on('manager', 'pluginDeactivated', self.removePluginActions.bind(this)) } async createNewFile () { diff --git a/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx b/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx index c049a93a65..69bdac6f2c 100644 --- a/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx +++ b/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx @@ -2,6 +2,7 @@ import React, { useRef, useEffect } from 'react' // eslint-disable-line import { action, FileExplorerContextMenuProps } from './types' import './css/file-explorer-context-menu.css' +import { customAction } from '@remixproject/plugin-api/lib/file-system/file-panel' 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 @@ -96,7 +97,7 @@ export const FileExplorerContextMenu = (props: FileExplorerContextMenuProps) => deletePath(getPath()) break default: - emit && emit(item.id, getPath()) + emit && emit({ ...item, path: [path] } as customAction) break } hideContextMenu() diff --git a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx index 9f2099026a..d862c19fc1 100644 --- a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx +++ b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx @@ -11,6 +11,7 @@ import { fileSystemReducer, fileSystemInitialState } from './reducers/fileSystem import { fetchDirectory, init, resolveDirectory, addInputField, removeInputField } from './actions/fileSystem' import * as helper from '../../../../../apps/remix-ide/src/lib/helper' import QueryParams from '../../../../../apps/remix-ide/src/lib/query-params' +import { customAction } from '@remixproject/plugin-api/lib/file-system/file-panel' import './css/file-explorer.css' @@ -601,8 +602,8 @@ export const FileExplorer = (props: FileExplorerProps) => { }) } - const emitContextMenuEvent = (id: string, path: string | string[]) => { - plugin.emit(id, path) + const emitContextMenuEvent = (cmd: customAction) => { + plugin.call(cmd.id, cmd.name, cmd) } const handleHideModal = () => { diff --git a/libs/remix-ui/file-explorer/src/lib/types/index.ts b/libs/remix-ui/file-explorer/src/lib/types/index.ts index 511d1b79a1..4aa1e97975 100644 --- a/libs/remix-ui/file-explorer/src/lib/types/index.ts +++ b/libs/remix-ui/file-explorer/src/lib/types/index.ts @@ -1,3 +1,5 @@ +import { customAction } from '@remixproject/plugin-api/lib/file-system/file-panel' + /* eslint-disable-next-line */ export interface FileExplorerProps { name: string, @@ -44,7 +46,7 @@ export interface FileExplorerContextMenuProps { publishFolderToGist?: (path?: string, type?: string) => void, publishFileToGist?: (path?: string, type?: string) => void, runScript?: (path: string) => void, - emit?: (id: string, path: string | string[]) => void, + emit?: (cmd: customAction) => void, pageX: number, pageY: number, path: string, diff --git a/package.json b/package.json index e238787d68..70cc4eea20 100644 --- a/package.json +++ b/package.json @@ -163,7 +163,6 @@ "jquery": "^3.3.1", "jszip": "^3.6.0", "latest-version": "^5.1.0", - "lodash": "^4.17.21", "merge": "^1.2.0", "npm-install-version": "^6.0.2", "react": "16.13.1", @@ -178,7 +177,7 @@ "web3": "1.2.4", "winston": "^3.3.3", "ws": "^7.3.0" - }, + }, "devDependencies": { "@babel/core": "^7.4.5", "@babel/plugin-transform-modules-amd": "^7.10.4", From 93ae1671f3a6b3ca4c86b6b9507579172f955293 Mon Sep 17 00:00:00 2001 From: filip mertens Date: Mon, 17 May 2021 15:20:47 +0200 Subject: [PATCH 48/56] remove items that are not sticky --- apps/remix-ide/src/app/panels/file-panel.js | 4 +- .../file-explorer/src/lib/file-explorer.tsx | 44 +++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/apps/remix-ide/src/app/panels/file-panel.js b/apps/remix-ide/src/app/panels/file-panel.js index 09d697acea..3021372b94 100644 --- a/apps/remix-ide/src/app/panels/file-panel.js +++ b/apps/remix-ide/src/app/panels/file-panel.js @@ -72,6 +72,7 @@ module.exports = class Filepanel extends ViewPlugin { } renderComponent () { + console.log("render", this.registeredMenuItems) ReactDOM.render( { - return item.id !== plugin.name + return item.id !== plugin.name || item.sticky === true }) + this.renderComponent() } async getCurrentWorkspace () { diff --git a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx index d862c19fc1..d104a3e16c 100644 --- a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx +++ b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx @@ -17,6 +17,50 @@ import './css/file-explorer.css' const queryParams = new QueryParams() +const initialActions = [{ + id: 'newFile', + name: 'New File', + type: ['folder'], + path: [], + extension: [], + pattern: [] +}, { + id: 'newFolder', + name: 'New Folder', + type: ['folder'], + path: [], + extension: [], + pattern: [] +}, { + id: 'rename', + name: 'Rename', + type: ['file', 'folder'], + path: [], + extension: [], + pattern: [] +}, { + id: 'delete', + name: 'Delete', + type: ['file', 'folder'], + path: [], + extension: [], + pattern: [] +}, { + id: 'pushChangesToGist', + name: 'Push changes to gist', + type: [], + path: [], + extension: [], + pattern: ['^browser/gists/([0-9]|[a-z])*$'] +}, { + id: 'run', + name: 'Run', + type: [], + path: [], + extension: ['.js'], + pattern: [] +}] + export const FileExplorer = (props: FileExplorerProps) => { const { name, registry, plugin, focusRoot, contextMenuItems, displayInput, externalUploads } = props const [state, setState] = useState({ From d1bd4d26e3ac04851f73c93958e48b7730b3dcec Mon Sep 17 00:00:00 2001 From: filip mertens Date: Fri, 21 May 2021 13:13:48 +0200 Subject: [PATCH 49/56] rm console --- apps/remix-ide/src/app/panels/file-panel.js | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/remix-ide/src/app/panels/file-panel.js b/apps/remix-ide/src/app/panels/file-panel.js index 3021372b94..65df3fe7c2 100644 --- a/apps/remix-ide/src/app/panels/file-panel.js +++ b/apps/remix-ide/src/app/panels/file-panel.js @@ -72,7 +72,6 @@ module.exports = class Filepanel extends ViewPlugin { } renderComponent () { - console.log("render", this.registeredMenuItems) ReactDOM.render( Date: Thu, 24 Jun 2021 15:03:18 +0200 Subject: [PATCH 50/56] remove on deactivation --- apps/remix-ide/src/app/panels/file-panel.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/remix-ide/src/app/panels/file-panel.js b/apps/remix-ide/src/app/panels/file-panel.js index 65df3fe7c2..90cde523d6 100644 --- a/apps/remix-ide/src/app/panels/file-panel.js +++ b/apps/remix-ide/src/app/panels/file-panel.js @@ -173,6 +173,9 @@ module.exports = class Filepanel extends ViewPlugin { } return } + + const self = this + this.appManager.on('manager', 'pluginDeactivated', self.removePluginActions.bind(this)) // insert example contracts if there are no files to show return new Promise((resolve, reject) => { this._deps.fileProviders.browser.resolveDirectory('/', async (error, filesList) => { @@ -196,8 +199,6 @@ module.exports = class Filepanel extends ViewPlugin { }) }) - const self = this - this.appManager.on('manager', 'pluginDeactivated', self.removePluginActions.bind(this)) } async createNewFile () { From 58f526c453d4965107f415c2a5d0d5e1885a81ff Mon Sep 17 00:00:00 2001 From: ioedeveloper Date: Thu, 1 Jul 2021 16:07:03 +0100 Subject: [PATCH 51/56] Implement removal of context menu items --- apps/remix-ide/src/app/panels/file-panel.js | 10 +++- .../file-explorer/src/lib/file-explorer.tsx | 52 +++---------------- .../file-explorer/src/lib/types/index.ts | 3 +- 3 files changed, 17 insertions(+), 48 deletions(-) diff --git a/apps/remix-ide/src/app/panels/file-panel.js b/apps/remix-ide/src/app/panels/file-panel.js index 90cde523d6..a8abde0d66 100644 --- a/apps/remix-ide/src/app/panels/file-panel.js +++ b/apps/remix-ide/src/app/panels/file-panel.js @@ -60,6 +60,7 @@ module.exports = class Filepanel extends ViewPlugin { this.gitHandle = new GitHandle() this.hardhatHandle = new HardhatHandle() this.registeredMenuItems = [] + this.removedMenuItems = [] this.request = {} this.workspaces = [] this.initialWorkspace = null @@ -89,6 +90,7 @@ module.exports = class Filepanel extends ViewPlugin { request={this.request} workspaces={this.workspaces} registeredMenuItems={this.registeredMenuItems} + removedMenuItems={this.removedMenuItems} initialWorkspace={this.initialWorkspace} /> , this.el) @@ -106,12 +108,17 @@ module.exports = class Filepanel extends ViewPlugin { return o.id === item.id & o.name === item.name }).length) throw new Error(`Action ${item.name} already exists on ${item.id}`) this.registeredMenuItems = [...this.registeredMenuItems, item] + this.removedMenuItems = this.removedMenuItems.filter(id => item.id !== id) this.renderComponent() } removePluginActions (plugin) { this.registeredMenuItems = this.registeredMenuItems.filter((item) => { - return item.id !== plugin.name || item.sticky === true + if (item.id !== plugin.name || item.sticky === true) return true + else { + this.removedMenuItems.push(item.id) + return false + } }) this.renderComponent() } @@ -198,7 +205,6 @@ module.exports = class Filepanel extends ViewPlugin { } }) }) - } async createNewFile () { diff --git a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx index d104a3e16c..d3a858f539 100644 --- a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx +++ b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx @@ -17,52 +17,8 @@ import './css/file-explorer.css' const queryParams = new QueryParams() -const initialActions = [{ - id: 'newFile', - name: 'New File', - type: ['folder'], - path: [], - extension: [], - pattern: [] -}, { - id: 'newFolder', - name: 'New Folder', - type: ['folder'], - path: [], - extension: [], - pattern: [] -}, { - id: 'rename', - name: 'Rename', - type: ['file', 'folder'], - path: [], - extension: [], - pattern: [] -}, { - id: 'delete', - name: 'Delete', - type: ['file', 'folder'], - path: [], - extension: [], - pattern: [] -}, { - id: 'pushChangesToGist', - name: 'Push changes to gist', - type: [], - path: [], - extension: [], - pattern: ['^browser/gists/([0-9]|[a-z])*$'] -}, { - id: 'run', - name: 'Run', - type: [], - path: [], - extension: ['.js'], - pattern: [] -}] - export const FileExplorer = (props: FileExplorerProps) => { - const { name, registry, plugin, focusRoot, contextMenuItems, displayInput, externalUploads } = props + const { name, registry, plugin, focusRoot, contextMenuItems, displayInput, externalUploads, removedContextMenuItems } = props const [state, setState] = useState({ focusElement: [{ key: '', @@ -248,6 +204,12 @@ export const FileExplorer = (props: FileExplorerProps) => { } }, [contextMenuItems]) + useEffect(() => { + if (removedContextMenuItems) { + removeMenuItems(removedContextMenuItems) + } + }, [removedContextMenuItems]) + useEffect(() => { if (displayInput) { handleNewFileInput() diff --git a/libs/remix-ui/file-explorer/src/lib/types/index.ts b/libs/remix-ui/file-explorer/src/lib/types/index.ts index 4aa1e97975..7e3f1ac7dc 100644 --- a/libs/remix-ui/file-explorer/src/lib/types/index.ts +++ b/libs/remix-ui/file-explorer/src/lib/types/index.ts @@ -9,8 +9,9 @@ export interface FileExplorerProps { plugin: any, focusRoot: boolean, contextMenuItems: MenuItems, + removedContextMenuItems: string[], displayInput?: boolean, - externalUploads?: EventTarget & HTMLInputElement + externalUploads?: EventTarget & HTMLInputElement, } export interface File { From 8d7ed1d7c20580fa7d85dae31aed96d492a7247f Mon Sep 17 00:00:00 2001 From: filip mertens Date: Thu, 1 Jul 2021 19:23:45 +0200 Subject: [PATCH 52/56] rm double func, check for name & id on remove, fix effect --- apps/remix-ide/src/app/panels/file-panel.js | 14 ++------------ .../file-explorer/src/lib/file-explorer.tsx | 17 ++++++++++++----- .../file-explorer/src/lib/types/index.ts | 2 +- .../workspace/src/lib/remix-ui-workspace.tsx | 3 +++ 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/apps/remix-ide/src/app/panels/file-panel.js b/apps/remix-ide/src/app/panels/file-panel.js index 0e212793d0..4e4769baad 100644 --- a/apps/remix-ide/src/app/panels/file-panel.js +++ b/apps/remix-ide/src/app/panels/file-panel.js @@ -108,7 +108,7 @@ module.exports = class Filepanel extends ViewPlugin { return o.id === item.id & o.name === item.name }).length) throw new Error(`Action ${item.name} already exists on ${item.id}`) this.registeredMenuItems = [...this.registeredMenuItems, item] - this.removedMenuItems = this.removedMenuItems.filter(id => item.id !== id) + this.removedMenuItems = this.removedMenuItems.filter(menuItem => item.id !== menuItem.id) this.renderComponent() } @@ -116,20 +116,13 @@ module.exports = class Filepanel extends ViewPlugin { this.registeredMenuItems = this.registeredMenuItems.filter((item) => { if (item.id !== plugin.name || item.sticky === true) return true else { - this.removedMenuItems.push(item.id) + this.removedMenuItems.push(item) return false } }) this.renderComponent() } - removePluginActions (plugin) { - this.registeredMenuItems = this.registeredMenuItems.filter((item) => { - return item.id !== plugin.name || item.sticky === true - }) - this.renderComponent() - } - async getCurrentWorkspace () { return await this.request.getCurrentWorkspace() } @@ -212,9 +205,6 @@ module.exports = class Filepanel extends ViewPlugin { } }) }) - - const self = this - this.appManager.on('manager', 'pluginDeactivated', self.removePluginActions.bind(this)) } async createNewFile () { diff --git a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx index d3a858f539..a5cbfb205f 100644 --- a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx +++ b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx @@ -208,7 +208,7 @@ export const FileExplorer = (props: FileExplorerProps) => { if (removedContextMenuItems) { removeMenuItems(removedContextMenuItems) } - }, [removedContextMenuItems]) + }, [contextMenuItems]) useEffect(() => { if (displayInput) { @@ -285,7 +285,15 @@ export const FileExplorer = (props: FileExplorerProps) => { multiselect: false }]) } else { - removeMenuItems(['paste']) + removeMenuItems([{ + id: 'paste', + name: 'Paste', + type: ['folder', 'file'], + path: [], + extension: [], + pattern: [], + multiselect: false + }]) } }, [canPaste]) @@ -298,10 +306,9 @@ export const FileExplorer = (props: FileExplorerProps) => { }) } - const removeMenuItems = (ids: string[]) => { + const removeMenuItems = (items: MenuItems) => { setState(prevState => { - const actions = prevState.actions.filter(({ id }) => ids.findIndex(value => value === id) === -1) - + const actions = prevState.actions.filter(({ id, name }) => items.findIndex(item => id === item.id && name === item.name) === -1) return { ...prevState, actions } }) } diff --git a/libs/remix-ui/file-explorer/src/lib/types/index.ts b/libs/remix-ui/file-explorer/src/lib/types/index.ts index 7e3f1ac7dc..61fcb4d752 100644 --- a/libs/remix-ui/file-explorer/src/lib/types/index.ts +++ b/libs/remix-ui/file-explorer/src/lib/types/index.ts @@ -9,7 +9,7 @@ export interface FileExplorerProps { plugin: any, focusRoot: boolean, contextMenuItems: MenuItems, - removedContextMenuItems: string[], + removedContextMenuItems: MenuItems, displayInput?: boolean, externalUploads?: EventTarget & HTMLInputElement, } 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 6a85a0febf..d974eca5a3 100644 --- a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx +++ b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx @@ -21,6 +21,7 @@ export interface WorkspaceProps { request: any // api request, workspaces: any, registeredMenuItems: [] // menu items + removedMenuItems: [] initialWorkspace: string } @@ -409,6 +410,7 @@ export const Workspace = (props: WorkspaceProps) => { plugin={props.plugin} focusRoot={state.reset} contextMenuItems={props.registeredMenuItems} + removedContextMenuItems={props.removedMenuItems} displayInput={state.displayNewFile} externalUploads={state.uploadFileEvent} /> @@ -426,6 +428,7 @@ export const Workspace = (props: WorkspaceProps) => { plugin={props.plugin} focusRoot={state.reset} contextMenuItems={props.registeredMenuItems} + removedContextMenuItems={props.removedMenuItems} /> }
From 93987aea7445ec908bce20687151de82f1812191 Mon Sep 17 00:00:00 2001 From: filip mertens Date: Thu, 1 Jul 2021 19:27:10 +0200 Subject: [PATCH 53/56] types --- libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 d974eca5a3..49676c2b08 100644 --- a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx +++ b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx @@ -3,6 +3,7 @@ import { FileExplorer } from '@remix-ui/file-explorer' // eslint-disable-line import './remix-ui-workspace.css' import { ModalDialog } from '@remix-ui/modal-dialog' // eslint-disable-line import { Toaster } from '@remix-ui/toaster'// eslint-disable-line +import { MenuItems } from 'libs/remix-ui/file-explorer/src/lib/types' /* eslint-disable-next-line */ export interface WorkspaceProps { @@ -20,8 +21,8 @@ export interface WorkspaceProps { plugin: any // plugin call and resetFocus request: any // api request, workspaces: any, - registeredMenuItems: [] // menu items - removedMenuItems: [] + registeredMenuItems: MenuItems // menu items + removedMenuItems: MenuItems initialWorkspace: string } From 829dd17c17829fd7d9f20fa080f28094525c67c5 Mon Sep 17 00:00:00 2001 From: lianahus Date: Fri, 11 Jun 2021 10:47:32 +0200 Subject: [PATCH 54/56] tracking compiler version --- apps/remix-ide/src/app/tabs/compileTab/compilerContainer.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/remix-ide/src/app/tabs/compileTab/compilerContainer.js b/apps/remix-ide/src/app/tabs/compileTab/compilerContainer.js index dfb0cfc5a4..00cf79233d 100644 --- a/apps/remix-ide/src/app/tabs/compileTab/compilerContainer.js +++ b/apps/remix-ide/src/app/tabs/compileTab/compilerContainer.js @@ -7,6 +7,7 @@ const addTooltip = require('../../ui/tooltip') const semver = require('semver') const modalDialogCustom = require('../../ui/modal-dialog-custom') const css = require('../styles/compile-tab-styles') +const _paq = window._paq = window._paq || [] class CompilerContainer { constructor (compileTabLogic, editor, config, queryParams) { @@ -111,6 +112,7 @@ class CompilerContainer { this._view.compileIcon.setAttribute('title', 'idle') this._view.compileIcon.classList.remove(`${css.spinningIcon}`) this._view.compileIcon.classList.remove(`${css.bouncingIcon}`) + _paq.push(['trackEvent', 'compiler', `compiled_with_v_${this._retrieveVersion()}`]) }) } From 8fcc3905df58cc25d0ceb7b32f87d8f2999cded9 Mon Sep 17 00:00:00 2001 From: filip mertens Date: Fri, 2 Jul 2021 00:05:22 +0200 Subject: [PATCH 55/56] && --- apps/remix-ide/src/app/panels/file-panel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/remix-ide/src/app/panels/file-panel.js b/apps/remix-ide/src/app/panels/file-panel.js index 4e4769baad..4374ab3a0d 100644 --- a/apps/remix-ide/src/app/panels/file-panel.js +++ b/apps/remix-ide/src/app/panels/file-panel.js @@ -105,7 +105,7 @@ module.exports = class Filepanel extends ViewPlugin { if (!item.name || !item.id) throw new Error('Item name and id is mandatory') if (!item.type && !item.path && !item.extension && !item.pattern) throw new Error('Invalid file matching criteria provided') if (this.registeredMenuItems.filter((o) => { - return o.id === item.id & o.name === item.name + return o.id === item.id && o.name === item.name }).length) throw new Error(`Action ${item.name} already exists on ${item.id}`) this.registeredMenuItems = [...this.registeredMenuItems, item] this.removedMenuItems = this.removedMenuItems.filter(menuItem => item.id !== menuItem.id) From a8aaf5ce2176ce5f8f4f6ceb1d557de678f6a29e Mon Sep 17 00:00:00 2001 From: filip mertens Date: Fri, 2 Jul 2021 15:00:11 +0200 Subject: [PATCH 56/56] fix debugger crash --- .../src/lib/vm-debugger/solidity-state.tsx | 46 ++++++------ .../src/utils/solidityTypeFormatter.ts | 70 ++++++++++--------- 2 files changed, 62 insertions(+), 54 deletions(-) diff --git a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/solidity-state.tsx b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/solidity-state.tsx index 0bc60b9a3f..c30569b307 100644 --- a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/solidity-state.tsx +++ b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/solidity-state.tsx @@ -5,32 +5,36 @@ import { ExtractData } from '../../types' // eslint-disable-line export const SolidityState = ({ calldata, message }) => { const formatSelf = (key: string, data: ExtractData) => { - let color = 'var(--primary)' - if (data.isArray || data.isStruct || data.isMapping) { - color = 'var(--info)' - } else if ( - data.type.indexOf('uint') === 0 || + try { + let color = 'var(--primary)' + if (data.isArray || data.isStruct || data.isMapping) { + color = 'var(--info)' + } else if ( + data.type.indexOf('uint') === 0 || data.type.indexOf('int') === 0 || data.type.indexOf('bool') === 0 || data.type.indexOf('enum') === 0 - ) { - color = 'var(--green)' - } else if (data.type === 'string') { - color = 'var(--teal)' + ) { + color = 'var(--green)' + } else if (data.type === 'string') { + color = 'var(--teal)' } else if (data.self == 0x0) { // eslint-disable-line - color = 'var(--gray)' - } - return ( -