Merge branch 'master' into theme-hacker-owl

pull/1527/head
U.M Andrew 3 years ago committed by GitHub
commit 10e5d56766
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 63
      .circleci/config.yml
  2. 2
      .eslintrc
  3. 2
      apps/remix-ide-e2e/nightwatch.ts
  4. 15
      apps/remix-ide-e2e/src/commands/clickElementAtPosition.ts
  5. 4
      apps/remix-ide-e2e/src/local-plugin/.babelrc
  6. 16
      apps/remix-ide-e2e/src/local-plugin/.browserslistrc
  7. 248
      apps/remix-ide-e2e/src/local-plugin/.eslintrc
  8. 128
      apps/remix-ide-e2e/src/local-plugin/src/app/app.css
  9. 39
      apps/remix-ide-e2e/src/local-plugin/src/app/app.tsx
  10. 17
      apps/remix-ide-e2e/src/local-plugin/src/app/logo.svg
  11. 11
      apps/remix-ide-e2e/src/local-plugin/src/app/star.svg
  12. 0
      apps/remix-ide-e2e/src/local-plugin/src/assets/.gitkeep
  13. 3
      apps/remix-ide-e2e/src/local-plugin/src/environments/environment.prod.ts
  14. 6
      apps/remix-ide-e2e/src/local-plugin/src/environments/environment.ts
  15. BIN
      apps/remix-ide-e2e/src/local-plugin/src/favicon.ico
  16. 14
      apps/remix-ide-e2e/src/local-plugin/src/index.html
  17. 11
      apps/remix-ide-e2e/src/local-plugin/src/main.tsx
  18. 7
      apps/remix-ide-e2e/src/local-plugin/src/polyfills.ts
  19. 1
      apps/remix-ide-e2e/src/local-plugin/src/styles.css
  20. 13
      apps/remix-ide-e2e/src/local-plugin/tsconfig.app.json
  21. 16
      apps/remix-ide-e2e/src/local-plugin/tsconfig.json
  22. 6
      apps/remix-ide-e2e/src/tests/ballot.test.ts
  23. 41
      apps/remix-ide-e2e/src/tests/pluginManager.ts
  24. 64
      apps/remix-ide-e2e/src/tests/solidityUnittests.spec.ts
  25. 63
      apps/remix-ide-e2e/src/tests/terminal.test.ts
  26. 8
      apps/remix-ide-e2e/src/tests/url.spec.ts
  27. 8
      apps/remix-ide-e2e/src/types/index.d.ts
  28. 21
      apps/remix-ide/ci/browser_tests_plugin_manager.sh
  29. 172
      apps/remix-ide/src/app/files/dgitProvider.js
  30. 24
      apps/remix-ide/src/app/files/fileManager.js
  31. 1
      apps/remix-ide/src/app/files/fileProvider.js
  32. 7
      apps/remix-ide/src/app/tabs/compile-tab.js
  33. 14
      apps/remix-ide/src/app/tabs/test-tab.js
  34. 1
      apps/remix-ide/src/remixEngine.js
  35. 4
      apps/solidity-compiler/src/app/compiler-api.ts
  36. 34
      apps/solidity-compiler/webpack.config.js
  37. 8
      jest.config.js
  38. 14
      libs/remix-analyzer/package.json
  39. 10
      libs/remix-astwalker/package.json
  40. 2
      libs/remix-astwalker/src/@types/remix-lib/index.d.ts
  41. 9
      libs/remix-debug/package.json
  42. 2
      libs/remix-debug/src/code/codeUtils.ts
  43. 2
      libs/remix-debug/src/source/sourceMappingDecoder.ts
  44. 2
      libs/remix-debug/src/storage/storageResolver.ts
  45. 2
      libs/remix-debug/src/trace/traceHelper.ts
  46. 24
      libs/remix-debug/test/debugger.ts
  47. 19
      libs/remix-debug/test/decoder/localDecoder.ts
  48. 21
      libs/remix-debug/test/decoder/localsTests/calldata.ts
  49. 16
      libs/remix-debug/test/decoder/localsTests/int.ts
  50. 16
      libs/remix-debug/test/decoder/localsTests/misc.ts
  51. 14
      libs/remix-debug/test/decoder/localsTests/misc2.ts
  52. 14
      libs/remix-debug/test/decoder/localsTests/structArray.ts
  53. 36
      libs/remix-debug/test/decoder/stateTests/mapping.ts
  54. 76
      libs/remix-debug/test/decoder/vmCall.ts
  55. 2
      libs/remix-debug/test/tests.ts
  56. 75
      libs/remix-debug/test/vmCall.ts
  57. 4
      libs/remix-lib/package.json
  58. 25
      libs/remix-lib/src/execution/logsManager.ts
  59. 40
      libs/remix-lib/src/execution/txFormat.ts
  60. 8
      libs/remix-lib/src/execution/txHelper.ts
  61. 1
      libs/remix-lib/src/execution/txRunnerVM.ts
  62. 2
      libs/remix-lib/src/helpers/uiHelper.ts
  63. 4
      libs/remix-lib/src/init.ts
  64. 20
      libs/remix-lib/src/util.ts
  65. 12
      libs/remix-lib/src/web3Provider/web3VmProvider.ts
  66. 6
      libs/remix-simulator/package.json
  67. 5
      libs/remix-simulator/src/methods/blocks.ts
  68. 20
      libs/remix-simulator/src/methods/misc.ts
  69. 6
      libs/remix-simulator/src/methods/net.ts
  70. 32
      libs/remix-simulator/src/methods/transactions.ts
  71. 31
      libs/remix-simulator/src/utils/logs.ts
  72. 72
      libs/remix-simulator/src/vm-context.ts
  73. 26
      libs/remix-simulator/test/blocks.ts
  74. 12
      libs/remix-solidity/package.json
  75. 10
      libs/remix-tests/package.json
  76. 9
      libs/remix-tests/src/testRunner.ts
  77. 4
      libs/remix-ui/plugin-manager/.eslintrc
  78. 12
      libs/remix-ui/plugin-manager/src/lib/components/LocalPluginForm.tsx
  79. 93
      libs/remix-ui/plugin-manager/src/types.d.ts
  80. 1
      libs/remix-ui/renderer/src/lib/renderer.css
  81. 2
      libs/remix-ui/renderer/src/lib/renderer.tsx
  82. 6
      libs/remix-ui/static-analyser/src/lib/remix-ui-static-analyser.tsx
  83. 10
      libs/remix-url-resolver/package.json
  84. 2
      libs/remixd/package.json
  85. 4
      libs/remixd/src/bin/remixd.ts
  86. 13
      nx.json
  87. 43945
      package-lock.json
  88. 73
      package.json
  89. 1
      release-management.md
  90. 8
      tsconfig.base.json
  91. 76
      workspace.json

@ -7,7 +7,7 @@ jobs:
lint:
docker:
# specify the version you desire here
- image: circleci/node:10.18.0-browsers
- image: circleci/node:14.17.6-browsers
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
@ -35,7 +35,7 @@ jobs:
remix-libs:
docker:
# specify the version you desire here
- image: circleci/node:10.18.0-browsers
- image: circleci/node:14.17.6-browsers
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
@ -56,7 +56,7 @@ jobs:
remix-ide-chrome-1:
docker:
# specify the version you desire here
- image: circleci/node:10.18.0-browsers
- image: circleci/node:14.17.6-browsers
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
@ -89,7 +89,7 @@ jobs:
remix-ide-chrome-2:
docker:
# specify the version you desire here
- image: circleci/node:10.18.0-browsers
- image: circleci/node:14.17.6-browsers
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
@ -123,7 +123,7 @@ jobs:
remix-ide-firefox-1:
docker:
# specify the version you desire here
- image: circleci/node:10.18.0-browsers
- image: circleci/node:14.17.6-browsers
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
@ -156,7 +156,7 @@ jobs:
remix-ide-firefox-2:
docker:
# specify the version you desire here
- image: circleci/node:10.18.0-browsers
- image: circleci/node:14.17.6-browsers
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
@ -190,7 +190,7 @@ jobs:
remix-ide-run-deploy:
docker:
# specify the version you desire here
- image: circleci/node:10.18.0-browsers
- image: circleci/node:14.17.6-browsers
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
@ -220,11 +220,45 @@ jobs:
- store_artifacts:
path: ./reports/screenshots
remix-ide-plugin-manager:
docker:
# specify the version you desire here
- image: circleci/node:14.17.6-browsers
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
# documented at https://circleci.com/docs/2.0/circleci-images/
resource_class: xlarge
# - image: circleci/mongo:3.4.4
environment:
- COMMIT_AUTHOR_EMAIL: "yann@ethereum.org"
- COMMIT_AUTHOR: "Circle CI"
- FILES_TO_PACKAGE: "dist/apps/remix-ide/assets dist/apps/remix-ide/index.html dist/apps/remix-ide/main.js dist/apps/remix-ide/polyfills.js dist/apps/remix-ide/runtime.js dist/apps/remix-ide/vendor.js dist/apps/remix-ide/favicon.ico"
working_directory: ~/remix-project
steps:
- checkout
- run: npm install
- run: npx nx build remix-ide --with-deps
- run: npx nx build remix-ide-e2e-src-local-plugin
- run:
name: Download Selenium
command: ./node_modules/.bin/selenium-standalone install --drivers.chrome.version=2.39 --drivers.chrome.baseURL=https://chromedriver.storage.googleapis.com
- run:
name: Start Selenium
command: ./node_modules/.bin/selenium-standalone start --drivers.chrome.version=2.39 --drivers.chrome.baseURL=https://chromedriver.storage.googleapis.com
background: true
- run: ./apps/remix-ide/ci/browser_tests_plugin_manager.sh
- store_test_results:
path: ./reports/tests
- store_artifacts:
path: ./reports/screenshots
deploy-remix-live:
docker:
# specify the version you desire here
- image: circleci/node:10.18.0-browsers
- image: circleci/node:14.17.6-browsers
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
@ -252,7 +286,7 @@ jobs:
publish:
docker:
# specify the version you desire here
- image: circleci/node:10.19.0-buster
- image: circleci/node:14.17.6-browsers
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
@ -278,7 +312,7 @@ jobs:
deploy-remix-alpha:
docker:
# specify the version you desire here
- image: circleci/node:10.18.0-browsers
- image: circleci/node:14.17.6-browsers
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
@ -306,7 +340,7 @@ jobs:
deploy-remix-beta:
docker:
# specify the version you desire here
- image: circleci/node:10.18.0-browsers
- image: circleci/node:14.17.6-browsers
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
@ -355,6 +389,9 @@ workflows:
- remix-ide-run-deploy:
requires:
- lint
- remix-ide-plugin-manager:
requires:
- lint
- publish:
requires:
- lint
@ -365,6 +402,7 @@ workflows:
- remix-ide-firefox-1
- remix-ide-firefox-2
- remix-ide-run-deploy
- remix-ide-plugin-manager
filters:
branches:
only: remix_live
@ -375,6 +413,7 @@ workflows:
- remix-ide-firefox-1
- remix-ide-firefox-2
- remix-ide-run-deploy
- remix-ide-plugin-manager
filters:
branches:
only: master
@ -385,6 +424,8 @@ workflows:
- remix-ide-firefox-1
- remix-ide-firefox-2
- remix-ide-run-deploy
- remix-ide-plugin-manager
filters:
branches:
only: remix_beta

@ -4,7 +4,7 @@
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module",
"project": "./tsconfig.json"
"project": "./tsconfig.base.json"
},
"plugins": ["@typescript-eslint", "@nrwl/nx"],
"extends": "standard",

