Merge branch 'pluginupdate' of https://github.com/ethereum/remix-project into pluginupdate

pull/3370/head
bunsenstraat 2 years ago
commit 9e60fff348
  1. 126
      .circleci/config.yml
  2. 13
      apps/debugger/.babelrc
  3. 2
      apps/debugger/src/app/debugger.ts
  4. 1
      apps/debugger/src/index.ts
  5. 1
      apps/debugger/tsconfig.app.json
  6. 109
      apps/debugger/webpack.config.js
  7. 3
      apps/etherscan/project.json
  8. 1
      apps/etherscan/tsconfig.app.json
  9. 23
      apps/remix-ide-e2e/package.json
  10. 16
      apps/remix-ide-e2e/src/commands/journalLastChildIncludes.ts
  11. 9
      apps/remix-ide-e2e/src/local-plugin/.babelrc
  12. 1
      apps/remix-ide-e2e/src/local-plugin/.eslintrc
  13. 15
      apps/remix-ide-e2e/src/local-plugin/project.json
  14. 21
      apps/remix-ide-e2e/src/local-plugin/webpack.config.js
  15. 2
      apps/remix-ide-e2e/src/tests/etherscan_api.ts
  16. 2
      apps/remix-ide-e2e/src/tests/plugin_api.ts
  17. 8
      apps/remix-ide-e2e/src/tests/recorder.test.ts
  18. 2
      apps/remix-ide-e2e/src/tests/remixd.test.ts
  19. 1
      apps/remix-ide-e2e/src/tests/runAndDeploy.test.ts
  20. 8
      apps/remix-ide-e2e/src/tests/specialFunctions.test.ts
  21. 1
      apps/remix-ide-e2e/src/tests/terminal.test.ts
  22. 2
      apps/remix-ide-e2e/src/tests/transactionExecution.test.ts
  23. 2
      apps/remix-ide-e2e/src/tests/vyper_api.ts
  24. 3936
      apps/remix-ide-e2e/yarn.lock
  25. 2
      apps/remix-ide/.babelrc
  26. 3
      apps/remix-ide/ci/browser_test.sh
  27. 6
      apps/remix-ide/ci/browser_test_plugin.sh
  28. 26
      apps/remix-ide/ci/browser_tests_etherscan_plugin.sh
  29. 26
      apps/remix-ide/ci/browser_tests_vyper_plugin.sh
  30. 5
      apps/remix-ide/ci/flaky.sh
  31. 23
      apps/remix-ide/project.json
  32. 13
      apps/remix-ide/src/app.js
  33. 25
      apps/remix-ide/src/app/plugins/code-format.ts
  34. 11
      apps/remix-ide/src/app/plugins/parser/services/code-parser-compiler.ts
  35. 3
      apps/remix-ide/src/app/providers/abstract-provider.tsx
  36. 16
      apps/remix-ide/src/app/providers/injected-provider.tsx
  37. 2
      apps/remix-ide/src/app/providers/mainnet-vm-fork-provider.tsx
  38. 2
      apps/remix-ide/src/app/tabs/compile-and-run.ts
  39. 2
      apps/remix-ide/src/app/tabs/compile-tab.js
  40. 2
      apps/remix-ide/src/app/tabs/debugger-tab.js
  41. 14
      apps/remix-ide/src/app/tabs/locales/en/filePanel.json
  42. 1
      apps/remix-ide/src/app/tabs/locales/zh/filePanel.json
  43. BIN
      apps/remix-ide/src/assets/img/remix-logo-blue.png
  44. 2
      apps/remix-ide/src/index.html
  45. 45
      apps/remix-ide/src/webpack.index.html
  46. 1
      apps/remix-ide/tsconfig.app.json
  47. 2
      apps/remix-ide/tsconfig.json
  48. 2
      apps/remix-ide/tsconfig.spec.json
  49. 3
      apps/remix-ide/webpack.config.js
  50. 9
      apps/solidity-compiler/.babelrc
  51. 2
      apps/solidity-compiler/src/app/compiler.ts
  52. 1
      apps/solidity-compiler/src/index.ts
  53. 1
      apps/solidity-compiler/tsconfig.app.json
  54. 127
      apps/solidity-compiler/webpack.config.js
  55. 3
      apps/vyper/project.json
  56. 108
      apps/vyper/webpack.config.js
  57. 2
      babel.config.js
  58. 4
      jest.preset.js
  59. 2
      libs/ghaction-helper/tsconfig.json
  60. 1
      libs/remix-core-plugin/package.json
  61. 5
      libs/remix-core-plugin/tsconfig.lib.json
  62. 26
      libs/remix-solidity/jest.config.js
  63. 2
      libs/remix-solidity/tsconfig.json
  64. 2
      libs/remix-tests/tsconfig.spec.json
  65. 1
      libs/remix-ui/debugger-ui/src/index.ts
  66. 0
      libs/remix-ui/debugger-ui/src/lib/api/debugger-api.ts
  67. 1
      libs/remix-ui/editor/src/index.ts
  68. 4
      libs/remix-ui/editor/src/lib/actions/editor.ts
  69. 45
      libs/remix-ui/editor/src/lib/providers/completion/completionGlobals.ts
  70. 12
      libs/remix-ui/editor/src/lib/providers/completionProvider.ts
  71. 6
      libs/remix-ui/editor/src/lib/providers/hoverProvider.ts
  72. 30
      libs/remix-ui/editor/src/lib/remix-ui-editor.tsx
  73. 23
      libs/remix-ui/home-tab/src/lib/components/homeTabTitle.tsx
  74. 1
      libs/remix-ui/run-tab/src/lib/components/account.tsx
  75. 3
      libs/remix-ui/settings/src/lib/github-settings.tsx
  76. 1
      libs/remix-ui/solidity-compiler/src/index.ts
  77. 0
      libs/remix-ui/solidity-compiler/src/lib/api/compiler-api.ts
  78. 2
      libs/remix-ui/solidity-compiler/src/lib/css/style.css
  79. 14
      libs/remix-ui/solidity-uml-gen/src/lib/solidity-uml-gen.tsx
  80. 2
      libs/remix-ui/tabs/src/lib/remix-ui-tabs.tsx
  81. 90
      libs/remix-ui/workspace/src/lib/actions/workspace.ts
  82. 51
      libs/remix-ui/workspace/src/lib/components/file-explorer-menu.tsx
  83. 9
      libs/remix-ui/workspace/src/lib/components/file-explorer.tsx
  84. 2
      libs/remix-ui/workspace/src/lib/components/workspace-hamburger.tsx
  85. 1
      libs/remix-ui/workspace/src/lib/contexts/index.ts
  86. 7
      libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx
  87. 4
      libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx
  88. 2
      libs/remix-ui/workspace/src/lib/types/index.ts
  89. 1
      libs/remix-ws-templates/package.json
  90. 2
      libs/remixd/tsconfig.spec.json
  91. 41
      package.json
  92. 3307
      yarn.lock

@ -24,23 +24,55 @@ jobs:
key: v1-deps-{{ checksum "yarn.lock" }} key: v1-deps-{{ checksum "yarn.lock" }}
paths: paths:
- node_modules - node_modules
- run: NX_BIN_URL=http://127.0.0.1:8080/assets/js NX_WASM_URL=http://127.0.0.1:8080/assets/js NPM_URL=http://localhost:9090/ yarn build:production - run:
- run: yarn nx build remix-ide-e2e-src-local-plugin & yarn run build:libs name: Build
- run: yarn nx run debugger:build:production command: |
- run: yarn nx run solidity-compiler:build:production if [ "${CIRCLE_BRANCH}" == "master" ]; then
- run: yarn nx run remixd:build NX_BIN_URL=http://127.0.0.1:8080/assets/js NX_WASM_URL=http://127.0.0.1:8080/assets/js NPM_URL=http://localhost:9090/ yarn build:production
else
NX_BIN_URL=http://127.0.0.1:8080/assets/js NX_WASM_URL=http://127.0.0.1:8080/assets/js NPM_URL=http://localhost:9090/ yarn build
fi
- run: yarn run build:e2e
- run: mkdir persist && zip -0 -r persist/dist.zip dist - run: mkdir persist && zip -0 -r persist/dist.zip dist
- persist_to_workspace: - persist_to_workspace:
root: . root: .
paths: paths:
- "persist" - "persist"
build-plugin:
docker:
- image: cimg/node:14.17.6-browsers
resource_class:
xlarge
working_directory: ~/remix-project
parameters:
plugin:
type: string
steps:
- checkout
- restore_cache:
keys:
- v1-deps-{{ checksum "yarn.lock" }}
- run: yarn
- save_cache:
key: v1-deps-{{ checksum "yarn.lock" }}
paths:
- node_modules
- run: yarn build << parameters.plugin >>
- run: mkdir persist && zip -0 -r persist/plugin-<< parameters.plugin >>.zip dist
- persist_to_workspace:
root: .
paths:
- "persist"
lint: lint:
docker: docker:
- image: cimg/node:14.17.6-browsers - image: cimg/node:14.17.6-browsers
resource_class: resource_class:
xlarge xlarge
working_directory: ~/remix-project working_directory: ~/remix-project
parallelism: 1
steps: steps:
- checkout - checkout
- restore_cache: - restore_cache:
@ -62,11 +94,11 @@ jobs:
- checkout - checkout
- attach_workspace: - attach_workspace:
at: . at: .
- run: unzip ./persist/dist.zip
- restore_cache: - restore_cache:
keys: keys:
- v1-deps-{{ checksum "yarn.lock" }} - v1-deps-{{ checksum "yarn.lock" }}
- run: yarn - run: yarn
- run: yarn build:libs
- run: cd dist/libs/remix-tests && yarn - run: cd dist/libs/remix-tests && yarn
- run: cd dist/libs/remix-tests && yarn add @remix-project/remix-url-resolver ../../libs/remix-url-resolver - run: cd dist/libs/remix-tests && yarn add @remix-project/remix-url-resolver ../../libs/remix-url-resolver
- run: cd dist/libs/remix-tests && yarn add @remix-project/remix-lib ../../libs/remix-lib - run: cd dist/libs/remix-tests && yarn add @remix-project/remix-lib ../../libs/remix-lib
@ -120,11 +152,7 @@ jobs:
- attach_workspace: - attach_workspace:
at: . at: .
- run: unzip ./persist/dist.zip - run: unzip ./persist/dist.zip
- run: yarn install --cwd ./apps/remix-ide-e2e --modules-folder ../../node_modules
- restore_cache:
keys:
- v1-deps-{{ checksum "yarn.lock" }}
- run: yarn
- run: yarn run downloadsolc_assets_e2e && yarn run downloadsolc_assets_dist - run: yarn run downloadsolc_assets_e2e && yarn run downloadsolc_assets_dist
- run: ls -la ./dist/apps/remix-ide/assets/js - run: ls -la ./dist/apps/remix-ide/assets/js
- run: yarn run selenium-install || yarn run selenium-install - run: yarn run selenium-install || yarn run selenium-install
@ -151,9 +179,12 @@ jobs:
xlarge xlarge
working_directory: ~/remix-project working_directory: ~/remix-project
parameters: parameters:
script: plugin:
type: string type: string
parallelism: 4 parallelism:
type: integer
default: 1
parallelism: << parameters.parallelism >>
steps: steps:
- browser-tools/install-browser-tools: - browser-tools/install-browser-tools:
install-firefox: false install-firefox: false
@ -166,19 +197,16 @@ jobs:
- checkout - checkout
- attach_workspace: - attach_workspace:
at: . at: .
- restore_cache:
keys:
- v1-deps-{{ checksum "yarn.lock" }}
- run: yarn
- run: unzip ./persist/dist.zip - run: unzip ./persist/dist.zip
- run: unzip ./persist/plugin-<< parameters.plugin >>.zip
- run: yarn install --cwd ./apps/remix-ide-e2e --modules-folder ../../node_modules
- run: yarn run downloadsolc_assets_e2e && yarn run downloadsolc_assets_dist - run: yarn run downloadsolc_assets_e2e && yarn run downloadsolc_assets_dist
- run: yarn run selenium-install || yarn run selenium-install - run: yarn run selenium-install || yarn run selenium-install
- run: - run:
name: Start Selenium name: Start Selenium
command: yarn run selenium command: yarn run selenium
background: true background: true
- run: ./apps/remix-ide/ci/<< parameters.script >> - run: ./apps/remix-ide/ci/browser_test_plugin.sh << parameters.plugin >>
- store_test_results: - store_test_results:
path: ./reports/tests path: ./reports/tests
- store_artifacts: - store_artifacts:
@ -193,12 +221,19 @@ jobs:
environment: environment:
- COMMIT_AUTHOR_EMAIL: "yann@ethereum.org" - COMMIT_AUTHOR_EMAIL: "yann@ethereum.org"
- COMMIT_AUTHOR: "Circle CI" - COMMIT_AUTHOR: "Circle CI"
- FILES_TO_PACKAGE: "dist/apps/remix-ide/index.html dist/apps/remix-ide/404.html dist/apps/remix-ide/*.js dist/apps/remix-ide/*.css dist/apps/remix-ide/assets dist/apps/remix-ide/favicon.ico" - FILES_TO_PACKAGE: "dist/apps/remix-ide/index.html dist/apps/remix-ide/404.html dist/apps/remix-ide/*.js dist/apps/remix-ide/assets dist/apps/remix-ide/favicon.ico"
working_directory: ~/remix-project working_directory: ~/remix-project
steps: steps:
- checkout - checkout
- restore_cache:
keys:
- v1-deps-{{ checksum "yarn.lock" }}
- run: yarn - run: yarn
- save_cache:
key: v1-deps-{{ checksum "yarn.lock" }}
paths:
- node_modules
- run: yarn run downloadsolc_assets - run: yarn run downloadsolc_assets
- run: yarn run build:production - run: yarn run build:production
- run: - run:
@ -217,12 +252,19 @@ jobs:
environment: environment:
- COMMIT_AUTHOR_EMAIL: "yann@ethereum.org" - COMMIT_AUTHOR_EMAIL: "yann@ethereum.org"
- COMMIT_AUTHOR: "Circle CI" - COMMIT_AUTHOR: "Circle CI"
- FILES_TO_PACKAGE: "dist/apps/remix-ide/index.html dist/apps/remix-ide/404.html dist/apps/remix-ide/*.js dist/apps/remix-ide/*.css dist/apps/remix-ide/assets dist/apps/remix-ide/favicon.ico" - FILES_TO_PACKAGE: "dist/apps/remix-ide/index.html dist/apps/remix-ide/404.html dist/apps/remix-ide/*.js dist/apps/remix-ide/assets dist/apps/remix-ide/favicon.ico"
working_directory: ~/remix-project working_directory: ~/remix-project
steps: steps:
- checkout - checkout
- restore_cache:
keys:
- v1-deps-{{ checksum "yarn.lock" }}
- run: yarn - run: yarn
- save_cache:
key: v1-deps-{{ checksum "yarn.lock" }}
paths:
- node_modules
- run: yarn run downloadsolc_assets - run: yarn run downloadsolc_assets
- run: yarn run build:production - run: yarn run build:production
- run: - run:
@ -241,13 +283,19 @@ jobs:
environment: environment:
- COMMIT_AUTHOR_EMAIL: "yann@ethereum.org" - COMMIT_AUTHOR_EMAIL: "yann@ethereum.org"
- COMMIT_AUTHOR: "Circle CI" - COMMIT_AUTHOR: "Circle CI"
- FILES_TO_PACKAGE: "dist/apps/remix-ide/index.html dist/apps/remix-ide/404.html dist/apps/remix-ide/*.js dist/apps/remix-ide/*.css dist/apps/remix-ide/assets dist/apps/remix-ide/favicon.ico" - FILES_TO_PACKAGE: "dist/apps/remix-ide/index.html dist/apps/remix-ide/404.html dist/apps/remix-ide/*.js dist/apps/remix-ide/assets dist/apps/remix-ide/favicon.ico"
working_directory: ~/remix-project working_directory: ~/remix-project
steps: steps:
- checkout - checkout
- restore_cache:
keys:
- v1-deps-{{ checksum "yarn.lock" }}
- run: yarn - run: yarn
- run: yarn run build:libs - save_cache:
key: v1-deps-{{ checksum "yarn.lock" }}
paths:
- node_modules
- run: yarn run downloadsolc_assets - run: yarn run downloadsolc_assets
- run: yarn run build:production - run: yarn run build:production
- run: - run:
@ -275,18 +323,32 @@ workflows:
unless: << pipeline.parameters.run_flaky_tests >> unless: << pipeline.parameters.run_flaky_tests >>
jobs: jobs:
- build - build
- build-plugin:
matrix:
parameters:
plugin: ["etherscan", "vyper", "plugin_api"]
- lint: - lint:
requires: requires:
- build - build
- remix-libs: - remix-libs
requires:
- build
- remix-test-plugins: - remix-test-plugins:
name: test-plugin-<< matrix.plugin >>
requires: requires:
- build - build
- build-plugin
matrix: matrix:
alias: plugins
parameters: parameters:
script: ["browser_tests_plugin_api.sh", "browser_tests_etherscan_plugin.sh", "browser_tests_vyper_plugin.sh"] plugin: ["etherscan", "vyper", "plugin_api"]
parallelism: [1, 9]
exclude:
- plugin: plugin_api
parallelism: 1
- plugin: etherscan
parallelism: 9
- plugin: vyper
parallelism: 9
- remix-ide-browser: - remix-ide-browser:
requires: requires:
- build - build
@ -301,13 +363,13 @@ workflows:
- lint - lint
- remix-libs - remix-libs
- remix-ide-browser - remix-ide-browser
- remix-test-plugins - plugins
- deploy-remix-live: - deploy-remix-live:
requires: requires:
- lint - lint
- remix-libs - remix-libs
- remix-ide-browser - remix-ide-browser
- remix-test-plugins - plugins
filters: filters:
branches: branches:
only: remix_live only: remix_live
@ -316,7 +378,7 @@ workflows:
- lint - lint
- remix-libs - remix-libs
- remix-ide-browser - remix-ide-browser
- remix-test-plugins - plugins
filters: filters:
branches: branches:
only: master only: master
@ -325,7 +387,7 @@ workflows:
- lint - lint
- remix-libs - remix-libs
- remix-ide-browser - remix-ide-browser
- remix-test-plugins - plugins
filters: filters:
branches: branches:
only: remix_beta only: remix_beta