@ -30,7 +30,7 @@ module.exports = {
javascriptEnabled: true,
acceptSslCerts: true
},
exclude: ['dist/apps/remix-ide-e2e/src/tests/runAndDeploy.js']
exclude: ['dist/apps/remix-ide-e2e/src/tests/runAndDeploy.js', 'dist/apps/remix-ide-e2e/src/tests/pluginManager.spec.ts']
},
chrome: {

@ -2,9 +2,9 @@ import { NightwatchBrowser } from 'nightwatch'
import EventEmitter from 'events'
class ClickElement extends EventEmitter {
command (this: NightwatchBrowser, cssSelector: string, index = 0): NightwatchBrowser {
command (this: NightwatchBrowser, cssSelector: string, index = 0, opt = { forceSelectIfUnselected: false }): NightwatchBrowser {
this.api.perform((done) => {
_clickElement(this.api, cssSelector, index, () => {
_clickElement(this.api, cssSelector, index, opt.forceSelectIfUnselected, () => {
done()
this.emit('complete')
})
@ -13,13 +13,14 @@ class ClickElement extends EventEmitter {
}
}
function _clickElement (browser: NightwatchBrowser, cssSelector: string, index: number, cb: VoidFunction) {
function _clickElement (browser: NightwatchBrowser, cssSelector: string, index: number, forceSelectIfUnselected: boolean, cb: VoidFunction) {
browser.waitForElementPresent(cssSelector)
.execute(function (cssSelector: string, index: number) {
.execute(function (cssSelector: string, index: number, forceSelectIfUnselected: boolean) {
const elem = document.querySelectorAll(cssSelector)[index] as HTMLElement
elem.click()
}, [cssSelector, index], function () {
if (forceSelectIfUnselected) {
if (!(elem as any).checked) elem.click()
} else elem.click()
}, [cssSelector, index, forceSelectIfUnselected], function () {
cb()
})
}

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

@ -0,0 +1,16 @@
# This file is used by:
# 1. autoprefixer to adjust CSS to support the below specified browsers
# 2. babel preset-env to adjust included polyfills
#
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
#
# If you need to support different browsers in production, you may tweak the list below.
last 1 Chrome version
last 1 Firefox version
last 2 Edge major versions
last 2 Safari major version
last 2 iOS major versions
Firefox ESR
not IE 9-11 # For IE 9-11 support, remove 'not'.

@ -0,0 +1,248 @@
{
"rules": {
"array-callback-return": "warn",
"dot-location": ["warn", "property"],
"eqeqeq": ["warn", "smart"],
"new-parens": "warn",
"no-caller": "warn",
"no-cond-assign": ["warn", "except-parens"],
"no-const-assign": "warn",
"no-control-regex": "warn",
"no-delete-var": "warn",
"no-dupe-args": "warn",
"no-dupe-keys": "warn",
"no-duplicate-case": "warn",
"no-empty-character-class": "warn",
"no-empty-pattern": "warn",
"no-eval": "warn",
"no-ex-assign": "warn",
"no-extend-native": "warn",
"no-extra-bind": "warn",
"no-extra-label": "warn",
"no-fallthrough": "warn",
"no-func-assign": "warn",
"no-implied-eval": "warn",
"no-invalid-regexp": "warn",
"no-iterator": "warn",
"no-label-var": "warn",
"no-labels": ["warn", { "allowLoop": true, "allowSwitch": false }],
"no-lone-blocks": "warn",
"no-loop-func": "warn",
"no-mixed-operators": [
"warn",
{
"groups": [
["&", "|", "^", "~", "<<", ">>", ">>>"],
["==", "!=", "===", "!==", ">", ">=", "<", "<="],
["&&", "||"],
["in", "instanceof"]
],
"allowSamePrecedence": false
}
],
"no-multi-str": "warn",
"no-native-reassign": "warn",
"no-negated-in-lhs": "warn",
"no-new-func": "warn",
"no-new-object": "warn",
"no-new-symbol": "warn",
"no-new-wrappers": "warn",
"no-obj-calls": "warn",
"no-octal": "warn",
"no-octal-escape": "warn",
"no-redeclare": "warn",
"no-regex-spaces": "warn",
"no-restricted-syntax": ["warn", "WithStatement"],
"no-script-url": "warn",
"no-self-assign": "warn",
"no-self-compare": "warn",
"no-sequences": "warn",
"no-shadow-restricted-names": "warn",
"no-sparse-arrays": "warn",
"no-template-curly-in-string": "warn",
"no-this-before-super": "warn",
"no-throw-literal": "warn",
"no-restricted-globals": [
"error",
"addEventListener",
"blur",
"close",
"closed",
"confirm",
"defaultStatus",
"defaultstatus",
"event",
"external",
"find",
"focus",
"frameElement",
"frames",
"history",
"innerHeight",
"innerWidth",
"length",
"location",
"locationbar",
"menubar",
"moveBy",
"moveTo",
"name",
"onblur",
"onerror",
"onfocus",
"onload",
"onresize",
"onunload",
"open",
"opener",
"opera",
"outerHeight",
"outerWidth",
"pageXOffset",
"pageYOffset",
"parent",
"print",
"removeEventListener",
"resizeBy",
"resizeTo",
"screen",
"screenLeft",
"screenTop",
"screenX",
"screenY",
"scroll",
"scrollbars",
"scrollBy",
"scrollTo",
"scrollX",
"scrollY",
"self",
"status",
"statusbar",
"stop",
"toolbar",
"top"
],
"no-unexpected-multiline": "warn",
"no-unreachable": "warn",
"no-unused-expressions": [
"error",
{
"allowShortCircuit": true,
"allowTernary": true,
"allowTaggedTemplates": true
}
],
"no-unused-labels": "warn",
"no-useless-computed-key": "warn",
"no-useless-concat": "warn",
"no-useless-escape": "warn",
"no-useless-rename": [
"warn",
{
"ignoreDestructuring": false,
"ignoreImport": false,
"ignoreExport": false
}
],
"no-with": "warn",
"no-whitespace-before-property": "warn",
"react-hooks/exhaustive-deps": "warn",
"require-yield": "warn",
"rest-spread-spacing": ["warn", "never"],
"strict": ["warn", "never"],
"unicode-bom": ["warn", "never"],
"use-isnan": "warn",
"valid-typeof": "warn",
"no-restricted-properties": [
"error",
{
"object": "require",
"property": "ensure",
"message": "Please use import() instead. More info: https://facebook.github.io/create-react-app/docs/code-splitting"
},
{
"object": "System",
"property": "import",
"message": "Please use import() instead. More info: https://facebook.github.io/create-react-app/docs/code-splitting"
}
],
"getter-return": "warn",
"import/first": "error",
"import/no-amd": "error",
"import/no-webpack-loader-syntax": "error",
"react/forbid-foreign-prop-types": ["warn", { "allowInPropTypes": true }],
"react/jsx-no-comment-textnodes": "warn",
"react/jsx-no-duplicate-props": "warn",
"react/jsx-no-target-blank": "warn",
"react/jsx-no-undef": "error",
"react/jsx-pascal-case": ["warn", { "allowAllCaps": true, "ignore": [] }],
"react/jsx-uses-react": "warn",
"react/jsx-uses-vars": "warn",
"react/no-danger-with-children": "warn",
"react/no-direct-mutation-state": "warn",
"react/no-is-mounted": "warn",
"react/no-typos": "error",
"react/react-in-jsx-scope": "error",
"react/require-render-return": "error",
"react/style-prop-object": "warn",
"react/jsx-no-useless-fragment": "warn",
"jsx-a11y/accessible-emoji": "warn",
"jsx-a11y/alt-text": "warn",
"jsx-a11y/anchor-has-content": "warn",
"jsx-a11y/anchor-is-valid": [
"warn",
{ "aspects": ["noHref", "invalidHref"] }
],
"jsx-a11y/aria-activedescendant-has-tabindex": "warn",
"jsx-a11y/aria-props": "warn",
"jsx-a11y/aria-proptypes": "warn",
"jsx-a11y/aria-role": "warn",
"jsx-a11y/aria-unsupported-elements": "warn",
"jsx-a11y/heading-has-content": "warn",
"jsx-a11y/iframe-has-title": "warn",
"jsx-a11y/img-redundant-alt": "warn",
"jsx-a11y/no-access-key": "warn",
"jsx-a11y/no-distracting-elements": "warn",
"jsx-a11y/no-redundant-roles": "warn",
"jsx-a11y/role-has-required-aria-props": "warn",
"jsx-a11y/role-supports-aria-props": "warn",
"jsx-a11y/scope": "warn",
"react-hooks/rules-of-hooks": "error",
"default-case": "off",
"no-dupe-class-members": "off",
"no-undef": "off",
"@typescript-eslint/consistent-type-assertions": "warn",
"no-array-constructor": "off",
"@typescript-eslint/no-array-constructor": "warn",
"@typescript-eslint/no-namespace": "error",
"no-use-before-define": "off",
"@typescript-eslint/no-use-before-define": [
"warn",
{
"functions": false,
"classes": false,
"variables": false,
"typedefs": false
}
],
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": [
"warn",
{ "args": "none", "ignoreRestSiblings": true }
],
"no-useless-constructor": "off",
"@typescript-eslint/no-useless-constructor": "warn"
},
"env": {
"browser": true,
"commonjs": true,
"es6": true,
"jest": true,
"node": true
},
"settings": { "react": { "version": "detect" } },
"plugins": ["import", "jsx-a11y", "react", "react-hooks"],
"extends": ["../../../../.eslintrc"],
"ignorePatterns": ["!**/*"]
}

@ -0,0 +1,128 @@
.app {
font-family: sans-serif;
min-width: 300px;
max-width: 600px;
margin: 50px auto;
}
.app .gutter-left {
margin-left: 9px;
}
.app .col-span-2 {
grid-column: span 2;
}
.app .flex {
display: flex;
align-items: center;
justify-content: center;
}
.app header {
background-color: #143055;
color: white;
padding: 5px;
border-radius: 3px;
}
.app main {
padding: 0 36px;
}
.app p {
text-align: center;
}
.app h1 {
text-align: center;
margin-left: 18px;
font-size: 24px;
}
.app h2 {
text-align: center;
font-size: 20px;
margin: 40px 0 10px 0;
}
.app .resources {
text-align: center;
list-style: none;
padding: 0;
display: grid;
grid-gap: 9px;
grid-template-columns: 1fr 1fr;
}
.app .resource {
color: #0094ba;
height: 36px;
background-color: rgba(0, 0, 0, 0);
border: 1px solid rgba(0, 0, 0, 0.12);
border-radius: 4px;
padding: 3px 9px;
text-decoration: none;
}
.app .resource:hover {
background-color: rgba(68, 138, 255, 0.04);
}
.app pre {
padding: 9px;
border-radius: 4px;
background-color: black;
color: #eee;
}
.app details {
border-radius: 4px;
color: #333;
background-color: rgba(0, 0, 0, 0);
border: 1px solid rgba(0, 0, 0, 0.12);
padding: 3px 9px;
margin-bottom: 9px;
}
.app summary {
outline: none;
height: 36px;
line-height: 36px;
}
.app .github-star-container {
margin-top: 12px;
line-height: 20px;
}
.app .github-star-container a {
display: flex;
align-items: center;
text-decoration: none;
color: #333;
}
.app .github-star-badge {
color: #24292e;
display: flex;
align-items: center;
font-size: 12px;
padding: 3px 10px;
border: 1px solid rgba(27, 31, 35, 0.2);
border-radius: 3px;
background-image: linear-gradient(-180deg, #fafbfc, #eff3f6 90%);
margin-left: 4px;
font-weight: 600;
}
.app .github-star-badge:hover {
background-image: linear-gradient(-180deg, #f0f3f6, #e6ebf1 90%);
border-color: rgba(27, 31, 35, 0.35);
background-position: -0.5em;
}
.app .github-star-badge .material-icons {
height: 16px;
width: 16px;
margin-right: 4px;
}

@ -0,0 +1,39 @@
import React, { useEffect, useState } from 'react'
import { PluginClient } from '@remixproject/plugin'
import { createClient } from '@remixproject/plugin-webview'
import './app.css'
import { ReactComponent as Logo } from './logo.svg'
export const App = () => {
const [remixClient, setRemixClient] = useState(null)
useEffect(() => {
(async () => {
const client = createClient(new PluginClient())
await client.onload()
console.log('Local plugin loaded')
setRemixClient(client)
})()
}, [])
const handleClick = () => {
remixClient.call('manager', 'activatePlugin', 'LearnEth')
}
return (
<div className="app">
<header className="flex">
<Logo width="75" height="75" />
<h1>Welcome to local-plugin!</h1>
</header>
<main>
<button data-id="btnActivateRemixd" onClick={handleClick}>Activate Learneth</button>
</main>
</div>
)
}
export default App

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="262px" height="163px" viewBox="0 0 262 163" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Styles-&amp;-Quick-Wins" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Nx---Quick-Wins" transform="translate(-476.000000, -1284.000000)" fill-rule="nonzero">
<g id="Logos" transform="translate(-11.000000, 782.000000)">
<g id="Nx_Flat_White" transform="translate(487.000000, 502.000000)">
<polygon id="Path" fill="#FFFFFF" points="130.68 104.59 97.49 52.71 97.44 96.3 40.24 0 0 0 0 162.57 39.79 162.57 39.92 66.39 96.53 158.26"></polygon>
<polygon id="Path" fill="#FFFFFF" points="97.5 41.79 137.24 41.79 137.33 41.33 137.33 0 97.54 0 97.49 41.33"></polygon>
<path d="M198.66,86.86 C189.139872,86.6795216 180.538723,92.516445 177.19,101.43 C182.764789,93.0931021 193.379673,89.7432211 202.73,93.37 C207.05,95.13 212.73,97.97 217.23,96.45 C212.950306,90.4438814 206.034895,86.8725952 198.66,86.86 L198.66,86.86 Z" id="Path" fill="#96D8E9"></path>
<path d="M243.75,106.42 C243.75,101.55 241.1,100.42 235.6,98.42 C231.52,97 226.89,95.4 223.52,91 C222.86,90.13 222.25,89.15 221.6,88.11 C220.14382,85.4164099 218.169266,83.037429 215.79,81.11 C212.58,78.75 208.37,77.6 202.91,77.6 C191.954261,77.6076705 182.084192,84.2206169 177.91,94.35 C183.186964,87.0278244 191.956716,83.0605026 200.940147,83.9314609 C209.923578,84.8024193 217.767888,90.3805017 221.54,98.58 C223.424615,101.689762 227.141337,103.174819 230.65,102.22 C236.02,101.07 235.65,106.15 243.76,107.87 L243.75,106.42 Z" id="Path" fill="#48C4E5"></path>
<path d="M261.46,105.38 L261.46,105.27 C261.34,73.03 235.17,45.45 202.91,45.45 C183.207085,45.4363165 164.821777,55.3450614 154,71.81 L153.79,71.45 L137.23,45.45 L97.5,45.4499858 L135.25,104.57 L98.41,162.57 L137,162.57 L153.79,136.78 L170.88,162.57 L209.48,162.57 L174.48,107.49 C173.899005,106.416838 173.583536,105.220114 173.56,104 C173.557346,96.2203871 176.64661,88.7586448 182.147627,83.2576275 C187.648645,77.7566101 195.110387,74.6673462 202.89,74.67 C219.11,74.67 221.82,84.37 225.32,88.93 C232.23,97.93 246.03,93.99 246.03,105.73 L246.03,105.73 C246.071086,108.480945 247.576662,111.001004 249.979593,112.340896 C252.382524,113.680787 255.317747,113.636949 257.679593,112.225896 C260.041438,110.814842 261.471086,108.250945 261.43,105.5 L261.43,105.5 L261.43,105.38 L261.46,105.38 Z" id="Path" fill="#FFFFFF"></path>
<path d="M261.5,113.68 C261.892278,116.421801 261.504116,119.218653 260.38,121.75 C258.18,126.84 254.51,125.14 254.51,125.14 C254.51,125.14 251.35,123.6 253.27,120.65 C255.4,117.36 259.61,117.74 261.5,113.68 Z" id="Path" fill="#FFFFFF"></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg
className="material-icons"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
>
<path d="M0 0h24v24H0z" fill="none" />
<path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z" />
</svg>

After

Width:  |  Height:  |  Size: 347 B

@ -0,0 +1,3 @@
export const environment = {
production: true
}

@ -0,0 +1,6 @@
// This file can be replaced during build by using the `fileReplacements` array.
// When building for production, this file is replaced with `environment.prod.ts`.
export const environment = {
production: false
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>LocalPlugin</title>
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
</head>
<body>
<div id="root"></div>
</body>
</html>

@ -0,0 +1,11 @@
import React from 'react'
import ReactDOM from 'react-dom'
import App from './app/app'
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
)

@ -0,0 +1,7 @@
/**
* Polyfill stable language features. These imports will be optimized by `@babel/preset-env`.
*
* See: https://github.com/zloirock/core-js#babel
*/
import 'core-js/stable'
import 'regenerator-runtime/runtime'

@ -0,0 +1 @@
/* You can add global styles to this file, and also import other style files */

@ -0,0 +1,13 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../../../dist/out-tsc",
"types": ["node"]
},
"files": [
"../../../../node_modules/@nrwl/react/typings/cssmodule.d.ts",
"../../../../node_modules/@nrwl/react/typings/image.d.ts"
],
"exclude": ["**/*.spec.ts", "**/*.spec.tsx"],
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
}

@ -0,0 +1,16 @@
{
"extends": "../../../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react",
"allowJs": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.app.json"
}
]
}

@ -56,7 +56,8 @@ module.exports = {
.waitForElementVisible('#stepdetail')
.goToVMTraceStep(144)
.pause(2000)
.checkVariableDebug('soliditystate', stateCheck)
// Should be uncommented while fixing https://github.com/ethereum/remix-project/issues/1644
// .checkVariableDebug('soliditystate', stateCheck)
.checkVariableDebug('soliditylocals', localsCheck)
},
@ -116,7 +117,7 @@ const localsCheck = {
type: 'address'
}
}
/*
const stateCheck = {
chairperson: {
value: '0xCA35B7D915458EF540ADE6068DFE2F44E8FA733C',
@ -174,6 +175,7 @@ const stateCheck = {
immutable: false
}
}
*/
const ballotABI = `[
{

@ -12,6 +12,13 @@ const testData = {
pluginUrl: 'https://zokrates.github.io/zokrates-remix-plugin/'
}
const localPluginData = {
pluginName: 'localPlugin',
pluginDisplayName: 'Local Plugin',
pluginCanActivate: 'LearnEth',
pluginUrl: 'http://localhost:2020'
}
module.exports = {
before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done, 'http://127.0.0.1:8080', false)
@ -147,8 +154,38 @@ module.exports = {
.assert.containsText('*[data-shared="tooltipPopup"]', 'Cannot create Plugin : This name has already been used')
},
'Local plugin should activate LearnEth plugin': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('*[data-id="pluginManagerComponentPluginManager"]')
.click('*[data-id="pluginManagerComponentPluginSearchButton"]')
.waitForElementVisible('*[data-id="pluginManagerLocalPluginModalDialogModalDialogContainer-react"]')
.click('*[data-id="pluginManagerLocalPluginModalDialogModalDialogModalBody-react"]')
.waitForElementVisible('*[data-id="localPluginName"]')
.clearValue('*[data-id="localPluginName"]').setValue('*[data-id="localPluginName"]', localPluginData.pluginName)
.clearValue('*[data-id="localPluginDisplayName"]').setValue('*[data-id="localPluginDisplayName"]', localPluginData.pluginDisplayName)
.clearValue('*[data-id="localPluginCanActivate"]').setValue('*[data-id="localPluginCanActivate"]', localPluginData.pluginCanActivate)
.clearValue('*[data-id="localPluginUrl"]').setValue('*[data-id="localPluginUrl"]', localPluginData.pluginUrl)
.click('*[data-id="localPluginRadioButtoniframe"]')
.click('*[data-id="localPluginRadioButtonsidePanel"]')
.click('*[data-id="pluginManagerLocalPluginModalDialogModalDialogModalFooter-react"]')
.click('*[data-id="pluginManagerLocalPluginModalDialog-modal-footer-ok-react')
.waitForElementVisible('[data-id="verticalIconsKindlocalPlugin"]')
.click('[data-id="verticalIconsKindlocalPlugin"]')
.waitForElementNotPresent('[data-id="verticalIconsKindLearnEth"]')
.pause(2000)
// @ts-ignore
.frame('plugin-localPlugin')
.useXpath().click("//button[text()='Activate Learneth']")
.pause(2000)
.frameParent()
.useCss().waitForElementPresent('[data-id="verticalIconsKindLearnEth"]')
},
'Should load back installed plugins after reload': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('*[data-id="pluginManagerComponentPluginManager"]')
browser
.waitForElementVisible('*[data-id="remixIdeSidePanel"]')
.click('*[plugin="pluginManager"]')
.waitForElementVisible('*[data-id="pluginManagerComponentPluginManager"]')
.getInstalledPlugins((plugins) => {
browser.refresh()
.waitForElementVisible('*[data-id="remixIdeSidePanel"]')
@ -156,7 +193,7 @@ module.exports = {
.perform((done) => {
// const filtered = plugins.filter(plugin => plugin !== 'testremixIde') // remove this when localplugin bug is resolved
plugins.forEach(plugin => {
if (plugin !== testData.pluginName && plugin !== 'testremixIde') {
if ((plugin !== testData.pluginName) && plugin !== localPluginData.pluginName) {
browser.waitForElementVisible(`[plugin="${plugin}"`)
}
})

@ -90,17 +90,23 @@ module.exports = {
.waitForElementContainsText('*[data-id="testTabTestsExecutionStopped"]', 'The test execution has been stopped', 60000)
},
'Should fail on compilation': function (browser: NightwatchBrowser) {
'Should fail on compilation, open file on error click, not disappear error': function (browser: NightwatchBrowser) {
browser.waitForElementPresent('*[data-id="verticalIconsKindfilePanel"]')
.addFile('tests/compilationError_test.sol', sources[0]['compilationError_test.sol'])
.clickLaunchIcon('filePanel')
.openFile('tests/compilationError_test.sol')
.click('div[title="default_workspace/tests/compilationError_test.sol"] span[class="close"]')
.clickLaunchIcon('solidityUnitTesting')
.pause(2000)
.click('*[data-id="testTabCheckAllTests"]')
.clickElementAtPosition('.singleTestLabel', 3)
.scrollAndClick('*[data-id="testTabRunTestsTabRunAction"]')
.waitForElementContainsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'SyntaxError: No visibility specified', 120000)
.waitForElementContainsText('*[data-id="testTabTestsExecutionStoppedError"]', 'The test execution has been stopped because of error(s) in your test file', 120000)
.click('*[data-id="tests/compilationError_test.sol"]')
.pause(1000)
.getEditorValue((content) => browser.assert.ok(content.indexOf('contract failOnCompilation {') !== -1))
// Verify that compilation error is still present after a file is opened
// usually, tests result is cleared on opening a new file
.verify.elementPresent('*[data-id="tests/compilationError_test.sol"]')
},
'Should fail on deploy': function (browser: NightwatchBrowser) {
@ -134,7 +140,7 @@ module.exports = {
.clickLaunchIcon('solidityUnitTesting')
.setValue('*[data-id="uiPathInput"]', 'myTests')
.click('*[data-id="testTabGenerateTestFolder"]')
.clickElementAtPosition('.singleTestLabel', 0)
.clickElementAtPosition('.singleTest', 0, { forceSelectIfUnselected: true })
.scrollAndClick('*[data-id="testTabRunTestsTabRunAction"]')
.waitForElementPresent('*[data-id="testTabSolidityUnitTestsOutputheader"]', 60000)
.waitForElementPresent('*[data-id="testTabSolidityUnitTestsOutput"]')
@ -206,6 +212,23 @@ module.exports = {
.removeFile('tests/hhLogs_test.sol', 'workspace_new')
},
'Solidity Unit tests with hardhat console log for EVM revert': function (browser: NightwatchBrowser) {
browser
.waitForElementPresent('*[data-id="verticalIconsKindfilePanel"]')
.addFile('tests/ballotFailedLog_test.sol', sources[0]['tests/ballotFailedLog_test.sol'])
.clickLaunchIcon('solidityUnitTesting')
.waitForElementVisible('*[id="singleTesttests/4_Ballot_test.sol"]', 60000)
.click('*[id="singleTesttests/4_Ballot_test.sol"]')
.click('#runTestsTabRunAction')
.pause(2000)
.waitForElementVisible('*[data-id="testTabSolidityUnitTestsOutputheader"]', 120000)
.waitForElementContainsText('#solidityUnittestsOutput', 'tests/ballotFailedLog_test.sol', 60000)
.assert.containsText('#journal > div:nth-child(6) > span > div', 'Check winning proposal:')
.assert.containsText('#journal > div:nth-child(6) > span > div', 'Inside checkWinningProposal')
.openFile('tests/ballotFailedLog_test.sol')
.removeFile('tests/ballotFailedLog_test.sol', 'workspace_new')
},
'Debug failed test using debugger': function (browser: NightwatchBrowser) {
browser
.waitForElementPresent('*[data-id="verticalIconsKindfilePanel"]')
@ -229,7 +252,8 @@ module.exports = {
.waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinningProposal()', 60000)
.waitForElementContainsText('*[data-id="functionPanel"]', 'vote(proposal)', 60000)
.pause(2000)
.checkVariableDebug('soliditylocals', locals)
// Should be uncommented while fixing https://github.com/ethereum/remix-project/issues/1644
// .checkVariableDebug('soliditylocals', locals)
.clickLaunchIcon('filePanel')
.pause(2000)
.openFile('tests/ballotFailedDebug_test.sol')
@ -423,7 +447,7 @@ const sources = [
},
'compilationError_test.sol': {
content: `
pragma solidity ^0.7.0;
pragma solidity ^0.8.0;
contract failOnCompilation {
fallback() {
@ -482,6 +506,31 @@ const sources = [
}
}`
},
'tests/ballotFailedLog_test.sol': {
content: `// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
import "remix_tests.sol"; // this import is automatically injected by Remix.
import "../contracts/3_Ballot.sol";
import "hardhat/console.sol";
contract BallotTest {
bytes32[] proposalNames;
Ballot ballotToTest;
function beforeAll () public {
proposalNames.push(bytes32("candidate1"));
ballotToTest = new Ballot(proposalNames);
}
function checkWinningProposal () public {
console.log("Inside checkWinningProposal");
ballotToTest.vote(1); // This will revert the transaction
}
}`
},
'tests/hhLogs_test.sol': {
content: `// SPDX-License-Identifier: GPL-3.0
@ -509,7 +558,7 @@ const sources = [
}
}
]
/*
const locals = {
sender: {
value: {
@ -537,3 +586,4 @@ const locals = {
type: 'uint256'
}
}
*/

@ -107,6 +107,32 @@ module.exports = {
.executeScript('remix.execute(\'resolveExternalUrlAndSaveToaPath.js\')')
.waitForElementContainsText('*[data-id="terminalJournal"]', 'abstract contract ERC20Burnable', 60000)
.openFile('.deps/github/newFile.sol')
},
'Deploy "Owner" using an ether.js script, listen to event and check event are logged in the terminal': function (browser: NightwatchBrowser) {
browser
.clickLaunchIcon('settings')
.clickLaunchIcon('udapp')
.click('*[data-id="settingsVMLondonMode"]')
.click('*[data-id="terminalClearConsole"]') // clear the terminal
.clickLaunchIcon('filePanel')
.click('*[data-id="treeViewDivtreeViewItem"]') // make sure we create the file at the root folder
.addFile('deployWithEthersJs.js', { content: deployWithEthersJs })
.openFile('deployWithEthersJs.js')
.pause(1000)
.openFile('contracts/2_Owner.sol')
.clickLaunchIcon('solidity')
.click('*[data-id="compilerContainerCompileBtn"]') // compile Owner
.executeScript('remix.execute(\'deployWithEthersJs.js\')')
.waitForElementContainsText('*[data-id="terminalJournal"]', 'Contract Address: 0xd9145CCE52D386f254917e481eB44e9943F39138', 60000)
.waitForElementContainsText('*[data-id="terminalJournal"]', 'Deployment successful.', 60000)
.addAtAddressInstance('0xd9145CCE52D386f254917e481eB44e9943F39138', true, true)
.click('*[data-id="terminalClearConsole"]') // clear the terminal
.waitForElementPresent('*[data-id="universalDappUiContractActionWrapper"]', 60000)
.click('*[data-id="universalDappUiTitleExpander"]')
.clickFunction('changeOwner - transact (not payable)', { types: 'address newOwner', values: '0xd9145CCE52D386f254917e481eB44e9943F39138' }) // execute the "changeOwner" function
.waitForElementContainsText('*[data-id="terminalJournal"]', 'previousOwner0x5B38Da6a701c568545dCfcB03FcB875f56beddC4', 60000) // check that the script is logging the event
.waitForElementContainsText('*[data-id="terminalJournal"]', 'newOwner0xd9145CCE52D386f254917e481eB44e9943F39138', 60000)
.end()
}
}
@ -180,3 +206,40 @@ const resolveUrl = `
}
})()
`
const deployWithEthersJs = `
// Right click on the script name and hit "Run" to execute
(async () => {
try {
console.log('Running deployWithEthers script...')
const constructorArgs = [] // Put constructor args (if any) here for your contract
// Note that the script needs the ABI which is generated from the compilation artifact.
// Make sure contract is compiled and artifacts are generated
const artifactsPath = 'contracts/artifacts/Owner.json' // Change this for different path
const metadata = JSON.parse(await remix.call('fileManager', 'getFile', artifactsPath))
// 'web3Provider' is a remix global variable object
const signer = (new ethers.providers.Web3Provider(web3Provider)).getSigner()
let factory = new ethers.ContractFactory(metadata.abi, metadata.data.bytecode.object, signer);
let contract = await factory.deploy(...constructorArgs);
console.log('Contract Address: ', contract.address);
// The contract is NOT deployed yet; we must wait until it is mined
await contract.deployed()
console.log('Deployment successful.')
contract.on('OwnerSet', (previousOwner, newOwner) => {
console.log('previousOwner' , previousOwner)
console.log('newOwner' , newOwner)
})
console.log('ok')
} catch (e) {
console.log(e.message)
}
})()`

@ -19,10 +19,16 @@ module.exports = {
'Should load the code from URL params (code param)': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('[for="autoCompile"]')
.click('[for="autoCompile"]') // we set it too false in the local storage
.pause(5000)
.url('http://127.0.0.1:8080/#optimize=true&runs=300&evmVersion=istanbul&version=soljson-v0.7.4+commit.3f05b770.js&code=cHJhZ21hIHNvbGlkaXR5ID49MC42LjAgPDAuNy4wOwoKaW1wb3J0ICJodHRwczovL2dpdGh1Yi5jb20vT3BlblplcHBlbGluL29wZW56ZXBwZWxpbi1jb250cmFjdHMvYmxvYi9tYXN0ZXIvY29udHJhY3RzL2FjY2Vzcy9Pd25hYmxlLnNvbCI7Cgpjb250cmFjdCBHZXRQYWlkIGlzIE93bmFibGUgewogIGZ1bmN0aW9uIHdpdGhkcmF3KCkgZXh0ZXJuYWwgb25seU93bmVyIHsKICB9Cn0')
.url('http://127.0.0.1:8080/#autoCompile=true&optimize=true&runs=300&evmVersion=istanbul&version=soljson-v0.7.4+commit.3f05b770.js&code=cHJhZ21hIHNvbGlkaXR5ID49MC42LjAgPDAuNy4wOwoKaW1wb3J0ICJodHRwczovL2dpdGh1Yi5jb20vT3BlblplcHBlbGluL29wZW56ZXBwZWxpbi1jb250cmFjdHMvYmxvYi9tYXN0ZXIvY29udHJhY3RzL2FjY2Vzcy9Pd25hYmxlLnNvbCI7Cgpjb250cmFjdCBHZXRQYWlkIGlzIE93bmFibGUgewogIGZ1bmN0aW9uIHdpdGhkcmF3KCkgZXh0ZXJuYWwgb25seU93bmVyIHsKICB9Cn0')
.refresh() // we do one reload for making sure we already have the default workspace
.pause(5000)
.verify.elementPresent('[data-id="compilerContainerAutoCompile"]:checked')
.click('[for="autoCompile"]') // we set it too false again
.click('[for="autoCompile"]') // back to True in the local storage
.assert.containsText('*[data-id="compilerContainerCompileBtn"]', 'contract-76747f6e19.sol')
.currentWorkspaceIs('code-sample')
.getEditorValue((content) => {
browser.assert.ok(content.indexOf(

@ -1,8 +1,8 @@
// Merge custom command types with nightwatch types
import { NightwatchBrowser, NightwatchBrowser, NightwatchBrowser } from "nightwatch";
import { NightwatchBrowser } from 'nightwatch'
declare module "nightwatch" {
declare module 'nightwatch' {
export interface NightwatchCustomCommands {
clickLaunchIcon(icon: string): NightwatchBrowser,
switchBrowserTab(index: number): NightwatchBrowser,
@ -46,7 +46,7 @@ declare module "nightwatch" {
setupMetamask(passphrase: string, password: string): NightwatchBrowser,
signMessage(msg: string, callback: (hash: { value: string }, signature: { value: string }) => void): NightwatchBrowser,
setSolidityCompilerVersion(version: string): NightwatchBrowser,
clickElementAtPosition(cssSelector: string, index: number): NightwatchBrowser,
clickElementAtPosition(cssSelector: string, index: number, opt?: { forceSelectIfUnselected: boolean }): NightwatchBrowser,
notContainsText(cssSelector: string, text: string): NightwatchBrowser,
sendLowLevelTx(address: string, value: string, callData: string): NightwatchBrowser,
journalLastChild(val: string): NightwatchBrowser,
@ -90,4 +90,4 @@ declare module "nightwatch" {
}
export type NightwatchCheckVariableDebugValue = NightwatchTestFunctionExpectedInput
}
}

@ -0,0 +1,21 @@
#!/usr/bin/env bash
set -e
BUILD_ID=${CIRCLE_BUILD_NUM:-${TRAVIS_JOB_NUMBER}}
echo "$BUILD_ID"
TEST_EXITCODE=0
npm run serve &
npx nx serve remix-ide-e2e-src-local-plugin &
sleep 5
npm run build:e2e
npm run nightwatch_local_pluginManager || TEST_EXITCODE=1
echo "$TEST_EXITCODE"
if [ "$TEST_EXITCODE" -eq 1 ]
then
exit 1
fi

@ -8,6 +8,7 @@ import IpfsHttpClient from 'ipfs-http-client'
import {
saveAs
} from 'file-saver'
import http from 'isomorphic-git/http/web'
const JSZip = require('jszip')
const path = require('path')
@ -20,7 +21,7 @@ const profile = {
description: '',
icon: 'assets/img/fileManager.webp',
version: '0.0.1',
methods: ['init', 'status', 'log', 'commit', 'add', 'remove', 'rm', 'lsfiles', 'readblob', 'resolveref', 'branches', 'branch', 'checkout', 'currentbranch', 'push', 'pin', 'pull', 'pinList', 'unPin', 'setIpfsConfig', 'zip', 'setItem', 'getItem'],
methods: ['init', 'localStorageUsed', 'addremote', 'delremote', 'remotes', 'fetch', 'clone', 'export', 'import', 'status', 'log', 'commit', 'add', 'remove', 'rm', 'lsfiles', 'readblob', 'resolveref', 'branches', 'branch', 'checkout', 'currentbranch', 'push', 'pin', 'pull', 'pinList', 'unPin', 'setIpfsConfig', 'zip', 'setItem', 'getItem'],
kind: 'file-system'
}
class DGitProvider extends Plugin {
@ -55,10 +56,24 @@ class DGitProvider extends Plugin {
}
}
async init () {
async parseInput (input) {
return {
corsProxy: 'https://corsproxy.remixproject.org/',
http,
onAuth: url => {
const auth = {
username: input.token,
password: ''
}
return auth
}
}
}
async init (input) {
await git.init({
...await this.getGitConfig(),
defaultBranch: 'main'
defaultBranch: (input && input.branch) || 'main'
})
}
@ -75,7 +90,7 @@ class DGitProvider extends Plugin {
...await this.getGitConfig(),
...cmd
})
this.call('fileManager', 'refresh')
await this.call('fileManager', 'refresh')
}
async rm (cmd) {
@ -83,7 +98,7 @@ class DGitProvider extends Plugin {
...await this.getGitConfig(),
...cmd
})
this.call('fileManager', 'refresh')
await this.call('fileManager', 'refresh')
}
async checkout (cmd) {
@ -91,7 +106,7 @@ class DGitProvider extends Plugin {
...await this.getGitConfig(),
...cmd
})
this.call('fileManager', 'refresh')
await this.call('fileManager', 'refresh')
}
async log (cmd) {
@ -102,12 +117,21 @@ class DGitProvider extends Plugin {
return status
}
async remotes () {
let remotes = []
try {
remotes = await git.listRemotes({ ...await this.getGitConfig() })
} catch (e) {
}
return remotes
}
async branch (cmd) {
const status = await git.branch({
...await this.getGitConfig(),
...cmd
})
this.call('fileManager', 'refresh')
await this.call('fileManager', 'refresh')
return status
}
@ -119,9 +143,17 @@ class DGitProvider extends Plugin {
}
async branches () {
const branches = await git.listBranches({
const cmd = {
...await this.getGitConfig()
})
}
const remotes = await this.remotes()
let branches = []
branches = (await git.listBranches(cmd)).map((branch) => { return { remote: undefined, name: branch } })
for (const remote of remotes) {
cmd.remote = remote.remote
const remotebranches = (await git.listBranches(cmd)).map((branch) => { return { remote: remote.remote, name: branch } })
branches = [...branches, ...remotebranches]
}
return branches
}
@ -133,7 +165,9 @@ class DGitProvider extends Plugin {
...cmd
})
return sha
} catch (e) {}
} catch (e) {
throw new Error(e)
}
}
async lsfiles (cmd) {
@ -177,8 +211,90 @@ class DGitProvider extends Plugin {
}
}
async push () {
if (!this.checkIpfsConfig()) return false
async addremote (input) {
await git.addRemote({ ...await this.getGitConfig(), url: input.url, remote: input.remote })
}
async delremote (input) {
await git.deleteRemote({ ...await this.getGitConfig(), remote: input.remote })
}
async localStorageUsed () {
return this.calculateLocalStorage()
}
async clone (input) {
const permission = await this.askUserPermission('clone', 'Import multiple files into your workspaces.')
if (!permission) return false
if (this.calculateLocalStorage() > 10000) throw new Error('The local storage of the browser is full.')
await this.call('filePanel', 'createWorkspace', `workspace_${Date.now()}`, false)
const cmd = {
url: input.url,
singleBranch: input.singleBranch,
ref: input.branch,
depth: input.depth || 10,
...await this.parseInput(input),
...await this.getGitConfig()
}
const result = await git.clone(cmd)
await this.call('fileManager', 'refresh')
return result
}
async push (input) {
const cmd = {
force: input.force,
ref: input.ref,
remoteRef: input.remoteRef,
remote: input.remote,
author: {
name: input.name,
email: input.email
},
...await this.parseInput(input),
...await this.getGitConfig()
}
return await git.push(cmd)
}
async pull (input) {
const cmd = {
ref: input.ref,
remoteRef: input.remoteRef,
author: {
name: input.name,
email: input.email
},
remote: input.remote,
...await this.parseInput(input),
...await this.getGitConfig()
}
const result = await git.pull(cmd)
await this.call('fileManager', 'refresh')
return result
}
async fetch (input) {
const cmd = {
ref: input.ref,
remoteRef: input.remoteRef,
author: {
name: input.name,
email: input.email
},
remote: input.remote,
...await this.parseInput(input),
...await this.getGitConfig()
}
const result = await git.fetch(cmd)
await this.call('fileManager', 'refresh')
return result
}
async export (config) {
if (!this.checkIpfsConfig(config)) return false
const workspace = await this.call('filePanel', 'getCurrentWorkspace')
const files = await this.getDirectory('/')
this.filesToSend = []
@ -255,7 +371,8 @@ class DGitProvider extends Plugin {
pinata_secret_api_key: pinataSecretApiKey
}
})
return result.data.IpfsHash
// also commit to remix IPFS for availability after pinning to Pinata
return await this.export(this.remixIPFS) || result.data.IpfsHash
} catch (error) {
throw new Error(error)
}
@ -312,12 +429,13 @@ class DGitProvider extends Plugin {
const dir = path.dirname(file.path)
try {
this.createDirectories(`${workspace.absolutePath}/${dir}`)
} catch (e) {}
} catch (e) { throw new Error(e) }
try {
window.remixFileSystem.writeFileSync(`${workspace.absolutePath}/${file.path}`, Buffer.concat(content) || new Uint8Array())
} catch (e) {}
} catch (e) { throw new Error(e) }
}
} catch (e) {
throw new Error(e)
}
return result
}
@ -336,14 +454,19 @@ class DGitProvider extends Plugin {
return (_lsTotal / 1024).toFixed(2)
}
async pull (cmd) {
const permission = await this.askUserPermission('pull', 'Import multiple files into your workspaces.')
async import (cmd) {
const permission = await this.askUserPermission('import', 'Import multiple files into your workspaces.')
if (!permission) return false
if (this.calculateLocalStorage() > 10000) throw new Error('Local browser storage is full.')
if (this.calculateLocalStorage() > 10000) throw new Error('The local storage of the browser is full.')
const cid = cmd.cid
await this.call('filePanel', 'createWorkspace', `workspace_${Date.now()}`, false)
const workspace = await this.call('filePanel', 'getCurrentWorkspace')
const result = await this.importIPFSFiles(this.remixIPFS, cid, workspace) || await this.importIPFSFiles(this.ipfsconfig, cid, workspace) || await this.importIPFSFiles(this.globalIPFSConfig, cid, workspace)
let result
if (cmd.local) {
result = await this.importIPFSFiles(this.ipfsconfig, cid, workspace)
} else {
result = await this.importIPFSFiles(this.remixIPFS, cid, workspace) || await this.importIPFSFiles(this.ipfsconfig, cid, workspace) || await this.importIPFSFiles(this.globalIPFSConfig, cid, workspace)
}
await this.call('fileManager', 'refresh')
if (!result) throw new Error(`Cannot pull files from IPFS at ${cid}`)
}
@ -359,7 +482,8 @@ class DGitProvider extends Plugin {
if (typeof window !== 'undefined') {
window.localStorage.setItem(name, content)
}
} catch (exception) {
} catch (e) {
console.log(e)
return false
}
return true
@ -391,8 +515,12 @@ class DGitProvider extends Plugin {
if (i > 0) previouspath = '/' + directories.slice(0, i).join('/')
const finalPath = previouspath + '/' + directories[i]
try {
window.remixFileSystem.mkdirSync(finalPath)
} catch (e) {}
if (!window.remixFileSystem.existsSync(finalPath)) {
window.remixFileSystem.mkdirSync(finalPath)
}
} catch (e) {
console.log(e)
}
}
}