@ -0,0 +1,13 @@
{
"presets": [
[
"@nrwl/react/babel", {
"runtime": "automatic"
}
]
],
"plugins": [
]
}

@ -2,7 +2,7 @@ import { PluginClient } from "@remixproject/plugin";
import { createClient } from "@remixproject/plugin-webview"; import { createClient } from "@remixproject/plugin-webview";
import { IDebuggerApi, LineColumnLocation, import { IDebuggerApi, LineColumnLocation,
onBreakpointClearedListener, onBreakpointAddedListener, onEditorContentChanged, onEnvChangedListener, TransactionReceipt } from '@remix-ui/debugger-ui' onBreakpointClearedListener, onBreakpointAddedListener, onEditorContentChanged, onEnvChangedListener, TransactionReceipt } from '@remix-ui/debugger-ui'
import { DebuggerApiMixin } from './debugger-api' import { DebuggerApiMixin } from '@remix-ui/debugger-ui'
import { CompilerAbstract } from '@remix-project/remix-solidity' import { CompilerAbstract } from '@remix-project/remix-solidity'
export class DebuggerClientApi extends DebuggerApiMixin(PluginClient) { export class DebuggerClientApi extends DebuggerApiMixin(PluginClient) {

@ -1 +0,0 @@
export * from './app/debugger-api';

@ -9,7 +9,6 @@
"../../node_modules/@nrwl/react/typings/image.d.ts" "../../node_modules/@nrwl/react/typings/image.d.ts"
], ],
"exclude": [ "exclude": [
"jest.config.ts",
"**/*.spec.ts", "**/*.spec.ts",
"**/*.test.ts", "**/*.test.ts",
"**/*.spec.tsx", "**/*.spec.tsx",

@ -1,32 +1,83 @@
const nxWebpack = require('@nrwl/react/plugins/webpack') const { composePlugins, withNx } = require('@nrwl/webpack')
const webpack = require('webpack')
module.exports = config => { const TerserPlugin = require("terser-webpack-plugin")
const nxWebpackConfig = nxWebpack(config) const CssMinimizerPlugin = require("css-minimizer-webpack-plugin")
const webpackConfig = {
...nxWebpackConfig, // Nx plugins for webpack.
resolve : { module.exports = composePlugins(withNx(), (config) => {
...nxWebpackConfig.resolve, // Update the webpack config as needed here.
fallback: { // e.g. `config.plugins.push(new MyPlugin())`
...nxWebpackConfig.resolve.fallback,
"crypto": require.resolve("crypto-browserify"), // add fallback for node modules
"stream": require.resolve("stream-browserify"), config.resolve.fallback = {
"http" : require.resolve("stream-http"), ...config.resolve.fallback,
"https" : require.resolve("https-browserify"), "crypto": require.resolve("crypto-browserify"),
"path" : require.resolve("path-browserify"), "stream": require.resolve("stream-browserify"),
"module": false, "path": require.resolve("path-browserify"),
"fs" : false "http": require.resolve("stream-http"),
}, "https": require.resolve("https-browserify"),
} "constants": require.resolve("constants-browserify"),
"os": false, //require.resolve("os-browserify/browser"),
"timers": false, // require.resolve("timers-browserify"),
"zlib": require.resolve("browserify-zlib"),
"fs": false,
"module": false,
"tls": false,
"net": false,
"readline": false,
"child_process": false,
"buffer": require.resolve("buffer/"),
"vm": require.resolve('vm-browserify'),
} }
if (process.env.NODE_ENV === 'production') {
return { // add externals
...webpackConfig, config.externals = {
mode: 'production', ...config.externals,
devtool: 'source-map', solc: 'solc',
}
} else {
return webpackConfig
} }
}
// add public path
config.output.publicPath = '/'
// add copy & provide plugin
config.plugins.push(
new webpack.ProvidePlugin({
Buffer: ['buffer', 'Buffer'],
url: ['url', 'URL'],
process: 'process/browser',
})
)
// souce-map loader
config.module.rules.push({
test: /\.js$/,
use: ["source-map-loader"],
enforce: "pre"
})
config.ignoreWarnings = [/Failed to parse source map/] // ignore source-map-loader warnings
// set minimizer
config.optimization.minimizer = [
new TerserPlugin({
parallel: true,
terserOptions: {
ecma: 2015,
compress: false,
mangle: false,
format: {
comments: false,
},
},
extractComments: false,
}),
new CssMinimizerPlugin(),
];
return config;
});

@ -3,9 +3,6 @@
"$schema": "../../node_modules/nx/schemas/project-schema.json", "$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/etherscan/src", "sourceRoot": "apps/etherscan/src",
"projectType": "application", "projectType": "application",
"implicitDependencies": [
"remix-debug"
],
"targets": { "targets": {
"build": { "build": {
"executor": "@nrwl/webpack:webpack", "executor": "@nrwl/webpack:webpack",

@ -9,7 +9,6 @@
"../../node_modules/@nrwl/react/typings/image.d.ts" "../../node_modules/@nrwl/react/typings/image.d.ts"
], ],
"exclude": [ "exclude": [
"jest.config.ts",
"**/*.spec.ts", "**/*.spec.ts",
"**/*.test.ts", "**/*.test.ts",
"**/*.spec.tsx", "**/*.spec.tsx",

@ -0,0 +1,23 @@
{
"name": "remix-ide-e2e",
"license": "MIT",
"engines": {
"node": "^14.17.6",
"npm": "^6.14.15"
},
"dependencies": {
"@openzeppelin/contracts": "^4.7.3",
"@openzeppelin/contracts-upgradeable": "^4.8.1",
"@openzeppelin/upgrades-core": "^1.22.0",
"@openzeppelin/wizard": "^0.1.1",
"@remix-project/remixd": "../../dist/libs/remixd",
"deep-equal": "^1.0.1",
"ganache-cli": "^6.8.1",
"selenium-standalone": "^8.2.3",
"tree-kill": "^1.2.2"
},
"devDependencies": {
"http-server": "^14.1.1",
"nightwatch": "2.3"
}
}

@ -5,14 +5,14 @@ import EventEmitter from 'events'
Check if the last log in the console contains a specific text Check if the last log in the console contains a specific text
*/ */
class JournalLastChildIncludes extends EventEmitter { class JournalLastChildIncludes extends EventEmitter {
command (this: NightwatchBrowser, val: string): NightwatchBrowser { command(this: NightwatchBrowser, val: string): NightwatchBrowser {
this.api this.api
.waitForElementVisible('*[data-id="terminalJournal"]', 10000) .waitForElementPresent({
.pause(1000) selector: `//*[@data-id='terminalJournal' and contains(.,'${val}')]`,
.getText('*[data-id="terminalJournal"]', (result) => { timeout: 10000,
console.log('JournalLastChildIncludes', result.value) locateStrategy: 'xpath'
if (typeof result.value === 'string' && result.value.indexOf(val) === -1) return this.api.assert.fail(`wait for ${val} in ${result.value}`) }).perform((done) => {
else this.api.assert.ok(true, `<*[data-id="terminalJournal"]> contains ${val}.`) done()
this.emit('complete') this.emit('complete')
}) })
return this return this

@ -1,4 +1,9 @@
{ {
"presets": ["@nrwl/react/babel"], "presets": ["@babel/preset-env", ["@babel/preset-react",
"plugins": [] {"runtime": "automatic"}
]],
"plugins": ["@babel/plugin-proposal-class-properties", "@babel/plugin-transform-runtime", "@babel/plugin-proposal-nullish-coalescing-operator"],
"ignore": [
"**/node_modules/**"
]
} }

@ -238,7 +238,6 @@
"browser": true, "browser": true,
"commonjs": true, "commonjs": true,
"es6": true, "es6": true,
"jest": true,
"node": true "node": true
}, },
"settings": { "react": { "version": "detect" } }, "settings": { "react": { "version": "detect" } },

@ -1,11 +1,8 @@
{ {
"name": "remix-ide-e2e-src-local-plugin", "name": "plugin_api",
"$schema": "../../node_modules/nx/schemas/project-schema.json", "$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/remix-ide-e2e/src/local-plugin/src/", "sourceRoot": "apps/remix-ide-e2e/src/local-plugin/src/",
"projectType": "application", "projectType": "application",
"implicitDependencies": [
"remix-debug"
],
"targets": { "targets": {
"build": { "build": {
"executor": "@nrwl/webpack:webpack", "executor": "@nrwl/webpack:webpack",
@ -13,7 +10,7 @@
"defaultConfiguration": "development", "defaultConfiguration": "development",
"options": { "options": {
"compiler": "babel", "compiler": "babel",
"outputPath": "dist/apps/remix-ide-e2e-src-local-plugin", "outputPath": "dist/apps/plugin_api",
"index": "apps/remix-ide-e2e/src/local-plugin/src/index.html", "index": "apps/remix-ide-e2e/src/local-plugin/src/index.html",
"baseHref": "/", "baseHref": "/",
"main": "apps/remix-ide-e2e/src/local-plugin/src/main.tsx", "main": "apps/remix-ide-e2e/src/local-plugin/src/main.tsx",
@ -25,7 +22,7 @@
"apps/remix-ide-e2e/src/local-plugin/src/styles.css" "apps/remix-ide-e2e/src/local-plugin/src/styles.css"
], ],
"scripts": [], "scripts": [],
"webpackConfig": "@nrwl/react/plugins/webpack" "webpackConfig": "apps/remix-ide-e2e/src/local-plugin/webpack.config.js"
}, },
"configurations": { "configurations": {
"development": { "development": {
@ -44,16 +41,16 @@
"executor": "@nrwl/webpack:dev-server", "executor": "@nrwl/webpack:dev-server",
"defaultConfiguration": "development", "defaultConfiguration": "development",
"options": { "options": {
"buildTarget": "remix-ide-e2e-src-local-plugin:build", "buildTarget": "plugin_api:build",
"hmr": true "hmr": true
}, },
"configurations": { "configurations": {
"development": { "development": {
"buildTarget": "remix-ide-e2e-src-local-plugin:build:development", "buildTarget": "plugin_api:build:development",
"port": 2020 "port": 2020
}, },
"production": { "production": {
"buildTarget": "remix-ide-e2e-src-local-plugin:build:production" "buildTarget": "plugin_api:build:production"
} }
} }
} }

@ -0,0 +1,21 @@
const { composePlugins, withNx } = require('@nrwl/webpack')
// Nx plugins for webpack.
module.exports = composePlugins(withNx(), (config) => {
// Update the webpack config as needed here.
// e.g. `config.plugins.push(new MyPlugin())`
// add public path
config.output.publicPath = '/'
// souce-map loader
config.module.rules.push({
test: /\.js$/,
use: ["source-map-loader"],
enforce: "pre"
})
config.ignoreWarnings = [/Failed to parse source map/] // ignore source-map-loader warnings
return config;
});

@ -9,7 +9,7 @@ declare global {
module.exports = { module.exports = {
'@disabled': true, '@disabled': true,
before: function (browser: NightwatchBrowser, done: VoidFunction) { before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done, null, true, { name: 'etherscan', url: 'http://127.0.0.1:5003'}) init(browser, done, null, true, { name: 'etherscan', url: 'http://127.0.0.1:9999'})
}, },
'Should load etherscan plugin #group1': function (browser: NightwatchBrowser) { 'Should load etherscan plugin #group1': function (browser: NightwatchBrowser) {

@ -11,7 +11,7 @@ const localPluginData: Profile & LocationProfile & ExternalProfile = {
name: 'localPlugin', name: 'localPlugin',
displayName: 'Local Plugin', displayName: 'Local Plugin',
canActivate: ['dGitProvider', 'flattener', 'solidityUnitTesting', 'udapp', 'hardhat-provider'], canActivate: ['dGitProvider', 'flattener', 'solidityUnitTesting', 'udapp', 'hardhat-provider'],
url: 'http://localhost:2020', url: 'http://localhost:9999',
location: 'sidePanel' location: 'sidePanel'
} }

@ -68,10 +68,9 @@ module.exports = {
}) })
}, },
'Record more than one contract #group1': function (browser: NightwatchBrowser) { 'Record more than one contract #group2': function (browser: NightwatchBrowser) {
// deploy 2 contracts (2 different ABIs), save the record, reexecute and test one of the function. // deploy 2 contracts (2 different ABIs), save the record, reexecute and test one of the function.
browser browser
.click('*[data-id="deployAndRunClearInstances"]')
.testContracts('multipleContracts.sol', sources[1]['multipleContracts.sol'], ['t1est', 't2est']) .testContracts('multipleContracts.sol', sources[1]['multipleContracts.sol'], ['t1est', 't2est'])
.clickLaunchIcon('udapp') .clickLaunchIcon('udapp')
.selectContract('t1est') .selectContract('t1est')
@ -81,6 +80,7 @@ module.exports = {
.selectContract('t2est') .selectContract('t2est')
.pause(1000) .pause(1000)
.createContract('') .createContract('')
.click('[data-id="udappRecorderTitleExpander"]')
.click('.savetransaction') .click('.savetransaction')
.waitForElementVisible('[data-id="udappNotify-modal-footer-ok-react"]') .waitForElementVisible('[data-id="udappNotify-modal-footer-ok-react"]')
.execute(function () { .execute(function () {
@ -92,7 +92,7 @@ module.exports = {
.click('*[data-id="deployAndRunClearInstances"]') // clear udapp .click('*[data-id="deployAndRunClearInstances"]') // clear udapp
.click('*[data-id="terminalClearConsole"]') // clear terminal .click('*[data-id="terminalClearConsole"]') // clear terminal
.click('[data-id="runtransaction"]') .click('[data-id="runtransaction"]')
.clickInstance(2) .clickInstance(1)
.pause(1000) .pause(1000)
.clickFunction('set2 - transact (not payable)', { types: 'uint256 _po', values: '10' }) .clickFunction('set2 - transact (not payable)', { types: 'uint256 _po', values: '10' })
.testFunction('last', .testFunction('last',
@ -103,7 +103,7 @@ module.exports = {
}, },
'Run with live "mode" #group1': function (browser: NightwatchBrowser) { 'Run with live "mode" #group2': function (browser: NightwatchBrowser) {
let addressRef: string let addressRef: string
browser.addFile('scenario_live_mode.json', { content: JSON.stringify(liveModeScenario, null, '\t') }) browser.addFile('scenario_live_mode.json', { content: JSON.stringify(liveModeScenario, null, '\t') })
.addFile('scenario_live_mode_storage.sol', { content: testStorageForLiveMode }) .addFile('scenario_live_mode_storage.sol', { content: testStorageForLiveMode })

@ -312,7 +312,7 @@ function testImportFromRemixd(browser: NightwatchBrowser, callback: VoidFunction
} }
async function spawnRemixd(path: string): Promise<ChildProcess> { async function spawnRemixd(path: string): Promise<ChildProcess> {
const remixd = spawn('yarn run remixd', [`-s ${path}`], { cwd: process.cwd(), shell: true, detached: true }) const remixd = spawn('chmod +x dist/libs/remixd/src/bin/remixd.js && dist/libs/remixd/src/bin/remixd.js --remix-ide http://127.0.0.1:8080', [`-s ${path}`], { cwd: process.cwd(), shell: true, detached: true })
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
remixd.stdout.on('data', function (data) { remixd.stdout.on('data', function (data) {
if( if(

@ -224,7 +224,6 @@ module.exports = {
'Call web3.eth.getAccounts() using Injected Provider (Metamask)': !function (browser: NightwatchBrowser) { 'Call web3.eth.getAccounts() using Injected Provider (Metamask)': !function (browser: NightwatchBrowser) {
browser browser
.executeScriptInTerminal('web3.eth.getAccounts()') .executeScriptInTerminal('web3.eth.getAccounts()')
.pause(2000)
.journalLastChildIncludes('[ "0x76a3ABb5a12dcd603B52Ed22195dED17ee82708f" ]') .journalLastChildIncludes('[ "0x76a3ABb5a12dcd603B52Ed22195dED17ee82708f" ]')
.end() .end()
} }

@ -29,7 +29,6 @@ module.exports = {
.perform((done) => { .perform((done) => {
browser.getAddressAtPosition(0, (address) => { browser.getAddressAtPosition(0, (address) => {
browser.sendLowLevelTx(address, '0', '0xaa') browser.sendLowLevelTx(address, '0', '0xaa')
.pause(1000)
.journalLastChildIncludes('to: CheckSpecials.(fallback)') .journalLastChildIncludes('to: CheckSpecials.(fallback)')
.journalLastChildIncludes('value: 0 wei') .journalLastChildIncludes('value: 0 wei')
.journalLastChildIncludes('data: 0xaa') .journalLastChildIncludes('data: 0xaa')
@ -67,7 +66,6 @@ module.exports = {
browser.perform((done) => { browser.perform((done) => {
browser.getAddressAtPosition(0, (address) => { browser.getAddressAtPosition(0, (address) => {
browser.sendLowLevelTx(address, '1', '') browser.sendLowLevelTx(address, '1', '')
.pause(1000)
.journalLastChildIncludes('to: CheckSpecials.(receive)') .journalLastChildIncludes('to: CheckSpecials.(receive)')
.journalLastChildIncludes('value: 1 wei') .journalLastChildIncludes('value: 1 wei')
.journalLastChildIncludes('data: 0x') .journalLastChildIncludes('data: 0x')
@ -80,7 +78,6 @@ module.exports = {
browser.perform((done) => { browser.perform((done) => {
browser.getAddressAtPosition(0, (address) => { browser.getAddressAtPosition(0, (address) => {
browser.sendLowLevelTx(address, '10', '0xaa') browser.sendLowLevelTx(address, '10', '0xaa')
.pause(1000)
.journalLastChildIncludes('to CheckSpecials.(fallback) errored:') .journalLastChildIncludes('to CheckSpecials.(fallback) errored:')
.journalLastChildIncludes('The called function should be payable if you send value') .journalLastChildIncludes('The called function should be payable if you send value')
.perform(done()) .perform(done())
@ -97,7 +94,6 @@ module.exports = {
.perform((done) => { .perform((done) => {
browser.getAddressAtPosition(0, (address) => { browser.getAddressAtPosition(0, (address) => {
browser.sendLowLevelTx(address, '1', '') browser.sendLowLevelTx(address, '1', '')
.pause(1000)
.journalLastChildIncludes('to: CheckSpecials.(receive)') .journalLastChildIncludes('to: CheckSpecials.(receive)')
.journalLastChildIncludes('value: 1 wei') .journalLastChildIncludes('value: 1 wei')
.journalLastChildIncludes('data: 0x') .journalLastChildIncludes('data: 0x')
@ -110,7 +106,6 @@ module.exports = {
browser.perform((done) => { browser.perform((done) => {
browser.getAddressAtPosition(0, (address) => { browser.getAddressAtPosition(0, (address) => {
browser.sendLowLevelTx(address, '0', '0xaa') browser.sendLowLevelTx(address, '0', '0xaa')
.pause(1000)
.waitForElementVisible(`#instance${address} label[id="deployAndRunLLTxError"]`) .waitForElementVisible(`#instance${address} label[id="deployAndRunLLTxError"]`)
.assert.containsText(`#instance${address} label[id="deployAndRunLLTxError"]`, '\'Fallback\' function is not defined') .assert.containsText(`#instance${address} label[id="deployAndRunLLTxError"]`, '\'Fallback\' function is not defined')
.perform(done()) .perform(done())
@ -127,7 +122,6 @@ module.exports = {
.perform((done) => { .perform((done) => {
browser.getAddressAtPosition(0, (address) => { browser.getAddressAtPosition(0, (address) => {
browser.sendLowLevelTx(address, '1', '') browser.sendLowLevelTx(address, '1', '')
.pause(1000)
.journalLastChildIncludes('to: CheckSpecials.(fallback)') .journalLastChildIncludes('to: CheckSpecials.(fallback)')
.journalLastChildIncludes('value: 1 wei') .journalLastChildIncludes('value: 1 wei')
.journalLastChildIncludes('data: 0x') .journalLastChildIncludes('data: 0x')
@ -140,7 +134,6 @@ module.exports = {
browser.perform((done) => { browser.perform((done) => {
browser.getAddressAtPosition(0, (address) => { browser.getAddressAtPosition(0, (address) => {
browser.sendLowLevelTx(address, '1', '0xaa') browser.sendLowLevelTx(address, '1', '0xaa')
.pause(1000)
.journalLastChildIncludes('to: CheckSpecials.(fallback)') .journalLastChildIncludes('to: CheckSpecials.(fallback)')
.journalLastChildIncludes('value: 1 wei') .journalLastChildIncludes('value: 1 wei')
.journalLastChildIncludes('data: 0xaa') .journalLastChildIncludes('data: 0xaa')
@ -180,7 +173,6 @@ module.exports = {
.perform((done) => { .perform((done) => {
browser.getAddressAtPosition(0, (address) => { browser.getAddressAtPosition(0, (address) => {
browser.sendLowLevelTx(address, '999999998765257135', '0xaa') browser.sendLowLevelTx(address, '999999998765257135', '0xaa')
.pause(1000)
.journalLastChildIncludes('to: CheckSpecials.(fallback)') .journalLastChildIncludes('to: CheckSpecials.(fallback)')
.journalLastChildIncludes('value: 999999998765257135 wei') .journalLastChildIncludes('value: 999999998765257135 wei')
.journalLastChildIncludes('data: 0xaa') .journalLastChildIncludes('data: 0xaa')

@ -202,7 +202,6 @@ module.exports = {
.addFile('scripts/deploy_storage.js', { content: scriptAutoExec.script }) .addFile('scripts/deploy_storage.js', { content: scriptAutoExec.script })
.openFile('contracts/storage.sol') .openFile('contracts/storage.sol')
.sendKeys('body', [browser.Keys.CONTROL, browser.Keys.SHIFT, 's']) .sendKeys('body', [browser.Keys.CONTROL, browser.Keys.SHIFT, 's'])
.pause(15000)
.journalLastChildIncludes('147') .journalLastChildIncludes('147')
}, },

@ -141,7 +141,6 @@ module.exports = {
.click('.udapp_contractActionsContainerSingle > button') .click('.udapp_contractActionsContainerSingle > button')
.clickInstance(0) .clickInstance(0)
.clickFunction('g - transact (not payable)') .clickFunction('g - transact (not payable)')
.pause(5000)
.journalLastChildIncludes('Error provided by the contract:') .journalLastChildIncludes('Error provided by the contract:')
.journalLastChildIncludes('CustomError : error description') .journalLastChildIncludes('CustomError : error description')
.journalLastChildIncludes('Parameters:') .journalLastChildIncludes('Parameters:')
@ -182,7 +181,6 @@ module.exports = {
.click('.udapp_contractActionsContainerSingle > button') .click('.udapp_contractActionsContainerSingle > button')
.clickInstance(1) .clickInstance(1)
.clickFunction('h - transact (not payable)') .clickFunction('h - transact (not payable)')
.pause(5000)
.journalLastChildIncludes('Error provided by the contract:') .journalLastChildIncludes('Error provided by the contract:')
.journalLastChildIncludes('CustomError : error description from library') .journalLastChildIncludes('CustomError : error description from library')
.journalLastChildIncludes('Parameters:') .journalLastChildIncludes('Parameters:')

@ -9,7 +9,7 @@ declare global {
module.exports = { module.exports = {
'@disabled': true, '@disabled': true,
before: function (browser: NightwatchBrowser, done: VoidFunction) { before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done, null, true, { name: 'vyper', url: 'http://127.0.0.1:5002'}) init(browser, done, null, true, { name: 'vyper', url: 'http://127.0.0.1:9999'})
}, },
'Should connect to vyper plugin #group1': function (browser: NightwatchBrowser) { 'Should connect to vyper plugin #group1': function (browser: NightwatchBrowser) {

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
{ {
"presets": ["@babel/preset-env", ["@babel/preset-react", "presets": ["@babel/preset-env", ["@nrwl/react/babel",
{"runtime": "automatic"} {"runtime": "automatic"}
]], ]],
"plugins": ["@babel/plugin-proposal-class-properties", "@babel/plugin-transform-runtime", "@babel/plugin-proposal-nullish-coalescing-operator"], "plugins": ["@babel/plugin-proposal-class-properties", "@babel/plugin-transform-runtime", "@babel/plugin-proposal-nullish-coalescing-operator"],

@ -10,11 +10,8 @@ TEST_EXITCODE=0
yarn run ganache-cli & yarn run ganache-cli &
npx http-server -p 9090 --cors='*' ./node_modules & npx http-server -p 9090 --cors='*' ./node_modules &
yarn run serve:production & yarn run serve:production &
echo 'sharing folder: ' $PWD '/apps/remix-ide/contracts' &
sleep 5 sleep 5
yarn run build:e2e
# grep -IRiL "@disabled" "dist/apps/remix-ide-e2e/src/tests" | grep "\.spec\|\.test" | xargs -I {} basename {} .test.js | grep -E "\b[${2}]" # grep -IRiL "@disabled" "dist/apps/remix-ide-e2e/src/tests" | grep "\.spec\|\.test" | xargs -I {} basename {} .test.js | grep -E "\b[${2}]"
# TESTFILES=$(grep -IRiL "@disabled" "dist/apps/remix-ide-e2e/src/tests" | grep "\.spec\|\.test" | xargs -I {} basename {} .test.js | grep -E "\b[$2]" | circleci tests split --split-by=timings ) # TESTFILES=$(grep -IRiL "@disabled" "dist/apps/remix-ide-e2e/src/tests" | grep "\.spec\|\.test" | xargs -I {} basename {} .test.js | grep -E "\b[$2]" | circleci tests split --split-by=timings )
node apps/remix-ide/ci/splice_tests.js $2 $3 node apps/remix-ide/ci/splice_tests.js $2 $3

@ -6,16 +6,14 @@ BUILD_ID=${CIRCLE_BUILD_NUM:-${TRAVIS_JOB_NUMBER}}
echo "$BUILD_ID" echo "$BUILD_ID"
TEST_EXITCODE=0 TEST_EXITCODE=0
npx http-server -p 9999 ./dist/apps/$1 &
yarn run ganache-cli & yarn run ganache-cli &
npx http-server -p 9090 --cors='*' ./node_modules & npx http-server -p 9090 --cors='*' ./node_modules &
yarn run serve:production & yarn run serve:production &
npx nx serve remix-ide-e2e-src-local-plugin &
sleep 5 sleep 5
yarn run build:e2e TESTFILES=$(grep -IRiL "\'@disabled\': \?true" "dist/apps/remix-ide-e2e/src/tests" | grep $1 | sort | circleci tests split )
TESTFILES=$(grep -IRiL "\'@disabled\': \?true" "dist/apps/remix-ide-e2e/src/tests" | grep "plugin_api" | sort | circleci tests split )
for TESTFILE in $TESTFILES; do for TESTFILE in $TESTFILES; do
npx nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js $TESTFILE --env=chrome || TEST_EXITCODE=1 npx nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js $TESTFILE --env=chrome || TEST_EXITCODE=1
done done

@ -1,26 +0,0 @@
#!/usr/bin/env bash
set -e
BUILD_ID=${CIRCLE_BUILD_NUM:-${TRAVIS_JOB_NUMBER}}
echo "$BUILD_ID"
TEST_EXITCODE=0
yarn build etherscan
yarn run serve:production &
npx nx serve etherscan &
sleep 5
yarn run build:e2e
TESTFILES=$(grep -IRiL "\'@disabled\': \?true" "dist/apps/remix-ide-e2e/src/tests" | grep "etherscan_api" | sort | circleci tests split )
for TESTFILE in $TESTFILES; do
npx nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js $TESTFILE --env=chrome || TEST_EXITCODE=1
done
echo "$TEST_EXITCODE"
if [ "$TEST_EXITCODE" -eq 1 ]
then
exit 1
fi

@ -1,26 +0,0 @@
#!/usr/bin/env bash
set -e
BUILD_ID=${CIRCLE_BUILD_NUM:-${TRAVIS_JOB_NUMBER}}
echo "$BUILD_ID"
TEST_EXITCODE=0
yarn build vyper
yarn run serve:production &
npx nx serve vyper &
sleep 5
yarn run build:e2e
TESTFILES=$(grep -IRiL "\'@disabled\': \?true" "dist/apps/remix-ide-e2e/src/tests" | grep "vyper_api" | sort | circleci tests split )
for TESTFILE in $TESTFILES; do
npx nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js $TESTFILE --env=chrome || TEST_EXITCODE=1
done
echo "$TEST_EXITCODE"
if [ "$TEST_EXITCODE" -eq 1 ]
then
exit 1
fi

@ -2,7 +2,6 @@
set -e set -e
yarn run build:e2e
TESTFILES=$(grep -IRiL "\'@disabled\': \?true" "dist/apps/remix-ide-e2e/src/tests" | grep "\.flaky" | sort ) TESTFILES=$(grep -IRiL "\'@disabled\': \?true" "dist/apps/remix-ide-e2e/src/tests" | grep "\.flaky" | sort )
# count test files # count test files
@ -19,10 +18,8 @@ echo "$BUILD_ID"
TEST_EXITCODE=0 TEST_EXITCODE=0
yarn run ganache-cli & yarn run ganache-cli &
npx http-server -p 9090 --cors='*' ./node_modules &
yarn run serve:production & yarn run serve:production &
echo 'sharing folder: ' $PWD '/apps/remix-ide/contracts' &
npx nx serve remix-ide-e2e-src-local-plugin &
sleep 5 sleep 5
for TESTFILE in $TESTFILES; do for TESTFILE in $TESTFILES; do

@ -30,17 +30,15 @@
}, },
"configurations": { "configurations": {
"development": { "development": {
"extractLicenses": false, "optimization": false,
"sourceMap": true, "generateIndexHtml": true,
"vendorChunk": true, "extractCss": false
"optimization": false
}, },
"production": { "production": {
"optimization": true, "optimization": true,
"outputHashing": "all", "generateIndexHtml": true,
"sourceMap": false, "extractCss": false,
"namedChunks": false,
"extractLicenses": false,
"vendorChunk": false "vendorChunk": false
} }
} }
@ -50,15 +48,18 @@
"defaultConfiguration": "development", "defaultConfiguration": "development",
"options": { "options": {
"buildTarget": "remix-ide:build", "buildTarget": "remix-ide:build",
"watch": true,
"liveReload": true,
"hmr": false
}, },
"configurations": { "configurations": {
"development": { "development": {
"buildTarget": "remix-ide:build:development", "buildTarget": "remix-ide:build:development",
"port": 8080 "port": 8080
}, },
"hot":{
"buildTarget": "remix-ide:build:development",
"port": 8080,
"hmr": true
},
"production": { "production": {
"buildTarget": "remix-ide:build:production", "buildTarget": "remix-ide:build:production",
"port": 8080 "port": 8080

@ -119,8 +119,6 @@ class AppComponent {
this.engine = new RemixEngine() this.engine = new RemixEngine()
this.engine.register(appManager); this.engine.register(appManager);
const matomoDomains = { const matomoDomains = {
'remix-alpha.ethereum.org': 27, 'remix-alpha.ethereum.org': 27,
'remix-beta.ethereum.org': 25, 'remix-beta.ethereum.org': 25,
@ -450,7 +448,11 @@ class AppComponent {
if ( if (
this.appManager.pluginLoader.current === 'queryParams' && this.appManager.pluginLoader.current === 'queryParams' &&
this.workspace.length > 0 this.workspace.length > 0
) { this.menuicons.select(this.workspace[this.workspace.length - 1]) } ) {
this.menuicons.select(this.workspace[this.workspace.length - 1])
} else {
this.appManager.call('tabs', 'focus', 'home')
}
} }
if (params.call) { if (params.call) {
@ -484,19 +486,16 @@ class AppComponent {
} }
} }
} }
}) })
.catch(console.error) .catch(console.error)
} }
const loadedElement = document.createElement('span') const loadedElement = document.createElement('span')
loadedElement.setAttribute('data-id', 'apploaded') loadedElement.setAttribute('data-id', 'apploaded')
document.body.appendChild(loadedElement) document.body.appendChild(loadedElement)
}) })
// activate solidity plugin // activate solidity plugin
this.appManager.activatePlugin(['solidity', 'udapp', 'deploy-libraries', 'link-libraries', 'openzeppelin-proxy']) this.appManager.activatePlugin(['solidity', 'udapp', 'deploy-libraries', 'link-libraries', 'openzeppelin-proxy'])
// Load and start the service who manager layout and frame
} }
} }

@ -1,12 +1,7 @@
'use strict' 'use strict'
import { Plugin } from '@remixproject/engine' import { Plugin } from '@remixproject/engine'
import prettier from 'prettier/standalone'
import { Options } from 'prettier'; import { Options } from 'prettier';
import sol from './code-format/index' import sol from './code-format/index'
import * as ts from 'prettier/parser-typescript'
import * as babel from 'prettier/parser-babel'
import * as espree from 'prettier/parser-espree'
import * as yml from 'prettier/parser-yaml'
import path from 'path' import path from 'path'
import yaml from 'js-yaml' import yaml from 'js-yaml'
import toml from 'toml' import toml from 'toml'
@ -67,12 +62,28 @@ const defaultOptions = {
export class CodeFormat extends Plugin { export class CodeFormat extends Plugin {
prettier: any
ts: any
babel: any
espree: any
yml: any
sol: any
constructor() { constructor() {
super(profile) super(profile)
} }
async format(file: string) { async format(file: string) {
// lazy load
if (!this.prettier) {
this.prettier = await import('prettier/standalone')
this.ts = await import('prettier/parser-typescript')
this.babel = await import('prettier/parser-babel')
this.espree = await import('prettier/parser-espree')
this.yml = await import('prettier/parser-yaml')
}
try { try {
const content = await this.call('fileManager', 'readFile', file) const content = await this.call('fileManager', 'readFile', file)
if (!content) return if (!content) return
@ -241,8 +252,8 @@ export class CodeFormat extends Plugin {
} }
const result = prettier.format(content, { const result = this.prettier.format(content, {
plugins: [sol as any, ts, babel, espree, yml], plugins: [sol as any, this.ts, this.babel, this.espree, this.yml],
parser: parserName, parser: parserName,
...options ...options
}) })

@ -7,13 +7,20 @@ import { CodeParser } from "../code-parser";
import { fileDecoration, fileDecorationType } from '@remix-ui/file-decorators' import { fileDecoration, fileDecorationType } from '@remix-ui/file-decorators'
import { sourceMappingDecoder } from '@remix-project/remix-debug' import { sourceMappingDecoder } from '@remix-project/remix-debug'
import { CompilerRetriggerMode, CompilationSourceCode } from '@remix-project/remix-solidity'; import { CompilerRetriggerMode, CompilationSourceCode } from '@remix-project/remix-solidity';
import { MarkerSeverity } from 'monaco-editor';
import { findLinesInStringWithMatch, SearchResultLine } from '@remix-ui/search' import { findLinesInStringWithMatch, SearchResultLine } from '@remix-ui/search'
import { lastCompilationResult } from '@remixproject/plugin-api'; import { lastCompilationResult } from '@remixproject/plugin-api';
import { monacoTypes } from '@remix-ui/editor';
enum MarkerSeverity {
Hint = 1,
Info = 2,
Warning = 4,
Error = 8
}
type errorMarker = { type errorMarker = {
message: string message: string
severity: MarkerSeverity severity: monacoTypes.MarkerSeverity
position: { position: {
start: { start: {
line: number line: number

@ -13,7 +13,8 @@ export type JsonDataRequest = {
export type JsonDataResult = { export type JsonDataResult = {
id: number, id: number,
jsonrpc: string // version jsonrpc: string // version
result: any result?: any,
error?: any,
} }
export type RejectRequest = (error: Error) => void export type RejectRequest = (error: Error) => void

@ -57,14 +57,20 @@ export class InjectedProvider extends Plugin implements IProvider {
// This will be displayed on UI tooltip as 'cannot get account list: Environment Updated !!' // This will be displayed on UI tooltip as 'cannot get account list: Environment Updated !!'
if (!this.provider) { if (!this.provider) {
this.call('notification', 'toast', 'No injected provider (e.g Metamask) has been found.') this.call('notification', 'toast', 'No injected provider (e.g Metamask) has been found.')
return reject(new Error('no injected provider found.')) return resolve({ jsonrpc: '2.0', error: 'no injected provider found', id: data.id })
} }
try { try {
if ((window as any) && typeof (window as any).ethereum.request === "function") (window as any).ethereum.request({ method: "eth_requestAccounts" }); let resultData = await this.provider.currentProvider.send(data.method, data.params)
const resultData = await this.provider.currentProvider.send(data.method, data.params) if (resultData) {
resolve({ jsonrpc: '2.0', result: resultData.result, id: data.id }) if (resultData.jsonrpc && resultData.jsonrpc === '2.0') {
resultData = resultData.result
}
resolve({ jsonrpc: '2.0', result: resultData, id: data.id })
} else {
resolve({ jsonrpc: '2.0', error: 'no return data provided', id: data.id })
}
} catch (error) { } catch (error) {
reject(error) resolve({ jsonrpc: '2.0', error: error.message, id: data.id })
} }
} }
} }

@ -15,7 +15,7 @@ export class MainnetForkVMProvider extends BasicVMProvider {
}, blockchain) }, blockchain)
this.blockchain = blockchain this.blockchain = blockchain
this.fork = 'london' this.fork = 'london'
this.nodeUrl = 'https://rpc.archivenode.io/e50zmkroshle2e2e50zm0044i7ao04ym' this.nodeUrl = 'https://mainnet.infura.io/v3/08b2a484451e4635a28b3d8234f24332'
this.blockNumber = 'latest' this.blockNumber = 'latest'
} }

@ -62,7 +62,7 @@ export class CompileAndRun extends Plugin {
if (clearAllInstances) { if (clearAllInstances) {
await this.call('udapp', 'clearAllInstances') await this.call('udapp', 'clearAllInstances')
} }
await this.call('scriptRunner', 'execute', content) await this.call('scriptRunner', 'execute', content, fileName)
} catch (e) { } catch (e) {
this.call('notification', 'toast', e.message || e) this.call('notification', 'toast', e.message || e)
} }

@ -2,7 +2,7 @@
import React from 'react' // eslint-disable-line import React from 'react' // eslint-disable-line
import { SolidityCompiler } from '@remix-ui/solidity-compiler' // eslint-disable-line import { SolidityCompiler } from '@remix-ui/solidity-compiler' // eslint-disable-line
import { CompileTabLogic } from '@remix-ui/solidity-compiler' // eslint-disable-line import { CompileTabLogic } from '@remix-ui/solidity-compiler' // eslint-disable-line
import { CompilerApiMixin } from '@remixproject/solidity-compiler-plugin' // eslint-disable-line import { CompilerApiMixin } from '@remix-ui/solidity-compiler'
import { ViewPlugin } from '@remixproject/engine-web' import { ViewPlugin } from '@remixproject/engine-web'
import { QueryParams } from '@remix-project/remix-lib' import { QueryParams } from '@remix-project/remix-lib'
// import { ICompilerApi } from '@remix-project/remix-lib' // import { ICompilerApi } from '@remix-project/remix-lib'

@ -1,6 +1,6 @@
import Web3 from 'web3' import Web3 from 'web3'
import { DebuggerUI } from '@remix-ui/debugger-ui' // eslint-disable-line import { DebuggerUI } from '@remix-ui/debugger-ui' // eslint-disable-line
import { DebuggerApiMixin } from '@remixproject/debugger-plugin' // eslint-disable-line import { DebuggerApiMixin } from '@remix-ui/debugger-ui'
import { ViewPlugin } from '@remixproject/engine-web' import { ViewPlugin } from '@remixproject/engine-web'
import * as packageJson from '../../../../../package.json' import * as packageJson from '../../../../../package.json'
import React from 'react' // eslint-disable-line import React from 'react' // eslint-disable-line

@ -3,7 +3,8 @@
"filePanel.workspace": "WORKSPACES", "filePanel.workspace": "WORKSPACES",
"filePanel.create": "Create", "filePanel.create": "Create",
"filePanel.clone": "Clone", "filePanel.clone": "Clone",
"filePanel.download": "Backup", "filePanel.download": "Download",
"filePanel.backup": "Backup",
"filePanel.restore": "Restore", "filePanel.restore": "Restore",
"filePanel.workspace.create": "Create Workspace", "filePanel.workspace.create": "Create Workspace",
"filePanel.workspace.rename": "Rename Workspace", "filePanel.workspace.rename": "Rename Workspace",
@ -14,7 +15,7 @@
"filePanel.workspace.deleteAllConfirm2": "Deleted workspaces can not be restored in any manner.", "filePanel.workspace.deleteAllConfirm2": "Deleted workspaces can not be restored in any manner.",
"filePanel.workspace.name": "Workspace name", "filePanel.workspace.name": "Workspace name",
"filePanel.workspace.chooseTemplate": "Choose a template", "filePanel.workspace.chooseTemplate": "Choose a template",
"filePanel.workspace.download": "Backup Workspaces", "filePanel.workspace.backup": "Backup Workspaces",
"filePanel.workspace.restore": "Restore Workspaces from the Backup", "filePanel.workspace.restore": "Restore Workspaces from the Backup",
"filePanel.workspace.clone": "Clone Git Repository", "filePanel.workspace.clone": "Clone Git Repository",
"filePanel.workspace.cloneMessage": "Please provide a valid git repository url.", "filePanel.workspace.cloneMessage": "Please provide a valid git repository url.",
@ -39,10 +40,11 @@
"filePanel.paste": "Paste", "filePanel.paste": "Paste",
"filePanel.compile": "Compile", "filePanel.compile": "Compile",
"filePanel.compileForNahmii": "Compile for Nahmii", "filePanel.compileForNahmii": "Compile for Nahmii",
"filePanel.createNewFile": "Create New File", "filePanel.createNewFile": "Create new file",
"filePanel.createNewFolder": "Create New Folder", "filePanel.createNewFolder": "Create new folder",
"filePanel.publishToGist": "Publish all the current workspace files to a github gist", "filePanel.publishToGist": "Publish all files to GitHub gist",
"filePanel.uploadFile": "Load a local file into current workspace", "filePanel.uploadFile": "Upload files",
"filePanel.uploadFolder": "Upload folder",
"filePanel.updateGist": "Update the current [gist] explorer", "filePanel.updateGist": "Update the current [gist] explorer",
"filePanel.viewAllBranches": "View all branches", "filePanel.viewAllBranches": "View all branches",
"filePanel.createBranch": "Create branch", "filePanel.createBranch": "Create branch",

@ -4,6 +4,7 @@
"filePanel.create": "新建", "filePanel.create": "新建",
"filePanel.clone": "克隆", "filePanel.clone": "克隆",
"filePanel.download": "下载", "filePanel.download": "下载",
"filePanel.backup": "Backup",
"filePanel.restore": "恢复", "filePanel.restore": "恢复",
"filePanel.workspace.create": "新建工作空间", "filePanel.workspace.create": "新建工作空间",
"filePanel.workspace.rename": "重命名工作空间", "filePanel.workspace.rename": "重命名工作空间",

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

@ -26,7 +26,7 @@
<meta http-equiv="X-UA-Compatible" content="chrome=1"> <meta http-equiv="X-UA-Compatible" content="chrome=1">
<title>Remix - Ethereum IDE</title> <title>Remix - Ethereum IDE</title>
<link rel="stylesheet" href="assets/css/pygment_trac.css"> <link rel="stylesheet" href="assets/css/pygment_trac.css">
<link rel="icon" type="x-icon" href="assets/img/icon.png"> <link rel="icon" type="x-icon" href="assets/img/remix-logo-blue.png">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/intro.js/4.1.0/introjs.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/intro.js/4.1.0/introjs.min.css">
<link rel="stylesheet" integrity="ha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" <link rel="stylesheet" integrity="ha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf"
crossorigin="anonymous" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css"> crossorigin="anonymous" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css">

@ -1,45 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<!--
The MIT License (MIT)
Copyright (c) 2014, 2015, the individual contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<title>Remix - Ethereum IDE</title>
<link rel="stylesheet" href="assets/css/pygment_trac.css">
<link rel="icon" type="x-icon" href="assets/img/icon.png">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/intro.js/4.1.0/introjs.min.css">
<link rel="stylesheet" integrity="ha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf"
crossorigin="anonymous" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css">
<script src="assets/js/browserfs.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/intro.js/2.7.0/introjs.min.css">
</head>
<body>
<div id="root"></div>
<script src="https://kit.fontawesome.com/41dd021e94.js" crossorigin="anonymous"></script>
<script type="text/javascript" src="assets/js/intro.min.js"></script>
</body>
</html>

@ -3,7 +3,6 @@
"compilerOptions": { "compilerOptions": {
"outDir": "../../dist/out-tsc", "outDir": "../../dist/out-tsc",
"types": ["node"], "types": ["node"],
"module": "es2020"
}, },
"exclude": ["**/*.spec.ts", "**/*.spec.tsx", "./src/assets/**/*"], "exclude": ["**/*.spec.ts", "**/*.spec.tsx", "./src/assets/**/*"],
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]

@ -5,7 +5,7 @@
"allowJs": true, "allowJs": true,
"esModuleInterop": true, "esModuleInterop": true,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"types": ["node", "jest"], "types": ["node"],
"resolveJsonModule": true "resolveJsonModule": true
}, },
"files": [ "files": [

@ -3,7 +3,7 @@
"compilerOptions": { "compilerOptions": {
"outDir": "../../dist/out-tsc", "outDir": "../../dist/out-tsc",
"module": "commonjs", "module": "commonjs",
"types": ["jest", "node"] "types": ["node"]
}, },
"include": [ "include": [
"**/*.spec.ts", "**/*.spec.ts",

@ -60,7 +60,7 @@ module.exports = composePlugins(withNx(), withReact(), (config) => {
config.plugins.push( config.plugins.push(
new CopyPlugin({ new CopyPlugin({
patterns: [ patterns: [
{ from: '../../node_modules/monaco-editor/dev/vs', to: 'assets/js/monaco-editor/dev/vs' } { from: '../../node_modules/monaco-editor/min/vs', to: 'assets/js/monaco-editor/min/vs' }
].filter(Boolean) ].filter(Boolean)
}), }),
new webpack.ProvidePlugin({ new webpack.ProvidePlugin({
@ -79,7 +79,6 @@ module.exports = composePlugins(withNx(), withReact(), (config) => {
config.ignoreWarnings = [/Failed to parse source map/] // ignore source-map-loader warnings config.ignoreWarnings = [/Failed to parse source map/] // ignore source-map-loader warnings
// set minimizer // set minimizer
config.optimization.minimizer = [ config.optimization.minimizer = [
new TerserPlugin({ new TerserPlugin({

@ -1,4 +1,9 @@
{ {
"presets": ["@nrwl/react/babel"], "presets": ["@babel/preset-env", ["@babel/preset-react",
"plugins": [] {"runtime": "automatic"}
]],
"plugins": ["@babel/plugin-proposal-class-properties", "@babel/plugin-transform-runtime", "@babel/plugin-proposal-nullish-coalescing-operator"],
"ignore": [
"**/node_modules/**"
]
} }

@ -2,7 +2,7 @@
/* eslint-disable no-unused-vars */ /* eslint-disable no-unused-vars */
import { PluginClient } from '@remixproject/plugin' import { PluginClient } from '@remixproject/plugin'
import { createClient } from '@remixproject/plugin-webview' import { createClient } from '@remixproject/plugin-webview'
import { CompilerApiMixin } from './compiler-api' import { CompilerApiMixin } from '@remix-ui/solidity-compiler'
import { ICompilerApi } from '@remix-project/remix-lib' import { ICompilerApi } from '@remix-project/remix-lib'
import { CompileTabLogic } from '@remix-ui/solidity-compiler' import { CompileTabLogic } from '@remix-ui/solidity-compiler'

@ -1 +0,0 @@
export * from './app/compiler-api'

@ -9,7 +9,6 @@
"../../node_modules/@nrwl/react/typings/image.d.ts" "../../node_modules/@nrwl/react/typings/image.d.ts"
], ],
"exclude": [ "exclude": [
"jest.config.ts",
"**/*.spec.ts", "**/*.spec.ts",
"**/*.test.ts", "**/*.test.ts",
"**/*.spec.tsx", "**/*.spec.tsx",

@ -1,44 +1,93 @@
const nxWebpack = require('@nrwl/react/plugins/webpack') const { composePlugins, withNx } = require('@nrwl/webpack')
const { withReact } = require('@nrwl/react')
const webpack = require('webpack') const webpack = require('webpack')
const version = require('../../package.json').version
const fs = require('fs')
const TerserPlugin = require("terser-webpack-plugin")
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin")
module.exports = config => { const versionData = {
const nxWebpackConfig = nxWebpack(config) version: version,
const webpackConfig = { timestamp: Date.now(),
...nxWebpackConfig, mode: process.env.NODE_ENV === 'production' ? 'production' : 'development'
resolve: { }
...nxWebpackConfig.resolve,
fallback: { fs.writeFileSync('./apps/remix-ide/src/assets/version.json', JSON.stringify(versionData))
...nxWebpackConfig.resolve.fallback,
"crypto": require.resolve("crypto-browserify"), // Nx plugins for webpack.
"stream": require.resolve("stream-browserify"), module.exports = composePlugins(withNx(), withReact(), (config) => {
"path": require.resolve("path-browserify"), // Update the webpack config as needed here.
"http": require.resolve("stream-http"), // e.g. `config.plugins.push(new MyPlugin())`
"https": require.resolve("https-browserify"),
"zlib": require.resolve("browserify-zlib"), // add fallback for node modules
"fs": false, config.resolve.fallback = {
"module": false, ...config.resolve.fallback,
"tls": false, "crypto": require.resolve("crypto-browserify"),
"net": false, "stream": require.resolve("stream-browserify"),
"readline": false, "path": require.resolve("path-browserify"),
"child_process": false, "http": require.resolve("stream-http"),
"buffer": require.resolve("buffer/"), "https": require.resolve("https-browserify"),
}, "constants": require.resolve("constants-browserify"),
}, "os": false, //require.resolve("os-browserify/browser"),
plugins: [ "timers": false, // require.resolve("timers-browserify"),
...nxWebpackConfig.plugins, "zlib": require.resolve("browserify-zlib"),
new webpack.ProvidePlugin({ "fs": false,
Buffer: ['buffer', 'Buffer'], "module": false,
}), "tls": false,
], "net": false,
"readline": false,
"child_process": false,
"buffer": require.resolve("buffer/"),
"vm": require.resolve('vm-browserify'),
} }
if (process.env.NODE_ENV === 'production') {
return { // add externals
...webpackConfig, config.externals = {
mode: 'production', ...config.externals,
devtool: 'source-map', solc: 'solc',
}
} else {
return webpackConfig
} }
}
// add public path
config.output.publicPath = '/'
// add copy & provide plugin
config.plugins.push(
new webpack.ProvidePlugin({
Buffer: ['buffer', 'Buffer'],
url: ['url', 'URL'],
process: 'process/browser',
})
)
// souce-map loader
config.module.rules.push({
test: /\.js$/,
use: ["source-map-loader"],
enforce: "pre"
})
config.ignoreWarnings = [/Failed to parse source map/] // ignore source-map-loader warnings
// set minimizer
config.optimization.minimizer = [
new TerserPlugin({
parallel: true,
terserOptions: {
ecma: 2015,
compress: false,
mangle: false,
format: {
comments: false,
},
},
extractComments: false,
}),
new CssMinimizerPlugin(),
];
return config;
});

@ -3,9 +3,6 @@
"$schema": "../../node_modules/nx/schemas/project-schema.json", "$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/vyper/src", "sourceRoot": "apps/vyper/src",
"projectType": "application", "projectType": "application",
"implicitDependencies": [
"remix-debug"
],
"targets": { "targets": {
"build": { "build": {
"executor": "@nrwl/webpack:webpack", "executor": "@nrwl/webpack:webpack",

@ -1,31 +1,83 @@
const nxWebpack = require('@nrwl/react/plugins/webpack') const { composePlugins, withNx } = require('@nrwl/webpack')
const webpack = require('webpack')
module.exports = config => { const TerserPlugin = require("terser-webpack-plugin")
const nxWebpackConfig = nxWebpack(config) const CssMinimizerPlugin = require("css-minimizer-webpack-plugin")
const webpackConfig = {
...nxWebpackConfig,
resolve : { // Nx plugins for webpack.
...nxWebpackConfig.resolve, module.exports = composePlugins(withNx(), (config) => {
fallback: { // Update the webpack config as needed here.
...nxWebpackConfig.resolve.fallback, // e.g. `config.plugins.push(new MyPlugin())`
"crypto": require.resolve("crypto-browserify"),
"stream": require.resolve("stream-browserify"), // add fallback for node modules
"http" : require.resolve("stream-http"), config.resolve.fallback = {
"https" : require.resolve("https-browserify"), ...config.resolve.fallback,
"path" : require.resolve("path-browserify"), "crypto": require.resolve("crypto-browserify"),
"module": false, "stream": require.resolve("stream-browserify"),
"fs" : false "path": require.resolve("path-browserify"),
}, "http": require.resolve("stream-http"),
} "https": require.resolve("https-browserify"),
"constants": require.resolve("constants-browserify"),
"os": false, //require.resolve("os-browserify/browser"),
"timers": false, // require.resolve("timers-browserify"),
"zlib": require.resolve("browserify-zlib"),
"fs": false,
"module": false,
"tls": false,
"net": false,
"readline": false,
"child_process": false,
"buffer": require.resolve("buffer/"),
"vm": require.resolve('vm-browserify'),
} }
if (process.env.NODE_ENV === 'production') {
return { // add externals
...webpackConfig, config.externals = {
mode: 'production', ...config.externals,
devtool: 'source-map', solc: 'solc',
}
} else {
return webpackConfig
} }
}
// add public path
config.output.publicPath = '/'
// add copy & provide plugin
config.plugins.push(
new webpack.ProvidePlugin({
Buffer: ['buffer', 'Buffer'],
url: ['url', 'URL'],
process: 'process/browser',
})
)
// souce-map loader
config.module.rules.push({
test: /\.js$/,
use: ["source-map-loader"],
enforce: "pre"
})
config.ignoreWarnings = [/Failed to parse source map/] // ignore source-map-loader warnings
// set minimizer
config.optimization.minimizer = [
new TerserPlugin({
parallel: true,
terserOptions: {
ecma: 2015,
compress: false,
mangle: false,
format: {
comments: false,
},
},
extractComments: false,
}),
new CssMinimizerPlugin(),
];
return config;
});

@ -1,5 +1,5 @@
module.exports = { module.exports = {
"presets": ["@babel/preset-typescript", "@babel/preset-env", "@babel/preset-react"], "presets": ["@babel/preset-typescript", "@babel/preset-env", "@nrwl/react/babel"],
"plugins": [ "plugins": [
"babel-plugin-replace-ts-export-assignment", "babel-plugin-replace-ts-export-assignment",
"@babel/plugin-transform-modules-commonjs", "@babel/plugin-transform-modules-commonjs",

@ -1,4 +0,0 @@
const nxPreset = require('@nrwl/jest/preset');
module.exports = { ...nxPreset }

@ -1,7 +1,7 @@
{ {
"extends": "../../tsconfig.base.json", "extends": "../../tsconfig.base.json",
"compilerOptions": { "compilerOptions": {
"types": ["jest", "node"] "types": ["node"]
}, },
"include": ["**/*.ts"] "include": ["**/*.ts"]
} }

@ -3,7 +3,6 @@
"version": "0.0.1", "version": "0.0.1",
"description": "This library was generated with [Nx](https://nx.dev).", "description": "This library was generated with [Nx](https://nx.dev).",
"main": "src/index.js", "main": "src/index.js",
"type": "module",
"author": "Remix Team", "author": "Remix Team",
"license": "ISC" "license": "ISC"
} }

@ -1,11 +1,6 @@
{ {
"extends": "./tsconfig.json", "extends": "./tsconfig.json",
"compilerOptions": { "compilerOptions": {
"module": "commonjs",
"outDir": "../../dist/out-tsc",
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"declaration": true,
"types": ["node"] "types": ["node"]
}, },
"exclude": [ "exclude": [

@ -1,26 +0,0 @@
module.exports = {
name: 'remix-solidity',
preset: '../../jest.config.js',
verbose: true,
silent: false, // Silent console messages, specially the 'remix-simulator' ones
transform: {
'^.+\\.[tj]sx?$': ['ts-jest',
{
useESM: true,
}]
},
transformIgnorePatterns: ["/node_modules/", "/dist/", "\\.pnp\\.[^\\/]+$"],
rootDir: "./",
testTimeout: 40000,
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html', 'json'],
// Coverage
collectCoverage: true,
coverageReporters: ['text', 'text-summary'],
collectCoverageFrom: [
"**/*.ts",
"!**/sol/**",
"!src/types.ts",
"!src/logger.ts"
],
coverageDirectory: '../../coverage/libs/remix-solidity'
};

@ -1,7 +1,7 @@
{ {
"extends": "../../tsconfig.base.json", "extends": "../../tsconfig.base.json",
"compilerOptions": { "compilerOptions": {
"types": ["jest", "node"], "types": ["node"],
}, },
"include": ["**/*.ts"] "include": ["**/*.ts"]
} }

@ -3,7 +3,7 @@
"compilerOptions": { "compilerOptions": {
"outDir": "../../dist/out-tsc", "outDir": "../../dist/out-tsc",
"module": "commonjs", "module": "commonjs",
"types": ["jest", "node"] "types": ["node"]
}, },
"include": [ "include": [
"**/*.spec.ts", "**/*.spec.ts",

@ -1,2 +1,3 @@
export * from './lib/debugger-ui' export * from './lib/debugger-ui'
export * from './lib/idebugger-api' export * from './lib/idebugger-api'
export * from './lib/api/debugger-api'

@ -1 +1,2 @@
export * from './lib/remix-ui-editor' export * from './lib/remix-ui-editor'
export { default as monacoTypes } from './types/monaco'

@ -1,5 +1,5 @@
import { IRange } from "monaco-editor";
import { monacoTypes } from '@remix-ui/editor';
export interface Action { export interface Action {
type: string; type: string;
payload: Record<string, any> payload: Record<string, any>
@ -58,7 +58,7 @@ export const reducerActions = (models = initialState, action: Action) => {
} }
case 'REVEAL_RANGE': { case 'REVEAL_RANGE': {
if (!editor) return models if (!editor) return models
const range: IRange = { const range: monacoTypes.IRange = {
startLineNumber: action.payload.startLineNumber + 1, startLineNumber: action.payload.startLineNumber + 1,
startColumn: action.payload.startColumn, startColumn: action.payload.startColumn,
endLineNumber: action.payload.endLineNumber + 1, endLineNumber: action.payload.endLineNumber + 1,

@ -1,6 +1,5 @@
import { IRange } from "monaco-editor";
import monaco from "../../../types/monaco";
import path from "path"; import path from "path";
import { monacoTypes } from '@remix-ui/editor';
type CodeParserImportsData = { type CodeParserImportsData = {
files?: string[], files?: string[],
@ -8,7 +7,7 @@ type CodeParserImportsData = {
packages?: string[], packages?: string[],
} }
export function getStringCompletionItems(range: IRange, monaco): monaco.languages.CompletionItem[] { export function getStringCompletionItems(range: monacoTypes.IRange, monaco): monacoTypes.languages.CompletionItem[] {
return [ return [
{ {
detail: 'concatenate an arbitrary number of string values', detail: 'concatenate an arbitrary number of string values',
@ -21,7 +20,7 @@ export function getStringCompletionItems(range: IRange, monaco): monaco.language
] ]
} }
export function getBytesCompletionItems(range: IRange, monaco): monaco.languages.CompletionItem[] { export function getBytesCompletionItems(range: monacoTypes.IRange, monaco): monacoTypes.languages.CompletionItem[] {
return [ return [
{ {
detail: 'concatenate an arbitrary number of values', detail: 'concatenate an arbitrary number of values',
@ -35,7 +34,7 @@ export function getBytesCompletionItems(range: IRange, monaco): monaco.languages
} }
export function getBlockCompletionItems(range: IRange, monaco): monaco.languages.CompletionItem[] { export function getBlockCompletionItems(range: monacoTypes.IRange, monaco): monacoTypes.languages.CompletionItem[] {
return [ return [
{ {
detail: '(address): Current block miner’s address', detail: '(address): Current block miner’s address',
@ -97,7 +96,7 @@ export function getBlockCompletionItems(range: IRange, monaco): monaco.languages
]; ];
} }
export function getCompletionSnippets(range: IRange, monaco): monaco.languages.CompletionItem[] { export function getCompletionSnippets(range: monacoTypes.IRange, monaco): monacoTypes.languages.CompletionItem[] {
return [ return [
{ {
label: 'contract', label: 'contract',
@ -193,7 +192,7 @@ export function getCompletionSnippets(range: IRange, monaco): monaco.languages.C
] ]
} }
export function getTxCompletionItems(range: IRange, monaco): monaco.languages.CompletionItem[] { export function getTxCompletionItems(range: monacoTypes.IRange, monaco): monacoTypes.languages.CompletionItem[] {
return [ return [
{ {
detail: '(uint): gas price of the transaction', detail: '(uint): gas price of the transaction',
@ -212,7 +211,7 @@ export function getTxCompletionItems(range: IRange, monaco): monaco.languages.Co
]; ];
} }
export function getMsgCompletionItems(range: IRange, monaco): monaco.languages.CompletionItem[] { export function getMsgCompletionItems(range: monacoTypes.IRange, monaco): monacoTypes.languages.CompletionItem[] {
return [ return [
{ {
detail: '(bytes): complete calldata', detail: '(bytes): complete calldata',
@ -252,7 +251,7 @@ export function getMsgCompletionItems(range: IRange, monaco): monaco.languages.C
]; ];
} }
export function getAbiCompletionItems(range: IRange, monaco): monaco.languages.CompletionItem[] { export function getAbiCompletionItems(range: monacoTypes.IRange, monaco): monacoTypes.languages.CompletionItem[] {
return [ return [
{ {
detail: 'encode(..) returs (bytes): ABI-encodes the given arguments', detail: 'encode(..) returs (bytes): ABI-encodes the given arguments',
@ -298,7 +297,7 @@ export function getAbiCompletionItems(range: IRange, monaco): monaco.languages.C
} }
export function GetCompletionTypes(range: IRange, monaco): monaco.languages.CompletionItem[] { export function GetCompletionTypes(range: monacoTypes.IRange, monaco): monacoTypes.languages.CompletionItem[] {
const completionItems = []; const completionItems = [];
const types = ['address', 'string', 'bytes', 'byte', 'int', 'uint', 'bool', 'hash']; const types = ['address', 'string', 'bytes', 'byte', 'int', 'uint', 'bool', 'hash'];
for (let index = 8; index <= 256; index += 8) { for (let index = 8; index <= 256; index += 8) {
@ -314,8 +313,8 @@ export function GetCompletionTypes(range: IRange, monaco): monaco.languages.Comp
return completionItems; return completionItems;
} }
function CreateCompletionItem(label: string, kind: monaco.languages.CompletionItemKind, detail: string, range: IRange) { function CreateCompletionItem(label: string, kind: monacoTypes.languages.CompletionItemKind, detail: string, range: monacoTypes.IRange) {
const completionItem: monaco.languages.CompletionItem = { const completionItem: monacoTypes.languages.CompletionItem = {
label, label,
kind, kind,
detail, detail,
@ -327,7 +326,7 @@ function CreateCompletionItem(label: string, kind: monaco.languages.CompletionIt
return completionItem; return completionItem;
} }
export function GetCompletionKeywords(range: IRange, monaco): monaco.languages.CompletionItem[] { export function GetCompletionKeywords(range: monacoTypes.IRange, monaco): monacoTypes.languages.CompletionItem[] {
const completionItems = []; const completionItems = [];
const keywords = ['modifier', 'mapping', 'break', 'continue', 'delete', 'else', 'for', const keywords = ['modifier', 'mapping', 'break', 'continue', 'delete', 'else', 'for',
'after', 'promise', 'alias', 'apply', 'auto', 'copyof', 'default', 'define', 'final', 'implements', 'after', 'promise', 'alias', 'apply', 'auto', 'copyof', 'default', 'define', 'final', 'implements',
@ -337,7 +336,7 @@ export function GetCompletionKeywords(range: IRange, monaco): monaco.languages.C
'private', 'public', 'external', 'internal', 'payable', 'nonpayable', 'view', 'pure', 'case', 'do', 'else', 'finally', 'private', 'public', 'external', 'internal', 'payable', 'nonpayable', 'view', 'pure', 'case', 'do', 'else', 'finally',
'in', 'instanceof', 'return', 'throw', 'try', 'catch', 'typeof', 'yield', 'void', 'virtual', 'override']; 'in', 'instanceof', 'return', 'throw', 'try', 'catch', 'typeof', 'yield', 'void', 'virtual', 'override'];
keywords.forEach(unit => { keywords.forEach(unit => {
const completionItem: monaco.languages.CompletionItem = { const completionItem: monacoTypes.languages.CompletionItem = {
label: unit, label: unit,
kind: monaco.languages.CompletionItemKind.Keyword, kind: monaco.languages.CompletionItemKind.Keyword,
detail: unit + ' keyword', detail: unit + ' keyword',
@ -366,7 +365,7 @@ export function GetCompletionKeywords(range: IRange, monaco): monaco.languages.C
} }
export function GeCompletionUnits(range: IRange, monaco): monaco.languages.CompletionItem[] { export function GeCompletionUnits(range: monacoTypes.IRange, monaco): monacoTypes.languages.CompletionItem[] {
const completionItems = []; const completionItems = [];
const etherUnits = ['wei', 'gwei', 'finney', 'szabo', 'ether']; const etherUnits = ['wei', 'gwei', 'finney', 'szabo', 'ether'];
etherUnits.forEach(unit => { etherUnits.forEach(unit => {
@ -390,10 +389,10 @@ export function GeCompletionUnits(range: IRange, monaco): monaco.languages.Compl
return completionItems; return completionItems;
} }
export function GetImports(range: IRange export function GetImports(range: monacoTypes.IRange
, monaco, data: CodeParserImportsData , monaco, data: CodeParserImportsData
, word: string , word: string
): monaco.languages.CompletionItem[] { ): monacoTypes.languages.CompletionItem[] {
let list = [] let list = []
if (!word.startsWith('@')) { if (!word.startsWith('@')) {
word = word.replace('"', ''); word = word.replace('"', '');
@ -473,7 +472,7 @@ export function GetImports(range: IRange
return list; return list;
}; };
export function GetGlobalVariable(range: IRange, monaco): monaco.languages.CompletionItem[] { export function GetGlobalVariable(range: monacoTypes.IRange, monaco): monacoTypes.languages.CompletionItem[] {
return [ return [
{ {
detail: 'Current block', detail: 'Current block',
@ -520,7 +519,7 @@ export function GetGlobalVariable(range: IRange, monaco): monaco.languages.Compl
]; ];
} }
export function GetGlobalFunctions(range: IRange, monaco): monaco.languages.CompletionItem[] { export function GetGlobalFunctions(range: monacoTypes.IRange, monaco): monacoTypes.languages.CompletionItem[] {
return [ return [
{ {
detail: 'assert(bool condition): throws if the condition is not met - to be used for internal errors.', detail: 'assert(bool condition): throws if the condition is not met - to be used for internal errors.',
@ -644,7 +643,7 @@ export function GetGlobalFunctions(range: IRange, monaco): monaco.languages.Comp
]; ];
} }
export function getContextualAutoCompleteByGlobalVariable(word: string, range: IRange, monaco): monaco.languages.CompletionItem[] { export function getContextualAutoCompleteByGlobalVariable(word: string, range: monacoTypes.IRange, monaco): monacoTypes.languages.CompletionItem[] {
if (word === 'block') { if (word === 'block') {
return getBlockCompletionItems(range, monaco); return getBlockCompletionItems(range, monaco);
} }
@ -669,7 +668,7 @@ export function getContextualAutoCompleteByGlobalVariable(word: string, range: I
return null; return null;
} }
export function getArrayCompletionItems(range: IRange, monaco): monaco.languages.CompletionItem[] { export function getArrayCompletionItems(range: monacoTypes.IRange, monaco): monacoTypes.languages.CompletionItem[] {
return [ return [
{ {
detail: '', detail: '',
@ -706,7 +705,7 @@ export function getArrayCompletionItems(range: IRange, monaco): monaco.languages
] ]
} }
export function getAddressCompletionItems(range: IRange, monaco): monaco.languages.CompletionItem[] { export function getAddressCompletionItems(range: monacoTypes.IRange, monaco): monacoTypes.languages.CompletionItem[] {
return [ return [
{ {
detail: '(uint256): balance of the Address in Wei', detail: '(uint256): balance of the Address in Wei',
@ -752,7 +751,7 @@ export function getAddressCompletionItems(range: IRange, monaco): monaco.languag
} }
export function getContextualAutoCompleteBTypeName(word: string, range: IRange, monaco): monaco.languages.CompletionItem[] { export function getContextualAutoCompleteBTypeName(word: string, range: monacoTypes.IRange, monaco): monacoTypes.languages.CompletionItem[] {
if (word === 'ArrayTypeName') { if (word === 'ArrayTypeName') {
return getArrayCompletionItems(range, monaco); return getArrayCompletionItems(range, monaco);
} }

@ -1,11 +1,9 @@
import { AstNode } from "@remix-project/remix-solidity" import { AstNode } from "@remix-project/remix-solidity"
import { isArray } from "lodash" import { isArray } from "lodash"
import { editor, languages, Position } from "monaco-editor"
import monaco from "../../types/monaco"
import { EditorUIProps } from "../remix-ui-editor" import { EditorUIProps } from "../remix-ui-editor"
import { GeCompletionUnits, GetCompletionKeywords, getCompletionSnippets, GetCompletionTypes, getContextualAutoCompleteBTypeName, getContextualAutoCompleteByGlobalVariable, GetGlobalFunctions, GetGlobalVariable, GetImports } from "./completion/completionGlobals" import { GeCompletionUnits, GetCompletionKeywords, getCompletionSnippets, GetCompletionTypes, getContextualAutoCompleteBTypeName, getContextualAutoCompleteByGlobalVariable, GetGlobalFunctions, GetGlobalVariable, GetImports } from "./completion/completionGlobals"
import { monacoTypes } from '@remix-ui/editor';
export class RemixCompletionProvider implements languages.CompletionItemProvider { export class RemixCompletionProvider implements monacoTypes.languages.CompletionItemProvider {
props: EditorUIProps props: EditorUIProps
monaco: any monaco: any
@ -17,7 +15,7 @@ export class RemixCompletionProvider implements languages.CompletionItemProvider
} }
triggerCharacters = ['.', '', '"', '@', '/'] triggerCharacters = ['.', '', '"', '@', '/']
async provideCompletionItems(model: editor.ITextModel, position: Position, context: monaco.languages.CompletionContext): Promise<monaco.languages.CompletionList | undefined> { async provideCompletionItems(model: monacoTypes.editor.ITextModel, position: monacoTypes.Position, context: monacoTypes.languages.CompletionContext): Promise<monacoTypes.languages.CompletionList | undefined> {
const completionSettings = await this.props.plugin.call('config', 'getAppParameter', 'settings/auto-completion') const completionSettings = await this.props.plugin.call('config', 'getAppParameter', 'settings/auto-completion')
if (!completionSettings) return if (!completionSettings) return
@ -32,7 +30,7 @@ export class RemixCompletionProvider implements languages.CompletionItemProvider
const line = model.getLineContent(position.lineNumber) const line = model.getLineContent(position.lineNumber)
let nodes: AstNode[] = [] let nodes: AstNode[] = []
let suggestions: monaco.languages.CompletionItem[] = [] let suggestions: monacoTypes.languages.CompletionItem[] = []
if (context.triggerCharacter === '"' || context.triggerCharacter === '@' || context.triggerCharacter === '/') { if (context.triggerCharacter === '"' || context.triggerCharacter === '@' || context.triggerCharacter === '/') {
const lastpart = line.substring(0, position.column - 1).split(';').pop() const lastpart = line.substring(0, position.column - 1).split(';').pop()
@ -342,7 +340,7 @@ export class RemixCompletionProvider implements languages.CompletionItemProvider
private getDotCompletions = async (nameOfLastTypedExpression: string, range) => { private getDotCompletions = async (nameOfLastTypedExpression: string, range) => {
const contractCompletions = await this.getContractCompletions() const contractCompletions = await this.getContractCompletions()
let nodes: any[] = [] let nodes: any[] = []
let suggestions: monaco.languages.CompletionItem[] = [] let suggestions: monacoTypes.languages.CompletionItem[] = []
const filterNodes = (nodes: any[], parentNode: any, declarationOf: any = null) => { const filterNodes = (nodes: any[], parentNode: any, declarationOf: any = null) => {
return nodes && nodes.filter(node => { return nodes && nodes.filter(node => {

@ -1,8 +1,8 @@
import { Monaco } from '@monaco-editor/react' import { Monaco } from '@monaco-editor/react'
import { editor, languages, Position } from 'monaco-editor'
import { EditorUIProps } from '../remix-ui-editor' import { EditorUIProps } from '../remix-ui-editor'
export class RemixHoverProvider implements languages.HoverProvider { import { monacoTypes } from '@remix-ui/editor';
export class RemixHoverProvider implements monacoTypes.languages.HoverProvider {
props: EditorUIProps props: EditorUIProps
monaco: Monaco monaco: Monaco
@ -11,7 +11,7 @@ export class RemixHoverProvider implements languages.HoverProvider {
this.monaco = monaco this.monaco = monaco
} }
provideHover = async function (model: editor.ITextModel, position: Position): Promise<languages.Hover> { provideHover = async function (model: monacoTypes.editor.ITextModel, position: monacoTypes.Position): Promise<monacoTypes.languages.Hover> {
const cursorPosition = this.props.editorAPI.getHoverPosition(position) const cursorPosition = this.props.editorAPI.getHoverPosition(position)
const nodeAtPosition = await this.props.plugin.call('codeParser', 'definitionAtPosition', cursorPosition) const nodeAtPosition = await this.props.plugin.call('codeParser', 'definitionAtPosition', cursorPosition)
const contents = [] const contents = []

@ -7,11 +7,12 @@ import { solidityTokensProvider, solidityLanguageConfig } from './syntaxes/solid
import { cairoTokensProvider, cairoLanguageConfig } from './syntaxes/cairo' import { cairoTokensProvider, cairoLanguageConfig } from './syntaxes/cairo'
import { zokratesTokensProvider, zokratesLanguageConfig } from './syntaxes/zokrates' import { zokratesTokensProvider, zokratesLanguageConfig } from './syntaxes/zokrates'
import { moveTokenProvider, moveLanguageConfig } from './syntaxes/move' import { moveTokenProvider, moveLanguageConfig } from './syntaxes/move'
import { monacoTypes } from '@remix-ui/editor';
import './remix-ui-editor.css' import './remix-ui-editor.css'
import { loadTypes } from './web-types' import { loadTypes } from './web-types'
import monaco from '../types/monaco'
import { IMarkdownString, IPosition, MarkerSeverity } from 'monaco-editor'
import { RemixHoverProvider } from './providers/hoverProvider' import { RemixHoverProvider } from './providers/hoverProvider'
import { RemixReferenceProvider } from './providers/referenceProvider' import { RemixReferenceProvider } from './providers/referenceProvider'
@ -19,6 +20,14 @@ import { RemixCompletionProvider } from './providers/completionProvider'
import { RemixHighLightProvider } from './providers/highlightProvider' import { RemixHighLightProvider } from './providers/highlightProvider'
import { RemixDefinitionProvider } from './providers/definitionProvider' import { RemixDefinitionProvider } from './providers/definitionProvider'
enum MarkerSeverity {
Hint = 1,
Info = 2,
Warning = 4,
Error = 8
}
type sourceAnnotation = { type sourceAnnotation = {
row: number, row: number,
column: number, column: number,
@ -59,12 +68,12 @@ export type lineText = {
className: string className: string
afterContentClassName: string afterContentClassName: string
hide: boolean, hide: boolean,
hoverMessage: IMarkdownString | IMarkdownString[] hoverMessage: monacoTypes.IMarkdownString | monacoTypes.IMarkdownString[]
} }
type errorMarker = { type errorMarker = {
message: string message: string
severity: MarkerSeverity | 'warning' | 'info' | 'error' | 'hint' severity: monacoTypes.MarkerSeverity | 'warning' | 'info' | 'error' | 'hint'
position: { position: {
start: { start: {
line: number line: number
@ -78,7 +87,8 @@ type errorMarker = {
file: string file: string
} }
loader.config({ paths: { vs: 'assets/js/monaco-editor/dev/vs' } })
loader.config({ paths: { vs: 'assets/js/monaco-editor/min/vs' } })
export type DecorationsReturn = { export type DecorationsReturn = {
currentDecorations: Array<string> currentDecorations: Array<string>
@ -105,8 +115,8 @@ export interface EditorUIProps {
findMatches: (uri: string, value: string) => any findMatches: (uri: string, value: string) => any
getFontSize: () => number, getFontSize: () => number,
getValue: (uri: string) => string getValue: (uri: string) => string
getCursorPosition: (offset?: boolean) => number | IPosition getCursorPosition: (offset?: boolean) => number | monacoTypes.IPosition
getHoverPosition: (position: IPosition) => number getHoverPosition: (position: monacoTypes.IPosition) => number
addDecoration: (marker: sourceMarker, filePath: string, typeOfDecoration: string) => DecorationsReturn addDecoration: (marker: sourceMarker, filePath: string, typeOfDecoration: string) => DecorationsReturn
clearDecorationsByPlugin: (filePath: string, plugin: string, typeOfDecoration: string, registeredDecorations: any, currentDecorations: any) => DecorationsReturn clearDecorationsByPlugin: (filePath: string, plugin: string, typeOfDecoration: string, registeredDecorations: any, currentDecorations: any) => DecorationsReturn
keepDecorationsFor: (filePath: string, plugin: string, typeOfDecoration: string, registeredDecorations: any, currentDecorations: any) => DecorationsReturn keepDecorationsFor: (filePath: string, plugin: string, typeOfDecoration: string, registeredDecorations: any, currentDecorations: any) => DecorationsReturn
@ -425,7 +435,7 @@ export const EditorUI = (props: EditorUIProps) => {
props.editorAPI.addErrorMarker = async (errors: errorMarker[], from: string) => { props.editorAPI.addErrorMarker = async (errors: errorMarker[], from: string) => {
const allMarkersPerfile: Record<string, Array<monaco.editor.IMarkerData>> = {} const allMarkersPerfile: Record<string, Array<monacoTypes.editor.IMarkerData>> = {}
for (const error of errors) { for (const error of errors) {
let filePath = error.file let filePath = error.file
@ -440,7 +450,7 @@ export const EditorUI = (props: EditorUIProps) => {
'info': MarkerSeverity.Info 'info': MarkerSeverity.Info
} }
if (model) { if (model) {
const markerData: monaco.editor.IMarkerData = { const markerData: monacoTypes.editor.IMarkerData = {
severity: (typeof error.severity === 'string') ? errorServerityMap[error.severity] : error.severity, severity: (typeof error.severity === 'string') ? errorServerityMap[error.severity] : error.severity,
startLineNumber: ((error.position.start && error.position.start.line) || 0), startLineNumber: ((error.position.start && error.position.start.line) || 0),
startColumn: ((error.position.start && error.position.start.column) || 0), startColumn: ((error.position.start && error.position.start.column) || 0),
@ -496,7 +506,7 @@ export const EditorUI = (props: EditorUIProps) => {
} }
} }
props.editorAPI.getHoverPosition = (position: monaco.Position) => { props.editorAPI.getHoverPosition = (position: monacoTypes.Position) => {
if (!monacoRef.current) return if (!monacoRef.current) return
const model = editorModelsState[currentFileRef.current]?.model const model = editorModelsState[currentFileRef.current]?.model
if (model) { if (model) {

@ -1,7 +1,5 @@
/* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable @typescript-eslint/no-unused-vars */
// eslint-disable-next-line @nrwl/nx/enforce-module-boundaries // eslint-disable-next-line @nrwl/nx/enforce-module-boundaries
import BasicLogo from 'libs/remix-ui/vertical-icons-panel/src/lib/components/BasicLogo'
import { ThemeContext } from '../themeContext'
import React, { useEffect, useState, useRef, useContext } from 'react' import React, { useEffect, useState, useRef, useContext } from 'react'
import { FormattedMessage, useIntl } from 'react-intl' import { FormattedMessage, useIntl } from 'react-intl'
import { CustomTooltip } from '@remix-ui/helper' import { CustomTooltip } from '@remix-ui/helper'
@ -21,7 +19,6 @@ function HomeTabTitle() {
searchDisable: true searchDisable: true
}) })
const themeFilter = useContext(ThemeContext)
const searchInputRef = useRef(null) const searchInputRef = useRef(null)
const remiAudioEl = useRef(null) const remiAudioEl = useRef(null)
const intl = useIntl() const intl = useIntl()
@ -52,13 +49,12 @@ function HomeTabTitle() {
return ( return (
<div className="px-2 pb-2 pt-2 d-flex flex-column border-bottom" id="hTTitleSection"> <div className="px-2 pb-2 pt-2 d-flex flex-column border-bottom" id="hTTitleSection">
<div className="d-flex py-2 justify-content-between"> <div className="d-flex py-2 justify-content-between">
<div className='d-flex justify-content-start'> <div className='d-flex justify-content-start'>
<span className="h-80 text-uppercase" style={{ fontSize: 'xx-large', fontFamily: "Noah, sans-serif" }}>Remix</span> <span className="h-80 text-uppercase" style={{ fontSize: 'xx-large', fontFamily: "Noah, sans-serif" }}>Remix</span>
<div className="ml-2 d-flex"> <div className="ml-2 d-flex">
<div onClick={() => playRemi()} > <div onClick={() => playRemi()} >
<img className="" src="assets/img/guitarRemiCroped.webp" style={{height: "3rem"}} alt=""></img> <img className="" src="assets/img/guitarRemiCroped.webp" style={{ height: "3rem" }} alt=""></img>
</div> </div>
<audio <audio
id="remiAudio" id="remiAudio"
@ -68,7 +64,7 @@ function HomeTabTitle() {
></audio> ></audio>
</div> </div>
</div> </div>
<span className="d-flex flex-nowrap"> <span className="d-flex flex-nowrap align-self-end">
<CustomTooltip <CustomTooltip
placement={'top'} placement={'top'}
tooltipId="overlay-tooltip" tooltipId="overlay-tooltip"
@ -81,10 +77,9 @@ function HomeTabTitle() {
openLink("https://www.youtube.com/channel/UCjTUPyFEr2xDGN6Cg8nKDaA") openLink("https://www.youtube.com/channel/UCjTUPyFEr2xDGN6Cg8nKDaA")
_paq.push(['trackEvent', 'hometab', 'socialMedia', 'youtube']) _paq.push(['trackEvent', 'hometab', 'socialMedia', 'youtube'])
}} }}
className="border-0 h-100 btn fab fa-youtube p-1 pl-2"> className="border-0 px-1 h-100 btn fab fa-youtube">
</button> </button>
</CustomTooltip> </CustomTooltip>
<CustomTooltip <CustomTooltip
placement={'top'} placement={'top'}
tooltipId="overlay-tooltip" tooltipId="overlay-tooltip"
@ -97,10 +92,9 @@ function HomeTabTitle() {
openLink("https://twitter.com/EthereumRemix") openLink("https://twitter.com/EthereumRemix")
_paq.push(['trackEvent', 'hometab', 'socialMedia', 'twitter']) _paq.push(['trackEvent', 'hometab', 'socialMedia', 'twitter'])
}} }}
className="border-0 p-1 h-100 pl-2 btn fab fa-twitter"> className="border-0 px-1 h-100 btn fab fa-twitter">
</button> </button>
</CustomTooltip> </CustomTooltip>
<CustomTooltip <CustomTooltip
placement={'top'} placement={'top'}
tooltipId="overlay-tooltip" tooltipId="overlay-tooltip"
@ -113,10 +107,9 @@ function HomeTabTitle() {
openLink("https://www.linkedin.com/company/ethereum-remix/") openLink("https://www.linkedin.com/company/ethereum-remix/")
_paq.push(['trackEvent', 'hometab', 'socialmedia', 'linkedin']) _paq.push(['trackEvent', 'hometab', 'socialmedia', 'linkedin'])
}} }}
className="border-0 p-1 h-100 pl-2 btn fa fa-linkedin"> className="border-0 px-1 h-100 btn fa fa-linkedin">
</button> </button>
</CustomTooltip> </CustomTooltip>
<CustomTooltip <CustomTooltip
placement={'top'} placement={'top'}
tooltipId="overlay-tooltip" tooltipId="overlay-tooltip"
@ -129,7 +122,7 @@ function HomeTabTitle() {
openLink("https://medium.com/remix-ide") openLink("https://medium.com/remix-ide")
_paq.push(['trackEvent', 'hometab', 'socialmedia', 'medium']) _paq.push(['trackEvent', 'hometab', 'socialmedia', 'medium'])
}} }}
className="border-0 p-1 h-100 pl-2 btn fab fa-medium"> className="border-0 h-100 px-1 btn fab fa-medium">
</button> </button>
</CustomTooltip> </CustomTooltip>
@ -145,7 +138,7 @@ function HomeTabTitle() {
openLink("https://discord.gg/mh9hFCKkEq") openLink("https://discord.gg/mh9hFCKkEq")
_paq.push(['trackEvent', 'hometab', 'socialmedia', 'discord']) _paq.push(['trackEvent', 'hometab', 'socialmedia', 'discord'])
}} }}
className="border-0 h-100 p-1 pr-2 btn fab fa-discord"> className="border-0 h-100 pl-1 pr-0 btn fab fa-discord">
</button> </button>
</CustomTooltip> </CustomTooltip>
</span> </span>

@ -120,6 +120,7 @@ export function AccountUI (props: AccountProps) {
<div> <div>
<textarea <textarea
id="prompt_text" id="prompt_text"
className='bg-light'
data-id="signMessageTextarea" data-id="signMessageTextarea"
style={{ width: '100%' }} style={{ width: '100%' }}
rows={4} rows={4}

@ -25,7 +25,8 @@ export function GithubSettings (props: GithubSettingsProps) {
}, [props.config]) }, [props.config])
const handleChangeTokenState = (event) => { const handleChangeTokenState = (event) => {
setGithubToken(event.target.value) const token = event.target.value ? event.target.value.trim() : event.target.value
setGithubToken(token)
} }
const handleChangeUserNameState = (event) => { const handleChangeUserNameState = (event) => {

@ -1,3 +1,4 @@
export * from './lib/solidity-compiler' export * from './lib/solidity-compiler'
export * from './lib/logic' export * from './lib/logic'
export * from './lib/logic/flattenerUtilities' export * from './lib/logic/flattenerUtilities'
export * from './lib/api/compiler-api'

@ -137,7 +137,7 @@
.remixui_log { .remixui_log {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
margin-bottom: 5%; margin-bottom: 0.5rem;
overflow: visible; overflow: visible;
} }
.remixui_key { .remixui_key {

@ -77,10 +77,16 @@ export function RemixUiSolidityUmlGen ({ updatedSvg, loading }: RemixUiSolidityU
} }
const DefaultInfo = () => ( const DefaultInfo = () => (
<div className="d-flex flex-column justify-content-center align-items-center mt-5"> <div className="d-flex flex-column justify-content-center align-items-center mt-5 ml-5">
<h2 className="h2 align-self-start"><p>To view your contract as a Uml Diragram</p></h2> <h3 className="h3 align-self-start text-dark"><p>To view your contract as a UML Diagram</p></h3>
<h3 className="h4 align-self-start"><p>Right Click on your contract file (Usually ends with .sol)</p></h3> <ul className="ml-3 justify-content-start align-self-start">
<h3 className="h4 align-self-start"><p>Click on Generate UML</p></h3> <li>
<h5 className="h5 align-self-start text-dark"><p>Right click on your contract file</p></h5>
</li>
<li>
<h5 className="h5 align-self-start text-dark"><p>Click on <b>Generate UML</b></p></h5>
</li>
</ul>
</div> </div>
) )
const Display = () => { const Display = () => {

@ -153,7 +153,7 @@ export const TabsUI = (props: TabsUIProps) => {
const path = active().substr(active().indexOf('/') + 1, active().length) const path = active().substr(active().indexOf('/') + 1, active().length)
const content = await props.plugin.call('fileManager', "readFile", path) const content = await props.plugin.call('fileManager', "readFile", path)
if (tabsState.currentExt === 'js' || tabsState.currentExt === 'ts') { if (tabsState.currentExt === 'js' || tabsState.currentExt === 'ts') {
await props.plugin.call('scriptRunner', 'execute', content) await props.plugin.call('scriptRunner', 'execute', content, path)
_paq.push(['trackEvent', 'editor', 'clickRunFromEditor', tabsState.currentExt]) _paq.push(['trackEvent', 'editor', 'clickRunFromEditor', tabsState.currentExt])
} else if (tabsState.currentExt === 'sol' || tabsState.currentExt === 'yul') { } else if (tabsState.currentExt === 'sol' || tabsState.currentExt === 'yul') {
await props.plugin.call('solidity', 'compile', path) await props.plugin.call('solidity', 'compile', path)

@ -12,6 +12,7 @@ import { ROOT_PATH, slitherYml, solTestYml, tsSolTestYml } from '../utils/consta
// eslint-disable-next-line @nrwl/nx/enforce-module-boundaries // eslint-disable-next-line @nrwl/nx/enforce-module-boundaries
import { IndexedDBStorage } from '../../../../../../apps/remix-ide/src/app/files/filesystems/indexedDB' import { IndexedDBStorage } from '../../../../../../apps/remix-ide/src/app/files/filesystems/indexedDB'
import { getUncommittedFiles } from '../utils/gitStatusFilter' import { getUncommittedFiles } from '../utils/gitStatusFilter'
import { AppModal, ModalTypes } from '@remix-ui/app'
declare global { declare global {
interface Window { remixFileSystemCallback: IndexedDBStorage; } interface Window { remixFileSystemCallback: IndexedDBStorage; }
@ -358,6 +359,30 @@ export const switchToWorkspace = async (name: string) => {
} }
} }
const loadFile = (name, file, provider, cb?): void => {
const fileReader = new FileReader()
fileReader.onload = async function (event) {
if (checkSpecialChars(file.name)) {
return dispatch(displayNotification('File Upload Failed', 'Special characters are not allowed', 'Close', null, async () => { }))
}
try {
await provider.set(name, event.target.result)
} catch (error) {
return dispatch(displayNotification('File Upload Failed', 'Failed to create file ' + name, 'Close', null, async () => { }))
}
const config = plugin.registry.get('config').api
const editor = plugin.registry.get('editor').api
if ((config.get('currentFile') === name) && (editor.currentContent() !== event.target.result)) {
editor.setText(name, event.target.result)
}
}
fileReader.readAsText(file)
cb && cb(null, true)
}
export const uploadFile = async (target, targetFolder: string, cb?: (err: Error, result?: string | number | boolean | Record<string, any>) => void) => { export const uploadFile = async (target, targetFolder: string, cb?: (err: Error, result?: string | number | boolean | Record<string, any>) => void) => {
// TODO The file explorer is merely a view on the current state of // TODO The file explorer is merely a view on the current state of
// the files module. Please ask the user here if they want to overwrite // the files module. Please ask the user here if they want to overwrite
@ -365,39 +390,52 @@ export const uploadFile = async (target, targetFolder: string, cb?: (err: Error,
// pick that up via the 'fileAdded' event from the files module. // pick that up via the 'fileAdded' event from the files module.
[...target.files].forEach(async (file) => { [...target.files].forEach(async (file) => {
const workspaceProvider = plugin.fileProviders.workspace const workspaceProvider = plugin.fileProviders.workspace
const loadFile = (name: string): void => { const name = targetFolder === '/' ? file.name : `${targetFolder}/${file.name}`
const fileReader = new FileReader()
fileReader.onload = async function (event) {
if (checkSpecialChars(file.name)) {
return dispatch(displayNotification('File Upload Failed', 'Special characters are not allowed', 'Close', null, async () => { }))
}
try {
await workspaceProvider.set(name, event.target.result)
} catch (error) {
return dispatch(displayNotification('File Upload Failed', 'Failed to create file ' + name, 'Close', null, async () => { }))
}
const config = plugin.registry.get('config').api
const editor = plugin.registry.get('editor').api
if ((config.get('currentFile') === name) && (editor.currentContent() !== event.target.result)) { if (!await workspaceProvider.exists(name)) {
editor.setText(name, event.target.result) loadFile(name, file, workspaceProvider, cb)
} } else {
const modalContent: AppModal = {
id: 'overwriteUploadFile',
title: 'Confirm overwrite',
message: `The file "${name}" already exists! Would you like to overwrite it?`,
modalType: ModalTypes.confirm,
okLabel: 'OK',
cancelLabel: 'Cancel',
okFn: () => {
loadFile(name, file, workspaceProvider, cb)
},
cancelFn: () => {},
hideFn: () => {}
} }
fileReader.readAsText(file) plugin.call('notification', 'modal', modalContent)
cb && cb(null, true)
} }
const name = targetFolder === '/' ? file.name : `${targetFolder}/${file.name}` })
}
export const uploadFolder = async (target, targetFolder: string, cb?: (err: Error, result?: string | number | boolean | Record<string, any>) => void) => {
for(const file of [...target.files]) {
const workspaceProvider = plugin.fileProviders.workspace
const name = targetFolder === '/' ? file.webkitRelativePath : `${targetFolder}/${file.webkitRelativePath}`
if (!await workspaceProvider.exists(name)) { if (!await workspaceProvider.exists(name)) {
loadFile(name) loadFile(name, file, workspaceProvider, cb)
} else { } else {
dispatch(displayNotification('Confirm overwrite', `The file ${name} already exists! Would you like to overwrite it?`, 'OK', null, () => { const modalContent: AppModal = {
loadFile(name) id: 'overwriteUploadFolderFile',
}, () => { })) title: 'Confirm overwrite',
message: `The file "${name}" already exists! Would you like to overwrite it?`,
modalType: ModalTypes.confirm,
okLabel: 'OK',
cancelLabel: 'Cancel',
okFn: () => {
loadFile(name, file, workspaceProvider, cb)
},
cancelFn: () => {},
hideFn: () => {}
}
plugin.call('notification', 'modal', modalContent)
} }
}) }
} }
export const getWorkspaces = async (): Promise<{ name: string, isGitRepo: boolean, branches?: { remote: any; name: string; }[], currentBranch?: string }[]> | undefined => { export const getWorkspaces = async (): Promise<{ name: string, isGitRepo: boolean, branches?: { remote: any; name: string; }[], currentBranch?: string }[]> | undefined => {

@ -10,27 +10,33 @@ export const FileExplorerMenu = (props: FileExplorerMenuProps) => {
menuItems: [ menuItems: [
{ {
action: 'createNewFile', action: 'createNewFile',
title: 'Create New File', title: 'Create new file',
icon: 'far fa-file', icon: 'far fa-file',
placement: 'top-start' placement: 'top'
}, },
{ {
action: 'createNewFolder', action: 'createNewFolder',
title: 'Create New Folder', title: 'Create new folder',
icon: 'far fa-folder', icon: 'far fa-folder',
placement: 'top-end' placement: 'top'
}, },
{ {
action: 'publishToGist', action: 'publishToGist',
title: 'Publish all the current workspace files to a github gist', title: 'Publish current workspace to GitHub gist',
icon: 'fab fa-github', icon: 'fab fa-github',
placement: 'bottom-start' placement: 'top'
}, },
{ {
action: 'uploadFile', action: 'uploadFile',
title: 'Load a local file into current workspace', title: 'Upload files into current workspace',
icon: 'fa fa-upload', icon: 'fa fa-upload',
placement: 'right' placement: 'top'
},
{
action: 'uploadFolder',
title: 'Upload folder into current workspace',
icon: 'fas fa-folder-upload',
placement: 'top'
}, },
{ {
action: 'updateGist', action: 'updateGist',
@ -41,6 +47,7 @@ export const FileExplorerMenu = (props: FileExplorerMenuProps) => {
].filter(item => props.menuItems && props.menuItems.find((name) => { return name === item.action })), ].filter(item => props.menuItems && props.menuItems.find((name) => { return name === item.action })),
actions: {} actions: {}
}) })
const enableDirUpload = { directory: "", webkitdirectory: "" }
useEffect(() => { useEffect(() => {
const actions = { const actions = {
@ -67,7 +74,7 @@ export const FileExplorerMenu = (props: FileExplorerMenuProps) => {
if (action === 'uploadFile') { if (action === 'uploadFile') {
return ( return (
<CustomTooltip <CustomTooltip
placement="right" placement={placement as Placement}
tooltipId="uploadFileTooltip" tooltipId="uploadFileTooltip"
tooltipClasses="text-nowrap" tooltipClasses="text-nowrap"
tooltipText={<FormattedMessage id={`filePanel.${action}`} defaultMessage={title} />} tooltipText={<FormattedMessage id={`filePanel.${action}`} defaultMessage={title} />}
@ -81,6 +88,7 @@ export const FileExplorerMenu = (props: FileExplorerMenuProps) => {
> >
<input id="fileUpload" data-id="fileExplorerFileUpload" type="file" onChange={(e) => { <input id="fileUpload" data-id="fileExplorerFileUpload" type="file" onChange={(e) => {
e.stopPropagation() e.stopPropagation()
_paq.push(['trackEvent', 'fileExplorer', 'fileAction', action])
props.uploadFile(e.target) props.uploadFile(e.target)
e.target.value = null e.target.value = null
}} }}
@ -88,6 +96,31 @@ export const FileExplorerMenu = (props: FileExplorerMenuProps) => {
</label> </label>
</CustomTooltip> </CustomTooltip>
) )
} else if (action === 'uploadFolder') {
return (
<CustomTooltip
placement={placement as Placement}
tooltipId="uploadFolderTooltip"
tooltipClasses="text-nowrap"
tooltipText={<FormattedMessage id={`filePanel.${action}`} defaultMessage={title} />}
key={`index-${action}-${placement}-${icon}`}
>
<label
id={action}
data-id={'fileExplorerUploadFolder' + action }
className={icon + ' mb-0 remixui_newFile'}
key={`index-${action}-${placement}-${icon}`}
>
<input id="folderUpload" data-id="fileExplorerFolderUpload" type="file" onChange={(e) => {
e.stopPropagation()
_paq.push(['trackEvent', 'fileExplorer', 'fileAction', action])
props.uploadFolder(e.target)
e.target.value = null
}}
{...enableDirUpload} multiple />
</label>
</CustomTooltip>
)
} else { } else {
return ( return (
<CustomTooltip <CustomTooltip

@ -190,6 +190,14 @@ export const FileExplorer = (props: FileExplorerProps) => {
props.dispatchUploadFile(target, parentFolder) props.dispatchUploadFile(target, parentFolder)
} }
const uploadFolder = (target) => {
const parentFolder = getFocusedFolder()
const expandPath = [...new Set([...props.expandPath, parentFolder])]
props.dispatchHandleExpandPath(expandPath)
props.dispatchUploadFolder(target, parentFolder)
}
const copyFile = (src: string, dest: string) => { const copyFile = (src: string, dest: string) => {
try { try {
props.dispatchCopyFile(src, dest) props.dispatchCopyFile(src, dest)
@ -459,6 +467,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
createNewFolder={handleNewFolderInput} createNewFolder={handleNewFolderInput}
publishToGist={publishToGist} publishToGist={publishToGist}
uploadFile={uploadFile} uploadFile={uploadFile}
uploadFolder={uploadFolder}
/> />
</div> </div>
} }

@ -45,7 +45,7 @@ export function HamburgerMenu (props: HamburgerMenuProps) {
props.hideIconsMenu(!showIconsMenu) props.hideIconsMenu(!showIconsMenu)
}}></HamburgerMenuItem> }}></HamburgerMenuItem>
<Dropdown.Divider className="border mt-0 mb-0 remixui_menuhr" style={{ pointerEvents: 'none' }}/> <Dropdown.Divider className="border mt-0 mb-0 remixui_menuhr" style={{ pointerEvents: 'none' }}/>
<HamburgerMenuItem kind='download' fa='far fa-download' hideOption={hideWorkspaceOptions || hideLocalhostOptions} actionOnClick={() => { <HamburgerMenuItem kind='backup' fa='far fa-download' hideOption={hideWorkspaceOptions || hideLocalhostOptions} actionOnClick={() => {
props.downloadWorkspaces() props.downloadWorkspaces()
props.hideIconsMenu(!showIconsMenu) props.hideIconsMenu(!showIconsMenu)
}}></HamburgerMenuItem> }}></HamburgerMenuItem>

@ -18,6 +18,7 @@ export const FileSystemContext = createContext<{
dispatchDeleteAllWorkspaces: () => Promise<void>, dispatchDeleteAllWorkspaces: () => Promise<void>,
dispatchPublishToGist: (path?: string, type?: string) => Promise<void>, dispatchPublishToGist: (path?: string, type?: string) => Promise<void>,
dispatchUploadFile: (target?: SyntheticEvent, targetFolder?: string) => Promise<void>, dispatchUploadFile: (target?: SyntheticEvent, targetFolder?: string) => Promise<void>,
dispatchUploadFolder: (target?: SyntheticEvent, targetFolder?: string) => Promise<void>,
dispatchCreateNewFile: (path: string, rootDir: string) => Promise<void>, dispatchCreateNewFile: (path: string, rootDir: string) => Promise<void>,
dispatchSetFocusElement: (elements: { key: string, type: 'file' | 'folder' | 'gist' }[]) => Promise<void>, dispatchSetFocusElement: (elements: { key: string, type: 'file' | 'folder' | 'gist' }[]) => Promise<void>,
dispatchCreateNewFolder: (path: string, rootDir: string) => Promise<void>, dispatchCreateNewFolder: (path: string, rootDir: string) => Promise<void>,

@ -7,7 +7,7 @@ import { FileSystemContext } from '../contexts'
import { browserReducer, browserInitialState } from '../reducers/workspace' import { browserReducer, browserInitialState } from '../reducers/workspace'
import { initWorkspace, fetchDirectory, removeInputField, deleteWorkspace, deleteAllWorkspaces, clearPopUp, publishToGist, createNewFile, setFocusElement, createNewFolder, import { initWorkspace, fetchDirectory, removeInputField, deleteWorkspace, deleteAllWorkspaces, clearPopUp, publishToGist, createNewFile, setFocusElement, createNewFolder,
deletePath, renamePath, downloadPath, copyFile, copyFolder, runScript, emitContextMenuEvent, handleClickFile, handleExpandPath, addInputField, createWorkspace, deletePath, renamePath, downloadPath, copyFile, copyFolder, runScript, emitContextMenuEvent, handleClickFile, handleExpandPath, addInputField, createWorkspace,
fetchWorkspaceDirectory, renameWorkspace, switchToWorkspace, uploadFile, handleDownloadFiles, restoreBackupZip, cloneRepository, moveFile, moveFolder, fetchWorkspaceDirectory, renameWorkspace, switchToWorkspace, uploadFile, uploadFolder, handleDownloadFiles, restoreBackupZip, cloneRepository, moveFile, moveFolder,
showAllBranches, switchBranch, createNewBranch, checkoutRemoteBranch, createSolidityGithubAction, createTsSolGithubAction, createSlitherGithubAction showAllBranches, switchBranch, createNewBranch, checkoutRemoteBranch, createSolidityGithubAction, createTsSolGithubAction, createSlitherGithubAction
} from '../actions' } from '../actions'
import { Modal, WorkspaceProps, WorkspaceTemplate } from '../types' import { Modal, WorkspaceProps, WorkspaceTemplate } from '../types'
@ -79,6 +79,10 @@ export const FileSystemProvider = (props: WorkspaceProps) => {
await uploadFile(target, targetFolder) await uploadFile(target, targetFolder)
} }
const dispatchUploadFolder = async (target?: SyntheticEvent, targetFolder?: string) => {
await uploadFolder(target, targetFolder)
}
const dispatchCreateNewFile = async (path: string, rootDir: string) => { const dispatchCreateNewFile = async (path: string, rootDir: string) => {
await createNewFile(path, rootDir) await createNewFile(path, rootDir)
} }
@ -265,6 +269,7 @@ export const FileSystemProvider = (props: WorkspaceProps) => {
dispatchDeleteAllWorkspaces, dispatchDeleteAllWorkspaces,
dispatchPublishToGist, dispatchPublishToGist,
dispatchUploadFile, dispatchUploadFile,
dispatchUploadFolder,
dispatchCreateNewFile, dispatchCreateNewFile,
dispatchSetFocusElement, dispatchSetFocusElement,
dispatchCreateNewFolder, dispatchCreateNewFolder,

@ -528,7 +528,7 @@ export function Workspace () {
<div className='h-100 remixui_treeview' data-id='filePanelFileExplorerTree'> <div className='h-100 remixui_treeview' data-id='filePanelFileExplorerTree'>
<FileExplorer <FileExplorer
name={currentWorkspace} name={currentWorkspace}
menuItems={['createNewFile', 'createNewFolder', 'publishToGist', canUpload ? 'uploadFile' : '']} menuItems={['createNewFile', 'createNewFolder', 'publishToGist', canUpload ? 'uploadFile' : '', canUpload ? 'uploadFolder' : '']}
contextMenuItems={global.fs.browser.contextMenu.registeredMenuItems} contextMenuItems={global.fs.browser.contextMenu.registeredMenuItems}
removedContextMenuItems={global.fs.browser.contextMenu.removedMenuItems} removedContextMenuItems={global.fs.browser.contextMenu.removedMenuItems}
files={global.fs.browser.files} files={global.fs.browser.files}
@ -547,6 +547,7 @@ export function Workspace () {
dispatchRenamePath={global.dispatchRenamePath} dispatchRenamePath={global.dispatchRenamePath}
dispatchDownloadPath={global.dispatchDownloadPath} dispatchDownloadPath={global.dispatchDownloadPath}
dispatchUploadFile={global.dispatchUploadFile} dispatchUploadFile={global.dispatchUploadFile}
dispatchUploadFolder={global.dispatchUploadFolder}
dispatchCopyFile={global.dispatchCopyFile} dispatchCopyFile={global.dispatchCopyFile}
dispatchCopyFolder={global.dispatchCopyFolder} dispatchCopyFolder={global.dispatchCopyFolder}
dispatchPublishToGist={global.dispatchPublishToGist} dispatchPublishToGist={global.dispatchPublishToGist}
@ -587,6 +588,7 @@ export function Workspace () {
dispatchRenamePath={global.dispatchRenamePath} dispatchRenamePath={global.dispatchRenamePath}
dispatchDownloadPath={global.dispatchDownloadPath} dispatchDownloadPath={global.dispatchDownloadPath}
dispatchUploadFile={global.dispatchUploadFile} dispatchUploadFile={global.dispatchUploadFile}
dispatchUploadFolder={global.dispatchUploadFolder}
dispatchCopyFile={global.dispatchCopyFile} dispatchCopyFile={global.dispatchCopyFile}
dispatchCopyFolder={global.dispatchCopyFolder} dispatchCopyFolder={global.dispatchCopyFolder}
dispatchPublishToGist={global.dispatchPublishToGist} dispatchPublishToGist={global.dispatchPublishToGist}

@ -98,6 +98,7 @@ export interface FileExplorerProps {
dispatchRenamePath: (oldPath: string, newPath: string) => Promise<void>, dispatchRenamePath: (oldPath: string, newPath: string) => Promise<void>,
dispatchDownloadPath: (path: string) => Promise<void>, dispatchDownloadPath: (path: string) => Promise<void>,
dispatchUploadFile: (target?: React.SyntheticEvent, targetFolder?: string) => Promise<void>, dispatchUploadFile: (target?: React.SyntheticEvent, targetFolder?: string) => Promise<void>,
dispatchUploadFolder: (target?: React.SyntheticEvent, targetFolder?: string) => Promise<void>,
dispatchCopyFile: (src: string, dest: string) => Promise<void>, dispatchCopyFile: (src: string, dest: string) => Promise<void>,
dispatchCopyFolder: (src: string, dest: string) => Promise<void>, dispatchCopyFolder: (src: string, dest: string) => Promise<void>,
dispatchRunScript: (path: string) => Promise<void>, dispatchRunScript: (path: string) => Promise<void>,
@ -120,6 +121,7 @@ export interface FileExplorerMenuProps {
createNewFolder: (parentFolder?: string) => void, createNewFolder: (parentFolder?: string) => void,
publishToGist: (path?: string) => void, publishToGist: (path?: string) => void,
uploadFile: (target: EventTarget & HTMLInputElement) => void uploadFile: (target: EventTarget & HTMLInputElement) => void
uploadFolder: (target: EventTarget & HTMLInputElement) => void
tooltipPlacement?: Placement tooltipPlacement?: Placement
} }
export interface FileExplorerContextMenuProps { export interface FileExplorerContextMenuProps {

@ -4,7 +4,6 @@
"description": "Create a Remix IDE workspace using different templates", "description": "Create a Remix IDE workspace using different templates",
"main": "src/index.js", "main": "src/index.js",
"types": "src/index.d.ts", "types": "src/index.d.ts",
"type": "module",
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },

@ -3,7 +3,7 @@
"compilerOptions": { "compilerOptions": {
"outDir": "../../dist/out-tsc", "outDir": "../../dist/out-tsc",
"module": "commonjs", "module": "commonjs",
"types": ["jest", "node"] "types": ["node"]
}, },
"include": [ "include": [
"**/*.spec.ts", "**/*.spec.ts",

@ -28,6 +28,7 @@
"nx": "nx", "nx": "nx",
"start": "nx start", "start": "nx start",
"serve": "nx serve remix-ide --configuration=development", "serve": "nx serve remix-ide --configuration=development",
"serve:hot": "nx serve remix-ide --configuration=hot",
"build": "nx build", "build": "nx build",
"test": "nx test", "test": "nx test",
"lint": "nx lint", "lint": "nx lint",
@ -57,8 +58,8 @@
"browsertest": "sleep 5 && yarn run nightwatch_local", "browsertest": "sleep 5 && yarn run nightwatch_local",
"csslint": "csslint --ignore=order-alphabetical --errors='errors,duplicate-properties,empty-rules' --exclude-list='apps/remix-ide/src/assets/css/font-awesome.min.css' apps/remix-ide/src/assets/css/", "csslint": "csslint --ignore=order-alphabetical --errors='errors,duplicate-properties,empty-rules' --exclude-list='apps/remix-ide/src/assets/css/font-awesome.min.css' apps/remix-ide/src/assets/css/",
"downloadsolc_assets_e2e": "node ./apps/remix-ide/ci/download_e2e_assets.js", "downloadsolc_assets_e2e": "node ./apps/remix-ide/ci/download_e2e_assets.js",
"downloadsolc_assets": "wget --no-check-certificate https://binaries.soliditylang.org/wasm/soljson-v0.8.18+commit.87f61d96.js -O ./apps/remix-ide/src/assets/js/soljson.js && wget --no-check-certificate https://binaries.soliditylang.org/wasm/soljson-v0.8.18+commit.87f61d96.js -O ./apps/solidity-compiler/src/assets/js/soljson.js", "downloadsolc_assets": "wget --no-check-certificate https://binaries.soliditylang.org/wasm/soljson-v0.8.18+commit.87f61d96.js -O ./apps/remix-ide/src/assets/js/soljson.js",
"downloadsolc_assets_dist": "wget --no-check-certificate https://binaries.soliditylang.org/wasm/soljson-v0.8.18+commit.87f61d96.js -O ./dist/apps/remix-ide/assets/js/soljson.js && wget --no-check-certificate https://binaries.soliditylang.org/wasm/soljson-v0.8.18+commit.87f61d96.js -O ./dist/apps/solidity-compiler/assets/js/soljson.js", "downloadsolc_assets_dist": "wget --no-check-certificate https://binaries.soliditylang.org/wasm/soljson-v0.8.18+commit.87f61d96.js -O ./dist/apps/remix-ide/assets/js/soljson.js",
"make-mock-compiler": "node apps/remix-ide/ci/makeMockCompiler.js", "make-mock-compiler": "node apps/remix-ide/ci/makeMockCompiler.js",
"minify": "uglifyjs --in-source-map inline --source-map-inline -c warnings=false", "minify": "uglifyjs --in-source-map inline --source-map-inline -c warnings=false",
"build:production": "NODE_ENV=production nx build remix-ide --configuration=production --skip-nx-cache", "build:production": "NODE_ENV=production nx build remix-ide --configuration=production --skip-nx-cache",
@ -128,7 +129,6 @@
"@ethereumjs/vm": "^6.3.0", "@ethereumjs/vm": "^6.3.0",
"@ethersphere/bee-js": "^3.2.0", "@ethersphere/bee-js": "^3.2.0",
"@isomorphic-git/lightning-fs": "^4.4.1", "@isomorphic-git/lightning-fs": "^4.4.1",
"@monaco-editor/react": "4.4.5",
"@openzeppelin/contracts": "^4.7.3", "@openzeppelin/contracts": "^4.7.3",
"@openzeppelin/upgrades-core": "^1.22.0", "@openzeppelin/upgrades-core": "^1.22.0",
"@openzeppelin/wizard": "^0.1.1", "@openzeppelin/wizard": "^0.1.1",
@ -174,10 +174,9 @@
"jszip": "^3.6.0", "jszip": "^3.6.0",
"latest-version": "^5.1.0", "latest-version": "^5.1.0",
"merge": "^2.1.1", "merge": "^2.1.1",
"monaco-editor": "^0.30.1",
"npm-install-version": "^6.0.2", "npm-install-version": "^6.0.2",
"path-browserify": "^1.0.1", "path-browserify": "^1.0.1",
"prettier": "^2.7.1", "prettier": "^2.8.4",
"prettier-plugin-solidity": "^1.0.0-beta.24", "prettier-plugin-solidity": "^1.0.0-beta.24",
"raw-loader": "^4.0.2", "raw-loader": "^4.0.2",
"react": "^17.0.2", "react": "^17.0.2",
@ -223,18 +222,19 @@
"@babel/preset-typescript": "^7.18.6", "@babel/preset-typescript": "^7.18.6",
"@babel/register": "^7.4.4", "@babel/register": "^7.4.4",
"@fortawesome/fontawesome-free": "^5.8.1", "@fortawesome/fontawesome-free": "^5.8.1",
"@nrwl/cli": "^15.6.3", "@monaco-editor/react": "4.4.5",
"@nrwl/eslint-plugin-nx": "^15.6.3", "@nrwl/cli": "^15.7.1",
"@nrwl/jest": "15.6.3", "@nrwl/eslint-plugin-nx": "^15.7.1",
"@nrwl/js": "15.6.3", "@nrwl/js": "15.7.1",
"@nrwl/linter": "15.6.3", "@nrwl/linter": "15.7.1",
"@nrwl/node": "15.6.3", "@nrwl/node": "15.7.1",
"@nrwl/react": "15.6.3", "@nrwl/react": "15.7.1",
"@nrwl/tao": "^15.6.3", "@nrwl/tao": "^15.7.1",
"@nrwl/web": "15.6.3", "@nrwl/web": "15.7.1",
"@nrwl/webpack": "15.6.3", "@nrwl/webpack": "15.7.1",
"@nrwl/workspace": "^15.6.3", "@nrwl/workspace": "^15.7.1",
"@openzeppelin/contracts-upgradeable": "^4.8.1", "@openzeppelin/contracts-upgradeable": "^4.8.1",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.10",
"@svgr/webpack": "^6.5.1", "@svgr/webpack": "^6.5.1",
"@testing-library/react": "13.4.0", "@testing-library/react": "13.4.0",
"@types/axios": "^0.14.0", "@types/axios": "^0.14.0",
@ -242,7 +242,6 @@
"@types/express-ws": "^3.0.1", "@types/express-ws": "^3.0.1",
"@types/fs-extra": "^9.0.1", "@types/fs-extra": "^9.0.1",
"@types/isomorphic-git__lightning-fs": "^4.4.2", "@types/isomorphic-git__lightning-fs": "^4.4.2",
"@types/jest": "28.1.1",
"@types/lodash": "^4.14.172", "@types/lodash": "^4.14.172",
"@types/mocha": "^9.1.1", "@types/mocha": "^9.1.1",
"@types/node": "18.7.18", "@types/node": "18.7.18",
@ -263,7 +262,6 @@
"ace-mode-solidity": "^0.1.0", "ace-mode-solidity": "^0.1.0",
"ace-mode-zokrates": "^1.0.4", "ace-mode-zokrates": "^1.0.4",
"babel-eslint": "^10.0.0", "babel-eslint": "^10.0.0",
"babel-jest": "25.1.0",
"babel-plugin-add-module-exports": "^1.0.2", "babel-plugin-add-module-exports": "^1.0.2",
"babel-plugin-fast-async": "^6.1.2", "babel-plugin-fast-async": "^6.1.2",
"babel-plugin-module-resolver": "^4.0.0", "babel-plugin-module-resolver": "^4.0.0",
@ -314,14 +312,13 @@
"ipfs-mini": "^1.1.5", "ipfs-mini": "^1.1.5",
"is-electron": "^2.2.0", "is-electron": "^2.2.0",
"javascript-serialize": "^1.6.1", "javascript-serialize": "^1.6.1",
"jest": "^29.3.1",
"jest-environment-jsdom": "28.1.1",
"js-base64": "^2.1.9", "js-base64": "^2.1.9",
"js-beautify": "1.6.14", "js-beautify": "1.6.14",
"lerna": "^3.22.1", "lerna": "^3.22.1",
"minixhr": "^4.0.0", "minixhr": "^4.0.0",
"mkdirp": "^0.5.1", "mkdirp": "^0.5.1",
"mocha": "^8.0.1", "mocha": "^8.0.1",
"monaco-editor": "^0.30.1",
"nanohtml": "^1.6.3", "nanohtml": "^1.6.3",
"nightwatch": "^2.3", "nightwatch": "^2.3",
"nodemon": "^2.0.4", "nodemon": "^2.0.4",
@ -329,11 +326,12 @@
"npm-link-local": "^1.1.0", "npm-link-local": "^1.1.0",
"npm-merge-driver": "^2.3.5", "npm-merge-driver": "^2.3.5",
"npm-run-all": "^4.0.2", "npm-run-all": "^4.0.2",
"nx": "15.6.3", "nx": "15.7.1",
"nyc": "^13.3.0", "nyc": "^13.3.0",
"onchange": "^3.2.1", "onchange": "^3.2.1",
"os-browserify": "^0.3.0", "os-browserify": "^0.3.0",
"process": "^0.11.10", "process": "^0.11.10",
"react-refresh": "^0.14.0",
"react-test-renderer": "^17.0.2", "react-test-renderer": "^17.0.2",
"request": "^2.83.0", "request": "^2.83.0",
"rimraf": "^2.6.1", "rimraf": "^2.6.1",
@ -347,7 +345,6 @@
"tape": "^4.13.3", "tape": "^4.13.3",
"terser-webpack-plugin": "^5.3.6", "terser-webpack-plugin": "^5.3.6",
"timers-browserify": "^2.0.12", "timers-browserify": "^2.0.12",
"ts-jest": "^29.0.3",
"ts-node": "10.9.1", "ts-node": "10.9.1",
"tslint": "~6.0.0", "tslint": "~6.0.0",
"typescript": "^4.8.4", "typescript": "^4.8.4",

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save