@ -22,7 +22,7 @@ const profile = {
icon: 'assets/img/fileManager.webp',
permission: true,
version: packageJson.version,
methods: ['file', 'exists', 'open', 'writeFile', 'readFile', 'copyFile', 'copyDir', 'rename', 'mkdir', 'readdir', 'remove', 'getCurrentFile', 'getFile', 'getFolder', 'setFile', 'switchFile', 'refresh', 'getProviderOf', 'getProviderByName', 'getPathFromUrl', 'getUrlFromPath', 'saveCurrentFile'],
methods: ['closeAllFiles', 'closeFile', 'file', 'exists', 'open', 'writeFile', 'readFile', 'copyFile', 'copyDir', 'rename', 'mkdir', 'readdir', 'remove', 'getCurrentFile', 'getFile', 'getFolder', 'setFile', 'switchFile', 'refresh', 'getProviderOf', 'getProviderByName', 'getPathFromUrl', 'getUrlFromPath', 'saveCurrentFile'],
kind: 'file-system'
}
const errorMsg = {
@ -61,6 +61,10 @@ class FileManager extends Plugin {
return path.replace(/^\/browser\//, '').replace(/^browser\//, '') // forbids plugin to access the root filesystem
}
normalize (path) {
return path.replace(/^\/+/, '')
}
/**
* Emit error if path doesn't exist
* @param {string} path path of the file/directory
@ -119,6 +123,7 @@ class FileManager extends Plugin {
*/
exists (path) {
try {
path = this.normalize(path)
path = this.limitPluginScope(path)
const provider = this.fileProviderOf(path)
const result = provider.exists(path)
@ -134,8 +139,8 @@ class FileManager extends Plugin {
*/
refresh () {
const provider = this.fileProviderOf('/')
// emit folderAdded so that File Explorer reloads the file tree
provider.event.emit('folderAdded', '/')
// emit rootFolderChanged so that File Explorer reloads the file tree
provider.event.emit('rootFolderChanged')
}
/**
@ -168,6 +173,7 @@ class FileManager extends Plugin {
* @returns {void}
*/
async open (path) {
path = this.normalize(path)
path = this.limitPluginScope(path)
path = this.getPathFromUrl(path).file
await this._handleExists(path, `Cannot open file ${path}`)
@ -183,6 +189,7 @@ class FileManager extends Plugin {
*/
async writeFile (path, data) {
try {
path = this.normalize(path)
path = this.limitPluginScope(path)
if (await this.exists(path)) {
await this._handleIsFile(path, `Cannot write file ${path}`)
@ -204,6 +211,7 @@ class FileManager extends Plugin {
*/
async readFile (path) {
try {
path = this.normalize(path)
path = this.limitPluginScope(path)
await this._handleExists(path, `Cannot read file ${path}`)
await this._handleIsFile(path, `Cannot read file ${path}`)
@ -221,6 +229,8 @@ class FileManager extends Plugin {
*/
async copyFile (src, dest, customName) {
try {
src = this.normalize(src)
dest = this.normalize(dest)
src = this.limitPluginScope(src)
dest = this.limitPluginScope(dest)
await this._handleExists(src, `Cannot copy from ${src}. Path does not exist.`)
@ -245,6 +255,8 @@ class FileManager extends Plugin {
*/
async copyDir (src, dest) {
try {
src = this.normalize(src)
dest = this.normalize(dest)
src = this.limitPluginScope(src)
dest = this.limitPluginScope(dest)
await this._handleExists(src, `Cannot copy from ${src}. Path does not exist.`)
@ -281,6 +293,8 @@ class FileManager extends Plugin {
*/
async rename (oldPath, newPath) {
try {
oldPath = this.normalize(oldPath)
newPath = this.normalize(newPath)
oldPath = this.limitPluginScope(oldPath)
newPath = this.limitPluginScope(newPath)
await this._handleExists(oldPath, `Cannot rename ${oldPath}`)
@ -313,6 +327,7 @@ class FileManager extends Plugin {
*/
async mkdir (path) {
try {
path = this.normalize(path)
path = this.limitPluginScope(path)
if (await this.exists(path)) {
throw createError({ code: 'EEXIST', message: `Cannot create directory ${path}` })
@ -332,6 +347,7 @@ class FileManager extends Plugin {
*/
async readdir (path) {
try {
path = this.normalize(path)
path = this.limitPluginScope(path)
await this._handleExists(path)
await this._handleIsDir(path)
@ -356,6 +372,7 @@ class FileManager extends Plugin {
*/
async remove (path) {
try {
path = this.normalize(path)
path = this.limitPluginScope(path)
await this._handleExists(path, `Cannot remove file or directory ${path}`)
const provider = this.fileProviderOf(path)
@ -710,7 +727,6 @@ class FileManager extends Plugin {
syncEditor (path) {
var currentFile = this._deps.config.get('currentFile')
if (path !== currentFile) return
var provider = this.fileProviderOf(currentFile)
if (provider) {
provider.get(currentFile, (error, content) => {

@ -276,7 +276,6 @@ class FileProvider {
}
resolveDirectory (path, callback) {
if (!path) return callback(null, { [this.type]: {} })
path = this.removePrefix(path)
if (path.indexOf('/') !== 0) path = '/' + path

@ -113,7 +113,7 @@ class CompileTab extends CompilerApiMixin(ViewPlugin) { // implements ICompilerA
return super.compileFile(event)
}
onActivation () {
async onActivation () {
super.onActivation()
this.call('filePanel', 'registerContextMenuItem', {
id: 'solidity',
@ -124,6 +124,7 @@ class CompileTab extends CompilerApiMixin(ViewPlugin) { // implements ICompilerA
path: [],
pattern: []
})
this.currentFile = await this.call('fileManager', 'file')
}
getCompilerParameters () {
@ -138,7 +139,9 @@ class CompileTab extends CompilerApiMixin(ViewPlugin) { // implements ICompilerA
}
getAppParameter (name) {
const param = this.config.get(name)
// first look in the URL params then in the local storage
const params = this.queryParams.get()
const param = params[name] ? params[name] : this.config.get(name)
if (param === 'true') return true
if (param === 'false') return false
return param

@ -44,6 +44,7 @@ module.exports = class TestTab extends ViewPlugin {
this.offsetToLineColumnConverter = offsetToLineColumnConverter
this.allFilesInvolved = []
this.isDebugging = false
this.currentErrors = []
appManager.event.on('activate', (name) => {
if (name === 'solidity') this.updateRunAction()
@ -117,6 +118,14 @@ module.exports = class TestTab extends ViewPlugin {
}
async updateForNewCurrent (file) {
// Ensure that when someone clicks on compilation error and that opens a new file
// Test result, which is compilation error in this case, is not cleared
if (this.currentErrors) {
if (Array.isArray(this.currentErrors) && this.currentErrors.length > 0) {
const errFiles = this.currentErrors.map(err => { if (err.sourceLocation && err.sourceLocation.file) return err.sourceLocation.file })
if (errFiles.includes(file)) return
} else if (this.currentErrors.sourceLocation && this.currentErrors.sourceLocation.file && this.currentErrors.sourceLocation.file === file) return
}
// if current file is changed while debugging and one of the files imported in test file are opened
// do not clear the test results in SUT plugin
if (this.isDebugging && this.allFilesInvolved.includes(file)) return
@ -377,12 +386,13 @@ module.exports = class TestTab extends ViewPlugin {
this.testsOutput.hidden = false
if (!result && (_errors && (_errors.errors || (Array.isArray(_errors) && (_errors[0].message || _errors[0].formattedMessage))))) {
this.testCallback({ type: 'contract', filename })
this.currentErrors = _errors.errors
this.setHeader(false)
}
if (_errors && _errors.errors) {
_errors.errors.forEach((err) => this.renderer.error(err.formattedMessage || err.message, this.testsOutput, { type: err.severity }))
_errors.errors.forEach((err) => this.renderer.error(err.formattedMessage || err.message, this.testsOutput, { type: err.severity, errorType: err.type }))
} else if (_errors && Array.isArray(_errors) && (_errors[0].message || _errors[0].formattedMessage)) {
_errors.forEach((err) => this.renderer.error(err.formattedMessage || err.message, this.testsOutput, { type: err.severity }))
_errors.forEach((err) => this.renderer.error(err.formattedMessage || err.message, this.testsOutput, { type: err.severity, errorType: err.type }))
} else if (_errors && !_errors.errors && !Array.isArray(_errors)) {
// To track error like this: https://github.com/ethereum/remix/pull/1438
this.renderer.error(_errors.formattedMessage || _errors.message, this.testsOutput, { type: 'error' })

@ -12,6 +12,7 @@ export class RemixEngine extends Engine {
if (name === 'LearnEth') return { queueTimeout: 60000 }
if (name === 'dGitProvider') return { queueTimeout: 60000 * 4 }
if (name === 'slither') return { queueTimeout: 60000 * 4 } // Requires when a solc version is installed
if (name === 'hardhat') return { queueTimeout: 60000 * 4 }
return { queueTimeout: 10000 }
}

@ -115,11 +115,13 @@ export const CompilerApiMixin = (Base) => class extends Base {
* @param {string} fileName to compile
*/
compile (fileName) {
this.currentFile = fileName
return this.compileTabLogic.compileFile(fileName)
}
compileFile (event) {
if (event.path.length > 0) {
this.currentFile = event.path[0]
this.compileTabLogic.compileFile(event.path[0])
}
}
@ -262,7 +264,7 @@ export const CompilerApiMixin = (Base) => class extends Base {
)
})
} else {
const count = (data.errors ? data.errors.filter(error => error.severity === 'error').length : 0) + data.error ? 1 : 0
const count = (data.errors ? data.errors.filter(error => error.severity === 'error').length : 0 + (data.error ? 1 : 0))
this.emit('statusChanged', { key: count, title: `compilation failed with ${count} error${count > 1 ? 's' : ''}`, type: 'error' })
}
// Update contract Selection

@ -1,17 +1,31 @@
const nxWebpack = require('@nrwl/react/plugins/webpack')
const TerserPlugin = require('terser-webpack-plugin')
module.exports = config => {
const nxWebpackConfig = nxWebpack(config)
const nxWebpackConfig = nxWebpack(config)
const webpackConfig = {
...nxWebpackConfig,
node: {
fs: 'empty',
tls: 'empty',
readline: 'empty',
net: 'empty',
module: 'empty',
child_process: 'empty'
}
}
if (process.env.NODE_ENV === 'production') {
return {
...nxWebpackConfig,
node: {
fs: 'empty',
tls: 'empty',
readline: 'empty',
net: 'empty',
module: 'empty',
child_process: 'empty'
}
...webpackConfig,
mode: 'production',
devtool: 'source-map',
optimization: {
minimize: true,
minimizer: [new TerserPlugin()]
}
}
} else {
return webpackConfig
}
}

@ -7,15 +7,15 @@ module.exports = {
moduleFileExtensions: ['ts', 'js', 'html'],
coverageReporters: ['html'],
moduleNameMapper:{
"@remix-project/remix-analyzer": "<rootDir>/../../dist/libs/remix-analyzer/index.js",
"@remix-project/remix-astwalker": "<rootDir>/../../dist/libs/remix-astwalker/index.js",
"@remix-project/remix-analyzer": "<rootDir>/../../dist/libs/remix-analyzer/src/index.js",
"@remix-project/remix-astwalker": "<rootDir>/../../dist/libs/remix-astwalker/src/index.js",
"@remix-project/remix-debug": "<rootDir>/../../dist/libs/remix-debug/src/index.js",
"@remix-project/remix-lib": "<rootDir>/../../dist/libs/remix-lib/src/index.js",
"@remix-project/remix-simulator": "<rootDir>/../../dist/libs/remix-simulator/src/index.js",
"@remix-project/remix-solidity": "<rootDir>/../../dist/libs/remix-solidity/index.js",
"@remix-project/remix-solidity": "<rootDir>/../../dist/libs/remix-solidity/src/index.js",
"@remix-project/remix-tests": "<rootDir>/../../dist/libs/remix-tests/src/index.js",
"@remix-project/remix-url-resolver":
"<rootDir>/../../dist/libs/remix-url-resolver/index.js"
"<rootDir>/../../dist/libs/remix-url-resolver/src/index.js"
,
"@remix-project/remixd": "<rootDir>/../../dist/libs/remixd/index.js"
}

@ -1,9 +1,9 @@
{
"name": "@remix-project/remix-analyzer",
"version": "0.5.15",
"version": "0.5.16",
"description": "Tool to perform static analysis on Solidity smart contracts",
"main": "index.js",
"types": ".index.d.ts",
"main": "src/index.js",
"types": "src/index.d.ts",
"contributors": [
{
"name": "Alex Beregszaszi",
@ -22,8 +22,8 @@
"@ethereumjs/block": "^3.4.0",
"@ethereumjs/tx": "^3.3.0",
"@ethereumjs/vm": "^5.5.0",
"@remix-project/remix-astwalker": "^0.0.26",
"@remix-project/remix-lib": "^0.5.6",
"@remix-project/remix-astwalker": "^0.0.37",
"@remix-project/remix-lib": "^0.5.7",
"async": "^2.6.2",
"ethereumjs-util": "^7.0.10",
"ethers": "^5.4.2",
@ -50,6 +50,6 @@
"ts-node": "^8.6.2",
"typescript": "^3.7.5"
},
"typings": "index.d.ts",
"gitHead": "39700b7c076d53d0f857f341774a8448ea5c8da9"
"typings": "src/index.d.ts",
"gitHead": "4705cbc4d1761f75267992552da9db6cff2f3ed5"
}

@ -1,8 +1,8 @@
{
"name": "@remix-project/remix-astwalker",
"version": "0.0.36",
"version": "0.0.37",
"description": "Tool to walk through Solidity AST",
"main": "index.js",
"main": "src/index.js",
"scripts": {
"build": "tsc",
"test": "./../../node_modules/.bin/nyc --reporter=lcov --require ts-node/register --require tsconfig-paths/register ./../../node_modules/.bin/tape ./tests/*.ts | ./../../node_modules/.bin/tap-spec; ./../../node_modules/.bin/nyc report ---reporter=text"
@ -37,7 +37,7 @@
"@ethereumjs/block": "^3.4.0",
"@ethereumjs/tx": "^3.3.0",
"@ethereumjs/vm": "^5.5.0",
"@remix-project/remix-lib": "^0.5.6",
"@remix-project/remix-lib": "^0.5.7",
"@types/tape": "^4.2.33",
"async": "^2.6.2",
"ethereumjs-util": "^7.0.10",
@ -52,6 +52,6 @@
"devDependencies": {
"tap-spec": "^5.0.0"
},
"typings": "index.d.ts",
"gitHead": "39700b7c076d53d0f857f341774a8448ea5c8da9"
"typings": "src/index.d.ts",
"gitHead": "4705cbc4d1761f75267992552da9db6cff2f3ed5"
}

@ -1,6 +1,6 @@
// Type definitions for the things we need from remix-lib
declare module "remix-lib" {
declare module 'remix-lib' {
export module util {
export function findLowerBound(target: number, array: Array<number>): number;
}

@ -1,6 +1,6 @@
{
"name": "@remix-project/remix-debug",
"version": "0.5.6",
"version": "0.5.7",
"description": "Tool to debug Ethereum transactions",
"contributors": [
{
@ -22,8 +22,9 @@
"@ethereumjs/common": "^2.2.0",
"@ethereumjs/tx": "^3.3.0",
"@ethereumjs/vm": "^5.5.0",
"@remix-project/remix-astwalker": "^0.0.26",
"@remix-project/remix-lib": "^0.5.6",
"@remix-project/remix-astwalker": "^0.0.37",
"@remix-project/remix-lib": "^0.5.7",
"@remix-project/remix-simulator": "^0.2.7",
"async": "^2.6.2",
"commander": "^2.19.0",
"deep-equal": "^1.0.1",
@ -61,5 +62,5 @@
},
"homepage": "https://github.com/ethereum/remix-project/tree/master/libs/remix-debug#readme",
"typings": "src/index.d.ts",
"gitHead": "39700b7c076d53d0f857f341774a8448ea5c8da9"
"gitHead": "4705cbc4d1761f75267992552da9db6cff2f3ed5"
}

@ -29,7 +29,7 @@ export function nameOpCodes (raw, hardfork) {
const data = (pushData as any).toString('hex') !== '' ? ' ' + (pushData as any).toString('hex') : ''
code.push(this.pad(pc, this.roundLog(raw.length, 10)) + ' ' + curOpCode + data)
code.push(pad(pc, roundLog(raw.length, 10)) + ' ' + curOpCode + data)
pushData = ''
}
return [code, codeMap]

@ -108,7 +108,7 @@ function sourceLocationFromAstNode (astNode) {
* @param {Object} ast - ast given by the compilation result
*/
export function findNodeAtInstructionIndex (astNodeType, instIndex, sourceMap, ast) {
const sourceLocation = this.atIndex(instIndex, sourceMap)
const sourceLocation = atIndex(instIndex, sourceMap)
return findNodeAtSourceLocation(astNodeType, sourceLocation, ast)
}

@ -133,7 +133,7 @@ export class StorageResolver {
resolve([{}, null])
} else {
this.web3.debug.storageRangeAt(
tx.blockHash, tx.transactionIndex === undefined ? tx.hash : tx.transactionIndex,
tx.blockHash, tx.hash,
address,
start,
maxSize,

@ -53,7 +53,7 @@ export function newContextStorage (step) {
export function isCallToPrecompiledContract (index, trace) {
// if stack empty => this is not a precompiled contract
const step = trace[index]
if (this.isCallInstruction(step)) {
if (isCallInstruction(step)) {
return index + 1 < trace.length && trace[index + 1].stack.length !== 0
}
return false

@ -7,7 +7,6 @@ import { BreakpointManager } from '../src/code/breakpointManager'
var compiler = require('solc')
var vmCall = require('./vmCall')
var remixLib = require('@remix-project/remix-lib')
var ballot = `pragma solidity >=0.4.22 <0.8.0;
@ -151,19 +150,17 @@ contract Ballot {
`;
(async () => {
var privateKey = Buffer.from('dae9801649ba2d95a21e688b56f77905e5667c44ce868ec83f82e838712a2c7a', 'hex')
var vm = await vmCall.initVM(privateKey)
var privateKey = Buffer.from('503f38a9c967ed597e47fe25643985f032b072db8075426a92110f82df48dfcb', 'hex')
var output = compiler.compile(compilerInput(ballot))
output = JSON.parse(output)
var web3VM = new remixLib.vm.Web3VMProvider()
web3VM.setVM(vm)
const param = '0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000148656c6c6f20576f726c64210000000000000000000000000000000000000000'
vmCall.sendTx(vm, {nonce: 0, privateKey: privateKey}, null, 0, output.contracts['test.sol']['Ballot'].evm.bytecode.object + param, (error, txHash) => {
console.log(error, txHash)
const web3 = await vmCall.getWeb3()
vmCall.sendTx(web3, {nonce: 0, privateKey: privateKey}, null, 0, output.contracts['test.sol']['Ballot'].evm.bytecode.object + param, (error, hash) => {
console.log(error, hash)
if (error) {
throw error
} else {
web3VM.eth.getTransaction(txHash, (error, tx) => {
web3.eth.getTransaction(hash, (error, tx) => {
if (error) {
throw error
} else {
@ -171,7 +168,7 @@ contract Ballot {
compilationResult: function () {
return { data: output }
},
web3: web3VM
web3: web3
})
debugManager.callTree.event.register('callTreeReady', () => {
@ -230,7 +227,7 @@ function testDebugging (debugManager) {
var storageView = debugManager.storageViewAt(196, address)
storageView.storageRange().then((storage) => {
t.equal(JSON.stringify(storage), JSON.stringify({ '0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563': { key: '0x0000000000000000000000000000000000000000000000000000000000000000', value: '0x0000000000000000000000004b0897b0513fdc7c541b6d9d7e929c4e5364d2db' } }))
t.equal(JSON.stringify(storage), JSON.stringify({ '0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563': { key: '0x0000000000000000000000000000000000000000000000000000000000000000', value: '0x0000000000000000000000005b38da6a701c568545dcfcb03fcb875f56beddc4' } }))
}).catch((error) => {
if (error) return t.end(error)
})
@ -245,7 +242,7 @@ function testDebugging (debugManager) {
const state = await debugManager.extractStateAt(312)
const decodedState = await debugManager.decodeStateAt(312, state)
console.log(decodedState)
t.equal(decodedState['chairperson'].value, '0x4B0897B0513FDC7C541B6D9D7E929C4E5364D2DB')
t.equal(decodedState['chairperson'].value, '0x5B38DA6A701C568545DCFCB03FCB875F56BEDDC4')
t.equal(decodedState['chairperson'].type, 'address')
t.equal(decodedState['proposals'].value[0].value.voteCount.value, '0')
t.equal(decodedState['proposals'].value[0].value.voteCount.type, 'uint256')
@ -259,13 +256,14 @@ function testDebugging (debugManager) {
tape('traceManager.decodeLocalsAt', async (t) => {
t.plan(1)
const tested = JSON.parse('{"proposalNames":{"value":[{"value":"0x48656C6C6F20576F726C64210000000000000000000000000000000000000000","type":"bytes32"}],"length":"0x1","type":"bytes32[]","cursor":1,"hasNext":false},"p":{"value":"45","type":"uint256"},"addressLocal":{"value":"0x4B0897B0513FDC7C541B6D9D7E929C4E5364D2DB","type":"address"},"i":{"value":"2","type":"uint256"},"proposalsLocals":{"value":[{"value":{"name":{"value":"0x48656C6C6F20576F726C64210000000000000000000000000000000000000000","type":"bytes32"},"voteCount":{"value":"0","type":"uint256"}},"type":"struct Ballot.Proposal"}],"length":"0x1","type":"struct Ballot.Proposal[]"}}')
const tested = JSON.parse('{"proposalNames":{"value":[{"value":"0x48656C6C6F20576F726C64210000000000000000000000000000000000000000","type":"bytes32"}],"length":"0x1","type":"bytes32[]","cursor":1,"hasNext":false},"p":{"value":"45","type":"uint256"},"addressLocal":{"value":"0x5B38DA6A701C568545DCFCB03FCB875F56BEDDC4","type":"address"},"i":{"value":"2","type":"uint256"},"proposalsLocals":{"value":[{"value":{"name":{"value":"0x48656C6C6F20576F726C64210000000000000000000000000000000000000000","type":"bytes32"},"voteCount":{"value":"0","type":"uint256"}},"type":"struct Ballot.Proposal"}],"length":"0x1","type":"struct Ballot.Proposal[]"}}')
try {
const address = debugManager.traceManager.getCurrentCalledAddressAt(327)
const location = await debugManager.sourceLocationFromVMTraceIndex(address, 327)
debugManager.decodeLocalsAt(327, location, (error, decodedlocals) => {
if (error) return t.end(error)
t.ok(deepequal(decodedlocals, tested), `locals does not match. expected: ${JSON.stringify(tested)} - current: ${decodedlocals}`)
const res = deepequal(decodedlocals, tested)
t.ok(res, `test if locals does match. expected: ${JSON.stringify(tested)} - current: ${JSON.stringify(decodedlocals)}`)
})
} catch (error) {
return t.end(error)

@ -5,7 +5,7 @@ var intLocal = require('./contracts/intLocal')
var miscLocal = require('./contracts/miscLocal')
var structArrayLocal = require('./contracts/structArrayLocal')
var calldataLocal = require('./contracts/calldata')
var vmCall = require('./vmCall')
var vmCall = require('../vmCall')
var intLocalTest = require('./localsTests/int')
var miscLocalTest = require('./localsTests/misc')
var misc2LocalTest = require('./localsTests/misc2')
@ -15,29 +15,28 @@ var compilerInput = require('../helpers/compilerHelper').compilerInput
tape('solidity', function (t) {
t.test('local decoder', async function (st) {
var privateKey = Buffer.from('dae9801649ba2d95a21e688b56f77905e5667c44ce868ec83f82e838712a2c7a', 'hex')
var vm = await vmCall.initVM(st, privateKey)
await test(st, vm, privateKey)
var privateKey = Buffer.from('503f38a9c967ed597e47fe25643985f032b072db8075426a92110f82df48dfcb', 'hex')
await test(st, privateKey)
})
})
async function test (st, vm, privateKey) {
async function test (st, privateKey) {
var output = compiler.compile(compilerInput(intLocal.contract))
output = JSON.parse(output)
await intLocalTest(st, vm, privateKey, output.contracts['test.sol']['intLocal'].evm.bytecode.object, output)
await intLocalTest(st, privateKey, output.contracts['test.sol']['intLocal'].evm.bytecode.object, output)
output = compiler.compile(compilerInput(miscLocal.contract))
output = JSON.parse(output)
await miscLocalTest(st, vm, privateKey, output.contracts['test.sol']['miscLocal'].evm.bytecode.object, output)
await miscLocalTest(st, privateKey, output.contracts['test.sol']['miscLocal'].evm.bytecode.object, output)
output = compiler.compile(compilerInput(miscLocal.contract))
output = JSON.parse(output)
await misc2LocalTest(st, vm, privateKey, output.contracts['test.sol']['miscLocal2'].evm.bytecode.object, output)
await misc2LocalTest(st, privateKey, output.contracts['test.sol']['miscLocal2'].evm.bytecode.object, output)
output = compiler.compile(compilerInput(structArrayLocal.contract))
output = JSON.parse(output)
await structArrayLocalTest(st, vm, privateKey, output.contracts['test.sol']['structArrayLocal'].evm.bytecode.object, output)
await structArrayLocalTest(st, privateKey, output.contracts['test.sol']['structArrayLocal'].evm.bytecode.object, output)
output = compiler.compile(compilerInput(calldataLocal.contract))
output = JSON.parse(output)
await calldataLocalTest(st, vm, privateKey, output.contracts['test.sol']['calldataLocal'].evm.bytecode.object, output)
await calldataLocalTest(st, privateKey, output.contracts['test.sol']['calldataLocal'].evm.bytecode.object, output)
st.end()
}

@ -1,7 +1,7 @@
'use strict'
import deepequal from 'deep-equal'
import { sendTx } from '../vmCall'
import * as vmCall from '../../vmCall'
import { TraceManager } from '../../../src/trace/traceManager'
import { CodeManager } from '../../../src/code/codeManager'
import { SolidityProxy } from '../../../src/solidity-decoder/solidityProxy'
@ -9,23 +9,26 @@ import { InternalCallTree } from '../../../src/solidity-decoder/internalCallTree
import { EventManager } from '../../../src/eventManager'
import * as helper from './helper'
module.exports = async function (st, vm, privateKey, contractBytecode, compilationResult) {
module.exports = async function (st, privateKey, contractBytecode, compilationResult) {
let txHash
let web3
try {
let data = await sendTx(vm, { nonce: 0, privateKey: privateKey }, null, 0, contractBytecode)
const to = (data as any).result.createdAddress.toString()
web3 = await (vmCall as any).getWeb3()
let hash = await (vmCall as any).sendTx(web3, { nonce: 0, privateKey: privateKey }, null, 0, contractBytecode)
const receipt = await web3.eth.getTransactionReceipt(hash)
const to = receipt.contractAddress
console.log('to', to)
// call to level11
data = await sendTx(vm, { nonce: 1, privateKey: privateKey }, to, 0, 'a372a595000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001520000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015400000000000000000000000000000000000000000000000000000000000000')
txHash = (data as any).hash
txHash = await (vmCall as any).sendTx(web3, { nonce: 1, privateKey: privateKey }, to, 0, 'a372a595000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001520000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015400000000000000000000000000000000000000000000000000000000000000')
} catch (e) {
return st.fail(e)
}
return new Promise((resolve) => {
vm.web3.eth.getTransaction(txHash, function (error, tx) {
return new Promise((resolve) => {
web3.eth.getTransaction(txHash, function (error, tx) {
if (error) {
return st.fail(error)
}
var traceManager = new TraceManager({ web3: vm.web3 })
var traceManager = new TraceManager({ web3 })
var codeManager = new CodeManager(traceManager)
codeManager.clear()
var solidityProxy = new SolidityProxy({ getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager), getCode: codeManager.getCode.bind(codeManager) })

@ -1,6 +1,6 @@
'use strict'
import { sendTx } from '../vmCall'
import * as vmCall from '../../vmCall'
import { TraceManager } from '../../../src/trace/traceManager'
import { CodeManager } from '../../../src/code/codeManager'
import { contractCreationToken } from '../../../src/trace/traceHelper'
@ -9,19 +9,19 @@ import { InternalCallTree } from '../../../src/solidity-decoder/internalCallTree
import { EventManager } from '../../../src/eventManager'
import * as helper from './helper'
module.exports = function (st, vm, privateKey, contractBytecode, compilationResult) {
return new Promise((resolve) => {
sendTx(vm, { nonce: 0, privateKey: privateKey }, null, 0, contractBytecode, function (error, data) {
module.exports = function (st, privateKey, contractBytecode, compilationResult) {
return new Promise(async (resolve) => {
let web3 = await (vmCall as any).getWeb3();
(vmCall as any).sendTx(web3, { nonce: 0, privateKey: privateKey }, null, 0, contractBytecode, function (error, hash) {
if (error) {
return st.fail(error)
}
const txHash = data.hash
vm.web3.eth.getTransaction(txHash, function (error, tx) {
web3.eth.getTransaction(hash, function (error, tx) {
if (error) {
return st.fail(error)
}
tx.to = contractCreationToken('0')
var traceManager = new TraceManager({ web3: vm.web3 })
var traceManager = new TraceManager({ web3 })
var codeManager = new CodeManager(traceManager)
codeManager.clear()
var solidityProxy = new SolidityProxy({ getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager), getCode: codeManager.getCode.bind(codeManager) })
@ -125,6 +125,6 @@ module.exports = function (st, vm, privateKey, contractBytecode, compilationResu
})
})
})
})
})
}

@ -1,5 +1,5 @@
'use strict'
import { sendTx } from '../vmCall'
import * as vmCall from '../../vmCall'
import { contractCreationToken } from '../../../src/trace/traceHelper'
import { SolidityProxy } from '../../../src/solidity-decoder/solidityProxy'
import { InternalCallTree } from '../../../src/solidity-decoder/internalCallTree'
@ -8,19 +8,19 @@ import * as helper from './helper'
import { TraceManager } from '../../../src/trace/traceManager'
import { CodeManager } from '../../../src/code/codeManager'
module.exports = function (st, vm, privateKey, contractBytecode, compilationResult) {
return new Promise((resolve) => {
sendTx(vm, { nonce: 0, privateKey: privateKey }, null, 0, contractBytecode, function (error, data) {
module.exports = function (st, privateKey, contractBytecode, compilationResult) {
return new Promise(async (resolve) => {
const web3 = await (vmCall as any).getWeb3();
(vmCall as any).sendTx(web3, { nonce: 0, privateKey: privateKey }, null, 0, contractBytecode, function (error, hash) {
if (error) {
return st.fail(error)
}
const txHash = data.hash
vm.web3.eth.getTransaction(txHash, function (error, tx) {
web3.eth.getTransaction(hash, function (error, tx) {
if (error) {
return st.fail(error)
}
tx.to = contractCreationToken('0')
var traceManager = new TraceManager({ web3: vm.web3 })
var traceManager = new TraceManager({ web3 })
var codeManager = new CodeManager(traceManager)
codeManager.clear()
var solidityProxy = new SolidityProxy({ getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager), getCode: codeManager.getCode.bind(codeManager) })
@ -36,7 +36,7 @@ module.exports = function (st, vm, privateKey, contractBytecode, compilationResu
st.equals(locals['boolFalse'].value, false)
st.equals(locals['boolTrue'].value, true)
st.equals(locals['testEnum'].value, 'three')
st.equals(locals['sender'].value, '0x4B0897B0513FDC7C541B6D9D7E929C4E5364D2DB')
st.equals(locals['sender'].value, '0x5B38DA6A701C568545DCFCB03FCB875F56BEDDC4')
st.equals(locals['_bytes1'].value, '0x99')
st.equals(locals['__bytes1'].value, '0x99')
st.equals(locals['__bytes2'].value, '0x99AB')

@ -1,5 +1,5 @@
'use strict'
import { sendTx } from '../vmCall'
import * as vmCall from '../../vmCall'
import { contractCreationToken } from '../../../src/trace/traceHelper'
import { SolidityProxy } from '../../../src/solidity-decoder/solidityProxy'
import { InternalCallTree } from '../../../src/solidity-decoder/internalCallTree'
@ -8,19 +8,19 @@ import * as helper from './helper'
import { TraceManager } from '../../../src/trace/traceManager'
import { CodeManager } from '../../../src/code/codeManager'
module.exports = function (st, vm, privateKey, contractBytecode, compilationResult) {
return new Promise((resolve) => {
sendTx(vm, { nonce: 0, privateKey: privateKey }, null, 0, contractBytecode, function (error, data) {
module.exports = function (st, privateKey, contractBytecode, compilationResult) {
return new Promise(async (resolve) => {
const web3 = await (vmCall as any).getWeb3();
(vmCall as any).sendTx(web3, { nonce: 0, privateKey: privateKey }, null, 0, contractBytecode, function (error, hash) {
if (error) {
return st.fail(error)
}
const txHash = data.hash
vm.web3.eth.getTransaction(txHash, function (error, tx) {
web3.eth.getTransaction(hash, function (error, tx) {
if (error) {
return st.fail(error)
}
tx.to = contractCreationToken('0')
var traceManager = new TraceManager({ web3: vm.web3 })
var traceManager = new TraceManager({ web3 })
var codeManager = new CodeManager(traceManager)
codeManager.clear()
var solidityProxy = new SolidityProxy({ getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager), getCode: codeManager.getCode.bind(codeManager) })

@ -1,5 +1,5 @@
'use strict'
import { sendTx } from '../vmCall'
import * as vmCall from '../../vmCall'
import { contractCreationToken } from '../../../src/trace/traceHelper'
import { SolidityProxy } from '../../../src/solidity-decoder/solidityProxy'
import { InternalCallTree } from '../../../src/solidity-decoder/internalCallTree'
@ -8,19 +8,19 @@ import * as helper from './helper'
import { TraceManager } from '../../../src/trace/traceManager'
import { CodeManager } from '../../../src/code/codeManager'
module.exports = function (st, vm, privateKey, contractBytecode, compilationResult) {
return new Promise((resolve) => {
sendTx(vm, { nonce: 0, privateKey: privateKey }, null, 0, contractBytecode, function (error, data) {
module.exports = function (st, privateKey, contractBytecode, compilationResult) {
return new Promise(async (resolve) => {
const web3 = await (vmCall as any).getWeb3();
(vmCall as any).sendTx(web3, { nonce: 0, privateKey: privateKey }, null, 0, contractBytecode, function (error, hash) {
if (error) {
return st.fail(error)
}
const txHash = data.hash
vm.web3.eth.getTransaction(txHash, function (error, tx) {
web3.eth.getTransaction(hash, function (error, tx) {
if (error) {
return st.fail(error)
}
tx.to = contractCreationToken('0')
var traceManager = new TraceManager({ web3: vm.web3 })
var traceManager = new TraceManager({ web3 })
var codeManager = new CodeManager(traceManager)
codeManager.clear()
var solidityProxy = new SolidityProxy({ getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager), getCode: codeManager.getCode.bind(codeManager) })

@ -2,57 +2,59 @@ import { compilerInput } from '../../helpers/compilerHelper'
import { TraceManager } from '../../../src/trace/traceManager'
import { compile } from 'solc'
import * as stateDecoder from '../../../src/solidity-decoder/stateDecoder'
import { sendTx, initVM } from '../vmCall'
import * as vmCall from '../../vmCall'
import { StorageResolver } from '../../../src/storage/storageResolver'
import { StorageViewer } from '../../../src/storage/storageViewer'
import { Address, bufferToHex } from 'ethereumjs-util'
module.exports = async function testMappingStorage (st, cb) {
var mappingStorage = require('../contracts/mappingStorage')
var privateKey = Buffer.from('dae9801649ba2d95a21e688b56f77905e5667c44ce868ec83f82e838712a2c7a', 'hex')
var vm = await initVM(st, privateKey)
var privateKey = Buffer.from('503f38a9c967ed597e47fe25643985f032b072db8075426a92110f82df48dfcb', 'hex')
var output = compile(compilerInput(mappingStorage.contract))
output = JSON.parse(output)
sendTx(vm, {nonce: 0, privateKey: privateKey}, null, 0, output.contracts['test.sol']['SimpleMappingState'].evm.bytecode.object, function (error, data) {
output = JSON.parse(output);
const web3 = await (vmCall as any).getWeb3();
(vmCall as any).sendTx(web3, {nonce: 0, privateKey: privateKey}, null, 0, output.contracts['test.sol']['SimpleMappingState'].evm.bytecode.object, function (error, hash) {
if (error) {
console.log(error)
st.end(error)
} else {
const txHash = data.hash
vm.web3.eth.getTransaction(txHash, (error, tx) => {
web3.eth.getTransactionReceipt(hash, (error, tx) => {
if (error) {
console.log(error)
st.end(error)
} else {
testMapping(st, vm, privateKey, tx.contractAddress, output, cb)
// const storage = await this.vm.stateManager.dumpStorage(data.to)
// (vmCall as any).web3().eth.getCode(tx.contractAddress).then((code) => console.log('code:', code))
// (vmCall as any).web3().debug.traceTransaction(hash).then((code) => console.log('trace:', code))
testMapping(st, privateKey, tx.contractAddress, output, web3, cb)
// st.end()
}
})
}
})
}
function testMapping (st, vm, privateKey, contractAddress, output, cb) {
sendTx(vm, {nonce: 1, privateKey: privateKey}, contractAddress, 0, '2fd0a83a00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001074686973206973206120737472696e6700000000000000000000000000000000',
function (error, data) {
function testMapping (st, privateKey, contractAddress, output, web3, cb) {
(vmCall as any).sendTx(web3, {nonce: 1, privateKey: privateKey}, contractAddress, 0, '2fd0a83a00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001074686973206973206120737472696e6700000000000000000000000000000000',
function (error, hash) {
if (error) {
console.log(error)
st.end(error)
} else {
const txHash = data.hash
vm.web3.eth.getTransaction(txHash, (error, tx) => {
} else {
web3.eth.getTransaction(hash, (error, tx) => {
if (error) {
console.log(error)
st.end(error)
} else {
var traceManager = new TraceManager({web3: vm.web3})
var traceManager = new TraceManager({web3})
traceManager.resolveTrace(tx).then(() => {
var storageViewer = new StorageViewer({
stepIndex: 268,
tx: tx,
address: contractAddress
}, new StorageResolver({web3: vm.web3}), traceManager)
}, new StorageResolver({web3}), traceManager)
var stateVars = stateDecoder.extractStateVariables('SimpleMappingState', output.sources)
stateDecoder.decodeState(stateVars, storageViewer).then((result) => {
console.log('ok', JSON.stringify(result))
st.equal(result['_num'].value, '1')
st.equal(result['_num'].type, 'uint256')
st.equal(result['_iBreakSolidityState'].type, 'mapping(string => uint256)')

@ -1,76 +0,0 @@
'use strict'
import { Transaction as Tx } from '@ethereumjs/tx'
import { Block } from '@ethereumjs/block'
import { BN, bufferToHex, Address } from 'ethereumjs-util'
import { vm as remixlibVM } from '@remix-project/remix-lib'
import VM from '@ethereumjs/vm'
import Common from '@ethereumjs/common'
export function sendTx (vm, from, to, value, data, cb?) {
cb = cb || (() => {})
return new Promise ((resolve, reject) => {
var tx = new Tx({
nonce: new BN(from.nonce++),
// gasPrice: new BN(1),
gasLimit: new BN(3000000, 10),
to: to,
value: new BN(value, 10),
data: Buffer.from(data, 'hex')
})
tx = tx.sign(from.privateKey)
var block = Block.fromBlockData({
header: {
timestamp: new Date().getTime() / 1000 | 0,
number: 0
}
}) // still using default common
try {
vm.runTx({block: block, tx: tx, skipBalance: true, skipNonce: true}).then(function (result) {
setTimeout(() => {
const hash = bufferToHex(tx.hash())
cb(null, { hash, result })
resolve({ hash, result })
}, 500)
}).catch((error) => {
console.error(error)
cb(error)
reject(error)
})
} catch (e) {
console.error(e)
}
})
}
async function createVm (hardfork) {
const common = new Common({ chain: 'mainnet', hardfork })
const vm = new VM({ common })
await vm.init()
return { vm, stateManager: vm.stateManager }
}
/*
Init VM / Send Transaction
*/
export async function initVM (st, privateKey) {
var VM = await createVm('berlin')
const vm = VM.vm
var address = Address.fromPrivateKey(privateKey)
try {
let account = await vm.stateManager.getAccount(address)
account.balance = new BN('f00000000000000001', 16)
await vm.stateManager.putAccount(address, account)
} catch (error) {
console.log(error)
}
var web3Provider = new remixlibVM.Web3VMProvider()
web3Provider.setVM(vm)
vm.web3 = web3Provider
return vm
}

@ -1,5 +1,5 @@
'use strict'
require('./vmCall')
require('./traceManager')
require('./codeManager')
require('./disassembler')

@ -1,63 +1,44 @@
'use strict'
import { Block } from '@ethereumjs/block'
import { Transaction } from '@ethereumjs/tx'
import VM from '@ethereumjs/vm'
import { rlp, keccak, bufferToHex } from 'ethereumjs-util'
import { extendWeb3 } from '../src/init'
var utileth = require('ethereumjs-util')
var Tx = require('@ethereumjs/tx').Transaction
var BN = require('ethereumjs-util').BN
var remixLib = require('@remix-project/remix-lib')
const { Provider, extend } = require('@remix-project/remix-simulator')
const Web3 = require('web3')
function sendTx (vm, from, to, value, data, cb) {
var tx = new Tx({
nonce: new BN(from.nonce++),
// gasPrice: new BN(1),
gasLimit: new BN(3000000, 10),
to: to,
value: new BN(value, 10),
data: Buffer.from(data, 'hex')
})
tx = tx.sign(from.privateKey)
var block = Block.fromBlockData({
header: {
timestamp: new Date().getTime() / 1000 | 0,
number: 0
}
}) // still using default common
vm.runTx({block: block, tx: tx, skipBalance: true, skipNonce: true}).then(function (result) {
setTimeout(() => {
cb(null, utileth.bufferToHex(tx.hash()))
}, 500)
}).catch((error) => {
console.error(error)
cb(error)
})
async function getWeb3 () {
const remixSimulatorProvider = new Provider({ fork: 'berlin' })
await remixSimulatorProvider.init()
await remixSimulatorProvider.Accounts.resetAccounts()
const web3 = new Web3(remixSimulatorProvider)
extendWeb3(web3)
return web3
}
/*
Init VM / Send Transaction
*/
async function initVM (privateKey) {
var address = utileth.Address.fromPrivateKey(privateKey)
var vm = new VM({
activatePrecompiles: true
})
await vm.init()
async function sendTx (web3, from, to, value, data, cb) {
try {
let account = await vm.stateManager.getAccount(address)
account.balance = new BN('f00000000000000001', 16)
await vm.stateManager.putAccount(address, account)
} catch (error) {
console.log(error)
}
var web3Provider = new remixLib.vm.Web3VMProvider()
web3Provider.setVM(vm)
vm.web3 = web3Provider
return vm
cb = cb || (() => {})
const receipt = await web3.eth.sendTransaction({
from: utileth.Address.fromPrivateKey(from.privateKey).toString('hex'),
to,
value,
data,
gas: 7000000
})
cb(null, receipt.transactionHash)
return receipt.transactionHash
} catch (e) {
cb(e)
}
}
module.exports = {
sendTx: sendTx,
initVM: initVM
sendTx,
getWeb3
}

@ -1,6 +1,6 @@
{
"name": "@remix-project/remix-lib",
"version": "0.5.6",
"version": "0.5.7",
"description": "Library to various Remix tools",
"contributors": [
{
@ -53,5 +53,5 @@
},
"homepage": "https://github.com/ethereum/remix-project/tree/master/libs/remix-lib#readme",
"typings": "src/index.d.ts",
"gitHead": "39700b7c076d53d0f857f341774a8448ea5c8da9"
"gitHead": "4705cbc4d1761f75267992552da9db6cff2f3ed5"
}

@ -55,10 +55,10 @@ export class LogsManager {
if (queryFilter.topics.filter((logTopic) => changeEvent.log.topics.indexOf(logTopic) >= 0).length === 0) return false
if (queryType === 'logs') {
if ((queryFilter.address === ('0x' + changeEvent.tx.to.toString('hex'))) && (queryFilter.address === ('0x' + changeEvent.tx.from.toString('hex')))) {
if (!queryFilter.toBlock) {
return true
} else if (parseInt(queryFilter.toBlock) > parseInt(changeEvent.blockNumber)) {
const fromBlock = queryFilter.fromBlock || '0x0'
const toBlock = queryFilter.toBlock || this.oldLogs.length ? this.oldLogs[this.oldLogs.length - 1].blockNumber : '0x0'
if ((queryFilter.address === (changeEvent.tx.to || '').toString()) || queryFilter.address === (changeEvent.tx.getSenderAddress().toString())) {
if ((parseInt(toBlock) >= parseInt(changeEvent.blockNumber)) && (parseInt(fromBlock) <= parseInt(changeEvent.blockNumber))) {
return true
}
}
@ -144,6 +144,23 @@ export class LogsManager {
}
}
getLogsByTxHash (hash) {
return this.oldLogs.filter((log) => '0x' + log.tx.hash().toString('hex') === hash)
.map((log) => {
return {
logIndex: '0x1', // 1
blockNumber: log.blockNumber,
blockHash: ('0x' + log.block.hash().toString('hex')),
transactionHash: ('0x' + log.tx.hash().toString('hex')),
transactionIndex: '0x' + log.txNumber.toString(16),
// TODO: if it's a contract deploy, it should be that address instead
address: log.log.address,
data: log.log.data,
topics: log.log.topics
}
})
}
getLogsFor (params) {
const results = []
for (const log of this.oldLogs) {

@ -77,7 +77,7 @@ export function encodeParams (params, funAbi, callback) {
* @param {Function} callback - callback
*/
export function encodeFunctionCall (params, funAbi, callback) {
this.encodeParams(params, funAbi, (error, encodedParam) => {
encodeParams(params, funAbi, (error, encodedParam) => {
if (error) return callback(error)
callback(null, { dataHex: encodeFunctionId(funAbi) + encodedParam.dataHex, funAbi, funArgs: encodedParam.funArgs })
})
@ -94,7 +94,7 @@ export function encodeFunctionCall (params, funAbi, callback) {
* @param {Function} callback - callback
*/
export function encodeConstructorCallAndLinkLibraries (contract, params, funAbi, linkLibraries, linkReferences, callback) {
this.encodeParams(params, funAbi, (error, encodedParam) => {
encodeParams(params, funAbi, (error, encodedParam) => {
if (error) return callback(error)
let bytecodeToDeploy = contract.evm.bytecode.object
if (bytecodeToDeploy.indexOf('_') >= 0) {
@ -103,7 +103,7 @@ export function encodeConstructorCallAndLinkLibraries (contract, params, funAbi,
for (const lib in linkLibraries[libFile]) {
const address = linkLibraries[libFile][lib]
if (!isValidAddress(address)) return callback(address + ' is not a valid address. Please check the provided address is valid.')
bytecodeToDeploy = this.linkLibraryStandardFromlinkReferences(lib, address.replace('0x', ''), bytecodeToDeploy, linkReferences)
bytecodeToDeploy = linkLibraryStandardFromlinkReferences(lib, address.replace('0x', ''), bytecodeToDeploy, linkReferences)
}
}
}
@ -129,13 +129,13 @@ export function encodeConstructorCallAndLinkLibraries (contract, params, funAbi,
* @param {Function} callback - callback
*/
export function encodeConstructorCallAndDeployLibraries (contractName, contract, contracts, params, funAbi, callback, callbackStep, callbackDeployLibrary) {
this.encodeParams(params, funAbi, (error, encodedParam) => {
encodeParams(params, funAbi, (error, encodedParam) => {
if (error) return callback(error)
let dataHex = ''
const contractBytecode = contract.evm.bytecode.object
let bytecodeToDeploy = contract.evm.bytecode.object
if (bytecodeToDeploy.indexOf('_') >= 0) {
this.linkBytecode(contract, contracts, (err, bytecode) => {
linkBytecode(contract, contracts, (err, bytecode) => {
if (err) {
callback('Error deploying required libraries: ' + err)
} else {
@ -176,7 +176,7 @@ export function buildData (contractName, contract, contracts, isConstructor, fun
} else {
try {
if (params.length > 0) {
funArgs = this.parseFunctionParams(params)
funArgs = parseFunctionParams(params)
}
} catch (e) {
return callback('Error encoding arguments: ' + e)
@ -199,7 +199,7 @@ export function buildData (contractName, contract, contracts, isConstructor, fun
contractBytecode = contract.evm.bytecode.object
let bytecodeToDeploy = contract.evm.bytecode.object
if (bytecodeToDeploy.indexOf('_') >= 0) {
this.linkBytecode(contract, contracts, (err, bytecode) => {
linkBytecode(contract, contracts, (err, bytecode) => {
if (err) {
callback('Error deploying required libraries: ' + err)
} else {
@ -225,7 +225,7 @@ export function linkBytecodeStandard (contract, contracts, callback, callbackSte
eachOfSeries(contract.evm.bytecode.linkReferences[file], (libRef, libName, cbLibDeployed) => {
const library = contracts[file][libName]
if (library) {
this.deployLibrary(file + ':' + libName, libName, library, contracts, (error, address) => {
deployLibrary(file + ':' + libName, libName, library, contracts, (error, address) => {
if (error) {
return cbLibDeployed(error)
}
@ -233,7 +233,7 @@ export function linkBytecodeStandard (contract, contracts, callback, callbackSte
if (hexAddress.slice(0, 2) === '0x') {
hexAddress = hexAddress.slice(2)
}
contractBytecode = this.linkLibraryStandard(libName, hexAddress, contractBytecode, contract)
contractBytecode = linkLibraryStandard(libName, hexAddress, contractBytecode, contract)
cbLibDeployed()
}, callbackStep, callbackDeployLibrary)
} else {
@ -269,7 +269,7 @@ export function linkBytecodeLegacy (contract, contracts, callback, callbackStep,
if (!library) {
return callback('Library ' + libraryName + ' not found.')
}
this.deployLibrary(libraryName, libraryShortName, library, contracts, (err, address) => {
deployLibrary(libraryName, libraryShortName, library, contracts, (err, address) => {
if (err) {
return callback(err)
}
@ -277,8 +277,8 @@ export function linkBytecodeLegacy (contract, contracts, callback, callbackStep,
if (hexAddress.slice(0, 2) === '0x') {
hexAddress = hexAddress.slice(2)
}
contract.evm.bytecode.object = this.linkLibrary(libraryName, hexAddress, contract.evm.bytecode.object)
this.linkBytecode(contract, contracts, callback, callbackStep, callbackDeployLibrary)
contract.evm.bytecode.object = linkLibrary(libraryName, hexAddress, contract.evm.bytecode.object)
linkBytecode(contract, contracts, callback, callbackStep, callbackDeployLibrary)
}, callbackStep, callbackDeployLibrary)
}
@ -287,9 +287,9 @@ export function linkBytecode (contract, contracts, callback?, callbackStep?, cal
return callback(null, contract.evm.bytecode.object)
}
if (contract.evm.bytecode.linkReferences && Object.keys(contract.evm.bytecode.linkReferences).length) {
this.linkBytecodeStandard(contract, contracts, callback, callbackStep, callbackDeployLibrary)
linkBytecodeStandard(contract, contracts, callback, callbackStep, callbackDeployLibrary)
} else {
this.linkBytecodeLegacy(contract, contracts, callback, callbackStep, callbackDeployLibrary)
linkBytecodeLegacy(contract, contracts, callback, callbackStep, callbackDeployLibrary)
}
}
@ -300,11 +300,11 @@ export function deployLibrary (libraryName, libraryShortName, library, contracts
}
const bytecode = library.evm.bytecode.object
if (bytecode.indexOf('_') >= 0) {
this.linkBytecode(library, contracts, (err, bytecode) => {
linkBytecode(library, contracts, (err, bytecode) => {
if (err) callback(err)
else {
library.evm.bytecode.object = bytecode
this.deployLibrary(libraryName, libraryShortName, library, contracts, callback, callbackStep, callbackDeployLibrary)
deployLibrary(libraryName, libraryShortName, library, contracts, callback, callbackStep, callbackDeployLibrary)
}
}, callbackStep, callbackDeployLibrary)
} else {
@ -325,7 +325,7 @@ export function linkLibraryStandardFromlinkReferences (libraryName, address, byt
for (const file in linkReferences) {
for (const libName in linkReferences[file]) {
if (libraryName === libName) {
bytecode = this.setLibraryAddress(address, bytecode, linkReferences[file][libName])
bytecode = setLibraryAddress(address, bytecode, linkReferences[file][libName])
}
}
}
@ -333,7 +333,7 @@ export function linkLibraryStandardFromlinkReferences (libraryName, address, byt
}
export function linkLibraryStandard (libraryName, address, bytecode, contract) {
return this.linkLibraryStandardFromlinkReferences(libraryName, address, bytecode, contract.evm.bytecode.linkReferences)
return linkLibraryStandardFromlinkReferences(libraryName, address, bytecode, contract.evm.bytecode.linkReferences)
}
export function setLibraryAddress (address, bytecodeToLink, positions) {
@ -384,7 +384,7 @@ export function decodeResponse (response, fnabi) {
export function parseFunctionParams (params) {
let args = []
// Check if parameter string starts with array or string
let startIndex = this.isArrayOrStringStart(params, 0) ? -1 : 0
let startIndex = isArrayOrStringStart(params, 0) ? -1 : 0
for (let i = 0; i < params.length; i++) {
// If a quote is received
if (params.charAt(i) === '"') {
@ -427,7 +427,7 @@ export function parseFunctionParams (params) {
args.push(params.substring(startIndex, i))
}
// Register start index of a parameter to parse
startIndex = this.isArrayOrStringStart(params, i + 1) ? -1 : i + 1
startIndex = isArrayOrStringStart(params, i + 1) ? -1 : i + 1
} else if (startIndex >= 0 && i === params.length - 1) {
// If start index is registered and string is completed (To handle last parameter)
args.push(params.substring(startIndex, params.length))

@ -3,8 +3,8 @@ import { ethers } from 'ethers'
export function makeFullTypeDefinition (typeDef) {
if (typeDef && typeDef.type.indexOf('tuple') === 0 && typeDef.components) {
const innerTypes = typeDef.components.map((innerType) => { return this.makeFullTypeDefinition(innerType) })
return `tuple(${innerTypes.join(',')})${this.extractSize(typeDef.type)}`
const innerTypes = typeDef.components.map((innerType) => { return makeFullTypeDefinition(innerType) })
return `tuple(${innerTypes.join(',')})${extractSize(typeDef.type)}`
}
return typeDef.type
}
@ -19,7 +19,7 @@ export function encodeParams (funABI, args) {
if (type === 'bool' && args[i] === 'false') {
args[i] = false
}
types.push(type.indexOf('tuple') === 0 ? this.makeFullTypeDefinition(funABI.inputs[i]) : type)
types.push(type.indexOf('tuple') === 0 ? makeFullTypeDefinition(funABI.inputs[i]) : type)
if (args.length < types.length) {
args.push('')
}
@ -107,7 +107,7 @@ export function getFunction (abi, fnName) {
const fn = abi[i]
if (fn.type === 'function' && fnName === fn.name + '(' + fn.inputs.map((value) => {
if (value.components) {
const fullType = this.makeFullTypeDefinition(value)
const fullType = makeFullTypeDefinition(value)
return fullType.replace(/tuple/g, '') // return of makeFullTypeDefinition might contain `tuple`, need to remove it cause `methodIdentifier` (fnName) does not include `tuple` keyword
} else {
return value.type

@ -13,7 +13,6 @@ export class TxRunnerVM {
vmaccounts
queusTxs
blocks
txs
logsManager
commonContext
getVMObject: () => any

@ -11,7 +11,7 @@ export function formatMemory (mem, width) {
for (let k = 0; k < mem.length; k += (width * 2)) {
const memory = mem.substr(k, width * 2)
const content = this.tryConvertAsciiFormat(memory)
const content = tryConvertAsciiFormat(memory)
ret['0x' + (k / 2).toString(16)] = content.raw + '\t' + content.ascii
}
return ret

@ -4,12 +4,12 @@ import Web3 from 'web3'
export function loadWeb3 (url = 'http://localhost:8545') {
const web3 = new Web3()
web3.setProvider(new Web3.providers.HttpProvider(url))
this.extend(web3)
extend(web3)
return web3
}
export function extendWeb3 (web3) {
this.extend(web3)
extend(web3)
}
export function extend (web3) {

@ -85,7 +85,7 @@ export function findLowerBound (target, array) {
return largest array[i] such that array[i] <= target; return null if array[0] > target || array is empty
*/
export function findLowerBoundValue (target, array) {
const index = this.findLowerBound(target, array)
const index = findLowerBound(target, array)
return index >= 0 ? array[index] : null
}
@ -99,7 +99,7 @@ export function findClosestIndex (target, array): number {
if (array.length === 0) {
return -1
}
const index = this.findLowerBound(target, array)
const index = findLowerBound(target, array)
if (index < 0) {
return 0
} else if (index >= array.length - 1) {
@ -185,13 +185,13 @@ export function cborEncodedValueExtraction () {
}
export function extractcborMetadata (value) {
return value.replace(this.cborEncodedValueExtraction(), '')
return value.replace(cborEncodedValueExtraction(), '')
}
export function extractSwarmHash (value) {
value = value.replace(this.swarmHashExtraction(), '')
value = value.replace(this.swarmHashExtractionPOC31(), '')
value = value.replace(this.swarmHashExtractionPOC32(), '')
value = value.replace(swarmHashExtraction(), '')
value = value.replace(swarmHashExtractionPOC31(), '')
value = value.replace(swarmHashExtractionPOC32(), '')
return value
}
@ -218,10 +218,10 @@ export function compareByteCode (code1, code2) {
code2 = replaceLibReference(code2, pos)
code1 = replaceLibReference(code1, pos)
}
code1 = this.extractSwarmHash(code1)
code1 = this.extractcborMetadata(code1)
code2 = this.extractSwarmHash(code2)
code2 = this.extractcborMetadata(code2)
code1 = extractSwarmHash(code1)
code1 = extractcborMetadata(code1)
code2 = extractSwarmHash(code2)
code2 = extractcborMetadata(code2)
if (code1 && code2) {
const compare = stringSimilarity.compareTwoStrings(code1, code2)

@ -129,7 +129,11 @@ export class Web3VmProvider {
this.storageCache[this.processingHash] = {}
if (data.to) {
try {
const storage = await this.vm.stateManager.dumpStorage(data.to)
// dumpStorage throws error as 'Missing Node in DB'
// This can be uncommented once that error is handled
// https://github.com/ethereum/remix-project/issues/1644
// const storage = await this.vm.stateManager.dumpStorage(data.to)
const storage = {}
this.storageCache[this.processingHash][tx['to']] = storage
this.lastProcessedStorageTxHash[tx['to']] = this.processingHash
} catch (e) {
@ -245,7 +249,11 @@ export class Web3VmProvider {
if (!this.storageCache[this.processingHash][this.processingAddress]) {
const account = Address.fromString(this.processingAddress)
try {
const storage = await this.vm.stateManager.dumpStorage(account)
// dumpStorage throws error as 'Missing Node in DB'
// This can be uncommented once that error is handled
// https://github.com/ethereum/remix-project/issues/1644
// const storage = await this.vm.stateManager.dumpStorage(account)
const storage = {}
this.storageCache[this.processingHash][this.processingAddress] = storage
this.lastProcessedStorageTxHash[this.processingAddress] = this.processingHash
} catch (e) {

@ -1,6 +1,6 @@
{
"name": "@remix-project/remix-simulator",
"version": "0.2.6",
"version": "0.2.7",
"description": "Ethereum IDE and tools for the web",
"contributors": [
{
@ -18,7 +18,7 @@
"@ethereumjs/common": "^2.2.0",
"@ethereumjs/tx": "^3.3.0",
"@ethereumjs/vm": "^5.5.0",
"@remix-project/remix-lib": "^0.5.6",
"@remix-project/remix-lib": "^0.5.7",
"ansi-gray": "^0.1.1",
"async": "^3.1.0",
"body-parser": "^1.18.2",
@ -66,5 +66,5 @@
},
"homepage": "https://github.com/ethereum/remix-project/tree/master/libs/remix-simulator#readme",
"typings": "src/index.d.ts",
"gitHead": "39700b7c076d53d0f857f341774a8448ea5c8da9"
"gitHead": "4705cbc4d1761f75267992552da9db6cff2f3ed5"
}

@ -1,13 +1,10 @@
export class Blocks {
vmContext
coinbase: string
blockNumber: number
constructor (vmContext, _options) {
this.vmContext = vmContext
const options = _options || {}
this.coinbase = options.coinbase || '0x0000000000000000000000000000000000000000'
this.blockNumber = 0
}
methods (): Record<string, unknown> {
@ -107,7 +104,7 @@ export class Blocks {
}
eth_blockNumber (payload, cb) {
cb(null, this.blockNumber)
cb(null, parseInt(this.vmContext.latestBlockNumber))
}
eth_getBlockTransactionCountByHash (payload, cb) {

@ -3,16 +3,16 @@ const version = require('../../package.json').version
export function methods () {
return {
web3_clientVersion: this.web3_clientVersion.bind(this),
eth_protocolVersion: this.eth_protocolVersion.bind(this),
eth_syncing: this.eth_syncing.bind(this),
eth_mining: this.eth_mining.bind(this),
eth_hashrate: this.eth_hashrate.bind(this),
web3_sha3: this.web3_sha3.bind(this),
eth_getCompilers: this.eth_getCompilers.bind(this),
eth_compileSolidity: this.eth_compileSolidity.bind(this),
eth_compileLLL: this.eth_compileLLL.bind(this),
eth_compileSerpent: this.eth_compileSerpent.bind(this)
web3_clientVersion: web3_clientVersion,
eth_protocolVersion: eth_protocolVersion,
eth_syncing: eth_syncing,
eth_mining: eth_mining,
eth_hashrate: eth_hashrate,
web3_sha3: web3_sha3,
eth_getCompilers: eth_getCompilers,
eth_compileSolidity: eth_compileSolidity,
eth_compileLLL: eth_compileLLL,
eth_compileSerpent: eth_compileSerpent
}
}

@ -1,8 +1,8 @@
export function methods (): Record<string, unknown> {
return {
net_version: this.net_version,
net_listening: this.net_listening,
net_peerCount: this.net_peerCount
net_version: net_version,
net_listening: net_listening,
net_peerCount: net_peerCount
}
}

@ -11,6 +11,7 @@ export class Transactions {
tags
txRunnerVMInstance
txRunnerInstance
TX_INDEX = '0x0' // currently there's always only 1 tx per block, so the transaction index will always be 0x0
constructor (vmContext) {
this.vmContext = vmContext
@ -71,7 +72,7 @@ export class Transactions {
if (!error && result) {
this.vmContext.addBlock(result.block)
const hash = '0x' + result.tx.hash().toString('hex')
this.vmContext.trackTx(hash, result.block)
this.vmContext.trackTx(hash, result.block, result.tx)
this.vmContext.trackExecResult(hash, result.result.execResult)
return cb(null, result.transactionHash)
}
@ -95,17 +96,19 @@ export class Transactions {
return cb(error)
}
const txBlock = this.vmContext.txs[receipt.hash]
const txBlock = this.vmContext.blockByTxHash[receipt.hash]
const logs = this.vmContext.logsManager.getLogsByTxHash(receipt.hash)
const r: Record <string, unknown> = {
transactionHash: receipt.hash,
transactionIndex: '0x00',
transactionIndex: this.TX_INDEX,
blockHash: '0x' + txBlock.hash().toString('hex'),
blockNumber: '0x' + txBlock.header.number.toString('hex'),
gasUsed: receipt.gasUsed,
cumulativeGasUsed: receipt.gasUsed, // only 1 tx per block
contractAddress: receipt.contractAddress,
logs: receipt.logs,
logs,
status: receipt.status,
to: receipt.to
}
@ -151,7 +154,7 @@ export class Transactions {
if (!error && result) {
this.vmContext.addBlock(result.block)
const hash = '0x' + result.tx.hash().toString('hex')
this.vmContext.trackTx(hash, result.block)
this.vmContext.trackTx(hash, result.block, result.tx)
this.vmContext.trackExecResult(hash, result.result.execResult)
this.tags[tag] = result.transactionHash
// calls are not supposed to return a transaction hash. we do this for keeping track of it and allowing debugging calls.
@ -185,7 +188,8 @@ export class Transactions {
return cb(error)
}
const txBlock = this.vmContext.txs[receipt.transactionHash]
const txBlock = this.vmContext.blockByTxHash[receipt.transactionHash]
const tx = this.vmContext.txByHash[receipt.transactionHash]
// TODO: params to add later
const r: Record<string, unknown> = {
@ -198,8 +202,8 @@ export class Transactions {
gasPrice: '0x4a817c800', // 20000000000
hash: receipt.transactionHash,
input: receipt.input,
nonce: 2, // 0x15 // the nonce should be updated
// "transactionIndex": 0,
nonce: '0x' + tx.nonce.toString('hex'),
transactionIndex: this.TX_INDEX,
value: receipt.value
// "value":"0xf3dbb76162000" // 4290000000000000
// "v": "0x25", // 37
@ -234,6 +238,8 @@ export class Transactions {
return cb(error)
}
const tx = this.vmContext.txByHash[receipt.transactionHash]
// TODO: params to add later
const r: Record<string, unknown> = {
blockHash: '0x' + txBlock.hash().toString('hex'),
@ -245,8 +251,8 @@ export class Transactions {
gasPrice: '0x4a817c800', // 20000000000
hash: receipt.transactionHash,
input: receipt.input,
nonce: 2, // 0x15 // the nonce should be updated
// "transactionIndex": 0,
nonce: '0x' + tx.nonce.toString('hex'),
transactionIndex: this.TX_INDEX,
value: receipt.value
// "value":"0xf3dbb76162000" // 4290000000000000
// "v": "0x25", // 37
@ -277,6 +283,8 @@ export class Transactions {
return cb(error)
}
const tx = this.vmContext.txByHash[receipt.transactionHash]
// TODO: params to add later
const r: Record<string, unknown> = {
blockHash: '0x' + txBlock.hash().toString('hex'),
@ -288,8 +296,8 @@ export class Transactions {
gasPrice: '0x4a817c800', // 20000000000
hash: receipt.transactionHash,
input: receipt.input,
nonce: 2, // 0x15 // the nonce should be updated
// "transactionIndex": 0,
nonce: '0x' + tx.nonce.toString('hex'),
transactionIndex: this.TX_INDEX,
value: receipt.value
// "value":"0xf3dbb76162000" // 4290000000000000
// "v": "0x25", // 37

@ -9,11 +9,11 @@ function hasFlag (flag) {
}
function addColor (str) {
if (this.hasFlag('no-color')) {
if (hasFlag('no-color')) {
return str
}
if (this.hasFlag('color')) {
if (hasFlag('color')) {
return gray(str)
}
@ -35,41 +35,36 @@ function stderr (arg) {
}
function getTimestamp () {
const coloredTimestamp = this.addColor(timestamp('HH:mm:ss'))
const coloredTimestamp = addColor(timestamp('HH:mm:ss'))
return '[' + coloredTimestamp + ']'
}
export function log (...args: any[]) {
const time = this.getTimestamp()
this.stdout(time + ' ')
const time = getTimestamp()
stdout(time + ' ')
console.log(args)
return this
}
export function info (...args: any[]) {
const time = this.getTimestamp()
this.stdout(time + ' ')
const time = getTimestamp()
stdout(time + ' ')
console.info(args)
return this
}
export function dir (...args: any[]) {
const time = this.getTimestamp()
this.stdout(time + ' ')
const time = getTimestamp()
stdout(time + ' ')
console.dir(args)
return this
}
export function warn (...args: any[]) {
const time = this.getTimestamp()
this.stderr(time + ' ')
const time = getTimestamp()
stderr(time + ' ')
console.warn(args)
return this
}
export function error (...args: any[]) {
const time = this.getTimestamp()
this.stderr(time + ' ')
const time = getTimestamp()
stderr(time + ' ')
console.error(args)
return this
}

@ -24,31 +24,27 @@ class StateManagerCommonStorageDump extends StateManager {
return super.putContractStorage(address, key, value)
}
async dumpStorage (address) {
let trie
try {
trie = await this._getStorageTrie(address)
} catch (e) {
console.log(e)
throw e
}
return new Promise<StorageDump>((resolve, reject) => {
try {
const storage = {}
const stream = trie.createReadStream()
stream.on('data', (val) => {
const value = rlp.decode(val.value)
storage['0x' + val.key.toString('hex')] = {
key: this.keyHashes[val.key.toString('hex')],
value: '0x' + value.toString('hex')
}
async dumpStorage (address): Promise<StorageDump> {
return new Promise((resolve, reject) => {
this._getStorageTrie(address)
.then((trie) => {
const storage = {}
const stream = trie.createReadStream()
stream.on('data', (val) => {
const value = rlp.decode(val.value)
storage['0x' + val.key.toString('hex')] = {
key: this.keyHashes[val.key.toString('hex')],
value: '0x' + value.toString('hex')
}
})
stream.on('end', () => {
resolve(storage)
})
})
stream.on('end', function () {
resolve(storage)
.catch((e) => {
reject(e)
})
} catch (e) {
reject(e)
}
})
}
@ -60,18 +56,17 @@ class StateManagerCommonStorageDump extends StateManager {
}
async setStateRoot (stateRoot) {
await this._cache.flush()
if (stateRoot === this._trie.EMPTY_TRIE_ROOT) {
this._trie.root = stateRoot
this._cache.clear()
this._storageTries = {}
return
if (this._checkpointCount !== 0) {
throw new Error('Cannot set state root with uncommitted checkpoints')
}
const hasRoot = await this._trie.checkRoot(stateRoot)
if (!hasRoot) {
throw new Error('State trie does not contain state root')
await this._cache.flush()
if (!stateRoot.equals(this._trie.EMPTY_TRIE_ROOT)) {
const hasRoot = await this._trie.checkRoot(stateRoot)
if (!hasRoot) {
throw new Error('State trie does not contain state root')
}
}
this._trie.root = stateRoot
@ -90,7 +85,8 @@ export class VMContext {
customNetWorks
blocks
latestBlockNumber
txs
blockByTxHash
txByHash
currentVm
web3vm
logsManager
@ -103,7 +99,8 @@ export class VMContext {
this.currentVm = this.createVm(this.currentFork)
this.blocks = {}
this.latestBlockNumber = 0
this.txs = {}
this.blockByTxHash = {}
this.txByHash = {}
this.exeResults = {}
this.logsManager = new execution.LogsManager()
}
@ -156,8 +153,9 @@ export class VMContext {
this.logsManager.checkBlock(blockNumber, block, this.web3())
}
trackTx (tx, block) {
this.txs[tx] = block
trackTx (txHash, block, tx) {
this.blockByTxHash[txHash] = block
this.txByHash[txHash] = tx
}
trackExecResult (tx, execReult) {

@ -116,6 +116,7 @@ describe('blocks', () => {
})
})
/*
describe('eth_getStorageAt', () => {
it('should get storage at position at given address', async () => {
const abi: any = [
@ -200,28 +201,29 @@ describe('blocks', () => {
}
]
const code = '0x608060405234801561001057600080fd5b506040516020806102018339810180604052602081101561003057600080fd5b810190808051906020019092919050505080600081905550506101a9806100586000396000f3fe60806040526004361061005c576000357c0100000000000000000000000000000000000000000000000000000000900480632a1afcd91461006157806360fe47b11461008c5780636d4ce63c146100c7578063ce01e1ec146100f2575b600080fd5b34801561006d57600080fd5b5061007661012d565b6040518082815260200191505060405180910390f35b34801561009857600080fd5b506100c5600480360360208110156100af57600080fd5b8101908080359060200190929190505050610133565b005b3480156100d357600080fd5b506100dc61013d565b6040518082815260200191505060405180910390f35b3480156100fe57600080fd5b5061012b6004803603602081101561011557600080fd5b8101908080359060200190929190505050610146565b005b60005481565b8060008190555050565b60008054905090565b80600081905550807f63a242a632efe33c0e210e04e4173612a17efa4f16aa4890bc7e46caece80de060405160405180910390a25056fea165627a7a7230582063160eb16dc361092a85ced1a773eed0b63738b83bea1e1c51cf066fa90e135d0029'
// const code = '0x608060405234801561001057600080fd5b506040516020806102018339810180604052602081101561003057600080fd5b810190808051906020019092919050505080600081905550506101a9806100586000396000f3fe60806040526004361061005c576000357c0100000000000000000000000000000000000000000000000000000000900480632a1afcd91461006157806360fe47b11461008c5780636d4ce63c146100c7578063ce01e1ec146100f2575b600080fd5b34801561006d57600080fd5b5061007661012d565b6040518082815260200191505060405180910390f35b34801561009857600080fd5b506100c5600480360360208110156100af57600080fd5b8101908080359060200190929190505050610133565b005b3480156100d357600080fd5b506100dc61013d565b6040518082815260200191505060405180910390f35b3480156100fe57600080fd5b5061012b6004803603602081101561011557600080fd5b8101908080359060200190929190505050610146565b005b60005481565b8060008190555050565b60008054905090565b80600081905550807f63a242a632efe33c0e210e04e4173612a17efa4f16aa4890bc7e46caece80de060405160405180910390a25056fea165627a7a7230582063160eb16dc361092a85ced1a773eed0b63738b83bea1e1c51cf066fa90e135d0029'
const contract = new web3.eth.Contract(abi)
const accounts = await web3.eth.getAccounts()
// const contract = new web3.eth.Contract(abi)
// const accounts = await web3.eth.getAccounts()
const contractInstance: any = await contract.deploy({ data: code, arguments: [100] }).send({ from: accounts[0], gas: 400000 })
contractInstance.currentProvider = web3.eth.currentProvider
contractInstance.givenProvider = web3.eth.currentProvider
// const contractInstance: any = await contract.deploy({ data: code, arguments: [100] }).send({ from: accounts[0], gas: 400000 })
// contractInstance.currentProvider = web3.eth.currentProvider
// contractInstance.givenProvider = web3.eth.currentProvider
await contractInstance.methods.set(100).send({ from: accounts[0].toLowerCase(), gas: 400000 })
let storage = await web3.eth.getStorageAt(contractInstance.options.address, 0)
assert.deepEqual(storage, '0x64')
// await contractInstance.methods.set(100).send({ from: accounts[0].toLowerCase(), gas: 400000 })
// let storage = await web3.eth.getStorageAt(contractInstance.options.address, 0)
// assert.deepEqual(storage, '0x64')
await contractInstance.methods.set(200).send({ from: accounts[0], gas: 400000 })
storage = await web3.eth.getStorageAt(contractInstance.options.address, 0)
assert.deepEqual(storage, '0x64')
// await contractInstance.methods.set(200).send({ from: accounts[0], gas: 400000 })
// storage = await web3.eth.getStorageAt(contractInstance.options.address, 0)
// assert.deepEqual(storage, '0x64')
await contractInstance.methods.set(200).send({ from: accounts[0], gas: 400000 })
storage = await web3.eth.getStorageAt(contractInstance.options.address, 0)
assert.deepEqual(storage, '0xc8')
})
})
*/
describe('eth_call', () => {
it('should get a value', async () => {

@ -1,9 +1,9 @@
{
"name": "@remix-project/remix-solidity",
"version": "0.4.6",
"version": "0.4.7",
"description": "Tool to load and run Solidity compiler",
"main": "index.js",
"types": "./index.d.ts",
"main": "src/index.js",
"types": "src/index.d.ts",
"contributors": [
{
"name": "Yann Levreau",
@ -18,7 +18,7 @@
"@ethereumjs/block": "^3.4.0",
"@ethereumjs/tx": "^3.3.0",
"@ethereumjs/vm": "^5.5.0",
"@remix-project/remix-lib": "^0.5.6",
"@remix-project/remix-lib": "^0.5.7",
"async": "^2.6.2",
"eslint-scope": "^5.0.0",
"ethereumjs-util": "^7.0.10",
@ -60,6 +60,6 @@
"url": "https://github.com/ethereum/remix-project/issues"
},
"homepage": "https://github.com/ethereum/remix-project/tree/master/libs/remix-solidity#readme",
"typings": "index.d.ts",
"gitHead": "39700b7c076d53d0f857f341774a8448ea5c8da9"
"typings": "src/index.d.ts",
"gitHead": "4705cbc4d1761f75267992552da9db6cff2f3ed5"
}

@ -1,6 +1,6 @@
{
"name": "@remix-project/remix-tests",
"version": "0.2.6",
"version": "0.2.7",
"description": "Tool to test Solidity smart contracts",
"main": "src/index.js",
"types": "./src/index.d.ts",
@ -39,9 +39,9 @@
"@ethereumjs/common": "^2.2.0",
"@ethereumjs/tx": "^3.3.0",
"@ethereumjs/vm": "^5.5.0",
"@remix-project/remix-lib": "^0.5.6",
"@remix-project/remix-simulator": "^0.2.6",
"@remix-project/remix-solidity": "^0.4.6",
"@remix-project/remix-lib": "^0.5.7",
"@remix-project/remix-simulator": "^0.2.7",
"@remix-project/remix-solidity": "^0.4.7",
"ansi-gray": "^0.1.1",
"async": "^2.6.0",
"axios": ">=0.21.1",
@ -77,5 +77,5 @@
"typescript": "^3.3.1"
},
"typings": "src/index.d.ts",
"gitHead": "39700b7c076d53d0f857f341774a8448ea5c8da9"
"gitHead": "4705cbc4d1761f75267992552da9db6cff2f3ed5"
}

@ -232,6 +232,7 @@ export function runTest (testName: string, testObject: any, contractDetails: Com
testCallback(undefined, resp)
async.eachOfLimit(runList, 1, function (func, index, next) {
let sender: string | null = null
let hhLogs
if (func.signature) {
sender = getOverridedSender(contractDetails.userdoc, func.signature, contractDetails.evm.methodIdentifiers)
if (opts.accounts && sender) {
@ -293,7 +294,6 @@ export function runTest (testName: string, testObject: any, contractDetails: Com
sendParams.gas = 10000000 * 8
method.send(sendParams).on('receipt', async (receipt) => {
try {
let hhLogs
if (web3.eth && web3.eth.getHHLogsForTx) hhLogs = await web3.eth.getHHLogsForTx(receipt.transactionHash)
const time: number = (Date.now() - startTime) / 1000.0
const assertionEventHashes = assertionEvents.map(e => Web3.utils.sha3(e.name + '(' + e.params.join() + ')'))
@ -366,7 +366,7 @@ export function runTest (testName: string, testObject: any, contractDetails: Com
console.error(err)
return next(err)
}
}).on('error', function (err: Error) {
}).on('error', async (err: Error) => {
const time: number = (Date.now() - startTime) / 1000.0
const resp: TestResultInterface = {
type: 'testFailure',
@ -377,6 +377,11 @@ export function runTest (testName: string, testObject: any, contractDetails: Com
context: testName,
web3
}
if (err.message.includes('Transaction has been reverted by the EVM')) {
const txHash = JSON.parse(err.message.replace('Transaction has been reverted by the EVM:', '')).transactionHash
if (web3.eth && web3.eth.getHHLogsForTx) hhLogs = await web3.eth.getHHLogsForTx(txHash)
if (hhLogs) resp.hhLogs = hhLogs
}
testCallback(undefined, resp)
failureNum += 1
timePassed += time

@ -14,6 +14,8 @@
},
"rules": {
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": "error"
"@typescript-eslint/no-unused-vars": "error",
"no-useless-constructor": "off",
"@typescript-eslint/no-useless-constructor": "error"
}
}

@ -5,7 +5,7 @@ import { Toaster } from '@remix-ui/toaster'
import { IframePlugin, WebsocketPlugin } from '@remixproject/engine-web'
import { localPluginReducerActionType, localPluginToastReducer } from '../reducers/pluginManagerReducer'
import { FormStateProps, PluginManagerComponent } from '../../types'
import { canActivate, FormStateProps, PluginManagerComponent } from '../../types'
interface LocalPluginFormProps {
closeModal: () => void
@ -20,7 +20,8 @@ const initialState: FormStateProps = {
type: 'iframe',
hash: '',
methods: [],
location: 'sidePanel'
location: 'sidePanel',
canActivate: []
}
const defaultProfile = {
@ -48,9 +49,10 @@ function LocalPluginForm ({ closeModal, visible, pluginManager }: LocalPluginFor
setName(storagePlugin.name)
setUrl(storagePlugin.url)
setLocation(storagePlugin.location as 'sidePanel' | 'mainPanel' | 'none')
setMethods(storagePlugin.methods)
setMethods(Array.isArray(storagePlugin.methods) ? storagePlugin.methods.join(',') : storagePlugin.methods)
setType(storagePlugin.type)
setDisplayName(storagePlugin.displayName)
setCanactivate(Array.isArray(storagePlugin.canActivate) ? storagePlugin.canActivate.join(',') : storagePlugin.canActivate)
}, [])
const handleModalOkClick = async () => {
@ -61,7 +63,7 @@ function LocalPluginForm ({ closeModal, visible, pluginManager }: LocalPluginFor
}
if (!location) throw new Error('Plugin should have a location')
if (!url) throw new Error('Plugin should have an URL')
const newMethods = typeof methods === 'string' ? methods.split(',').filter(val => val) : []
const newMethods = typeof methods === 'string' ? methods.split(',').filter(val => val).map(val => { return val.trim() }) : []
const targetPlugin = {
name: name,
displayName: displayName,
@ -75,7 +77,7 @@ function LocalPluginForm ({ closeModal, visible, pluginManager }: LocalPluginFor
type: type,
location: location,
icon: 'assets/img/localPlugin.webp',
canActivate: typeof canactivate === 'string' ? canactivate.split(',').filter(val => val) : []
canActivate: typeof canactivate === 'string' ? canactivate.split(',').filter(val => val).map(val => { return val.trim() }) : []
}
const localPlugin = type === 'iframe' ? new IframePlugin(initialState) : new WebsocketPlugin(initialState)
localPlugin.profile.hash = `local-${name}`

@ -11,12 +11,12 @@ interface SetPluginOptionType {
}
export class RemixEngine extends Engine {
event: EventEmitter;
event: EventEmitter
setPluginOption ({ name, kind }) : SetPluginOptionType
onRegistration (plugin) : void
}
export function isNative(name: any): any;
export function isNative(name: any): any
/**
* Checks if plugin caller 'from' is allowed to activate plugin 'to'
* The caller can have 'canActivate' as a optional property in the plugin profile.
@ -27,33 +27,33 @@ export function isNative(name: any): any;
* @param {any, any}
* @returns {boolean}
*/
export function canActivate(from: any, to: any): boolean;
export function canActivate(from: any, to: any): boolean
export class RemixAppManager extends PluginManager {
constructor();
event: EventEmitter;
pluginsDirectory: string;
pluginLoader: PluginLoader;
permissionHandler: PermissionHandler;
getAll(): import('@remixproject/plugin-utils').Profile<any>[];
getIds(): string[];
isDependent(name: any): any;
isRequired(name: any): any;
registeredPlugins(): Promise<any>;
turnPluginOn(name: string | string[]);
turnPluginOff(name: string);
constructor()
event: EventEmitter
pluginsDirectory: string
pluginLoader: PluginLoader
permissionHandler: PermissionHandler
getAll(): import('@remixproject/plugin-utils').Profile<any>[]
getIds(): string[]
isDependent(name: any): any
isRequired(name: any): any
registeredPlugins(): Promise<any>
turnPluginOn(name: string | string[])
turnPluginOff(name: string)
}
export class PluginManagerSettings {
openDialog(): void;
permissions: any;
currentSetting: any;
onValidation(): void;
openDialog(): void
permissions: any
currentSetting: any
onValidation(): void
/** Clear one permission from a plugin */
clearPersmission(from: string, to: string, method: string): void;
clearPersmission(from: string, to: string, method: string): void
/** Clear all persmissions from a plugin */
clearAllPersmission(to: string): void;
settings(): any;
render(): any;
clearAllPersmission(to: string): void
settings(): any
render(): any
}
export type PluginPermissions = {
@ -94,7 +94,7 @@ export class PluginManagerComponent extends ViewPlugin extends Plugin implements
}
// eslint-disable-next-line no-use-before-define
export = LocalPlugin;
export = LocalPlugin
declare class LocalPlugin {
/**
* Open a modal to create a local plugin
@ -102,34 +102,34 @@ declare class LocalPlugin {
* @returns {Promise<{api: any, profile: any}>} A promise with the new plugin profile
*/
open(plugins: any[]): Promise<{
api: any;
profile: any;
}>;
api: any
profile: any
}>
profile: any;
profile: any
/**
* Create the object to add to the plugin-list
*/
create(): any;
create(): any
updateName({ target }: {
target: any;
}): void;
target: any
}): void
updateUrl({ target }: {
target: any;
}): void;
target: any
}): void
updateDisplayName({ target }: {
target: any;
}): void;
target: any
}): void
updateProfile(key: any, e: any): void;
updateProfile(key: any, e: any): void
updateMethods({ target }: {
target: any;
}): void;
target: any
}): void
/** The form to create a local plugin */
form(): any;
form(): any
}
export interface PluginManagerContextProviderProps {
@ -146,12 +146,12 @@ export interface RemixUiPluginManagerProps {
* (localStorage, queryParams)
**/
declare class PluginLoader {
get currentLoader(): any;
donotAutoReload: string[];
loaders: {};
current: string;
set(plugin: any, actives: any): void;
get(): any;
get currentLoader(): any
donotAutoReload: string[]
loaders: {}
current: string
set(plugin: any, actives: any): void
get(): any
}
export type PluginManagerSettings = {
@ -178,8 +178,9 @@ export interface FormStateProps {
url: string
type: 'iframe' | 'ws'
hash: string
methods: any
methods: string[]
location: string
canActivate: string[]
}
export type PluginManagerProfile = Profile & {

@ -27,6 +27,7 @@
.remixui_sol.success .close,
.remixui_sol.error .close,
.remixui_sol.warning .close {
visibility: hidden;
white-space: pre-line;
font-weight: bold;
position: absolute;

@ -102,7 +102,7 @@ export const Renderer = ({ message, opt = {}, plugin }: RendererProps) => {
<>
{
messageText && !close && (
<div className={`sol ${editorOptions.type} ${classList}`} data-id={editorOptions.errFile} onClick={() => handleErrorClick(editorOptions)}>
<div className={`remixui_sol ${editorOptions.type} ${classList}`} data-id={editorOptions.errFile} onClick={() => handleErrorClick(editorOptions)}>
{ editorOptions.useSpan ? <span> { messageText } </span> : <pre><span>{ messageText }</span></pre> }
<div className="close" data-id="renderer" onClick={handleClose}>
<i className="fas fa-times"></i>

@ -8,7 +8,7 @@ import ErrorRenderer from './ErrorRenderer' // eslint-disable-line
import { compilation } from './actions/staticAnalysisActions'
import { initialState, analysisReducer } from './reducers/staticAnalysisReducer'
import { OverlayTrigger, Tooltip } from 'react-bootstrap'// eslint-disable-line
const StaticAnalysisRunner = require('@remix-project/remix-analyzer').CodeAnalysis
import { CodeAnalysis } from '@remix-project/remix-analyzer'
declare global {
interface Window {
@ -25,7 +25,7 @@ export interface RemixUiStaticAnalyserProps {
}
export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => {
const [runner] = useState(new StaticAnalysisRunner())
const [runner] = useState(new CodeAnalysis())
const preProcessModules = (arr: any) => {
return arr.map((Item, i) => {
@ -196,7 +196,7 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => {
fileName = Object.keys(lastCompilationResult.sources)[file]
}
warningCount++
const msg = message(item.name, item.warning, item.more, fileName, locationString)
const msg = message(result.name, item.warning, item.more, fileName, locationString)
const options = {
type: 'warning',
useSpan: true,

@ -1,9 +1,9 @@
{
"name": "@remix-project/remix-url-resolver",
"version": "0.0.27",
"version": "0.0.28",
"description": "Solidity import url resolver engine",
"main": "index.js",
"types": "./index.d.ts",
"main": "src/index.js",
"types": "src/index.d.ts",
"scripts": {
"build": "tsc",
"test": "./../../node_modules/.bin/mocha --require ts-node/register --require tsconfig-paths/register tests/*.ts -t 300000"
@ -41,6 +41,6 @@
"tslint": "^5.11.0",
"typescript": "^3.1.6"
},
"typings": "index.d.ts",
"gitHead": "39700b7c076d53d0f857f341774a8448ea5c8da9"
"typings": "src/index.d.ts",
"gitHead": "4705cbc4d1761f75267992552da9db6cff2f3ed5"
}

@ -1,6 +1,6 @@
{
"name": "@remix-project/remixd",
"version": "0.5.1",
"version": "0.5.2",
"description": "remix server: allow accessing file system from remix.ethereum.org and start a dev environment (see help section)",
"main": "index.js",
"types": "./index.d.ts",

@ -12,7 +12,7 @@ import * as program from 'commander'
async function warnLatestVersion () {
const latest = await latestVersion('@remix-project/remixd')
const pjson = require('../package.json')
const pjson = require('../../package.json')
if (semver.eq(latest, pjson.version)) {
console.log('\x1b[32m%s\x1b[0m', `[INFO] you are using the latest version ${latest}`)
} else if (semver.gt(latest, pjson.version)) {
@ -54,7 +54,7 @@ function errorHandler (error: any, service: string) {
}
(async () => {
const { version } = require('../package.json')
const { version } = require('../../package.json')
program.version(version, '-v, --version')
program

@ -123,6 +123,17 @@
},
"solidity-compiler": {
"tags": []
},
"remix-ide-e2e-src-local-plugin": {
"tags": []
}
}
},
"targetDependencies": {
"build": [
{
"target": "build",
"projects": "dependencies"
}
]
}
}

43945
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -1,6 +1,6 @@
{
"name": "remix-project",
"version": "0.18.0-dev",
"version": "0.19.0-dev",
"license": "MIT",
"description": "Ethereum Remix Monorepo",
"keywords": [
@ -20,6 +20,10 @@
"bin": {
"remix-ide": "./apps/remix-ide/bin/remix-ide"
},
"engines": {
"node": "^14.17.6",
"npm": "^6.14.15"
},
"scripts": {
"nx": "nx",
"start": "nx start",
@ -42,7 +46,7 @@
"dep-graph": "nx dep-graph",
"help": "nx help",
"lint:libs": "nx run-many --target=lint --projects=remix-analyzer,remix-astwalker,remix-debug,remix-lib,remix-simulator,remix-solidity,remix-tests,remix-url-resolver,remixd,remix-ui-tree-view,remix-ui-modal-dialog,remix-ui-toaster,remix-ui-file-explorer,remix-ui-debugger-ui,remix-ui-workspace,remix-ui-static-analyser,remix-ui-checkbox,remix-ui-settings,remix-core-plugin,remix-ui-renderer,remix-ui-publish-to-storage,remix-ui-solidity-compiler,remix-ui-plugin-manager",
"build:libs": "nx run-many --target=build --parallel=false --with-deps=true --projects=remix-analyzer,remix-astwalker,remix-debug,remix-lib,remix-simulator,remix-solidity,remix-tests,remix-url-resolver,remixd",
"build:libs": "nx run-many --target=build --parallel=false --projects=remix-analyzer,remix-astwalker,remix-debug,remix-lib,remix-simulator,remix-solidity,remix-tests,remix-url-resolver,remixd",
"test:libs": "nx run-many --target=test --projects=remix-analyzer,remix-astwalker,remix-debug,remix-lib,remix-simulator,remix-solidity,remix-tests,remix-url-resolver,remixd",
"publish:libs": "npm run build:libs && lerna publish --skip-git && npm run bumpVersion:libs",
"build:e2e": "tsc -p apps/remix-ide-e2e/tsconfig.e2e.json",
@ -53,7 +57,7 @@
"downloadsolc_assets": "wget --no-check-certificate https://binaries.soliditylang.org/wasm/soljson-v0.8.7+commit.e28d00a7.js -O ./apps/remix-ide/src/assets/js/soljson.js && wget --no-check-certificate https://binaries.soliditylang.org/wasm/soljson-v0.8.7+commit.e28d00a7.js -O ./apps/solidity-compiler/src/assets/js/soljson.js",
"make-mock-compiler": "node apps/remix-ide/ci/makeMockCompiler.js",
"minify": "uglifyjs --in-source-map inline --source-map-inline -c warnings=false",
"build:production": "NODE_ENV=production npx nx build remix-ide --with-deps --skip-nx-cache",
"build:production": "NODE_ENV=production nx build remix-ide --skip-nx-cache",
"serve:production": "npx http-server ./dist/apps/remix-ide",
"nightwatch_parallel": "npm run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js --env=chrome,firefox",
"nightwatch_local_firefox": "npm run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js --env=firefox",
@ -74,7 +78,7 @@
"nightwatch_local_gist": "npm run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js dist/apps/remix-ide-e2e/src/tests/gist.spec.js --env=chrome",
"nightwatch_local_workspace": "npm run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js dist/apps/remix-ide-e2e/src/tests/workspace.test.js --env=chrome",
"nightwatch_local_defaultLayout": "npm run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js dist/apps/remix-ide-e2e/src/tests/defaultLayout.test.js --env=chrome",
"nightwatch_local_pluginManager": "npm run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js dist/apps/remix-ide-e2e/src/tests/pluginManager.spec.js --env=chrome",
"nightwatch_local_pluginManager": "npm run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js dist/apps/remix-ide-e2e/src/tests/pluginManager.js --env=chrome",
"nightwatch_local_publishContract": "npm run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js dist/apps/remix-ide-e2e/src/tests/publishContract.test.js --env=chrome",
"nightwatch_local_generalSettings": "npm run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js dist/apps/remix-ide-e2e/src/tests/generalSettings.test.js --env=chrome",
"nightwatch_local_fileExplorer": "npm run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js dist/apps/remix-ide-e2e/src/tests/fileExplorer.test.js --env=chrome",
@ -132,17 +136,17 @@
},
"dependencies": {
"@erebos/bzz-node": "^0.13.0",
"@ethereumjs/block": "^3.4.0",
"@ethereumjs/common": "^2.4.0",
"@ethereumjs/tx": "^3.3.0",
"@ethereumjs/vm": "^5.5.0",
"@remixproject/engine": "^0.3.17",
"@remixproject/engine-web": "^0.3.17",
"@remixproject/plugin": "^0.3.17",
"@remixproject/plugin-api": "^0.3.17",
"@remixproject/plugin-utils": "^0.3.17",
"@remixproject/plugin-webview": "^0.3.17",
"@remixproject/plugin-ws": "^0.3.17",
"@ethereumjs/block": "^3.5.1",
"@ethereumjs/common": "^2.5.0",
"@ethereumjs/tx": "^3.3.2",
"@ethereumjs/vm": "^5.5.3",
"@remixproject/engine": "^0.3.20",
"@remixproject/engine-web": "^0.3.20",
"@remixproject/plugin": "^0.3.20",
"@remixproject/plugin-api": "^0.3.20",
"@remixproject/plugin-utils": "^0.3.20",
"@remixproject/plugin-webview": "^0.3.20",
"@remixproject/plugin-ws": "^0.3.20",
"ansi-gray": "^0.1.1",
"async": "^2.6.2",
"axios": ">=0.21.1",
@ -168,10 +172,10 @@
"latest-version": "^5.1.0",
"merge": "^1.2.0",
"npm-install-version": "^6.0.2",
"react": "16.13.1",
"react-beautiful-dnd": "^13.0.0",
"react-bootstrap": "^1.3.0",
"react-dom": "16.13.1",
"react": "^17.0.2",
"react-beautiful-dnd": "^13.1.0",
"react-bootstrap": "^1.6.4",
"react-dom": "^17.0.2",
"selenium": "^2.20.0",
"signale": "^1.4.0",
"string-similarity": "^4.0.4",
@ -196,26 +200,27 @@
"@babel/preset-typescript": "7.9.0",
"@babel/register": "^7.4.4",
"@fortawesome/fontawesome-free": "^5.8.1",
"@nrwl/eslint-plugin-nx": "^10.0.6",
"@nrwl/jest": "10.0.6",
"@nrwl/linter": "^10.0.6",
"@nrwl/node": "^10.0.6",
"@nrwl/react": "10.0.6",
"@nrwl/web": "10.0.6",
"@nrwl/workspace": "10.0.6",
"@nrwl/cli": "12.3.6",
"@nrwl/eslint-plugin-nx": "12.3.6",
"@nrwl/jest": "12.3.6",
"@nrwl/linter": "12.3.6",
"@nrwl/node": "12.3.6",
"@nrwl/react": "12.3.6",
"@nrwl/web": "12.3.6",
"@nrwl/workspace": "12.3.6",
"@testing-library/react": "10.4.1",
"@types/axios": "^0.14.0",
"@types/chai": "^4.2.11",
"@types/fs-extra": "^9.0.1",
"@types/jest": "25.1.4",
"@types/jest": "^27.0.2",
"@types/lodash": "^4.14.172",
"@types/mocha": "^7.0.2",
"@types/nightwatch": "^1.1.6",
"@types/node": "~8.9.4",
"@types/react": "16.9.17",
"@types/react-beautiful-dnd": "^13.0.0",
"@types/react-dom": "16.9.4",
"@types/react-router-dom": "5.1.3",
"@types/react": "^17.0.24",
"@types/react-beautiful-dnd": "^13.1.2",
"@types/react-dom": "^17.0.9",
"@types/react-router-dom": "^5.3.0",
"@types/tape": "^4.13.0",
"@types/ws": "^7.2.4",
"@typescript-eslint/eslint-plugin": "^3.3.0",
@ -262,7 +267,7 @@
"ipfs-mini": "^1.1.5",
"is-electron": "^2.2.0",
"javascript-serialize": "^1.6.1",
"jest": "25.2.3",
"jest": "^27.2.4",
"js-base64": "^2.1.9",
"js-beautify": "1.6.14",
"lerna": "^3.22.1",
@ -289,10 +294,10 @@
"tap-spec": "^5.0.0",
"tape": "^4.13.3",
"terser-webpack-plugin": "^4.2.3",
"ts-jest": "25.2.1",
"ts-jest": "^27.0.5",
"ts-node": "^7.0.1",
"tslint": "~6.0.0",
"typescript": "~3.8.3",
"typescript": "^4.4.3",
"uglify-js": "^2.8.16",
"vm-browserify": "0.0.4",
"watchify": "^3.9.0",

@ -15,6 +15,7 @@ Release managers will oversee the various aspects of a project before it is due
## Quality checks:
The quality of the release needs to be reviewed before a project is officially launched.
The release manager is in charge of ensuring manual testing is properly planned and done.
During the feature freeze time, only the release manager has permission to merge pull requests. As staging should at this point be already deployed, this is to ensure that the release manager has enough visibility on the changes being applied.
Also that unit testing and e2e for new feaures have been included.
## Deployment:

@ -16,14 +16,14 @@
"skipDefaultLibCheck": true,
"baseUrl": ".",
"paths": {
"@remix-project/remix-analyzer": ["dist/libs/remix-analyzer/index.js"],
"@remix-project/remix-astwalker": ["dist/libs/remix-astwalker/index.js"],
"@remix-project/remix-analyzer": ["dist/libs/remix-analyzer/src/index.js"],
"@remix-project/remix-astwalker": ["dist/libs/remix-astwalker/src/index.js"],
"@remix-project/remix-debug": ["dist/libs/remix-debug/src/index.js"],
"@remix-project/remix-lib": ["dist/libs/remix-lib/src/index.js"],
"@remix-project/remix-simulator": ["dist/libs/remix-simulator/src/index.js"],
"@remix-project/remix-solidity": ["dist/libs/remix-solidity/index.js"],
"@remix-project/remix-solidity": ["dist/libs/remix-solidity/src/index.js"],
"@remix-project/remix-tests": ["dist/libs/remix-tests/src/index.js"],
"@remix-project/remix-url-resolver": ["dist/libs/remix-url-resolver/index.js"],
"@remix-project/remix-url-resolver": ["dist/libs/remix-url-resolver/src/index.js"],
"@remixproject/debugger-plugin": ["apps/debugger/src/index.ts"],
"@remixproject/solidity-compiler-plugin": ["apps/solidity-compiler/src/index.ts"],
"@remix-project/remixd": ["dist/libs/remixd/index.js"],

@ -462,7 +462,7 @@
"options": {
"commands": [
{
"command": "SERVE_SCRIPT='chmod +x dist/libs/remixd/bin/remixd.js; dist/libs/remixd/bin/remixd.js '; if [ {args.folder} != undefined ]; then SERVE_SCRIPT=${SERVE_SCRIPT}' -s {args.folder}'; fi; if [ {args.remixide} != undefined ]; then SERVE_SCRIPT=${SERVE_SCRIPT}' --remix-ide {args.remixide}'; fi; eval $SERVE_SCRIPT;"
"command": "SERVE_SCRIPT='chmod +x dist/libs/remixd/src/bin/remixd.js; dist/libs/remixd/src/bin/remixd.js '; if [ {args.folder} != undefined ]; then SERVE_SCRIPT=${SERVE_SCRIPT}' -s {args.folder}'; fi; if [ {args.remixide} != undefined ]; then SERVE_SCRIPT=${SERVE_SCRIPT}' --remix-ide {args.remixide}'; fi; eval $SERVE_SCRIPT;"
}
]
}
@ -945,6 +945,80 @@
}
}
}
},
"remix-ide-e2e-src-local-plugin": {
"root": "apps/remix-ide-e2e/src/local-plugin",
"sourceRoot": "apps/remix-ide-e2e/src/local-plugin/src",
"projectType": "application",
"schematics": {},
"architect": {
"build": {
"builder": "@nrwl/web:build",
"options": {
"outputPath": "dist/apps/remix-ide-e2e/src/local-plugin",
"index": "apps/remix-ide-e2e/src/local-plugin/src/index.html",
"main": "apps/remix-ide-e2e/src/local-plugin/src/main.tsx",
"polyfills": "apps/remix-ide-e2e/src/local-plugin/src/polyfills.ts",
"tsConfig": "apps/remix-ide-e2e/src/local-plugin/tsconfig.app.json",
"assets": [
"apps/remix-ide-e2e/src/local-plugin/src/favicon.ico",
"apps/remix-ide-e2e/src/local-plugin/src/assets"
],
"styles": ["apps/remix-ide-e2e/src/local-plugin/src/styles.css"],
"scripts": [],
"webpackConfig": "@nrwl/react/plugins/webpack"
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "apps/remix-ide-e2e/src/local-plugin/src/environments/environment.ts",
"with": "apps/remix-ide-e2e/src/local-plugin/src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
}
]
}
}
},
"serve": {
"builder": "@nrwl/web:dev-server",
"options": {
"buildTarget": "remix-ide-e2e-src-local-plugin:build",
"port": 2020
},
"configurations": {
"production": {
"buildTarget": "remix-ide-e2e-src-local-plugin:build:production"
}
}
},
"lint": {
"builder": "@nrwl/linter:lint",
"options": {
"linter": "eslint",
"tsConfig": [
"apps/remix-ide-e2e/src/local-plugin/tsconfig.app.json"
],
"exclude": [
"**/node_modules/**",
"!apps/remix-ide-e2e/src/local-plugin/**/*"
]
}
}
}
}
},
"cli": {

Loading…
Cancel
Save