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

pull/4925/head
filip mertens 5 months ago
commit f3913deebd
  1. 8
      .eslintrc.json
  2. 32
      .github/ISSUE_TEMPLATE/bug_report.md
  3. 20
      .github/ISSUE_TEMPLATE/feature_request.md
  4. 2
      .github/workflows/pr-reminder.yml
  5. 1
      README.md
  6. 3
      apps/circuit-compiler/.eslintrc
  7. 8
      apps/circuit-compiler/project.json
  8. 8
      apps/circuit-compiler/src/app/components/container.tsx
  9. 2
      apps/circuit-compiler/src/app/components/feedbackAlert.tsx
  10. 4
      apps/circuit-compiler/src/app/contexts/index.ts
  11. 2
      apps/circuit-compiler/src/app/reducers/state.ts
  12. 34
      apps/circuit-compiler/src/app/services/circomPluginClient.ts
  13. 2
      apps/circuit-compiler/src/app/types/index.ts
  14. 3
      apps/debugger/.eslintrc
  15. 8
      apps/debugger/project.json
  16. 6
      apps/debugger/src/app/debugger.ts
  17. 3
      apps/doc-gen/.eslintrc
  18. 8
      apps/doc-gen/project.json
  19. 6
      apps/doc-gen/src/app/docgen-client.ts
  20. 72
      apps/doc-gen/src/app/docgen/common/properties.ts
  21. 7
      apps/doc-gen/src/app/docgen/templates.ts
  22. 18
      apps/doc-gen/src/app/docgen/utils/memoized-getter.ts
  23. 8
      apps/doc-gen/src/app/docgen/utils/natspec.ts
  24. 2
      apps/doc-gen/src/app/docgen/utils/normalizeContractPath.ts
  25. 3
      apps/doc-viewer/.eslintrc
  26. 8
      apps/doc-viewer/project.json
  27. 3
      apps/etherscan/.eslintrc
  28. 8
      apps/etherscan/project.json
  29. 8
      apps/etherscan/src/app/EtherscanPluginClient.ts
  30. 6
      apps/etherscan/src/app/utils/utilities.ts
  31. 14
      apps/etherscan/src/app/utils/verify.ts
  32. 3
      apps/learneth/.eslintrc
  33. 8
      apps/learneth/project.json
  34. 4
      apps/learneth/src/redux/hooks.ts
  35. 8
      apps/learneth/src/redux/models/loading.ts
  36. 40
      apps/learneth/src/redux/models/remixide.ts
  37. 26
      apps/learneth/src/redux/models/workshop.ts
  38. 6
      apps/learneth/src/redux/store.ts
  39. 8
      apps/learneth/src/remix-client.ts
  40. 2
      apps/remix-ide-e2e/nightwatch-chrome.ts
  41. 2
      apps/remix-ide-e2e/nightwatch-firefox.ts
  42. 2
      apps/remix-ide-e2e/src/commands/addFileSnekmate.ts
  43. 121
      apps/remix-ide-e2e/src/tests/fileExplorer.test.ts
  44. 46
      apps/remix-ide-e2e/src/tests/file_explorer_context_menu.test.ts
  45. 3
      apps/remix-ide-e2e/src/tests/file_explorer_dragdrop.test.ts
  46. 49
      apps/remix-ide-e2e/src/tests/homeTab.test.ts
  47. 79
      apps/remix-ide-e2e/src/tests/layout.test.ts
  48. 319
      apps/remix-ide-e2e/src/tests/remixd.test.ts
  49. 159
      apps/remix-ide-e2e/src/tests/terminal.test.ts
  50. 33
      apps/remix-ide-e2e/src/tests/url.test.ts
  51. 90
      apps/remix-ide-e2e/src/tests/vyper_api.test.ts
  52. 2
      apps/remix-ide-e2e/src/tests/workspace.test.ts
  53. 107
      apps/remix-ide-e2e/src/tests/workspace_git.test.ts
  54. 5
      apps/remix-ide/contracts/ballot.sol
  55. 398
      apps/remix-ide/contracts/foundry/cache/solidity-files-cache.json
  56. 6
      apps/remix-ide/contracts/foundry/foundry.toml
  57. 385
      apps/remix-ide/contracts/foundry/out/Counter.s.sol/CounterScript.json
  58. 377
      apps/remix-ide/contracts/foundry/out/Counter.sol/Counter.json
  59. 1865
      apps/remix-ide/contracts/foundry/out/Counter.t.sol/CounterTest.json
  60. 3729
      apps/remix-ide/contracts/foundry/out/Script.sol/Script.json
  61. 38186
      apps/remix-ide/contracts/foundry/out/Test.sol/Test.json
  62. 37620
      apps/remix-ide/contracts/foundry/out/Test.sol/stdError.json
  63. 37347
      apps/remix-ide/contracts/foundry/out/Test.sol/stdMath.json
  64. 37499
      apps/remix-ide/contracts/foundry/out/Test.sol/stdStorage.json
  65. 10800
      apps/remix-ide/contracts/foundry/out/Vm.sol/Vm.json
  66. 110867
      apps/remix-ide/contracts/foundry/out/console.sol/console.json
  67. 110866
      apps/remix-ide/contracts/foundry/out/console2.sol/console2.json
  68. 23713
      apps/remix-ide/contracts/foundry/out/test.sol/DSTest.json
  69. 14
      apps/remix-ide/contracts/foundry/src/Counter.sol
  70. 43
      apps/remix-ide/src/app.js
  71. 6
      apps/remix-ide/src/app/components/hidden-panel.tsx
  72. 8
      apps/remix-ide/src/app/components/main-panel.tsx
  73. 9
      apps/remix-ide/src/app/components/panel.ts
  74. 91
      apps/remix-ide/src/app/components/pinned-panel.tsx
  75. 19
      apps/remix-ide/src/app/components/preload.tsx
  76. 39
      apps/remix-ide/src/app/components/side-panel.tsx
  77. 105
      apps/remix-ide/src/app/components/status-bar.tsx
  78. 32
      apps/remix-ide/src/app/components/vertical-icons.tsx
  79. 3
      apps/remix-ide/src/app/editor/editor.js
  80. 26
      apps/remix-ide/src/app/files/dgitProvider.ts
  81. 2
      apps/remix-ide/src/app/files/electronProvider.ts
  82. 19
      apps/remix-ide/src/app/files/fileManager.ts
  83. 3
      apps/remix-ide/src/app/files/fileProvider.ts
  84. 1
      apps/remix-ide/src/app/files/fileSystem.ts
  85. 2
      apps/remix-ide/src/app/files/filesystems/fileSystemUtility.ts
  86. 1
      apps/remix-ide/src/app/files/filesystems/indexedDB.ts
  87. 2
      apps/remix-ide/src/app/files/filesystems/localStorage.ts
  88. 7
      apps/remix-ide/src/app/panels/file-panel.js
  89. 24
      apps/remix-ide/src/app/panels/layout.ts
  90. 11
      apps/remix-ide/src/app/panels/tab-proxy.js
  91. 6
      apps/remix-ide/src/app/panels/terminal.tsx
  92. 3
      apps/remix-ide/src/app/plugins/code-format.ts
  93. 1
      apps/remix-ide/src/app/plugins/code-format/parser.ts
  94. 3
      apps/remix-ide/src/app/plugins/compile-details.tsx
  95. 2
      apps/remix-ide/src/app/plugins/config.ts
  96. 14
      apps/remix-ide/src/app/plugins/contractFlattener.tsx
  97. 4
      apps/remix-ide/src/app/plugins/electron/compilerLoaderPlugin.ts
  98. 6
      apps/remix-ide/src/app/plugins/electron/fsPlugin.ts
  99. 4
      apps/remix-ide/src/app/plugins/file-decorator.ts
  100. 10
      apps/remix-ide/src/app/plugins/notification.tsx
  101. Some files were not shown because too many files have changed in this diff Show More

@ -54,7 +54,13 @@
"react-hooks/exhaustive-deps": "off",
"array-callback-return": "off",
"prefer-spread": "off",
"indent": ["error", 2]
"indent": ["error", 2],
"keyword-spacing": ["error", { "after": true, "before": true }],
"array-bracket-spacing": ["error", "never"],
"object-curly-spacing": ["error", "always", { "arraysInObjects": false }],
"no-trailing-spaces": "error",
"no-multi-spaces": "error",
"no-multiple-empty-lines": ["error" , { "max": 1}]
}
},
{

@ -0,0 +1,32 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. Windows, Linux or MacOS]
- Browser [e.g. chrome, firefox]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

@ -14,4 +14,4 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }}
freeze-date: '2024-04-22T18:00:00Z'
freeze-date: '2024-06-17T18:00:00Z'

@ -32,7 +32,6 @@
![Remix screenshot](https://github.com/ethereum/remix-project/raw/master/apps/remix-ide/remix-screenshot-400h.png)
**VSCode extension**, see: [Ethereum-Remix](https://marketplace.visualstudio.com/items?itemName=RemixProject.ethereum-remix)
## Remix libraries
Remix libraries are essential for Remix IDE's native plugins. Read more about libraries [here](libs/README.md)

@ -0,0 +1,3 @@
{
"extends": "../../.eslintrc.json",
}

@ -35,6 +35,14 @@
}
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["apps/circuit-compiler/**/*.ts"],
"eslintConfig": "apps/circuit-compiler/.eslintrc"
}
},
"serve": {
"executor": "@nrwl/webpack:dev-server",
"defaultConfiguration": "development",

@ -53,7 +53,7 @@ export function Container () {
const handleCircuitAutoCompile = (value: boolean) => {
circuitApp.dispatch({ type: 'SET_AUTO_COMPILE', payload: value })
}
const handleCircuitHideWarnings = (value: boolean) => {
circuitApp.dispatch({ type: 'SET_HIDE_WARNINGS', payload: value })
}
@ -73,7 +73,7 @@ export function Container () {
explain why the error occurred and how to fix it.
`
// @ts-ignore
await circuitApp.plugin.call('openaigpt', 'message', message)
await circuitApp.plugin.call('solcoder', 'error_explaining', message)
} else {
const message = `
error message: ${error}
@ -81,7 +81,7 @@ export function Container () {
explain why the error occurred and how to fix it.
`
// @ts-ignore
await circuitApp.plugin.call('openaigpt', 'message', message)
await circuitApp.plugin.call('solcoder', 'error_explaining', message)
}
} else {
const error = report.message
@ -91,7 +91,7 @@ export function Container () {
explain why the error occurred and how to fix it.
`
// @ts-ignore
await circuitApp.plugin.call('openaigpt', 'message', message)
await circuitApp.plugin.call('solcoder', 'error_explaining', message)
}
}

@ -24,7 +24,7 @@ export function FeedbackAlert ({ message, askGPT }: FeedbackAlertProps) {
<span className="border border-success text-success btn-sm" onClick={(e) => {
e.stopPropagation()
askGPT()
}}>ASK GPT</span>
}}>Ask RemixAI</span>
</div>
</>
</RenderIf>

@ -1,4 +1,4 @@
import {createContext} from 'react'
import {ICircuitAppContext} from '../types'
import { createContext } from 'react'
import { ICircuitAppContext } from '../types'
export const CircuitAppContext = createContext<ICircuitAppContext>({} as ICircuitAppContext)

@ -1,4 +1,4 @@
import {Actions, AppState} from '../types'
import { Actions, AppState } from '../types'
import { compiler_list } from 'circom_wasm'
export const appInitialState: AppState = {

@ -10,6 +10,8 @@ import * as compilerV215 from 'circom_wasm/v2.1.5'
import { extractNameFromKey, extractParentFromKey } from '@remix-ui/helper'
import { CompilationConfig, CompilerReport, PrimeValue, ResolverOutput } from '../types'
// @ts-ignore
const _paq = (window._paq = window._paq || [])
export class CircomPluginClient extends PluginClient {
public internalEvents: EventManager
private _compilationConfig: CompilationConfig = {
@ -119,6 +121,7 @@ export class CircomPluginClient extends PluginClient {
} else {
// @ts-ignore
await this.call('editor', 'clearErrorMarkers', [path])
this.emit('statusChanged', { key: 'none' })
}
}
@ -130,6 +133,7 @@ export class CircomPluginClient extends PluginClient {
async compile(path: string, compilationConfig?: CompilationConfig): Promise<void> {
this.internalEvents.emit('circuit_compiling_start')
this.emit('statusChanged', { key: 'loading', title: 'Compiling...', type: 'info' })
// @ts-ignore
this.call('terminal', 'log', { type: 'log', value: 'Compiling ' + path })
const [parseErrors, filePathToId] = await this.parse(path)
@ -145,6 +149,7 @@ export class CircomPluginClient extends PluginClient {
}
} else {
this.internalEvents.emit('circuit_parsing_done', parseErrors, filePathToId)
this.emit('statusChanged', { key: 'succeed', title: 'circuit compiled successfully', type: 'success' })
}
if (compilationConfig) {
const { prime, version } = compilationConfig
@ -159,11 +164,12 @@ export class CircomPluginClient extends PluginClient {
const circuitErrors = circuitApi.report()
this.logCompilerReport(circuitErrors)
_paq.push(['trackEvent', 'circuit-compiler', 'compile', 'Compilation failed'])
throw new Error(circuitErrors)
} else {
this.lastCompiledFile = path
const fileName = extractNameFromKey(path)
this.lastCompiledCircuitPath = extractParentFromKey(path) + "/.bin/" + fileName.replace('circom', 'wasm')
// @ts-ignore
await this.call('fileManager', 'writeFile', this.lastCompiledCircuitPath, circuitProgram, { encoding: null })
@ -178,8 +184,9 @@ export class CircomPluginClient extends PluginClient {
} else {
this.internalEvents.emit('circuit_compiling_done', [])
}
_paq.push(['trackEvent', 'circuit-compiler', 'compile', 'Compilation successful'])
circuitApi.log().map(log => {
log && this.call('terminal', 'log', { type: 'log', value: log })
log && this.call('terminal', 'log', { type: 'log', value: log })
})
// @ts-ignore
this.call('terminal', 'log', { type: 'typewritersuccess', value: 'Everything went okay' })
@ -188,6 +195,7 @@ export class CircomPluginClient extends PluginClient {
async generateR1cs (path: string, compilationConfig?: CompilationConfig): Promise<void> {
this.internalEvents.emit('circuit_generating_r1cs_start')
this.emit('statusChanged', { key: 'loading', title: 'Generating...', type: 'info' })
// @ts-ignore
this.call('terminal', 'log', { type: 'log', value: 'Generating R1CS for ' + path })
const [parseErrors, filePathToId] = await this.parse(path)
@ -203,6 +211,7 @@ export class CircomPluginClient extends PluginClient {
}
} else {
this.internalEvents.emit('circuit_parsing_done', parseErrors, filePathToId)
this.emit('statusChanged', { key: 'succeed', title: 'r1cs generated successfully', type: 'success' })
}
if (compilationConfig) {
const { prime, version } = compilationConfig
@ -217,16 +226,18 @@ export class CircomPluginClient extends PluginClient {
const r1csErrors = r1csApi.report()
this.logCompilerReport(r1csErrors)
_paq.push(['trackEvent', 'circuit-compiler', 'generateR1cs', 'R1CS Generation failed'])
throw new Error(r1csErrors)
} else {
this.internalEvents.emit('circuit_generating_r1cs_done')
const fileName = extractNameFromKey(path)
const writePath = extractParentFromKey(path) + "/.bin/" + fileName.replace('circom', 'r1cs')
// @ts-ignore
await this.call('fileManager', 'writeFile', writePath, r1csProgram, true)
_paq.push(['trackEvent', 'circuit-compiler', 'generateR1cs', 'R1CS Generation successful'])
r1csApi.log().map(log => {
log && this.call('terminal', 'log', { type: 'log', value: log })
log && this.call('terminal', 'log', { type: 'log', value: log })
})
// @ts-ignore
this.call('terminal', 'log', { type: 'typewritersuccess', value: 'Everything went okay' })
@ -235,6 +246,7 @@ export class CircomPluginClient extends PluginClient {
async computeWitness (input: string): Promise<void> {
this.internalEvents.emit('circuit_computing_witness_start')
this.emit('statusChanged', { key: 'loading', title: 'Computing...', type: 'info' })
const wasmPath = this.lastCompiledCircuitPath
if (!wasmPath) throw new Error('No wasm file found')
@ -244,7 +256,9 @@ export class CircomPluginClient extends PluginClient {
const witness = this.compiler ? await this.compiler.generate_witness(dataRead, input) : await generate_witness(dataRead, input)
// @ts-ignore
await this.call('fileManager', 'writeFile', wasmPath.replace('.wasm', '.wtn'), witness, true)
_paq.push(['trackEvent', 'circuit-compiler', 'computeWitness', 'Witness computing successful'])
this.internalEvents.emit('circuit_computing_witness_done')
this.emit('statusChanged', { key: 'succeed', title: 'witness computed successfully', type: 'success' })
}
async resolveDependencies(filePath: string, fileContent: string, output?: Record<string, string>, depPath: string = '', blackPath: string[] = []): Promise<Record<string, string>> {
@ -339,7 +353,7 @@ export class CircomPluginClient extends PluginClient {
absFilePath = include.startsWith('circomlib') ? absFilePath.substring(1) : absFilePath
if (!blackPath.includes(absFilePath)) {
if(!includeName.startsWith('circomlib')) {
if (!includeName.startsWith('circomlib')) {
dependencyContent = dependencyContent.replace(`${includeName}`, `${absFilePath}`)
return absFilePath
}
@ -403,7 +417,13 @@ export class CircomPluginClient extends PluginClient {
async logCompilerReport (report: CompilerReport[]): Promise<void> {
this.call('terminal', 'log', { type: 'log', value: JSON.stringify(report, null, 2) })
if (report[0].type === 'Error') this.call('terminal', 'log', { type: 'error', value: 'previous errors were found' })
if (report[0].type === 'Warning') this.call('terminal', 'log', { type: 'log', value: 'previous warnings were found' })
if (report[0].type === 'Error') {
this.call('terminal', 'log', { type: 'error', value: 'previous errors were found' })
this.emit('statusChanged', { key: report.length, title: `You have ${report.length} problem${report.length === 1 ? '' : 's'}`, type: 'error' })
}
if (report[0].type === 'Warning') {
this.call('terminal', 'log', { type: 'log', value: 'previous warnings were found' })
this.emit('statusChanged', { key: report.length, title: `You have ${report.length} problem${report.length === 1 ? '' : 's'}`, type: 'warning' })
}
}
}

@ -1,5 +1,5 @@
import { compiler_list } from 'circom_wasm'
import {Dispatch} from 'react'
import { Dispatch } from 'react'
import type { CircomPluginClient } from '../services/circomPluginClient'
export type CompilerStatus = "compiling" | "generating" | "computing" | "idle" | "errored" | "warning"

@ -0,0 +1,3 @@
{
"extends": "../../.eslintrc.json",
}

@ -40,6 +40,14 @@
}
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["apps/debugger/**/*.ts"],
"eslintConfig": "apps/debugger/.eslintrc"
}
},
"serve": {
"executor": "@nrwl/webpack:dev-server",
"defaultConfiguration": "development",

@ -1,13 +1,13 @@
import { PluginClient } from "@remixproject/plugin";
import { createClient } from "@remixproject/plugin-webview";
import { IDebuggerApi, LineColumnLocation,
import { IDebuggerApi, LineColumnLocation,
onBreakpointClearedListener, onBreakpointAddedListener, onEditorContentChanged, onEnvChangedListener, TransactionReceipt } from '@remix-ui/debugger-ui'
import { DebuggerApiMixin } from '@remix-ui/debugger-ui'
import { CompilerAbstract } from '@remix-project/remix-solidity'
export class DebuggerClientApi extends DebuggerApiMixin(PluginClient) {
export class DebuggerClientApi extends DebuggerApiMixin(PluginClient) {
constructor () {
super()
super()
createClient(this as any)
this.initDebuggerApi()
}

@ -0,0 +1,3 @@
{
"extends": "../../.eslintrc.json",
}

@ -38,6 +38,14 @@
}
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["apps/doc-gen/**/*.ts"],
"eslintConfig": "apps/doc-gen/.eslintrc"
}
},
"serve": {
"executor": "@nrwl/webpack:dev-server",
"defaultConfiguration": "development",

@ -17,7 +17,7 @@ export class DocGenClient extends PluginClient {
public docs: string[] = []
private fileName: string = ''
private contractPath: string = ''
constructor() {
super()
this.eventEmitter = new EventEmitter()
@ -30,7 +30,7 @@ export class DocGenClient extends PluginClient {
async setListeners() {
this.currentTheme = await this.call('theme', 'currentTheme')
this.on('theme', 'themeChanged', (theme: any) => {
this.currentTheme = theme
this.eventEmitter.emit('themeChanged', this.currentTheme)
@ -50,7 +50,7 @@ export class DocGenClient extends PluginClient {
}
const segmentedPathList = normalizeContractPath(fileName)
this.fileName = segmentedPathList[segmentedPathList.length - 1]
this.contractPath = segmentedPathList[0]
this.contractPath = segmentedPathList[0]
this.eventEmitter.emit('compilationFinished', this.build, this.fileName)
})
}

@ -36,47 +36,47 @@ export function fullName ({ item, contract }: DocItemContext): string {
export function signature ({ item }: DocItemContext): string | undefined {
switch (item.nodeType) {
case 'ContractDefinition':
return undefined;
case 'FunctionDefinition': {
const { kind, name } = item;
const params = item.parameters.parameters;
const returns = item.returnParameters.parameters;
const head = (kind === 'function' || kind === 'freeFunction') ? [kind, name].join(' ') : kind;
const res = [
`${head}(${params.map(formatVariable).join(', ')})`,
item.visibility,
];
if (item.stateMutability !== 'nonpayable') {
res.push(item.stateMutability);
}
if (item.virtual) {
res.push('virtual');
}
if (returns.length > 0) {
res.push(`returns (${returns.map(formatVariable).join(', ')})`);
}
return res.join(' ');
case 'ContractDefinition':
return undefined;
case 'FunctionDefinition': {
const { kind, name } = item;
const params = item.parameters.parameters;
const returns = item.returnParameters.parameters;
const head = (kind === 'function' || kind === 'freeFunction') ? [kind, name].join(' ') : kind;
const res = [
`${head}(${params.map(formatVariable).join(', ')})`,
item.visibility,
];
if (item.stateMutability !== 'nonpayable') {
res.push(item.stateMutability);
}
case 'EventDefinition': {
const params = item.parameters.parameters;
return `event ${item.name}(${params.map(formatVariable).join(', ')})`;
if (item.virtual) {
res.push('virtual');
}
case 'ErrorDefinition': {
const params = item.parameters.parameters;
return `error ${item.name}(${params.map(formatVariable).join(', ')})`;
if (returns.length > 0) {
res.push(`returns (${returns.map(formatVariable).join(', ')})`);
}
return res.join(' ');
}
case 'ModifierDefinition': {
const params = item.parameters.parameters;
return `modifier ${item.name}(${params.map(formatVariable).join(', ')})`;
}
case 'EventDefinition': {
const params = item.parameters.parameters;
return `event ${item.name}(${params.map(formatVariable).join(', ')})`;
}
case 'ErrorDefinition': {
const params = item.parameters.parameters;
return `error ${item.name}(${params.map(formatVariable).join(', ')})`;
}
case 'ModifierDefinition': {
const params = item.parameters.parameters;
return `modifier ${item.name}(${params.map(formatVariable).join(', ')})`;
}
case 'VariableDeclaration':
return formatVariable(item);
case 'VariableDeclaration':
return formatVariable(item);
}
}

@ -3,7 +3,7 @@ import { mapKeys } from './utils/map-keys';
import { DocItemContext } from './site';
import * as defaultProperties from './common/properties';
import * as themeHelpers from './themes/markdown/helpers'
import * as themeHelpers from './themes/markdown/helpers'
const common = require('./themes/markdown/common.hbs');
const contract = require('./themes/markdown/contract.hbs');
@ -45,7 +45,6 @@ export async function loadTemplates(defaultTheme: string, root: string, userTemp
properties: { ...defaultProperties },
};
// Add partials and helpers from all themes, prefixed with the theme name.
for (const [themeName, theme] of Object.entries(themes)) {
const addPrefix = (k: string) => `${themeName}/${k}`;
@ -86,7 +85,7 @@ async function readPartials() {
}
async function readHelpers(name: string) {
const helpers: Record<string, (...args: any[]) => any> = {};
for (const name in themeHelpers) {
@ -94,7 +93,7 @@ async function readHelpers(name: string) {
helpers[name] = themeHelpers[name];
}
}
return helpers;
}

@ -6,17 +6,17 @@ export function defineGetterMemoized<K extends keyof any, T, O extends { [k in K
enumerable: true,
get() {
switch (state) {
case 'done':
return value;
case 'done':
return value;
case 'doing':
throw new Error("Detected recursion");
case 'doing':
throw new Error("Detected recursion");
case 'todo':
state = 'doing';
value = getter();
state = 'done';
return value;
case 'todo':
state = 'doing';
value = getter();
state = 'done';
return value;
}
}
});

@ -34,10 +34,10 @@ export function parseNatspec(item: DocItemWithContext): NatSpec {
const docString = docSource !== undefined
? cleanUpDocstringFromSource(docSource)
: 'documentation' in item && item.documentation
? typeof item.documentation === 'string'
? item.documentation
: cleanUpDocstringFromSolc(item.documentation.text)
: '';
? typeof item.documentation === 'string'
? item.documentation
: cleanUpDocstringFromSolc(item.documentation.text)
: '';
const tagMatches = execAll(
/^(?:@(\w+|custom:[a-z][a-z-]*) )?((?:(?!^@(?:\w+|custom:[a-z][a-z-]*) )[^])*)/m,

@ -4,7 +4,7 @@ export function normalizeContractPath(contractPath: string): string[]{
const filename = paths[paths.length - 1]
let folders = ''
for (let i = 0; i < paths.length - 1; i++) {
if(i !== paths.length -1) {
if (i !== paths.length -1) {
folders += `${paths[i]}/`
}
}

@ -0,0 +1,3 @@
{
"extends": "../../.eslintrc.json",
}

@ -38,6 +38,14 @@
}
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["apps/doc-viewer/**/*.ts"],
"eslintConfig": "apps/doc-viewer/.eslintrc"
}
},
"serve": {
"executor": "@nrwl/webpack:dev-server",
"defaultConfiguration": "development",

@ -0,0 +1,3 @@
{
"extends": "../../.eslintrc.json",
}

@ -38,6 +38,14 @@
}
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["apps/etherscan/**/*.ts"],
"eslintConfig": "apps/etherscan/.eslintrc"
}
},
"serve": {
"executor": "@nrwl/webpack:dev-server",
"defaultConfiguration": "development",

@ -1,7 +1,7 @@
import {PluginClient} from '@remixproject/plugin'
import { PluginClient } from '@remixproject/plugin'
import { createClient } from '@remixproject/plugin-webview'
import {verify, EtherScanReturn} from './utils/verify'
import {getReceiptStatus, getEtherScanApi, getNetworkName, getProxyContractReceiptStatus} from './utils'
import { verify, EtherScanReturn } from './utils/verify'
import { getReceiptStatus, getEtherScanApi, getNetworkName, getProxyContractReceiptStatus } from './utils'
import EventManager from 'events'
export class EtherscanPluginClient extends PluginClient {
@ -46,7 +46,7 @@ export class EtherscanPluginClient extends PluginClient {
async receiptStatus(receiptGuid: string, apiKey: string, isProxyContract: boolean) {
try {
const {network, networkId} = await getNetworkName(this)
const { network, networkId } = await getNetworkName(this)
if (network === 'vm') {
throw new Error('Cannot check the receipt status in the selected network')
}

@ -4,7 +4,7 @@ import { scanAPIurls } from "./networks"
type RemixClient = PluginClient
/*
status: 0=Error, 1=Pass
status: 0=Error, 1=Pass
message: OK, NOTOK
result: explanation
*/
@ -14,7 +14,7 @@ export type receiptStatus = {
status: string
}
export const getEtherScanApi = (networkId: any) => {
export const getEtherScanApi = (networkId: any) => {
if (!(networkId in scanAPIurls)) {
throw new Error("no known network to verify against")
}
@ -26,7 +26,7 @@ export const getNetworkName = async (client: RemixClient) => {
const network = await client.call("network", "detectNetwork")
if (!network) {
throw new Error("no known network to verify against")
}
}
return { network: network.name!.toLowerCase(), networkId: network.id }
}

@ -23,7 +23,7 @@ export const verify = async (
compilationResultParam: CompilerAbstract,
chainRef: number | string,
isProxyContract: boolean,
expectedImplAddress: string,
expectedImplAddress: string,
client: PluginClient,
onVerifiedContract: (value: EtherScanReturn) => void,
setResults: (value: string) => void
@ -47,7 +47,7 @@ export const verify = async (
etherscanApi = getEtherScanApi(networkChainId)
}
}
try {
const contractMetadata = getContractMetadata(
// cast from the remix-plugin interface to the solidity one. Should be fixed when remix-plugin move to the remix-project repository
@ -61,7 +61,7 @@ export const verify = async (
message: "Please recompile contract"
}
}
const contractMetadataParsed = JSON.parse(contractMetadata)
const fileName = getContractFileName(
@ -146,9 +146,9 @@ export const verify = async (
title: result,
})
const returnValue = {
message: result,
succeed: false,
isProxyContract
message: result,
succeed: false,
isProxyContract
}
resetAfter10Seconds(client, setResults)
return returnValue
@ -184,7 +184,7 @@ export const getContractFileName = (
}
return fileName
}
export const getContractMetadata = (
compilationResult: CompilationResult,
contractName: string

@ -0,0 +1,3 @@
{
"extends": "../../.eslintrc.json",
}

@ -35,6 +35,14 @@
}
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["apps/learneth/**/*.ts"],
"eslintConfig": "apps/learneth/.eslintrc"
}
},
"serve": {
"executor": "@nrwl/webpack:dev-server",
"defaultConfiguration": "development",

@ -1,5 +1,5 @@
import {useDispatch, type TypedUseSelectorHook, useSelector} from 'react-redux'
import {type AppDispatch, type RootState} from './store'
import { useDispatch, type TypedUseSelectorHook, useSelector } from 'react-redux'
import { type AppDispatch, type RootState } from './store'
export const useAppDispatch: () => AppDispatch = useDispatch
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector

@ -1,11 +1,11 @@
import {type ModelType} from '../store'
import { type ModelType } from '../store'
const Model: ModelType = {
namespace: 'loading',
state: {screen: true},
state: { screen: true },
reducers: {
save(state, {payload}) {
return {...state, ...payload}
save(state, { payload }) {
return { ...state, ...payload }
},
},
effects: {},

@ -1,7 +1,7 @@
import {toast} from 'react-toastify'
import {type ModelType} from '../store'
import { toast } from 'react-toastify'
import { type ModelType } from '../store'
import remixClient from '../../remix-client'
import {router} from '../../App'
import { router } from '../../App'
function getFilePath(file: string): string {
const name = file.split('/')
@ -17,12 +17,12 @@ const Model: ModelType = {
// theme: '',
},
reducers: {
save(state, {payload}) {
return {...state, ...payload}
save(state, { payload }) {
return { ...state, ...payload }
},
},
effects: {
*connect(_, {put}) {
*connect(_, { put }) {
toast.info('connecting to the REMIX IDE')
yield put({
@ -45,7 +45,7 @@ const Model: ModelType = {
yield router.navigate('/home')
},
*displayFile({payload: step}, {select, put}) {
*displayFile({ payload: step }, { select, put }) {
let content = ''
let path = ''
if (step.solidity?.file) {
@ -73,7 +73,7 @@ const Model: ModelType = {
},
})
const {detail, selectedId} = yield select((state) => state.workshop)
const { detail, selectedId } = yield select((state) => state.workshop)
const workshop = detail[selectedId]
console.log('loading ', step, workshop)
@ -87,7 +87,7 @@ const Model: ModelType = {
yield remixClient.call('fileManager', 'switchFile', `${path}`)
yield put({
type: 'remixide/save',
payload: {errorLoadingFile: false},
payload: { errorLoadingFile: false },
})
toast.dismiss()
} catch (error) {
@ -95,7 +95,7 @@ const Model: ModelType = {
toast.error('File could not be loaded. Please try again.')
yield put({
type: 'remixide/save',
payload: {errorLoadingFile: true},
payload: { errorLoadingFile: true },
})
}
yield put({
@ -105,7 +105,7 @@ const Model: ModelType = {
},
})
},
*testStep({payload: step}, {select, put}) {
*testStep({ payload: step }, { select, put }) {
yield put({
type: 'loading/save',
payload: {
@ -116,9 +116,9 @@ const Model: ModelType = {
try {
yield put({
type: 'remixide/save',
payload: {success: false},
payload: { success: false },
})
const {detail, selectedId} = yield select((state) => state.workshop)
const { detail, selectedId } = yield select((state) => state.workshop)
const workshop = detail[selectedId]
@ -141,7 +141,7 @@ const Model: ModelType = {
if (!result) {
yield put({
type: 'remixide/save',
payload: {errors: ['Compiler failed to test this file']},
payload: { errors: ['Compiler failed to test this file']},
})
} else {
const success = result.totalFailing === 0
@ -149,7 +149,7 @@ const Model: ModelType = {
if (success) {
yield put({
type: 'remixide/save',
payload: {errors: [], success: true},
payload: { errors: [], success: true },
})
} else {
yield put({
@ -164,7 +164,7 @@ const Model: ModelType = {
console.log('TESTING ERROR', err)
yield put({
type: 'remixide/save',
payload: {errors: [String(err)]},
payload: { errors: [String(err)]},
})
}
yield put({
@ -174,7 +174,7 @@ const Model: ModelType = {
},
})
},
*showAnswer({payload: step}, {select, put}) {
*showAnswer({ payload: step }, { select, put }) {
yield put({
type: 'loading/save',
payload: {
@ -189,7 +189,7 @@ const Model: ModelType = {
const content = step.answer.content
let path = getFilePath(step.answer.file)
const {detail, selectedId} = yield select((state) => state.workshop)
const { detail, selectedId } = yield select((state) => state.workshop)
const workshop = detail[selectedId]
path = `.learneth/${workshop.name}/${step.name}/${path}`
@ -198,7 +198,7 @@ const Model: ModelType = {
} catch (err) {
yield put({
type: 'remixide/save',
payload: {errors: [String(err)]},
payload: { errors: [String(err)]},
})
}
@ -210,7 +210,7 @@ const Model: ModelType = {
},
})
},
*testSolidityCompiler(_, {put, select}) {
*testSolidityCompiler(_, { put, select }) {
try {
yield remixClient.call('solidity', 'getCompilationResult')
} catch (err) {

@ -1,10 +1,10 @@
import axios from 'axios'
import {toast} from 'react-toastify'
import { toast } from 'react-toastify'
import groupBy from 'lodash/groupBy'
import pick from 'lodash/pick'
import {type ModelType} from '../store'
import { type ModelType } from '../store'
import remixClient from '../../remix-client'
import {router} from '../../App'
import { router } from '../../App'
// const apiUrl = 'http://localhost:3001';
const apiUrl = 'https://static.220.14.12.49.clients.your-server.de:3000'
@ -17,12 +17,12 @@ const Model: ModelType = {
selectedId: '',
},
reducers: {
save(state, {payload}) {
return {...state, ...payload}
save(state, { payload }) {
return { ...state, ...payload }
},
},
effects: {
*init(_, {put}) {
*init(_, { put }) {
const cache = localStorage.getItem('workshop.state')
if (cache) {
@ -41,7 +41,7 @@ const Model: ModelType = {
})
}
},
*loadRepo({payload}, {put, select}) {
*loadRepo({ payload }, { put, select }) {
toast.info(`loading ${payload.name}/${payload.branch}`)
yield put({
@ -51,18 +51,18 @@ const Model: ModelType = {
},
})
const {list, detail} = yield select((state) => state.workshop)
const { list, detail } = yield select((state) => state.workshop)
const url = `${apiUrl}/clone/${encodeURIComponent(payload.name)}/${payload.branch}?${Math.random()}`
console.log('loading ', url)
const {data} = yield axios.get(url)
const { data } = yield axios.get(url)
const repoId = `${payload.name}-${payload.branch}`
for (let i = 0; i < data.ids.length; i++) {
const {
steps,
metadata: {
data: {steps: metadataSteps},
data: { steps: metadataSteps },
},
} = data.entities[data.ids[i]]
@ -130,8 +130,8 @@ const Model: ModelType = {
})
if (payload.id) {
const {detail, selectedId} = workshopState
const {ids, entities} = detail[selectedId]
const { detail, selectedId } = workshopState
const { ids, entities } = detail[selectedId]
for (let i = 0; i < ids.length; i++) {
const entity = entities[ids[i]]
if (entity.metadata.data.id === payload.id || i + 1 === payload.id) {
@ -141,7 +141,7 @@ const Model: ModelType = {
}
}
},
*resetAll(_, {put}) {
*resetAll(_, { put }) {
yield put({
type: 'workshop/save',
payload: {

@ -1,6 +1,6 @@
import {configureStore, createSlice, type PayloadAction, type Reducer} from '@reduxjs/toolkit'
import { configureStore, createSlice, type PayloadAction, type Reducer } from '@reduxjs/toolkit'
import createSagaMiddleware from 'redux-saga'
import {call, put, takeEvery, delay, select, all, fork, type ForkEffect} from 'redux-saga/effects'
import { call, put, takeEvery, delay, select, all, fork, type ForkEffect } from 'redux-saga/effects'
// @ts-expect-error
const context = require.context('./models', false, /\.ts$/)
@ -39,7 +39,7 @@ function createReducer(model: ModelType): Reducer {
}
const rootReducer = models.reduce((prev: any, model: ModelType) => {
return {...prev, [model.namespace]: createReducer(model)}
return { ...prev, [model.namespace]: createReducer(model) }
}, {})
function watchEffects(model: ModelType): ForkEffect {

@ -1,7 +1,7 @@
import {PluginClient} from '@remixproject/plugin'
import {createClient} from '@remixproject/plugin-webview'
import {store} from './redux/store'
import {router} from './App'
import { PluginClient } from '@remixproject/plugin'
import { createClient } from '@remixproject/plugin-webview'
import { store } from './redux/store'
import { router } from './App'
class RemixClient extends PluginClient {
constructor() {

@ -21,7 +21,7 @@ module.exports = {
'default': {
globals: {
waitForConditionTimeout: 10000,
asyncHookTimeout: 100000
asyncHookTimeout: 10000000
},
screenshots: {
enabled: true,

@ -18,7 +18,7 @@ module.exports = {
'default': {
globals: {
waitForConditionTimeout: 10000,
asyncHookTimeout: 100000
asyncHookTimeout: 10000000
},
screenshots: {
enabled: true,

@ -60,7 +60,7 @@ function addFileSnekmate(browser: NightwatchBrowser, name: string, content: Nigh
})
.setEditorValue(content.content)
.getEditorValue((result) => {
if(result != content.content) {
if (result != content.content) {
browser.setEditorValue(content.content)
}
})

@ -117,69 +117,68 @@ module.exports = {
'Should add deep tree with buttons #group3': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('div[data-id="remixIdeSidePanel"]')
.clickLaunchIcon('filePanel')
.waitForElementVisible('*[data-id="filePanelFileExplorerTree"]')
.waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFolder"]')
.click('[data-id="fileExplorerNewFilecreateNewFolder"]')
.waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep1')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemdeep1"]')
.waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFolder"]')
.click('[data-id="fileExplorerNewFilecreateNewFolder"]')
.waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep2')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemdeep1/deep2"]')
.waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFolder"]')
.click('[data-id="fileExplorerNewFilecreateNewFolder"]')
.waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep3')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemdeep1/deep2/deep3"]')
.waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFile"]')
.click('[data-id="fileExplorerNewFilecreateNewFile"]')
.waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep4.sol')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemdeep1/deep2/deep3/deep4.sol"]')
.waitForElementVisible('div[data-id="remixIdeSidePanel"]')
.clickLaunchIcon('filePanel')
.waitForElementVisible('*[data-id="filePanelFileExplorerTree"]')
.waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFolder"]')
.click('[data-id="fileExplorerNewFilecreateNewFolder"]')
.waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep1')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemdeep1"]')
.waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFolder"]')
.click('[data-id="fileExplorerNewFilecreateNewFolder"]')
.waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep2')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemdeep1/deep2"]')
.waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFolder"]')
.click('[data-id="fileExplorerNewFilecreateNewFolder"]')
.waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep3')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemdeep1/deep2/deep3"]')
.waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFile"]')
.click('[data-id="fileExplorerNewFilecreateNewFile"]')
.waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep4.sol')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemdeep1/deep2/deep3/deep4.sol"]')
// click on root to focus
.click('li[data-id="treeViewLitreeViewItemREADME.txt"]')
.waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFolder"]')
.click('[data-id="fileExplorerNewFilecreateNewFolder"]')
.waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep5')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemdeep5"]')
.waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFolder"]')
.click('[data-id="fileExplorerNewFilecreateNewFolder"]')
.waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep6')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemdeep5/deep6"]')
.click('li[data-id="treeViewLitreeViewItemREADME.txt"]')
.waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFolder"]')
.click('[data-id="fileExplorerNewFilecreateNewFolder"]')
.waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep5')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemdeep5"]')
.waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFolder"]')
.click('[data-id="fileExplorerNewFilecreateNewFolder"]')
.waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep6')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemdeep5/deep6"]')
// focus on contracts
.click('li[data-id="treeViewLitreeViewItemcontracts"]')
.waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFolder"]')
.click('[data-id="fileExplorerNewFilecreateNewFolder"]')
.waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep7')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/deep7"]')
.waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFolder"]')
.click('[data-id="fileExplorerNewFilecreateNewFolder"]')
.waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep8')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/deep7/deep8"]')
.waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFile"]')
.click('[data-id="fileExplorerNewFilecreateNewFile"]')
.waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep9.sol')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/deep7/deep8/deep9.sol"]')
.end()
.click('li[data-id="treeViewLitreeViewItemcontracts"]')
.waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFolder"]')
.click('[data-id="fileExplorerNewFilecreateNewFolder"]')
.waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep7')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/deep7"]')
.waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFolder"]')
.click('[data-id="fileExplorerNewFilecreateNewFolder"]')
.waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep8')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/deep7/deep8"]')
.waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFile"]')
.click('[data-id="fileExplorerNewFilecreateNewFile"]')
.waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep9.sol')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/deep7/deep8/deep9.sol"]')
.end()
}
}

@ -90,7 +90,7 @@ module.exports = {
.rightClick('li[data-id="treeViewLitreeViewItemREADME.txt"]')
.waitForElementPresent('[data-id="contextMenuItemcopy')
.click('[data-id="contextMenuItemcopy"]')
.rightClick('*[data-id="treeViewLiMenu"]')
.rightClick('*[data-id="treeViewUltreeViewMenu"]')
.saveScreenshot('./reports/screenshot/file_explorer_context_menu.png')
.click('*[data-id="contextMenuItempaste"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemCopy_README.txt"]', 7000)
@ -105,25 +105,25 @@ module.exports = {
.click('*[data-id="contextMenuItempaste"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/Copy_README.txt"]', 7000)
},
// folder copy paste tests
'Should copy folder and paste in root with right click and it will contain a copied folder #group1 ': function (browser: NightwatchBrowser) {
browser
.rightClick('li[data-id="treeViewLitreeViewItemcontracts"]')
.waitForElementPresent('[data-id="contextMenuItemcopy')
.click('[data-id="contextMenuItemcopy"]')
.rightClick('*[data-id="treeViewLiMenu"]')
.click('*[data-id="contextMenuItempaste"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemCopy_contracts"]', 7000)
},
'Should copy folder and paste in contracts with right click and it will contain a copied folder #group1 ': function (browser: NightwatchBrowser) {
browser
.pause(1000)
.waitForElementVisible('li[data-id="treeViewLitreeViewItemscripts"]')
.rightClick('li[data-id="treeViewLitreeViewItemscripts"]')
.waitForElementPresent('[data-id="contextMenuItemcopy')
.click('[data-id="contextMenuItemcopy"]')
.rightClick('*[data-id="treeViewLitreeViewItemcontracts"]')
.click('*[data-id="contextMenuItempaste"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/Copy_scripts"]', 7000)
}
}
// folder copy paste tests
'Should copy folder and paste in root with right click and it will contain a copied folder #group1 ': function (browser: NightwatchBrowser) {
browser
.rightClick('li[data-id="treeViewLitreeViewItemcontracts"]')
.waitForElementPresent('[data-id="contextMenuItemcopy')
.click('[data-id="contextMenuItemcopy"]')
.rightClick('*[data-id="treeViewUltreeViewMenu"]')
.click('*[data-id="contextMenuItempaste"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemCopy_contracts"]', 7000)
},
'Should copy folder and paste in contracts with right click and it will contain a copied folder #group1 ': function (browser: NightwatchBrowser) {
browser
.pause(1000)
.waitForElementVisible('li[data-id="treeViewLitreeViewItemscripts"]')
.rightClick('li[data-id="treeViewLitreeViewItemscripts"]')
.waitForElementPresent('[data-id="contextMenuItemcopy')
.click('[data-id="contextMenuItemcopy"]')
.rightClick('*[data-id="treeViewLitreeViewItemcontracts"]')
.click('*[data-id="contextMenuItempaste"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/Copy_scripts"]', 7000)
}
}

@ -6,7 +6,6 @@ const checkBrowserIsChrome = function (browser: NightwatchBrowser) {
return browser.browserName.indexOf('chrome') > -1
}
module.exports = {
'@disabled': true,
before: function (browser: NightwatchBrowser, done: VoidFunction) {
@ -98,6 +97,4 @@ module.exports = {
}
}
}

@ -3,15 +3,52 @@ import { NightwatchBrowser } from 'nightwatch'
import init from '../helpers/init'
module.exports = {
'@disabled': true,
before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done)
},
'Should start coding': function (browser: NightwatchBrowser) {
'Should start coding #group1': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('*[data-id="homeTabGetStartedremixDefault"]')
.click('*[data-id="homeTabGetStartedremixDefault"]')
.waitForElementVisible('*[data-id="treeViewDivtreeViewItemcontracts/1_Storage.sol"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/2_Owner.sol"')
.waitForElementVisible('*[data-id="treeViewDivDraggableItemREADME.txt"')
.click('*[data-id="treeViewDivtreeViewItemcontracts/1_Storage.sol"]')
.waitForElementPresent({
selector: "//div[contains(@class, 'view-line') and contains(.//span, 'pragma')]",
locateStrategy: 'xpath'
})
.getEditorValue((editorContent) => {
browser.assert.ok(editorContent.indexOf(`pragma solidity`) !== -1, 'unexpected content encountered!')
})
},
'Should start with ERC20 workspace #group1': function (browser: NightwatchBrowser) {
browser
.click('*[data-path="home"')
.waitForElementVisible('*[data-id="homeTabGetStartedERC20"]')
.click('*[data-id="homeTabGetStartedERC20"')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/MyToken.sol"]')
.waitForElementVisible('*[data-id="treeViewDivtreeViewItemtests/MyToken_test.sol"]')
.click('*[data-id="treeViewDivtreeViewItemtests/MyToken_test.sol"]')
.waitForElementPresent({
selector: "//div[contains(@class, 'view-line') and contains(.//span, 'pragma')]",
locateStrategy: 'xpath'
})
.getEditorValue((editorContent) => {
browser.assert.ok(editorContent.indexOf(`import "../contracts/MyToken.sol";`) !== -1, 'content encountered!')
})
},
'Should create a new file in the current workspace': '' +function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('*[data-id="homeTabStartCoding"]')
.click('*[data-id="homeTabStartCoding"]')
.waitForElementVisible('div[data-id="treeViewDivtreeViewItemcontracts/HelloWorld.sol"]')
.click('*[data-path="home"]')
.waitForElementVisible('*[data-id="homeTabNewFile"]')
.click('*[data-id="homeTabNewFile"]')
.waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'HometabNewFile.txt')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemHometabNewFile.txt"]', 7000)
}
}
}

@ -0,0 +1,79 @@
'use strict'
import { NightwatchBrowser } from 'nightwatch'
import init from '../helpers/init'
module.exports = {
before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done)
},
'@sources': function () {
return sources
},
'Should pin solidity compiler plugin to the right and switch focus for left side panel to the file-explorer': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('[data-id="movePluginToRight"]')
.click('[data-id="movePluginToRight"]')
.waitForElementVisible('[data-id="movePluginToLeft"]')
.waitForElementVisible('.pinned-panel h6[data-id="sidePanelSwapitTitle"]')
.assert.containsText('.sidepanel h6[data-id="sidePanelSwapitTitle"]', 'FILE EXPLORER')
.assert.containsText('.pinned-panel h6[data-id="sidePanelSwapitTitle"]', 'SOLIDITY COMPILER')
},
'Should unpin and focus on solidity compiler in the left side panel': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('[data-id="movePluginToLeft"]')
.click('[data-id="movePluginToLeft"]')
.waitForElementVisible('[data-id="movePluginToRight"]')
.assert.containsText('.sidepanel h6[data-id="sidePanelSwapitTitle"]', 'SOLIDITY COMPILER')
.waitForElementNotVisible('.pinned-panel h6[data-id="sidePanelSwapitTitle"]')
},
'Should pin a plugin while a another plugin is already pinned': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('[data-id="movePluginToRight"]')
.click('[data-id="movePluginToRight"]')
.waitForElementVisible('[data-id="movePluginToLeft"]')
.waitForElementVisible('.pinned-panel h6[data-id="sidePanelSwapitTitle"]')
.assert.containsText('.pinned-panel h6[data-id="sidePanelSwapitTitle"]', 'SOLIDITY COMPILER')
.clickLaunchIcon('udapp')
.click('[data-id="movePluginToRight"]')
.waitForElementVisible('[data-id="movePluginToLeft"]')
.assert.containsText('.pinned-panel h6[data-id="sidePanelSwapitTitle"]', 'DEPLOY & RUN TRANSACTIONS')
.assert.containsText('.sidepanel h6[data-id="sidePanelSwapitTitle"]', 'SOLIDITY COMPILER')
},
'Should pin a pinned plugin to the right after reloading the page': function (browser: NightwatchBrowser) {
browser.refreshPage()
.waitForElementVisible('.pinned-panel h6[data-id="sidePanelSwapitTitle"]')
.assert.containsText('.pinned-panel h6[data-id="sidePanelSwapitTitle"]', 'DEPLOY & RUN TRANSACTIONS')
},
'Should maintain logged state of udapp plugin after pinning and unpinning': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts"]')
.click('*[data-id="treeViewLitreeViewItemcontracts"]')
.openFile('contracts/1_Storage.sol')
.pause(5000)
.waitForElementPresent('*[data-id="Deploy - transact (not payable)"]')
.click('*[data-id="Deploy - transact (not payable)"]')
.waitForElementPresent('#instance0xd9145CCE52D386f254917e481eB44e9943F39138')
.clickInstance(0)
.clickFunction('store - transact (not payable)', { types: 'uint256 num', values: '10' })
.clickFunction('retrieve - call')
.click('[data-id="movePluginToLeft"]')
.waitForElementVisible('[data-id="movePluginToRight"]')
.clickInstance(0)
.waitForElementContainsText('[data-id="treeViewLi0"]', 'uint256: 10')
},
'Should maintain logged state of search plugin after pinning and unpinning': function (browser: NightwatchBrowser) {
browser.clickLaunchIcon('search')
.waitForElementVisible('*[id="search_input"]')
.waitForElementVisible('*[id="search_include"]')
.setValue('*[id="search_include"]', ', *.*').pause(2000)
.setValue('*[id="search_input"]', 'read').sendKeys('*[id="search_input"]', browser.Keys.ENTER)
.pause(1000)
.waitForElementContainsText('*[data-id="search_results"]', '3_BALLOT.SOL', 60000)
.waitForElementContainsText('*[data-id="search_results"]', 'contracts', 60000)
.waitForElementContainsText('*[data-id="search_results"]', 'README.TXT', 60000)
.click('[data-id="movePluginToRight"]')
.waitForElementContainsText('*[data-id="search_results"]', '3_BALLOT.SOL')
.waitForElementContainsText('*[data-id="search_results"]', 'contracts')
.waitForElementContainsText('*[data-id="search_results"]', 'README.TXT')
}
}
const sources = []

@ -3,13 +3,8 @@ import { NightwatchBrowser } from 'nightwatch'
import init from '../helpers/init'
import { join } from 'path'
import { ChildProcess, spawn } from 'child_process'
import { writeFileSync } from 'fs'
import * as hardhatCompilation from '../helpers/hardhat_compilation_7839ba878952cc00ff316061405f273a.json'
import * as hardhat_compilation_Lock_dbg from '../helpers/hardhat_compilation_Lock.dbg.json'
import * as hardhat_compilation_Lock from '../helpers/hardhat_compilation_Lock.json'
import { homedir } from 'os'
import * as foundryCompilation from '../helpers/foundry_compilation.json'
import * as truffle_compilation from '../helpers/truffle_compilation.json'
import kill from 'tree-kill'
let remixd: ChildProcess
@ -71,9 +66,13 @@ module.exports = {
'@sources': function () {
return sources
},
'run Remixd tests #group4': function (browser) {
'run Remixd tests #group1': function (browser) {
browser.perform(async (done) => {
remixd = await spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts'))
try {
remixd = await spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts'))
} catch (err) {
console.error(err)
}
console.log('working directory', process.cwd())
connectRemixd(browser, done)
})
@ -81,10 +80,10 @@ module.exports = {
runTests(browser, done)
})
},
'Import from node_modules #group1': function (browser) {
'Import from node_modules #group2': function (browser) {
/*
when a relative import is used (i.e import "openzeppelin-solidity/contracts/math/SafeMath.sol")
remix (as well as truffle) try to resolve it against the node_modules and installed_contracts folder.
remix try to resolve it against the node_modules and installed_contracts folder.
*/
browser.perform(async (done) => {
remixd = await spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts'))
@ -96,7 +95,7 @@ module.exports = {
.setSolidityCompilerVersion('soljson-v0.5.0+commit.1d4f565a.js')
.testContracts('test_import_node_modules.sol', sources[3]['test_import_node_modules.sol'], ['SafeMath'])
},
'Import from node_modules and reference a github import #group2': function (browser) {
'Import from node_modules and reference a github import #group3': function (browser) {
browser.perform(async (done) => {
remixd = await spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts'))
console.log('working directory', process.cwd())
@ -107,102 +106,93 @@ module.exports = {
.setSolidityCompilerVersion('soljson-v0.8.20+commit.a1b79de6.js') // open-zeppelin moved to pragma ^0.8.20
.testContracts('test_import_node_modules_with_github_import.sol', sources[4]['test_import_node_modules_with_github_import.sol'], ['ERC20', 'test11'])
},
'Static Analysis run with remixd #group3': '' + function (browser) {
browser.testContracts('test_static_analysis_with_remixd_and_hardhat.sol', sources[5]['test_static_analysis_with_remixd_and_hardhat.sol'], ['test5']).pause(2000)
.clickLaunchIcon('solidityStaticAnalysis')
/*
.click('#staticanalysisButton button').pause(4000)
.waitForElementPresent('#staticanalysisresult .warning', 2000, true, function () {
browser
.waitForElementVisible('[data-id="staticAnalysisModuleMiscellaneous1Button"]')
.click('[data-id="staticAnalysisModuleMiscellaneous1Button"]')
.waitForElementVisible('.highlightLine16', 60000)
.getEditorValue((content) => {
browser.assert.ok(content.indexOf(
'function _sendLogPayload(bytes memory payload) private view {') !== -1,
'code has not been loaded')
})
'Should setup a hardhat project #group4': function (browser: NightwatchBrowser) {
browser.perform(async (done) => {
await setupHardhatProject()
done()
})
*/
},
'Run git status': '' + function (browser) {
browser
.executeScriptInTerminal('git status')
.pause(3000)
.journalLastChildIncludes('On branch ')
},
'Close Remixd #group3': '' + function (browser) {
browser
.clickLaunchIcon('pluginManager')
.scrollAndClick('#pluginManager *[data-id="pluginManagerComponentDeactivateButtonremixd"]')
},
'Should listen on compilation result from hardhat #group5': function (browser: NightwatchBrowser) {
'Should listen on compilation result from hardhat #group4': function (browser: NightwatchBrowser) {
browser.perform(async (done) => {
remixd = await spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts/hardhat'))
remixd = await spawnRemixd(join(process.cwd(), '/apps/remix-ide/hardhat-boilerplate'))
console.log('working directory', process.cwd())
connectRemixd(browser, done)
})
.perform((done) => {
.perform(async (done) => {
console.log('generating compilation result')
writeFileSync('./apps/remix-ide/contracts/hardhat/artifacts/build-info/7839ba878952cc00ff316061405f273a.json', JSON.stringify(hardhatCompilation))
writeFileSync('./apps/remix-ide/contracts/hardhat/artifacts/contracts/Lock.sol/Lock.json', JSON.stringify(hardhat_compilation_Lock))
writeFileSync('./apps/remix-ide/contracts/hardhat/artifacts/contracts/Lock.sol/Lock.dbg.json', JSON.stringify(hardhat_compilation_Lock_dbg))
await compileHardhatProject()
done()
})
.expect.element('*[data-id="terminalJournal"]').text.to.contain('receiving compilation result from Hardhat').before(60000)
let addressRef
browser.clickLaunchIcon('filePanel')
.openFile('contracts')
.openFile('contracts/Lock.sol')
.openFile('contracts/Token.sol')
.clickLaunchIcon('udapp')
.selectContract('Lock')
.createContract('1')
.expect.element('*[data-id="terminalJournal"]').text.to.contain('Unlock time should be in the future').before(60000)
.selectAccount('0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c')
.selectContract('Token')
.createContract('')
.clickInstance(0)
.clickFunction('balanceOf - call', { types: 'address account', values: '0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c' })
.getAddressAtPosition(0, (address) => {
addressRef = address
})
.perform((done) => {
browser.verifyCallReturnValue(addressRef, ['0:uint256: 1000000'])
.perform(() => done())
})
},
'Should load compilation result from hardhat when remixd connects #group6': function (browser: NightwatchBrowser) {
// artifacts/build-info/c7062fdd360381a85af23eeef31c98f8.json has already been created
'Should load compilation result from hardhat when remixd connects #group4': function (browser: NightwatchBrowser) {
let addressRef
browser
.perform((done) => {
writeFileSync('./apps/remix-ide/contracts/hardhat/artifacts/contracts/Lock.sol/Lock.dbg.json', JSON.stringify(hardhat_compilation_Lock_dbg))
writeFileSync('./apps/remix-ide/contracts/hardhat/artifacts/contracts/Lock.sol/Lock.json', JSON.stringify(hardhat_compilation_Lock))
writeFileSync('./apps/remix-ide/contracts/hardhat/artifacts/build-info/7839ba878952cc00ff316061405f273a.json', JSON.stringify(hardhatCompilation))
done()
})
.refresh()
.perform(async (done) => {
remixd = await spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts/hardhat'))
console.log('working directory', process.cwd())
connectRemixd(browser, done)
})
.expect.element('*[data-id="terminalJournal"]').text.to.contain('receiving compilation result from Hardhat').before(60000)
browser.clickLaunchIcon('filePanel')
browser.clickLaunchIcon('filePanel')
.openFile('contracts')
.openFile('contracts/Lock.sol')
.openFile('contracts/Token.sol')
.clickLaunchIcon('udapp')
.selectContract('Lock')
.createContract('1')
.expect.element('*[data-id="terminalJournal"]').text.to.contain('Unlock time should be in the future').before(60000)
.selectAccount('0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c')
.selectContract('Token')
.createContract('')
.clickInstance(0)
.clickFunction('balanceOf - call', { types: 'address account', values: '0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c' })
.getAddressAtPosition(0, (address) => {
addressRef = address
})
.perform((done) => {
browser.verifyCallReturnValue(addressRef, ['0:uint256: 1000000'])
.perform(() => done())
})
},
'Should install foundry #group5': function (browser: NightwatchBrowser) {
browser.perform(async (done) => {
await downloadFoundry()
await installFoundry()
await initFoundryProject()
done()
})
},
'Should listen on compilation result from foundry #group7': function (browser: NightwatchBrowser) {
'Should listen on compilation result from foundry #group5': function (browser: NightwatchBrowser) {
browser.perform(async (done) => {
remixd = await spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts/foundry'))
console.log('working directory', process.cwd())
console.log('working directory', homedir() + '/foundry_tmp/hello_foundry')
remixd = await spawnRemixd(join(homedir(), '/foundry_tmp/hello_foundry'))
connectRemixd(browser, done)
})
.perform((done) => {
writeFileSync('./apps/remix-ide/contracts/foundry/out/Counter.sol/Counter.json', JSON.stringify(foundryCompilation))
.perform(async (done) => {
await buildFoundryProject()
done()
})
.expect.element('*[data-id="terminalJournal"]').text.to.contain('receiving compilation result from Foundry').before(60000)
@ -225,36 +215,35 @@ module.exports = {
done()
})
})
},
'Should listen on compilation result from truffle #group8': function (browser: NightwatchBrowser) {
'Should load compilation result from hardhat when remixd connects #group5': function (browser: NightwatchBrowser) {
browser.perform(async (done) => {
remixd = await spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts/truffle'))
console.log('working directory', process.cwd())
browser.refresh().perform(async (done) => {
console.log('working directory', homedir() + '/foundry_tmp/hello_foundry')
connectRemixd(browser, done)
})
.perform((done) => {
writeFileSync('./apps/remix-ide/contracts/truffle/build/contracts/Migrations.json', JSON.stringify(truffle_compilation))
done()
})
.expect.element('*[data-id="terminalJournal"]').text.to.contain('receiving compilation result from Truffle').before(60000)
.expect.element('*[data-id="terminalJournal"]').text.to.contain('receiving compilation result from Foundry').before(60000)
let contractAaddress
browser.clickLaunchIcon('filePanel')
.openFile('contracts')
.openFile('contracts/Migrations.sol')
.openFile('src')
.openFile('src/Counter.sol')
.clickLaunchIcon('udapp')
.selectContract('Migrations')
.selectContract('Counter')
.createContract('')
.testFunction('last',
{
status: '0x1 Transaction mined and execution succeed'
.getAddressAtPosition(0, (address) => {
console.log(contractAaddress)
contractAaddress = address
})
.clickInstance(0)
.clickFunction('increment - transact (not payable)')
.perform((done) => {
browser.testConstantFunction(contractAaddress, 'number - call', null, '0:\nuint256: 1').perform(() => {
done()
})
}
})
}
}
function runTests(browser: NightwatchBrowser, done: any) {
@ -306,10 +295,34 @@ function testImportFromRemixd(browser: NightwatchBrowser, callback: VoidFunction
.perform(() => { callback() })
}
async function installRemixd(): Promise<void> {
console.log('installRemixd')
const remixd = spawn('yarn install', [], { cwd: process.cwd() + '/dist/libs/remixd', shell: true, detached: true })
return new Promise((resolve, reject) => {
remixd.stdout.on('data', function (data) {
console.log(data.toString())
if(
data.toString().includes('success Saved lockfile')
|| data.toString().includes('success Already up-to-date')
) {
resolve()
}
})
remixd.stderr.on('err', function (data) {
console.log(data.toString())
reject(data.toString())
})
})
}
async function spawnRemixd(path: string): Promise<ChildProcess> {
console.log('spawnRemixd', path)
await installRemixd()
const remixd = spawn('chmod +x dist/libs/remixd/src/bin/remixd.js && dist/libs/remixd/src/bin/remixd.js --remix-ide http://127.0.0.1:8080', [`-s ${path}`], { cwd: process.cwd(), shell: true, detached: true })
return new Promise((resolve, reject) => {
remixd.stdout.on('data', function (data) {
console.log(data.toString())
if(
data.toString().includes('is listening')
|| data.toString().includes('There is already a client running')
@ -319,6 +332,7 @@ async function spawnRemixd(path: string): Promise<ChildProcess> {
}
})
remixd.stderr.on('err', function (data) {
console.log(data.toString())
reject(data.toString())
})
})
@ -346,3 +360,120 @@ function connectRemixd(browser: NightwatchBrowser, done: any) {
.perform(() => done())
}
async function setupHardhatProject(): Promise<void> {
console.log(process.cwd())
try {
const server = spawn('git clone https://github.com/NomicFoundation/hardhat-boilerplate && cd hardhat-boilerplate && yarn install && yarn add "@typechain/ethers-v5@^10.1.0" && yarn add "@typechain/hardhat@^6.1.2" && yarn add "typechain@^8.1.0" && echo "END"', [], { cwd: process.cwd() + '/apps/remix-ide', shell: true, detached: true })
return new Promise((resolve, reject) => {
server.on('exit', function (exitCode) {
console.log("Child exited with code: " + exitCode);
console.log('end')
resolve()
})
})
} catch (e) {
console.log(e)
}
}
async function compileHardhatProject(): Promise<void> {
console.log(process.cwd())
try {
const server = spawn('npx hardhat compile', [], { cwd: process.cwd() + '/apps/remix-ide/hardhat-boilerplate', shell: true, detached: true })
return new Promise((resolve, reject) => {
server.on('exit', function (exitCode) {
console.log("Child exited with code: " + exitCode);
console.log('end')
resolve()
})
})
} catch (e) {
console.log(e)
}
}
async function downloadFoundry(): Promise<void> {
console.log('downloadFoundry', process.cwd())
try {
const server = spawn('curl -L https://foundry.paradigm.xyz | bash', [], { cwd: process.cwd(), shell: true, detached: true })
return new Promise((resolve, reject) => {
server.stdout.on('data', function (data) {
console.log(data.toString())
if (
data.toString().includes("simply run 'foundryup' to install Foundry")
|| data.toString().includes("foundryup: could not detect shell, manually add")
) {
console.log('resolving')
resolve()
}
})
server.stderr.on('err', function (data) {
console.log(data.toString())
reject(data.toString())
})
})
} catch (e) {
console.log(e)
}
}
async function installFoundry(): Promise<void> {
console.log('installFoundry', process.cwd())
try {
const server = spawn('export PATH="' + homedir() + '/.foundry/bin:$PATH" && foundryup', [], { cwd: process.cwd(), shell: true, detached: true })
return new Promise((resolve, reject) => {
server.stdout.on('data', function (data) {
console.log(data.toString())
if (
data.toString().includes("foundryup: done!")
) {
console.log('resolving')
resolve()
}
})
server.stderr.on('err', function (data) {
console.log(data.toString())
reject(data.toString())
})
})
} catch (e) {
console.log(e)
}
}
async function initFoundryProject(): Promise<void> {
console.log('initFoundryProject', homedir())
try {
spawn('git config --global user.email \"you@example.com\"', [], { cwd: homedir(), shell: true, detached: true })
spawn('git config --global user.name \"Your Name\"', [], { cwd: homedir(), shell: true, detached: true })
spawn('mkdir foundry_tmp', [], { cwd: homedir(), shell: true, detached: true })
const server = spawn('export PATH="' + homedir() + '/.foundry/bin:$PATH" && forge init hello_foundry', [], { cwd: homedir() + '/foundry_tmp', shell: true, detached: true })
server.stdout.pipe(process.stdout)
return new Promise((resolve, reject) => {
server.on('exit', function (exitCode) {
console.log("Child exited with code: " + exitCode);
console.log('end')
resolve()
})
})
} catch (e) {
console.log(e)
}
}
async function buildFoundryProject(): Promise<void> {
console.log('buildFoundryProject', homedir())
try {
const server = spawn('export PATH="' + homedir() + '/.foundry/bin:$PATH" && forge build', [], { cwd: homedir() + '/foundry_tmp/hello_foundry', shell: true, detached: true })
server.stdout.pipe(process.stdout)
return new Promise((resolve, reject) => {
server.on('exit', function (exitCode) {
console.log("Child exited with code: " + exitCode);
console.log('end')
resolve()
})
})
} catch (e) {
console.log(e)
}
}

@ -167,7 +167,7 @@ module.exports = {
},
'Should print hardhat logs #group4': function (browser: NightwatchBrowser) {
browser
.addFile('printHardhatlog.sol', { content: hardhatLog })
.addFile('printHardhatlog.sol', { content: hardhatLog })
.clickLaunchIcon('solidity')
.click('*[data-id="terminalClearConsole"]') // clear the terminal
.waitForElementVisible('[for="autoCompile"]')
@ -266,22 +266,22 @@ module.exports = {
if (Array.isArray(result.value) && result.value.length > 0) {
console.log('Found ' + result.value.length + ' transactions')
browser
.click({
selector: '[data-id="listenNetworkCheckInput"]',
})
.click({
selector: '*[data-id="terminalClearConsole"]',
})
.click({
selector: '*[data-id="compilerContainerCompileAndRunBtn"]',
})
.pause(10000)
.waitForElementNotPresent({
locateStrategy: 'xpath',
selector: "//*[@class='remix_ui_terminal_log' and contains(.,'to:') and contains(.,'from:')]",
timeout: 120000
})
.end()
.click({
selector: '[data-id="listenNetworkCheckInput"]',
})
.click({
selector: '*[data-id="terminalClearConsole"]',
})
.click({
selector: '*[data-id="compilerContainerCompileAndRunBtn"]',
})
.pause(10000)
.waitForElementNotPresent({
locateStrategy: 'xpath',
selector: "//*[@class='remix_ui_terminal_log' and contains(.,'to:') and contains(.,'from:')]",
timeout: 120000
})
.end()
} else {
browser
.assert.fail('No transaction found')
@ -309,7 +309,7 @@ module.exports = {
.switchEnvironment('vm-custom-fork')
.waitForElementVisible('[data-id="vm-custom-fork-modal-footer-ok-react"]')
.execute(() => {
(document.querySelector('*[data-id="vm-custom-forkModalDialogContainer-react"] input[data-id="CustomForkNodeUrl"]') as any).focus()
(document.querySelector('*[data-id="vm-custom-forkModalDialogContainer-react"] input[data-id="CustomForkNodeUrl"]') as any).focus()
}, [], () => { })
.clearValue('*[data-id="CustomForkNodeUrl"]').pause(1000).setValue('*[data-id="CustomForkNodeUrl"]', 'https://go.getblock.io/ee42d0a88f314707be11dd799b122cb9')
.execute(() => {
@ -331,7 +331,7 @@ module.exports = {
.executeScriptInTerminal(`web3.eth.getCode('0x75F509A4eDA030470272DfBAf99A47D587E76709')`) // sepolia contract
.waitForElementContainsText('*[data-id="terminalJournal"]', byteCodeInSepolia, 120000)
.click('*[data-id="terminalClearConsole"]')
},
},
'Should run a free function while being connected to mainnet #group9': function (browser: NightwatchBrowser) {
const script = `
@ -359,10 +359,10 @@ module.exports = {
.switchEnvironment('vm-mainnet-fork')
.clickLaunchIcon('filePanel')
.addFile('test_mainnet.sol', { content: script })
const path = "//*[@class='view-line' and contains(.,'resolveENS') and contains(.,'view')]//span//span[contains(.,'(')]"
const path = "//*[@class='view-line' and contains(.,'resolveENS') and contains(.,'view')]//span//span[contains(.,'(')]"
const pathRunFunction = `//li//*[@aria-label='Run the free function "resolveENS"']`
browser.waitForElementVisible('#editorView')
browser.waitForElementVisible('#editorView')
//.waitForElementPresent(pathRunFunction)
.pause(10000) // the parser need to parse the code
.useXpath()
@ -371,25 +371,25 @@ module.exports = {
.perform(function () {
const actions = this.actions({ async: true });
return actions
.keyDown(this.Keys.SHIFT)
.keyDown(this.Keys.ALT)
.sendKeys('r')
.keyDown(this.Keys.SHIFT)
.keyDown(this.Keys.ALT)
.sendKeys('r')
})
.useCss()
.waitForElementContainsText('*[data-id="terminalJournal"]', '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045', 120000)
},
'Should run free function which logs in the terminal #group10': function (browser: NightwatchBrowser) {
const script = `import "hardhat/console.sol";
function runSomething () view {
console.log("test running free function");
}
}
`
browser
.addFile('test.sol', { content: script })
.scrollToLine(3)
const path = "//*[@class='view-line' and contains(.,'runSomething') and contains(.,'view')]//span//span[contains(.,'(')]"
const path = "//*[@class='view-line' and contains(.,'runSomething') and contains(.,'view')]//span//span[contains(.,'(')]"
const pathRunFunction = `//li//*[@aria-label='Run the free function "runSomething"']`
browser.waitForElementVisible('#editorView')
.useXpath()
@ -398,18 +398,15 @@ module.exports = {
.perform(function () {
const actions = this.actions({ async: true });
return actions
.keyDown(this.Keys.SHIFT)
.keyDown(this.Keys.ALT)
.sendKeys('r')
.keyDown(this.Keys.SHIFT)
.keyDown(this.Keys.ALT)
.sendKeys('r')
})
.useCss()
.waitForElementContainsText('*[data-id="terminalJournal"]', 'test running free function', 120000)
}
}
const asyncAwait = `
var p = function () {
return new Promise(function (resolve, reject) {
@ -417,7 +414,7 @@ const asyncAwait = `
resolve("Promise Resolved")
}, 5000)
})
}
}
var run = async () => {
console.log('Waiting Promise')
@ -455,7 +452,7 @@ const resolveExternalUrlAndSave = `
} catch (e) {
console.log(e.message)
}
})()
})()
`
const resolveExternalUrlAndSaveToaPath = `
@ -466,7 +463,7 @@ const resolveExternalUrlAndSaveToaPath = `
} catch (e) {
console.log(e.message)
}
})()
})()
`
const resolveUrl = `
@ -477,7 +474,7 @@ const resolveUrl = `
} catch (e) {
console.log(e.message)
}
})()
})()
`
const deployWithEthersJs = `
@ -485,32 +482,32 @@ const deployWithEthersJs = `
(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)
@ -577,12 +574,12 @@ contract StorageWithLib {
* @dev Store valrue in variable
* @param num value to store
*/
function store(uint256 num) public {
number = num;
function store(uint256 num) public {
number = num;
}
/**
* @dev Return value
* @dev Return value
* @return value of 'number'
*/
function retrieve() public view returns (uint256){
@ -629,11 +626,11 @@ describe("Storage", function () {
deployedLinkReferences: metadata.data.deployedBytecode.linkReferences,
}
const options = {
libraries: {
libraries: {
'Lib': lib.address
}
}
const factory = await ethers.getContractFactoryFromArtifact(artifact, options)
const storage = await factory.deploy();
await storage.deployed()
@ -657,10 +654,10 @@ import "hardhat/console.sol";
contract OwnerTest {
address private owner;
// event for EVM logging
event OwnerSet(address indexed oldOwner, address indexed newOwner);
// modifier to check if caller is owner
modifier isOwner() {
// If the first argument of 'require' evaluates to 'false', execution terminates and all
@ -671,7 +668,7 @@ contract OwnerTest {
require(msg.sender == owner, "Caller is not owner");
_;
}
/**
* @dev Set contract deployer as owner
*/
@ -692,7 +689,7 @@ contract OwnerTest {
}
/**
* @dev Return owner address
* @dev Return owner address
* @return address of owner
*/
function getOwner() external view returns (address) {
@ -705,39 +702,39 @@ const scriptAutoExec = {
contract: `// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.2 <0.9.0;
library lib {
function test () public view returns (uint) {
return 147;
}
}
/**
* @title Storage
* @dev Store & retrieve value inr a variable
* @custom:dev-run-script ./scripts/deploy_storage.js
*/
contract Storage {
uint256 number;
/**
* @dev Store valrue in variable
* @param num value to store
*/
function store(uint256 num) public {
number = num;
number = num;
}
/**
* @dev Return value
* @dev Return value
* @return value of 'number'
*/
function retrieve() public view returns (uint256){
return number;
}
function getFromLib() public view returns (uint) {
return lib.test();
}
@ -747,16 +744,16 @@ const scriptAutoExec = {
// Right click on the script name and hit "Run" to execute
const { expect } = require("chai");
const { ethers } = require("hardhat");
(async () => {
try {
// function getContractFactoryFromArtifact(artifact: Artifact, signer?: ethers.Signer): Promise<ethers.ContractFactory>;
// function getContractFactoryFromArtifact(artifact: Artifact, factoryOptions: FactoryOptions): Promise<ethers.ContractFactory>;
const metadataLib = JSON.parse(await remix.call('fileManager', 'readFile', 'contracts/artifacts/lib.json'))
console.log('deploying lib:')
const artifactLib = {
contractName: 'Lib',
sourceName: 'contracts/1_Storage.sol',
@ -767,15 +764,15 @@ const scriptAutoExec = {
deployedLinkReferences: metadataLib.data.deployedBytecode.linkReferences,
}
const optionsLib = {}
const factoryLib = await ethers.getContractFactoryFromArtifact(artifactLib, optionsLib)
const lib = await factoryLib.deploy();
await lib.deployed()
console.log('lib deployed', lib.address)
const metadata = JSON.parse(await remix.call('fileManager', 'readFile', 'contracts/artifacts/Storage.json'))
const artifact = {
contractName: 'Storage',
@ -787,25 +784,25 @@ const scriptAutoExec = {
deployedLinkReferences: metadata.data.deployedBytecode.linkReferences,
}
const options = {
libraries: {
libraries: {
'lib': lib.address
}
}
const factory = await ethers.getContractFactoryFromArtifact(artifact, options)
const storage = await factory.deploy();
await storage.deployed()
const storeValue = await storage.store(333);
// wait until the transaction is mined
await storeValue.wait();
console.log((await storage.getFromLib()).toString())
// expect((await storage.getFromLib()).toString()).to.equal('34');
} catch (e) {
console.error(e.message)
}

@ -11,31 +11,31 @@ const sources = [
content: `
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
contract MyToken is Initializable, ERC721Upgradeable, OwnableUpgradeable, UUPSUpgradeable {
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
function initialize(address initialOwner) initializer public {
__ERC721_init("MyToken", "MTK");
__Ownable_init(initialOwner);
__UUPSUpgradeable_init();
}
function _authorizeUpgrade(address newImplementation)
internal
onlyOwner
override
{}
}
`
}
}
@ -70,7 +70,7 @@ module.exports = {
.getEditorValue((content) => {
browser.assert.ok(content && content.indexOf(
'https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol') !== -1,
'code has not been loaded')
'code has not been loaded')
})
},
@ -87,7 +87,7 @@ module.exports = {
.getEditorValue((content) => {
browser.assert.ok(content && content.indexOf(
'proposals.length = _numProposals;') !== -1,
'url has not been loaded')
'url has not been loaded')
})
},
@ -97,9 +97,19 @@ module.exports = {
.refreshPage()
.pause(7000)
.currentWorkspaceIs('code-sample')
.waitForElementVisible('*[data-id=treeViewLitreeViewItemsepolia]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemsepolia/0xdac17f958d2ee523a2206206994597c13d831ec7/contracts/MetaMultiSigWallet.sol"]')
.getEditorValue((content) => {
browser.assert.ok(content && content.indexOf(
'contract MetaMultiSigWallet {') !== -1)
})
.waitForElementVisible('*[data-id=treeViewLitreeViewItemmainnet]')
.click('*[data-id=treeViewLitreeViewItemmainnet]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemmainnet/0xdac17f958d2ee523a2206206994597c13d831ec7"]')
.click('*[data-id="treeViewLitreeViewItemmainnet/0xdac17f958d2ee523a2206206994597c13d831ec7"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemmainnet/0xdac17f958d2ee523a2206206994597c13d831ec7/TetherToken.sol"]')
.click('*[data-id="treeViewLitreeViewItemmainnet/0xdac17f958d2ee523a2206206994597c13d831ec7/TetherToken.sol"]')
.getEditorValue((content) => {
browser.assert.ok(content && content.indexOf(
'contract TetherToken is Pausable, StandardToken, BlackList {') !== -1)
@ -107,7 +117,7 @@ module.exports = {
})
},
'Should load Blockscout verified contracts from URL "address" and "blockscout" params (single source)': function (browser: NightwatchBrowser) {
'Should load Blockscout verified contracts from URL "address" and "blockscout" params (single source)': ''+function (browser: NightwatchBrowser) {
browser
.url('http://127.0.0.1:8080/#address=0xdAC17F958D2ee523a2206206994597C13D831ec7&blockscout=eth.blockscout.com')
.refreshPage()
@ -121,8 +131,8 @@ module.exports = {
})
},
'Should load Blockscout verified contracts from URL "address" and "blockscout" params (multiple sources)': function (browser: NightwatchBrowser) {
//Disabled due to failure from blockscout api
'Should load Blockscout verified contracts from URL "address" and "blockscout" params (multiple sources)': '' + function (browser: NightwatchBrowser) {
browser
.url('http://127.0.0.1:8080/#address=0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9&blockscout=eth.blockscout.com')
.refreshPage()
@ -162,9 +172,10 @@ module.exports = {
.getEditorValue((content) => {
browser.assert.ok(content && content.indexOf(
'proposals.length = _numProposals;') !== -1,
'code has been loaded')
'code has been loaded')
})
.url('http://127.0.0.1:8080') // refresh without loading the code sample
.pause(2000)
.currentWorkspaceIs('default_workspace')
.execute(() => {
return document.querySelector('[data-id="dropdown-item-code-sample"]') === null

@ -27,30 +27,30 @@ module.exports = {
.frameParent()
.clickLaunchIcon('filePanel')
.waitForElementVisible({
selector: "//*[@data-id='workspacesSelect' and contains(.,'snekmate')]",
selector: "//*[@data-id='workspacesSelect' and contains(.,'vyper-lang')]",
locateStrategy: 'xpath',
timeout: 60000
})
.currentWorkspaceIs('snekmate')
.waitForElementVisible({
selector: "//*[@data-id='treeViewLitreeViewItemsrc' and contains(.,'src')]",
locateStrategy: 'xpath',
timeout: 60000
})
.openFile('src')
.openFile('src/snekmate')
.openFile('src/snekmate/tokens')
.openFile('src/snekmate/tokens/ERC721.vy')
.currentWorkspaceIs('vyper-lang')
// .waitForElementVisible({
// selector: "//*[@data-id='treeViewLitreeViewItemsrc' and contains(.,'src')]",
// locateStrategy: 'xpath',
// timeout: 60000
// })
.openFile('examples')
.openFile('examples/auctions')
.openFile('examples/auctions/simple_open_auction.vy')
},
// 'Add vyper file to run tests #group1': function (browser: NightwatchBrowser) {
// browser.addFile('TestBallot.sol', sources[0]['TestBallot.sol'])
// },
'@sources': () => sources,
// '@sources': () => sources,
// 'Context menu click to compile blind_auction should succeed #group1': function (browser: NightwatchBrowser) {
// browser
// .addFileSnekmate('blind_auction.vy', sources[0]['blindAuction'])
'Context menu click to compile blind_auction should succeed #group1': function (browser: NightwatchBrowser) {
browser
.addFileSnekmate('blind_auction.vy', sources[0]['blindAuction'])
.click('*[data-id="treeViewLitreeViewItemblind_auction.vy"]')
.rightClick('*[data-id="treeViewLitreeViewItemblind_auction.vy"]')
.click('*[data-id="treeViewDivtreeViewItemexamples/auctions/blind_auction.vy"]')
.rightClick('*[data-id="treeViewDivtreeViewItemexamples/auctions/blind_auction.vy"]')
.waitForElementPresent('[data-id="contextMenuItemvyper"]')
.click('[data-id="contextMenuItemvyper"]')
.clickLaunchIcon('vyper')
@ -149,32 +149,32 @@ module.exports = {
})
},
'Compile Ownable contract from snekmate #group1': function (browser: NightwatchBrowser) {
let contractAddress
browser
.frameParent()
.clickLaunchIcon('filePanel')
.switchWorkspace('snekmate')
.openFile('src')
.openFile('src/snekmate')
.openFile('src/snekmate/auth')
.openFile('src/snekmate/auth/Ownable.vy')
.rightClick('*[data-id="treeViewLitreeViewItemsrc/snekmate/auth/Ownable.vy"]')
.waitForElementVisible('*[data-id="contextMenuItemvyper"]')
.click('*[data-id="contextMenuItemvyper"]')
.clickLaunchIcon('vyper')
// @ts-ignore
.frame(0)
.click('[data-id="compile"]')
.waitForElementVisible({
selector:'[data-id="compilation-details"]',
timeout: 60000
})
.click('[data-id="compilation-details"]')
.frameParent()
.waitForElementVisible('[data-id="copy-abi"]')
.end()
}
// 'Compile Ownable contract from snekmate #group1': function (browser: NightwatchBrowser) {
// let contractAddress
// browser
// .frameParent()
// .clickLaunchIcon('filePanel')
// .switchWorkspace('snekmate')
// .openFile('src')
// .openFile('src/snekmate')
// .openFile('src/snekmate/auth')
// .openFile('src/snekmate/auth/Ownable.vy')
// .rightClick('*[data-id="treeViewLitreeViewItemsrc/snekmate/auth/Ownable.vy"]')
// .waitForElementVisible('*[data-id="contextMenuItemvyper"]')
// .click('*[data-id="contextMenuItemvyper"]')
// .clickLaunchIcon('vyper')
// // @ts-ignore
// .frame(0)
// .click('[data-id="compile"]')
// .waitForElementVisible({
// selector:'[data-id="compilation-details"]',
// timeout: 60000
// })
// .click('[data-id="compilation-details"]')
// .frameParent()
// .waitForElementVisible('[data-id="copy-abi"]')
// .end()
// }
}
const testContract = `
@ -388,6 +388,6 @@ def auctionEnd():
# Transfer funds to beneficiary
send(self.beneficiary, self.highestBid)
`}
` }
}
]

@ -577,7 +577,7 @@ module.exports = {
.getEditorValue((content) => {
browser.assert.ok(content.indexOf(`contract Create2FactoryAssembly {`) !== -1,
'current displayed content is not Create2FactoryAssembly')
})
})
},
tearDown: sauce

@ -159,11 +159,13 @@ module.exports = {
.setValue('[data-id="modalDialogCustomPromptTextClone"]', 'https://github.com/ioedeveloper/test-branch-change')
.click('[data-id="fileSystem-modal-footer-ok-react"]')
.waitForElementPresent('.fa-spinner')
.pause(5000)
.pause(7000)
.waitForElementNotPresent('.fa-spinner')
.waitForElementContainsText('[data-id="workspacesSelect"]', 'test-branch-change')
.waitForElementVisible('[data-id="workspaceGitPanel"]')
.waitForElementVisible('[data-id="workspaceGitBranchesDropdown"]')
.click('[data-id="workspaceGitBranchesDropdown"]')
.pause()
.waitForElementVisible('[data-id="custom-dropdown-menu"]')
.waitForElementContainsText('[data-id="custom-dropdown-items"]', 'origin/dev')
.waitForElementContainsText('[data-id="custom-dropdown-items"]', 'origin/production')
@ -311,66 +313,67 @@ module.exports = {
},
'When switching branches the submodules should disappear #group4': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('[data-id="workspaceGitBranchesDropdown"]')
.click('[data-id="workspaceGitBranchesDropdown"]')
.waitForElementVisible('[data-id="custom-dropdown-menu"]')
.waitForElementContainsText('[data-id="custom-dropdown-items"]', 'origin/empty')
.waitForElementPresent('[data-id="workspaceGit-origin/empty"]')
.click('[data-id="workspaceGit-origin/empty"]')
.waitForElementNotPresent('[data-id="treeViewDivtreeViewItemlibdeep"]')
.waitForElementNotPresent('[data-id="treeViewDivtreeViewItemtest-branch-submodule-recursive"]')
.waitForElementNotPresent('[data-id="treeViewDivtreeViewItemtest-branch-submodule-2"]')
.waitForElementVisible('[data-id="workspaceGitBranchesDropdown"]')
.pause()
.click('[data-id="workspaceGitBranchesDropdown"]')
.waitForElementVisible('[data-id="custom-dropdown-menu"]')
.waitForElementContainsText('[data-id="custom-dropdown-items"]', 'origin/empty')
.waitForElementPresent('[data-id="workspaceGit-origin/empty"]')
.click('[data-id="workspaceGit-origin/empty"]')
.waitForElementNotPresent('[data-id="treeViewDivtreeViewItemlibdeep"]')
.waitForElementNotPresent('[data-id="treeViewDivtreeViewItemtest-branch-submodule-recursive"]')
.waitForElementNotPresent('[data-id="treeViewDivtreeViewItemtest-branch-submodule-2"]')
},
'When switching to main update the modules #group4': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('[data-id="workspaceGitBranchesDropdown"]')
.click('[data-id="workspaceGitBranchesDropdown"]')
.waitForElementVisible('[data-id="custom-dropdown-menu"]')
.waitForElementContainsText('[data-id="custom-dropdown-items"]', 'origin/main')
.waitForElementPresent('[data-id="workspaceGit-origin/main"]')
.click('[data-id="workspaceGit-origin/main"]')
.waitForElementVisible('[data-id="updatesubmodules"]')
.click('[data-id="updatesubmodules"]')
.waitForElementPresent('.fa-spinner')
.waitForElementVisible({
selector: '*[data-id="treeViewLitreeViewItem.git"]',
timeout: 240000
})
.pause(2000)
.waitForElementVisible('[data-id="workspaceGitBranchesDropdown"]')
.click('[data-id="workspaceGitBranchesDropdown"]')
.waitForElementVisible('[data-id="custom-dropdown-menu"]')
.waitForElementContainsText('[data-id="custom-dropdown-items"]', 'origin/main')
.waitForElementPresent('[data-id="workspaceGit-origin/main"]')
.click('[data-id="workspaceGit-origin/main"]')
.waitForElementVisible('[data-id="updatesubmodules"]')
.click('[data-id="updatesubmodules"]')
.waitForElementPresent('.fa-spinner')
.waitForElementVisible({
selector: '*[data-id="treeViewLitreeViewItem.git"]',
timeout: 240000
})
.pause(2000)
// check recursive submodule
.waitForElementVisible('[data-id="treeViewDivtreeViewItemtest-branch-submodule-recursive"]')
.click('[data-id="treeViewDivtreeViewItemtest-branch-submodule-recursive"]')
.click('[data-id="treeViewDivtreeViewItemtest-branch-submodule-recursive"]')
.waitForElementVisible('[data-id="treeViewDivtreeViewItemtest-branch-submodule-recursive/test-branch-submodule-2"]')
.click('[data-id="treeViewDivtreeViewItemtest-branch-submodule-recursive/test-branch-submodule-2"]')
.waitForElementVisible('[data-id="treeViewDivtreeViewItemtest-branch-submodule-recursive/test-branch-submodule-2/submodule2.ts"]')
.waitForElementVisible('[data-id="treeViewDivtreeViewItemtest-branch-submodule-recursive"]')
.click('[data-id="treeViewDivtreeViewItemtest-branch-submodule-recursive"]')
.click('[data-id="treeViewDivtreeViewItemtest-branch-submodule-recursive"]')
.waitForElementVisible('[data-id="treeViewDivtreeViewItemtest-branch-submodule-recursive/test-branch-submodule-2"]')
.click('[data-id="treeViewDivtreeViewItemtest-branch-submodule-recursive/test-branch-submodule-2"]')
.waitForElementVisible('[data-id="treeViewDivtreeViewItemtest-branch-submodule-recursive/test-branch-submodule-2/submodule2.ts"]')
// check test-branch-submodule-2 submodule
.waitForElementVisible('[data-id="treeViewDivtreeViewItemtest-branch-submodule-2"]')
.click('[data-id="treeViewDivtreeViewItemtest-branch-submodule-2"]')
.click('[data-id="treeViewDivtreeViewItemtest-branch-submodule-2"]')
.waitForElementVisible('[data-id="treeViewDivtreeViewItemtest-branch-submodule-2/submodule2.ts"]')
.waitForElementVisible('[data-id="treeViewDivtreeViewItemtest-branch-submodule-2"]')
.click('[data-id="treeViewDivtreeViewItemtest-branch-submodule-2"]')
.click('[data-id="treeViewDivtreeViewItemtest-branch-submodule-2"]')
.waitForElementVisible('[data-id="treeViewDivtreeViewItemtest-branch-submodule-2/submodule2.ts"]')
// check libdeep submodule
.waitForElementVisible('[data-id="treeViewDivtreeViewItemlibdeep"]')
.click('[data-id="treeViewDivtreeViewItemlibdeep"]')
.click('[data-id="treeViewDivtreeViewItemlibdeep"]')
.waitForElementVisible('[data-id="treeViewDivtreeViewItemlibdeep/test-branch-submodule-2"]')
.click('[data-id="treeViewDivtreeViewItemlibdeep/test-branch-submodule-2"]')
.waitForElementVisible('[data-id="treeViewDivtreeViewItemlibdeep/test-branch-submodule-2/submodule2.ts"]')
.waitForElementVisible('[data-id="treeViewDivtreeViewItemlibdeep"]')
.click('[data-id="treeViewDivtreeViewItemlibdeep"]')
.click('[data-id="treeViewDivtreeViewItemlibdeep"]')
.waitForElementVisible('[data-id="treeViewDivtreeViewItemlibdeep/test-branch-submodule-2"]')
.click('[data-id="treeViewDivtreeViewItemlibdeep/test-branch-submodule-2"]')
.waitForElementVisible('[data-id="treeViewDivtreeViewItemlibdeep/test-branch-submodule-2/submodule2.ts"]')
// check libdeep2 submodule
.waitForElementVisible('[data-id="treeViewDivtreeViewItemlibdeep2"]')
.click('[data-id="treeViewDivtreeViewItemlibdeep2"]')
.waitForElementVisible('[data-id="treeViewDivtreeViewItemlibdeep2/recursive"]')
.click('[data-id="treeViewDivtreeViewItemlibdeep2/recursive"]')
.waitForElementVisible('[data-id="treeViewDivtreeViewItemlibdeep2/recursive/test-branch-submodule-2"]')
.click('[data-id="treeViewDivtreeViewItemlibdeep2/recursive/test-branch-submodule-2"]')
.waitForElementVisible('[data-id="treeViewDivtreeViewItemlibdeep2/recursive/test-branch-submodule-2/submodule2.ts"]')
.waitForElementVisible('[data-id="treeViewDivtreeViewItemlibdeep2"]')
.click('[data-id="treeViewDivtreeViewItemlibdeep2"]')
.waitForElementVisible('[data-id="treeViewDivtreeViewItemlibdeep2/recursive"]')
.click('[data-id="treeViewDivtreeViewItemlibdeep2/recursive"]')
.waitForElementVisible('[data-id="treeViewDivtreeViewItemlibdeep2/recursive/test-branch-submodule-2"]')
.click('[data-id="treeViewDivtreeViewItemlibdeep2/recursive/test-branch-submodule-2"]')
.waitForElementVisible('[data-id="treeViewDivtreeViewItemlibdeep2/recursive/test-branch-submodule-2/submodule2.ts"]')
},
// GIT SUBMODULES E2E ENDS
// GIT SUBMODULES E2E ENDS
// GIT WORKSPACE E2E STARTS
// GIT WORKSPACE E2E STARTS
'Should create a git workspace (uniswapV4Template) #group4': function (browser: NightwatchBrowser) {
'Should create a git workspace (uniswapV4Template) #group4': function (browser: NightwatchBrowser) {
browser
.click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]')
@ -389,15 +392,13 @@ module.exports = {
browser.assert.ok(content.indexOf(`contract Counter is BaseHook {`) !== -1,
'Incorrect content')
})
},
},
// GIT WORKSPACE E2E ENDS
tearDown: sauce,
}
const gitmodules = `[submodule "subdemo3"]
path = subdemo3
url = https://github.com/bunsenstraat/empty3

@ -60,7 +60,7 @@ contract Ballot {
!voters[voter].voted,
"The voter already voted."
);
require(voters[voter].weight == 0);
require(voters[voter].weight == 0, "Voter already has the right to vote.");
voters[voter].weight = 1;
}
@ -101,6 +101,7 @@ contract Ballot {
Voter storage sender = voters[msg.sender];
require(sender.weight != 0, "Has no right to vote");
require(!sender.voted, "Already voted.");
require(proposal < proposals.length, "Invalid proposal index.");
sender.voted = true;
sender.vote = proposal;
@ -135,4 +136,4 @@ contract Ballot {
{
winnerName_ = proposals[winningProposal()].name;
}
}
}

@ -1,398 +0,0 @@
{
"_format": "ethers-rs-sol-cache-3",
"paths": {
"artifacts": "out",
"build_infos": "out/build-info",
"sources": "src",
"tests": "test",
"scripts": "script",
"libraries": [
"lib"
]
},
"files": {
"lib/forge-std/lib/ds-test/src/test.sol": {
"lastModificationDate": 1661541843388,
"contentHash": "962996f0e05d5218857a538a62d7c47e",
"sourceName": "lib/forge-std/lib/ds-test/src/test.sol",
"solcConfig": {
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"bytecodeHash": "ipfs"
},
"outputSelection": {
"*": {
"": [
"ast"
],
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata"
]
}
},
"evmVersion": "london",
"libraries": {}
}
},
"imports": [],
"versionRequirement": ">=0.5.0",
"artifacts": {
"DSTest": {
"0.8.16+commit.07a7930e.Linux.gcc": "test.sol/DSTest.json"
}
}
},
"lib/forge-std/src/Script.sol": {
"lastModificationDate": 1661541842048,
"contentHash": "b313d0193442f5a12848be9c422a0064",
"sourceName": "lib/forge-std/src/Script.sol",
"solcConfig": {
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"bytecodeHash": "ipfs"
},
"outputSelection": {
"*": {
"": [
"ast"
],
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata"
]
}
},
"evmVersion": "london",
"libraries": {}
}
},
"imports": [
"lib/forge-std/src/Vm.sol",
"lib/forge-std/src/console.sol",
"lib/forge-std/src/console2.sol"
],
"versionRequirement": ">=0.6.0, <0.9.0",
"artifacts": {
"Script": {
"0.8.16+commit.07a7930e.Linux.gcc": "Script.sol/Script.json"
}
}
},
"lib/forge-std/src/Test.sol": {
"lastModificationDate": 1661541842048,
"contentHash": "8e1ae731c7bb8023f36077d86d18693f",
"sourceName": "lib/forge-std/src/Test.sol",
"solcConfig": {
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"bytecodeHash": "ipfs"
},
"outputSelection": {
"*": {
"": [
"ast"
],
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata"
]
}
},
"evmVersion": "london",
"libraries": {}
}
},
"imports": [
"lib/forge-std/lib/ds-test/src/test.sol",
"lib/forge-std/src/Script.sol",
"lib/forge-std/src/Vm.sol",
"lib/forge-std/src/console.sol",
"lib/forge-std/src/console2.sol"
],
"versionRequirement": ">=0.6.0, <0.9.0",
"artifacts": {
"Test": {
"0.8.16+commit.07a7930e.Linux.gcc": "Test.sol/Test.json"
},
"stdError": {
"0.8.16+commit.07a7930e.Linux.gcc": "Test.sol/stdError.json"
},
"stdMath": {
"0.8.16+commit.07a7930e.Linux.gcc": "Test.sol/stdMath.json"
},
"stdStorage": {
"0.8.16+commit.07a7930e.Linux.gcc": "Test.sol/stdStorage.json"
}
}
},
"lib/forge-std/src/Vm.sol": {
"lastModificationDate": 1661541842048,
"contentHash": "225040109969e43ff90255e34aaecc99",
"sourceName": "lib/forge-std/src/Vm.sol",
"solcConfig": {
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"bytecodeHash": "ipfs"
},
"outputSelection": {
"*": {
"": [
"ast"
],
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata"
]
}
},
"evmVersion": "london",
"libraries": {}
}
},
"imports": [],
"versionRequirement": ">=0.6.0, <0.9.0",
"artifacts": {
"Vm": {
"0.8.16+commit.07a7930e.Linux.gcc": "Vm.sol/Vm.json"
}
}
},
"lib/forge-std/src/console.sol": {
"lastModificationDate": 1663196945880,
"contentHash": "100b8a33b917da1147740d7ab8b0ded3",
"sourceName": "lib/forge-std/src/console.sol",
"solcConfig": {
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"bytecodeHash": "ipfs"
},
"outputSelection": {
"*": {
"": [
"ast"
],
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata"
]
}
},
"evmVersion": "london",
"libraries": {}
}
},
"imports": [],
"versionRequirement": ">=0.4.22, <0.9.0",
"artifacts": {
"console": {
"0.8.16+commit.07a7930e.Linux.gcc": "console.sol/console.json"
}
}
},
"lib/forge-std/src/console2.sol": {
"lastModificationDate": 1661541842052,
"contentHash": "5df91f8e93efbfcccf68973dc1b74a70",
"sourceName": "lib/forge-std/src/console2.sol",
"solcConfig": {
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"bytecodeHash": "ipfs"
},
"outputSelection": {
"*": {
"": [
"ast"
],
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata"
]
}
},
"evmVersion": "london",
"libraries": {}
}
},
"imports": [],
"versionRequirement": ">=0.4.22, <0.9.0",
"artifacts": {
"console2": {
"0.8.16+commit.07a7930e.Linux.gcc": "console2.sol/console2.json"
}
}
},
"script/Counter.s.sol": {
"lastModificationDate": 1661541840908,
"contentHash": "0705c52104730a78aef4aa6694175c81",
"sourceName": "script/Counter.s.sol",
"solcConfig": {
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"bytecodeHash": "ipfs"
},
"outputSelection": {
"*": {
"": [
"ast"
],
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata"
]
}
},
"evmVersion": "london",
"libraries": {}
}
},
"imports": [
"lib/forge-std/src/Script.sol",
"lib/forge-std/src/Vm.sol",
"lib/forge-std/src/console.sol",
"lib/forge-std/src/console2.sol"
],
"versionRequirement": "^0.8.13",
"artifacts": {
"CounterScript": {
"0.8.16+commit.07a7930e.Linux.gcc": "Counter.s.sol/CounterScript.json"
}
}
},
"src/Counter.sol": {
"lastModificationDate": 1664875932853,
"contentHash": "ae6c800a2b4c57768024d6e9423d39e8",
"sourceName": "src/Counter.sol",
"solcConfig": {
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"bytecodeHash": "ipfs"
},
"outputSelection": {
"*": {
"": [
"ast"
],
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata"
]
}
},
"evmVersion": "london",
"libraries": {}
}
},
"imports": [],
"versionRequirement": "^0.8.13",
"artifacts": {
"Counter": {
"0.8.16+commit.07a7930e.Linux.gcc": "Counter.sol/Counter.json"
}
}
},
"test/Counter.t.sol": {
"lastModificationDate": 1661541840908,
"contentHash": "5122f4f87ee8fbf9a2468a4c9c780b6a",
"sourceName": "test/Counter.t.sol",
"solcConfig": {
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"bytecodeHash": "ipfs"
},
"outputSelection": {
"*": {
"": [
"ast"
],
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata"
]
}
},
"evmVersion": "london",
"libraries": {}
}
},
"imports": [
"lib/forge-std/lib/ds-test/src/test.sol",
"lib/forge-std/src/Script.sol",
"lib/forge-std/src/Test.sol",
"lib/forge-std/src/Vm.sol",
"lib/forge-std/src/console.sol",
"lib/forge-std/src/console2.sol",
"src/Counter.sol"
],
"versionRequirement": "^0.8.13",
"artifacts": {
"CounterTest": {
"0.8.16+commit.07a7930e.Linux.gcc": "Counter.t.sol/CounterTest.json"
}
}
}
}
}

@ -1,6 +0,0 @@
[profile.default]
src = 'src'
out = 'out'
libs = ['lib']
# See more config options https://github.com/foundry-rs/foundry/tree/master/config

@ -1,385 +0,0 @@
{
"abi": [
{
"inputs": [],
"name": "IS_SCRIPT",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "run",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "setUp",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "vm",
"outputs": [
{
"internalType": "contract Vm",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
}
],
"bytecode": {
"object": "0x60806040526000805460ff1916600117905534801561001d57600080fd5b5061014c8061002d6000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80630a9254e4146100515780633a76846314610053578063c04062261461008b578063f8ccbf4714610093575b600080fd5b005b61006e737109709ecfa91a80626ff3989d68f67f5b1dd12d81565b6040516001600160a01b0390911681526020015b60405180910390f35b6100516100b0565b6000546100a09060ff1681565b6040519015158152602001610082565b604080516302bf260160e61b81529051737109709ecfa91a80626ff3989d68f67f5b1dd12d9163afc9804091600480830192600092919082900301818387803b1580156100fc57600080fd5b505af1158015610110573d6000803e3d6000fd5b5050505056fea26469706673582212203a39488c6d5e73072e1dd0c6593caff56e39d0849abc1557f1c6e25cf7dedc2e64736f6c63430008100033",
"sourceMap": "97:126:6:-:0;;;165:28:1;;;-1:-1:-1;;165:28:1;189:4;165:28;;;97:126:6;;;;;;;;;;;;;;;;",
"linkReferences": {}
},
"deployedBytecode": {
"object": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80630a9254e4146100515780633a76846314610053578063c04062261461008b578063f8ccbf4714610093575b600080fd5b005b61006e737109709ecfa91a80626ff3989d68f67f5b1dd12d81565b6040516001600160a01b0390911681526020015b60405180910390f35b6100516100b0565b6000546100a09060ff1681565b6040519015158152602001610082565b604080516302bf260160e61b81529051737109709ecfa91a80626ff3989d68f67f5b1dd12d9163afc9804091600480830192600092919082900301818387803b1580156100fc57600080fd5b505af1158015610110573d6000803e3d6000fd5b5050505056fea26469706673582212203a39488c6d5e73072e1dd0c6593caff56e39d0849abc1557f1c6e25cf7dedc2e64736f6c63430008100033",
"sourceMap": "97:126:6:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;136:26;;316:38:1;;245:64;316:38;;;;;-1:-1:-1;;;;;189:32:9;;;171:51;;159:2;144:18;316:38:1;;;;;;;;168:53:6;;;:::i;165:28:1:-;;;;;;;;;;;;398:14:9;;391:22;373:41;;361:2;346:18;165:28:1;233:187:9;168:53:6;200:14;;;-1:-1:-1;;;200:14:6;;;;245:64:1;;200:12:6;;:14;;;;;269:37:1;;200:14:6;;;;;;;269:37:1;245:64;200:14:6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;168:53::o",
"linkReferences": {}
},
"methodIdentifiers": {
"IS_SCRIPT()": "f8ccbf47",
"run()": "c0406226",
"setUp()": "0a9254e4",
"vm()": "3a768463"
},
"rawMetadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"IS_SCRIPT\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"run\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"setUp\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vm\",\"outputs\":[{\"internalType\":\"contract Vm\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"script/Counter.s.sol\":\"CounterScript\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\"]},\"sources\":{\"lib/forge-std/src/Script.sol\":{\"keccak256\":\"0x4424dbcb8f5b741475445726f87408fcd89951fad973bec2ca442ee157f910e7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5b0b9f6dfb69245d8f888558ae82bf1d2cdeace46201444fe4b2e6a5283f944a\",\"dweb:/ipfs/QmWFSKeFEZngNcwNn7A84EF7pASo5qe6r5oK24r9Kwca7Z\"]},\"lib/forge-std/src/Vm.sol\":{\"keccak256\":\"0xa0ede8e0d3dc3246912530aed6cacbc4703e4430c4b4acd91963ccea709755ea\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a28e7d00aab57ad5159247b0f0f268eda4c6980b29eee7f903578254a2be677f\",\"dweb:/ipfs/QmZrM8gY5BpW8o1QckmPNCYbBP5Q7k5DkcHdaVULKVntxp\"]},\"lib/forge-std/src/console.sol\":{\"keccak256\":\"0x91d5413c2434ca58fd278b6e1e79fd98d10c83931cc2596a6038eee4daeb34ba\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://91ccea707361e48b9b7a161fe81f496b9932bc471e9c4e4e1e9c283f2453cc70\",\"dweb:/ipfs/QmcB66sZhQ6Kz7MUHcLE78YXRUZxoZnnxZjN6yATsbB2ec\"]},\"lib/forge-std/src/console2.sol\":{\"keccak256\":\"0xbeb823fcdb356244a83aaccdf828ad019ecc1ffaa3dff18e624fc6d5714ea671\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4cbe9400340e5f9ec55e2aff3bad1c15fa3afbbe37e80800e6f3fed2ad26854f\",\"dweb:/ipfs/QmdJBABsuXkvWxVzEyGXsTE3vyfBPXDdw5xvvtUz3JeoYW\"]},\"script/Counter.s.sol\":{\"keccak256\":\"0x01edaa1835b1a5bd3f4f66f73451488b8441d30642d3bf1f5fa2c5bf7c005bee\",\"license\":\"UNLICENSED\",\"urls\":[\"bzz-raw://3c6a0f19216ceeebf4ec16f8f2662a3bebbe18d4037d1399adf2e3e4ccbb57a2\",\"dweb:/ipfs/Qmc8NknjPkSgbXLg6zZQ8uKT6kAWBvBXz5JrDvZfa88UNT\"]}},\"version\":1}",
"metadata": {
"compiler": {
"version": "0.8.16+commit.07a7930e"
},
"language": "Solidity",
"output": {
"abi": [
{
"inputs": [],
"stateMutability": "view",
"type": "function",
"name": "IS_SCRIPT",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
]
},
{
"inputs": [],
"stateMutability": "nonpayable",
"type": "function",
"name": "run"
},
{
"inputs": [],
"stateMutability": "nonpayable",
"type": "function",
"name": "setUp"
},
{
"inputs": [],
"stateMutability": "view",
"type": "function",
"name": "vm",
"outputs": [
{
"internalType": "contract Vm",
"name": "",
"type": "address"
}
]
}
],
"devdoc": {
"kind": "dev",
"methods": {},
"version": 1
},
"userdoc": {
"kind": "user",
"methods": {},
"version": 1
}
},
"settings": {
"remappings": [
":ds-test/=lib/forge-std/lib/ds-test/src/",
":forge-std/=lib/forge-std/src/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"bytecodeHash": "ipfs"
},
"compilationTarget": {
"script/Counter.s.sol": "CounterScript"
},
"libraries": {}
},
"sources": {
"lib/forge-std/src/Script.sol": {
"keccak256": "0x4424dbcb8f5b741475445726f87408fcd89951fad973bec2ca442ee157f910e7",
"urls": [
"bzz-raw://5b0b9f6dfb69245d8f888558ae82bf1d2cdeace46201444fe4b2e6a5283f944a",
"dweb:/ipfs/QmWFSKeFEZngNcwNn7A84EF7pASo5qe6r5oK24r9Kwca7Z"
],
"license": "MIT"
},
"lib/forge-std/src/Vm.sol": {
"keccak256": "0xa0ede8e0d3dc3246912530aed6cacbc4703e4430c4b4acd91963ccea709755ea",
"urls": [
"bzz-raw://a28e7d00aab57ad5159247b0f0f268eda4c6980b29eee7f903578254a2be677f",
"dweb:/ipfs/QmZrM8gY5BpW8o1QckmPNCYbBP5Q7k5DkcHdaVULKVntxp"
],
"license": "MIT"
},
"lib/forge-std/src/console.sol": {
"keccak256": "0x91d5413c2434ca58fd278b6e1e79fd98d10c83931cc2596a6038eee4daeb34ba",
"urls": [
"bzz-raw://91ccea707361e48b9b7a161fe81f496b9932bc471e9c4e4e1e9c283f2453cc70",
"dweb:/ipfs/QmcB66sZhQ6Kz7MUHcLE78YXRUZxoZnnxZjN6yATsbB2ec"
],
"license": "MIT"
},
"lib/forge-std/src/console2.sol": {
"keccak256": "0xbeb823fcdb356244a83aaccdf828ad019ecc1ffaa3dff18e624fc6d5714ea671",
"urls": [
"bzz-raw://4cbe9400340e5f9ec55e2aff3bad1c15fa3afbbe37e80800e6f3fed2ad26854f",
"dweb:/ipfs/QmdJBABsuXkvWxVzEyGXsTE3vyfBPXDdw5xvvtUz3JeoYW"
],
"license": "MIT"
},
"script/Counter.s.sol": {
"keccak256": "0x01edaa1835b1a5bd3f4f66f73451488b8441d30642d3bf1f5fa2c5bf7c005bee",
"urls": [
"bzz-raw://3c6a0f19216ceeebf4ec16f8f2662a3bebbe18d4037d1399adf2e3e4ccbb57a2",
"dweb:/ipfs/Qmc8NknjPkSgbXLg6zZQ8uKT6kAWBvBXz5JrDvZfa88UNT"
],
"license": "UNLICENSED"
}
},
"version": 1
},
"ast": {
"absolutePath": "script/Counter.s.sol",
"id": 21582,
"exportedSymbols": {
"CounterScript": [
21581
],
"Script": [
2022
],
"Vm": [
5434
],
"console": [
13498
],
"console2": [
21562
]
},
"nodeType": "SourceUnit",
"src": "39:185:6",
"nodes": [
{
"id": 21564,
"nodeType": "PragmaDirective",
"src": "39:24:6",
"literals": [
"solidity",
"^",
"0.8",
".13"
]
},
{
"id": 21565,
"nodeType": "ImportDirective",
"src": "65:30:6",
"absolutePath": "lib/forge-std/src/Script.sol",
"file": "forge-std/Script.sol",
"nameLocation": "-1:-1:-1",
"scope": 21582,
"sourceUnit": 2023,
"symbolAliases": [],
"unitAlias": ""
},
{
"id": 21581,
"nodeType": "ContractDefinition",
"src": "97:126:6",
"nodes": [
{
"id": 21571,
"nodeType": "FunctionDefinition",
"src": "136:26:6",
"body": {
"id": 21570,
"nodeType": "Block",
"src": "160:2:6",
"statements": []
},
"functionSelector": "0a9254e4",
"implemented": true,
"kind": "function",
"modifiers": [],
"name": "setUp",
"nameLocation": "145:5:6",
"parameters": {
"id": 21568,
"nodeType": "ParameterList",
"parameters": [],
"src": "150:2:6"
},
"returnParameters": {
"id": 21569,
"nodeType": "ParameterList",
"parameters": [],
"src": "160:0:6"
},
"scope": 21581,
"stateMutability": "nonpayable",
"virtual": false,
"visibility": "public"
},
{
"id": 21580,
"nodeType": "FunctionDefinition",
"src": "168:53:6",
"body": {
"id": 21579,
"nodeType": "Block",
"src": "190:31:6",
"statements": [
{
"expression": {
"arguments": [],
"expression": {
"argumentTypes": [],
"expression": {
"id": 21574,
"name": "vm",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 1817,
"src": "200:2:6",
"typeDescriptions": {
"typeIdentifier": "t_contract$_Vm_$5434",
"typeString": "contract Vm"
}
},
"id": 21576,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"memberLocation": "203:9:6",
"memberName": "broadcast",
"nodeType": "MemberAccess",
"referencedDeclaration": 5173,
"src": "200:12:6",
"typeDescriptions": {
"typeIdentifier": "t_function_external_nonpayable$__$returns$__$",
"typeString": "function () external"
}
},
"id": 21577,
"isConstant": false,
"isLValue": false,
"isPure": false,
"kind": "functionCall",
"lValueRequested": false,
"nameLocations": [],
"names": [],
"nodeType": "FunctionCall",
"src": "200:14:6",
"tryCall": false,
"typeDescriptions": {
"typeIdentifier": "t_tuple$__$",
"typeString": "tuple()"
}
},
"id": 21578,
"nodeType": "ExpressionStatement",
"src": "200:14:6"
}
]
},
"functionSelector": "c0406226",
"implemented": true,
"kind": "function",
"modifiers": [],
"name": "run",
"nameLocation": "177:3:6",
"parameters": {
"id": 21572,
"nodeType": "ParameterList",
"parameters": [],
"src": "180:2:6"
},
"returnParameters": {
"id": 21573,
"nodeType": "ParameterList",
"parameters": [],
"src": "190:0:6"
},
"scope": 21581,
"stateMutability": "nonpayable",
"virtual": false,
"visibility": "public"
}
],
"abstract": false,
"baseContracts": [
{
"baseName": {
"id": 21566,
"name": "Script",
"nameLocations": [
"123:6:6"
],
"nodeType": "IdentifierPath",
"referencedDeclaration": 2022,
"src": "123:6:6"
},
"id": 21567,
"nodeType": "InheritanceSpecifier",
"src": "123:6:6"
}
],
"canonicalName": "CounterScript",
"contractDependencies": [],
"contractKind": "contract",
"fullyImplemented": true,
"linearizedBaseContracts": [
21581,
2022
],
"name": "CounterScript",
"nameLocation": "106:13:6",
"scope": 21582,
"usedErrors": []
}
],
"license": "UNLICENSED"
},
"id": 6
}

@ -1,377 +0,0 @@
{
"abi": [
{
"inputs": [],
"name": "increment",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "number",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "newNumber",
"type": "uint256"
}
],
"name": "setNumber",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
],
"bytecode": {
"object": "0x608060405234801561001057600080fd5b5060f78061001f6000396000f3fe6080604052348015600f57600080fd5b5060043610603c5760003560e01c80633fb5c1cb1460415780638381f58a146053578063d09de08a14606d575b600080fd5b6051604c3660046083565b600055565b005b605b60005481565b60405190815260200160405180910390f35b6051600080549080607c83609b565b9190505550565b600060208284031215609457600080fd5b5035919050565b60006001820160ba57634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220f4a9b22e7a2d64c24355b4e7a6f8c62115ca728f26fc2a1e98e364ee91f794fa64736f6c63430008100033",
"sourceMap": "65:192:7:-:0;;;;;;;;;;;;;;;;;;;",
"linkReferences": {}
},
"deployedBytecode": {
"object": "0x6080604052348015600f57600080fd5b5060043610603c5760003560e01c80633fb5c1cb1460415780638381f58a146053578063d09de08a14606d575b600080fd5b6051604c3660046083565b600055565b005b605b60005481565b60405190815260200160405180910390f35b6051600080549080607c83609b565b9190505550565b600060208284031215609457600080fd5b5035919050565b60006001820160ba57634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220f4a9b22e7a2d64c24355b4e7a6f8c62115ca728f26fc2a1e98e364ee91f794fa64736f6c63430008100033",
"sourceMap": "65:192:7:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;116:80;;;;;;:::i;:::-;171:6;:18;116:80;;;88:21;;;;;;;;;345:25:9;;;333:2;318:18;88:21:7;;;;;;;202:53;;240:6;:8;;;:6;:8;;;:::i;:::-;;;;;;202:53::o;14:180:9:-;73:6;126:2;114:9;105:7;101:23;97:32;94:52;;;142:1;139;132:12;94:52;-1:-1:-1;165:23:9;;14:180;-1:-1:-1;14:180:9:o;381:232::-;420:3;441:17;;;438:140;;500:10;495:3;491:20;488:1;481:31;535:4;532:1;525:15;563:4;560:1;553:15;438:140;-1:-1:-1;605:1:9;594:13;;381:232::o",
"linkReferences": {}
},
"methodIdentifiers": {
"increment()": "d09de08a",
"number()": "8381f58a",
"setNumber(uint256)": "3fb5c1cb"
},
"rawMetadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"increment\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"number\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newNumber\",\"type\":\"uint256\"}],\"name\":\"setNumber\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/Counter.sol\":\"Counter\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\"]},\"sources\":{\"src/Counter.sol\":{\"keccak256\":\"0x09277f949d59a9521708c870dc39c2c434ad8f86a5472efda6a732ef728c0053\",\"license\":\"UNLICENSED\",\"urls\":[\"bzz-raw://94cd5258357da018bf911aeda60ed9f5b130dce27445669ee200313cd3389200\",\"dweb:/ipfs/QmNbEfWAqXCtfQpk6u7TpGa8sTHXFLpUz7uebz2FVbchSC\"]}},\"version\":1}",
"metadata": {
"compiler": {
"version": "0.8.16+commit.07a7930e"
},
"language": "Solidity",
"output": {
"abi": [
{
"inputs": [],
"stateMutability": "nonpayable",
"type": "function",
"name": "increment"
},
{
"inputs": [],
"stateMutability": "view",
"type": "function",
"name": "number",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
]
},
{
"inputs": [
{
"internalType": "uint256",
"name": "newNumber",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
"type": "function",
"name": "setNumber"
}
],
"devdoc": {
"kind": "dev",
"methods": {},
"version": 1
},
"userdoc": {
"kind": "user",
"methods": {},
"version": 1
}
},
"settings": {
"remappings": [
":ds-test/=lib/forge-std/lib/ds-test/src/",
":forge-std/=lib/forge-std/src/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"bytecodeHash": "ipfs"
},
"compilationTarget": {
"src/Counter.sol": "Counter"
},
"libraries": {}
},
"sources": {
"src/Counter.sol": {
"keccak256": "0x09277f949d59a9521708c870dc39c2c434ad8f86a5472efda6a732ef728c0053",
"urls": [
"bzz-raw://94cd5258357da018bf911aeda60ed9f5b130dce27445669ee200313cd3389200",
"dweb:/ipfs/QmNbEfWAqXCtfQpk6u7TpGa8sTHXFLpUz7uebz2FVbchSC"
],
"license": "UNLICENSED"
}
},
"version": 1
},
"ast": {
"absolutePath": "src/Counter.sol",
"id": 21604,
"exportedSymbols": {
"Counter": [
21603
]
},
"nodeType": "SourceUnit",
"src": "39:219:7",
"nodes": [
{
"id": 21583,
"nodeType": "PragmaDirective",
"src": "39:24:7",
"literals": [
"solidity",
"^",
"0.8",
".13"
]
},
{
"id": 21603,
"nodeType": "ContractDefinition",
"src": "65:192:7",
"nodes": [
{
"id": 21585,
"nodeType": "VariableDeclaration",
"src": "88:21:7",
"constant": false,
"functionSelector": "8381f58a",
"mutability": "mutable",
"name": "number",
"nameLocation": "103:6:7",
"scope": 21603,
"stateVariable": true,
"storageLocation": "default",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"typeName": {
"id": 21584,
"name": "uint256",
"nodeType": "ElementaryTypeName",
"src": "88:7:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"visibility": "public"
},
{
"id": 21595,
"nodeType": "FunctionDefinition",
"src": "116:80:7",
"body": {
"id": 21594,
"nodeType": "Block",
"src": "161:35:7",
"statements": [
{
"expression": {
"id": 21592,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftHandSide": {
"id": 21590,
"name": "number",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 21585,
"src": "171:6:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"nodeType": "Assignment",
"operator": "=",
"rightHandSide": {
"id": 21591,
"name": "newNumber",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 21587,
"src": "180:9:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"src": "171:18:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"id": 21593,
"nodeType": "ExpressionStatement",
"src": "171:18:7"
}
]
},
"functionSelector": "3fb5c1cb",
"implemented": true,
"kind": "function",
"modifiers": [],
"name": "setNumber",
"nameLocation": "125:9:7",
"parameters": {
"id": 21588,
"nodeType": "ParameterList",
"parameters": [
{
"constant": false,
"id": 21587,
"mutability": "mutable",
"name": "newNumber",
"nameLocation": "143:9:7",
"nodeType": "VariableDeclaration",
"scope": 21595,
"src": "135:17:7",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"typeName": {
"id": 21586,
"name": "uint256",
"nodeType": "ElementaryTypeName",
"src": "135:7:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"visibility": "internal"
}
],
"src": "134:19:7"
},
"returnParameters": {
"id": 21589,
"nodeType": "ParameterList",
"parameters": [],
"src": "161:0:7"
},
"scope": 21603,
"stateMutability": "nonpayable",
"virtual": false,
"visibility": "public"
},
{
"id": 21602,
"nodeType": "FunctionDefinition",
"src": "202:53:7",
"body": {
"id": 21601,
"nodeType": "Block",
"src": "230:25:7",
"statements": [
{
"expression": {
"id": 21599,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"nodeType": "UnaryOperation",
"operator": "++",
"prefix": false,
"src": "240:8:7",
"subExpression": {
"id": 21598,
"name": "number",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 21585,
"src": "240:6:7",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"id": 21600,
"nodeType": "ExpressionStatement",
"src": "240:8:7"
}
]
},
"functionSelector": "d09de08a",
"implemented": true,
"kind": "function",
"modifiers": [],
"name": "increment",
"nameLocation": "211:9:7",
"parameters": {
"id": 21596,
"nodeType": "ParameterList",
"parameters": [],
"src": "220:2:7"
},
"returnParameters": {
"id": 21597,
"nodeType": "ParameterList",
"parameters": [],
"src": "230:0:7"
},
"scope": 21603,
"stateMutability": "nonpayable",
"virtual": false,
"visibility": "public"
}
],
"abstract": false,
"baseContracts": [],
"canonicalName": "Counter",
"contractDependencies": [],
"contractKind": "contract",
"fullyImplemented": true,
"linearizedBaseContracts": [
21603
],
"name": "Counter",
"nameLocation": "74:7:7",
"scope": 21604,
"usedErrors": []
}
],
"license": "UNLICENSED"
},
"id": 7
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,14 +0,0 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
contract Counter {
uint256 public number;
function setNumber(uint256 newNumber) public {
number = newNumber;
}
function increment() public {
number++;
}
}

@ -7,8 +7,11 @@ import {LocaleModule} from './app/tabs/locale-module'
import {NetworkModule} from './app/tabs/network-module'
import {Web3ProviderModule} from './app/tabs/web3-provider'
import {CompileAndRun} from './app/tabs/compile-and-run'
import {PluginStateLogger} from './app/tabs/state-logger'
import {SidePanel} from './app/components/side-panel'
import {StatusBar} from './app/components/status-bar'
import {HiddenPanel} from './app/components/hidden-panel'
import {PinnedPanel} from './app/components/pinned-panel'
import {VerticalIcons} from './app/components/vertical-icons'
import {LandingPage} from './app/ui/landing-page/landing-page'
import {MainPanel} from './app/components/main-panel'
@ -53,8 +56,6 @@ import { xtermPlugin } from './app/plugins/electron/xtermPlugin'
import { ripgrepPlugin } from './app/plugins/electron/ripgrepPlugin'
import { compilerLoaderPlugin, compilerLoaderPluginDesktop } from './app/plugins/electron/compilerLoaderPlugin'
import { appUpdaterPlugin } from './app/plugins/electron/appUpdaterPlugin'
import {OpenAIGpt} from './app/plugins/openaigpt'
import {SolCoder} from './app/plugins/solcoderAI'
const isElectron = require('is-electron')
@ -232,7 +233,6 @@ class AppComponent {
const contractFlattener = new ContractFlattener()
// ----------------- AI --------------------------------------
const openaigpt = new OpenAIGpt()
const solcoder = new SolCoder()
// ----------------- import content service ------------------------
@ -301,8 +301,9 @@ class AppComponent {
this.layout = new Layout()
const permissionHandler = new PermissionHandlerPlugin()
// ----------------- run script after each compilation results -----------
const pluginStateLogger = new PluginStateLogger()
this.engine.register([
permissionHandler,
this.layout,
@ -340,18 +341,18 @@ class AppComponent {
hardhatProvider,
ganacheProvider,
foundryProvider,
externalHttpProvider,
externalHttpProvider,
this.walkthroughService,
search,
solidityumlgen,
compilationDetails,
vyperCompilationDetails,
// remixGuide,
remixGuide,
contractFlattener,
solidityScript,
templates,
openaigpt,
solcoder,
pluginStateLogger
])
//---- fs plugin
@ -385,13 +386,15 @@ class AppComponent {
this.menuicons = new VerticalIcons()
this.sidePanel = new SidePanel()
this.hiddenPanel = new HiddenPanel()
this.pinnedPanel = new PinnedPanel()
const pluginManagerComponent = new PluginManagerComponent(appManager, this.engine)
const filePanel = new FilePanel(appManager)
this.statusBar = new StatusBar(filePanel, this.menuicons)
const landingPage = new LandingPage(appManager, this.menuicons, fileManager, filePanel, contentImport)
this.settings = new SettingsTab(Registry.getInstance().get('config').api, editor, appManager)
this.engine.register([this.menuicons, landingPage, this.hiddenPanel, this.sidePanel, filePanel, pluginManagerComponent, this.settings])
this.engine.register([this.menuicons, landingPage, this.hiddenPanel, this.sidePanel, this.statusBar, filePanel, pluginManagerComponent, this.settings, this.pinnedPanel])
// CONTENT VIEWS & DEFAULT PLUGINS
const openZeppelinProxy = new OpenZeppelinProxy(blockchain)
@ -469,10 +472,13 @@ class AppComponent {
'compilerArtefacts',
'network',
'web3Provider',
'offsetToLineColumnConverter'
'offsetToLineColumnConverter',
'pluginStateLogger'
])
await this.appManager.activatePlugin(['mainPanel', 'menuicons', 'tabs'])
await this.appManager.activatePlugin(['statusBar'])
await this.appManager.activatePlugin(['sidePanel']) // activating host plugin separately
await this.appManager.activatePlugin(['pinnedPanel'])
await this.appManager.activatePlugin(['home'])
await this.appManager.activatePlugin(['settings', 'config'])
await this.appManager.activatePlugin([
@ -508,11 +514,8 @@ class AppComponent {
await this.appManager.registerContextMenuItems()
}
)
await this.appManager.activatePlugin(['solidity-script', 'openaigpt'])
await this.appManager.activatePlugin(['solidity-script'])
await this.appManager.activatePlugin(['solcoder'])
await this.appManager.activatePlugin(['filePanel'])
// Set workspace after initial activation
@ -567,6 +570,12 @@ class AppComponent {
}
}
}
}).then(async () => {
const lastPinned = localStorage.getItem('pinnedPlugin')
if (lastPinned) {
this.appManager.call('sidePanel', 'pinView', JSON.parse(lastPinned))
}
})
.catch(console.error)
}
@ -575,6 +584,14 @@ class AppComponent {
document.body.appendChild(loadedElement)
})
this.appManager.on('pinnedPanel', 'pinnedPlugin', (pluginProfile) => {
localStorage.setItem('pinnedPlugin', JSON.stringify(pluginProfile))
})
this.appManager.on('pinnedPanel', 'unPinnedPlugin', () => {
localStorage.setItem('pinnedPlugin', '')
})
// activate solidity plugin
this.appManager.activatePlugin(['solidity', 'udapp', 'deploy-libraries', 'link-libraries', 'openzeppelin-proxy'])
}

@ -1,9 +1,9 @@
// eslint-disable-next-line no-use-before-define
import React from 'react'
import {AbstractPanel} from './panel'
import { AbstractPanel } from './panel'
import * as packageJson from '../../../../../package.json'
import {RemixPluginPanel} from '@remix-ui/panel'
import {PluginViewWrapper} from '@remix-ui/helper'
import { RemixPluginPanel } from '@remix-ui/panel'
import { PluginViewWrapper } from '@remix-ui/helper'
const profile = {
name: 'hiddenPanel',

@ -1,8 +1,8 @@
import React from 'react' // eslint-disable-line
import {AbstractPanel} from './panel'
import {RemixPluginPanel} from '@remix-ui/panel'
import { AbstractPanel } from './panel'
import { RemixPluginPanel } from '@remix-ui/panel'
import packageJson from '../../../../../package.json'
import {PluginViewWrapper} from '@remix-ui/helper'
import { PluginViewWrapper } from '@remix-ui/helper'
const profile = {
name: 'mainPanel',
@ -60,7 +60,7 @@ export class MainPanel extends AbstractPanel {
render() {
return (
<div style={{height: '100%', width: '100%'}} data-id="mainPanelPluginsContainer">
<div style={{ height: '100%', width: '100%' }} data-id="mainPanelPluginsContainer">
<PluginViewWrapper plugin={this} />
</div>
)

@ -15,9 +15,11 @@ export class AbstractPanel extends HostPlugin {
}
currentFocus (): string {
return Object.values(this.plugins).find(plugin => {
const activePlugin = Object.values(this.plugins).find(plugin => {
return plugin.active
}).profile.name
})
return activePlugin ? activePlugin.profile.name : null
}
addView (profile, view) {
@ -26,6 +28,7 @@ export class AbstractPanel extends HostPlugin {
profile: profile,
view: view,
active: false,
pinned: false,
class: 'plugItIn active'
}
}
@ -49,7 +52,7 @@ export class AbstractPanel extends HostPlugin {
* @param {String} name The name of the plugin to display the content
*/
showContent (name) {
if (!this.plugins[name]) throw new Error(`Plugin ${name} is not yet activated`)
if (!this.plugins[name]) throw new Error(`Plugin ${name} is not yet activated`)
Object.values(this.plugins).forEach(plugin => {
plugin.active = false
})

@ -0,0 +1,91 @@
// eslint-disable-next-line no-use-before-define
import React from 'react'
import { AbstractPanel } from './panel'
import { PluginRecord, RemixPluginPanel } from '@remix-ui/panel'
import packageJson from '../../../../../package.json'
import { RemixUIPanelHeader } from '@remix-ui/panel'
import { PluginViewWrapper } from '@remix-ui/helper'
const pinnedPanel = {
name: 'pinnedPanel',
displayName: 'Pinned Panel',
description: 'Remix IDE pinned panel',
version: packageJson.version,
methods: ['addView', 'removeView', 'currentFocus', 'pinView', 'unPinView', 'highlight']
}
export class PinnedPanel extends AbstractPanel {
dispatch: React.Dispatch<any> = () => {}
loggedState: Record<string, any>
highlightStamp: number
constructor() {
super(pinnedPanel)
}
onActivation() {
this.renderComponent()
this.on('sidePanel', 'pluginDisabled', (name) => {
if (this.plugins[name] && this.plugins[name].active) {
this.emit('unPinnedPlugin', name)
this.events.emit('unPinnedPlugin', name)
super.remove(name)
}
})
}
async pinView (profile, view) {
const activePlugin = this.currentFocus()
if (activePlugin === profile.name) throw new Error(`Plugin ${profile.name} already pinned`)
if (activePlugin) {
await this.call('sidePanel', 'unPinView', this.plugins[activePlugin].profile, this.plugins[activePlugin].view)
this.remove(activePlugin)
}
this.loggedState = await this.call('pluginStateLogger', 'getPluginState', profile.name)
this.addView(profile, view)
this.plugins[profile.name].pinned = true
this.plugins[profile.name].active = true
this.renderComponent()
this.events.emit('pinnedPlugin', profile)
this.emit('pinnedPlugin', profile)
}
async unPinView (profile) {
const activePlugin = this.currentFocus()
if (activePlugin !== profile.name) throw new Error(`Plugin ${profile.name} is not pinned`)
await this.call('sidePanel', 'unPinView', profile, this.plugins[profile.name].view)
super.remove(profile.name)
this.renderComponent()
this.events.emit('unPinnedPlugin', profile)
this.emit('unPinnedPlugin', profile)
}
highlight () {
this.highlightStamp = Date.now()
this.renderComponent()
}
setDispatch (dispatch: React.Dispatch<any>) {
this.dispatch = dispatch
}
render() {
return (
<section className='panel pinned-panel'> <PluginViewWrapper plugin={this} /></section>
)
}
updateComponent(state: any) {
return <RemixPluginPanel header={<RemixUIPanelHeader plugins={state.plugins} pinView={this.pinView.bind(this)} unPinView={this.unPinView.bind(this)}></RemixUIPanelHeader>} { ...state } />
}
renderComponent() {
this.dispatch({
plugins: this.plugins,
pluginState: this.loggedState,
highlightStamp: this.highlightStamp
})
}
}

@ -1,12 +1,11 @@
import {RemixApp} from '@remix-ui/app'
import { RemixApp } from '@remix-ui/app'
import axios from 'axios'
import React, {useEffect, useRef, useState} from 'react'
import { createRoot } from 'react-dom/client'
import React, { useEffect, useRef, useState } from 'react'
import * as packageJson from '../../../../../package.json'
import {fileSystem, fileSystems} from '../files/fileSystem'
import {indexedDBFileSystem} from '../files/filesystems/indexedDB'
import {localStorageFS} from '../files/filesystems/localStorage'
import {fileSystemUtility, migrationTestData} from '../files/filesystems/fileSystemUtility'
import { fileSystem, fileSystems } from '../files/fileSystem'
import { indexedDBFileSystem } from '../files/filesystems/indexedDB'
import { localStorageFS } from '../files/filesystems/localStorage'
import { fileSystemUtility, migrationTestData } from '../files/filesystems/fileSystemUtility'
import './styles/preload.css'
import isElectron from 'is-electron'
const _paq = (window._paq = window._paq || [])
@ -83,7 +82,7 @@ export const Preload = (props: any) => {
}
useEffect (() => {
if(isElectron()){
if (isElectron()){
loadAppComponent()
return
}
@ -177,8 +176,8 @@ export const Preload = (props: any) => {
) : null}
{supported && !error && !showDownloader ? (
<div>
<div className='text-center'>
<i className="fas fa-spinner fa-spin fa-2x"></i>
<div className='text-center'>
<i className="fas fa-spinner fa-spin fa-2x"></i>
</div>
{ tip && <div className='remix_tips text-center mt-3'>
<div><b>DID YOU KNOW</b></div>

@ -1,10 +1,10 @@
// eslint-disable-next-line no-use-before-define
import React from 'react'
import {AbstractPanel} from './panel'
import {RemixPluginPanel} from '@remix-ui/panel'
import { AbstractPanel } from './panel'
import { RemixPluginPanel } from '@remix-ui/panel'
import packageJson from '../../../../../package.json'
import {RemixUIPanelHeader} from '@remix-ui/panel'
import {PluginViewWrapper} from '@remix-ui/helper'
import { RemixUIPanelHeader } from '@remix-ui/panel'
import { PluginViewWrapper } from '@remix-ui/helper'
// const csjs = require('csjs-inject')
const sidePanel = {
@ -12,12 +12,14 @@ const sidePanel = {
displayName: 'Side Panel',
description: 'Remix IDE side panel',
version: packageJson.version,
methods: ['addView', 'removeView', 'currentFocus']
methods: ['addView', 'removeView', 'currentFocus', 'pinView', 'unPinView', 'focus']
}
export class SidePanel extends AbstractPanel {
sideelement: any
loggedState: any
dispatch: React.Dispatch<any> = () => {}
constructor() {
super(sidePanel)
this.sideelement = document.createElement('section')
@ -56,10 +58,8 @@ export class SidePanel extends AbstractPanel {
}
removeView(profile) {
if (this.plugins[profile.name].active) this.call('menuicons', 'select', 'filePanel')
if (this.plugins[profile.name] && this.plugins[profile.name].active) this.call('menuicons', 'select', 'filePanel')
super.removeView(profile)
this.emit('pluginDisabled', profile.name)
this.call('menuicons', 'unlinkContent', profile)
this.renderComponent()
}
@ -69,6 +69,24 @@ export class SidePanel extends AbstractPanel {
this.renderComponent()
}
async pinView (profile) {
await this.call('pinnedPanel', 'pinView', profile, this.plugins[profile.name].view)
if (this.plugins[profile.name].active) this.call('menuicons', 'select', 'filePanel')
super.remove(profile.name)
this.renderComponent()
}
async unPinView (profile, view) {
const activePlugin = this.currentFocus()
if (activePlugin === profile.name) throw new Error(`Plugin ${profile.name} already unpinned`)
this.loggedState = await this.call('pluginStateLogger', 'getPluginState', profile.name)
super.addView(profile, view)
this.plugins[activePlugin].active = false
this.plugins[profile.name].active = true
this.showContent(profile.name)
}
/**
* Display content and update the header
* @param {String} name The name of the plugin to display
@ -93,12 +111,13 @@ export class SidePanel extends AbstractPanel {
}
updateComponent(state: any) {
return <RemixPluginPanel header={<RemixUIPanelHeader plugins={state.plugins}></RemixUIPanelHeader>} plugins={state.plugins} />
return <RemixPluginPanel header={<RemixUIPanelHeader plugins={state.plugins} pinView={this.pinView.bind(this)} unPinView={this.unPinView.bind(this)}></RemixUIPanelHeader>} plugins={state.plugins} pluginState={state.pluginState} />
}
renderComponent() {
this.dispatch({
plugins: this.plugins
plugins: this.plugins,
pluginState: this.loggedState
})
}
}

@ -0,0 +1,105 @@
import React from 'react'
import { EventEmitter } from 'events'
import { Plugin } from '@remixproject/engine'
import packageJson from '../../../../../package.json'
import { PluginViewWrapper } from '@remix-ui/helper'
import { PluginProfile, StatusBarInterface } from '../../types'
import { RemixUIStatusBar } from '@remix-ui/statusbar'
import { FilePanelType } from '@remix-ui/workspace'
import { VerticalIcons } from './vertical-icons'
const statusBarProfile: PluginProfile = {
name: 'statusBar',
displayName: 'Status Bar',
description: 'Remix IDE status bar panel',
methods: ['isAIActive'],
version: packageJson.version,
}
export class StatusBar extends Plugin implements StatusBarInterface {
htmlElement: HTMLDivElement
events: EventEmitter
filePanelPlugin: FilePanelType
verticalIcons: VerticalIcons
dispatch: React.Dispatch<any> = () => {}
currentWorkspaceName: string = ''
isGitRepo: boolean = false
isAiActive: boolean = false
constructor(filePanel: FilePanelType, veritcalIcons: VerticalIcons) {
super(statusBarProfile)
this.filePanelPlugin = filePanel
this.verticalIcons = veritcalIcons
this.events = new EventEmitter()
this.htmlElement = document.createElement('div')
this.htmlElement.setAttribute('id', 'status-bar')
this.filePanelPlugin
}
async isWorkspaceAGitRepo() {
const isGit = await this.call('fileManager', 'isGitRepo')
if (!isGit) return
this.isGitRepo = true
this.renderComponent()
}
async setCurrentGitWorkspaceName() {
if (!this.isGitRepo) return
const workspaceName = localStorage.getItem('currentWorkspace')
workspaceName && workspaceName.length > 0 ? this.currentWorkspaceName = workspaceName : this.currentWorkspaceName = 'unknown'
this.renderComponent()
}
async isAIActive() {
let aiActive
this.on('settings', 'copilotChoiceUpdated', async (isChecked) => {
aiActive = isChecked
this.isAiActive = isChecked
})
this.renderComponent()
return aiActive
}
onActivation(): void {
this.on('filePanel', 'workspaceInitializationCompleted', async () => {
const isGit = await this.call('fileManager', 'isGitRepo')
if (!isGit) return
const workspaceName = localStorage.getItem('currentWorkspace')
workspaceName && workspaceName.length > 0 ? this.currentWorkspaceName = workspaceName : this.currentWorkspaceName = ''
})
this.on('filePanel', 'switchToWorkspace', async (workspace: string) => {
await this.isWorkspaceAGitRepo()
if (!this.isGitRepo) {
this.currentWorkspaceName = 'Not a git repo'
return
}
const workspaceName = localStorage.getItem('currentWorkspace')
workspaceName && workspaceName.length > 0 ? this.currentWorkspaceName = workspaceName : this.currentWorkspaceName = 'error'
})
this.on('settings', 'copilotChoiceChanged', (isAiActive) => {
this.isAiActive = isAiActive
})
this.renderComponent()
}
setDispatch(dispatch: React.Dispatch<any>) {
this.dispatch = dispatch
}
renderComponent() {
this.dispatch({
plugins: this,
})
}
updateComponent(state: any) {
return <RemixUIStatusBar statusBarPlugin={state.plugins} />
}
render() {
return (
<div data-id="status-bar-container">
<PluginViewWrapper plugin={this} />
</div>
)
}
}

@ -1,11 +1,11 @@
// eslint-disable-next-line no-use-before-define
import React from 'react'
import packageJson from '../../../../../package.json'
import {Plugin} from '@remixproject/engine'
import {EventEmitter} from 'events'
import {IconRecord, RemixUiVerticalIconsPanel} from '@remix-ui/vertical-icons-panel'
import {Profile} from '@remixproject/plugin-utils'
import {PluginViewWrapper} from '@remix-ui/helper'
import { Plugin } from '@remixproject/engine'
import { EventEmitter } from 'events'
import { IconRecord, RemixUiVerticalIconsPanel } from '@remix-ui/vertical-icons-panel'
import { Profile } from '@remixproject/plugin-utils'
import { PluginViewWrapper } from '@remix-ui/helper'
const profile = {
name: 'menuicons',
@ -73,7 +73,26 @@ export class VerticalIcons extends Plugin {
Object.keys(this.icons).map((o) => {
this.icons[o].active = false
})
this.icons[name].active = true
if (this.icons[name]) {
this.icons[name].active = true
}
this.renderComponent()
})
this.on('pinnedPanel', 'pinnedPlugin', (profile) => {
Object.keys(this.icons).map((icon) => {
if (this.icons[icon].profile.name === profile.name) {
this.icons[icon].pinned = true
} else {
this.icons[icon].pinned = false
}
})
this.renderComponent()
})
this.on('pinnedPanel', 'unPinnedPlugin', (profile) => {
if (this.icons[profile.name]) this.icons[profile.name].pinned = false
this.renderComponent()
})
}
@ -84,6 +103,7 @@ export class VerticalIcons extends Plugin {
this.icons[profile.name] = {
profile: profile,
active: false,
pinned: false,
canbeDeactivated: await this.call('manager', 'canDeactivate', this.profile, profile),
timestamp: Date.now()
}

@ -53,7 +53,8 @@ class Editor extends Plugin {
ts: 'typescript',
move: 'move',
circom: 'circom',
nr: 'rust'
nr: 'rust',
toml: 'toml'
}
this.activated = false

@ -14,7 +14,7 @@ import JSZip from 'jszip'
import path from 'path'
import FormData from 'form-data'
import axios from 'axios'
import {Registry} from '@remix-project/remix-lib'
import { Registry } from '@remix-project/remix-lib'
const profile = {
name: 'dGitProvider',
@ -121,7 +121,6 @@ class DGitProvider extends Plugin {
return status
}
const status = await git.statusMatrix({
...await this.getGitConfig(),
...cmd
@ -189,7 +188,7 @@ class DGitProvider extends Plugin {
return newmodule.name === module.name
})
})
for (const module of toRemove) {
const path = (await this.getGitConfig(module.path)).dir
if (await window.remixFileSystem.exists(path)) {
@ -224,7 +223,6 @@ class DGitProvider extends Plugin {
return status
}
const status = await git.log({
...await this.getGitConfig(),
...cmd,
@ -269,8 +267,6 @@ class DGitProvider extends Plugin {
async currentbranch(config) {
if ((Registry.getInstance().get('platform').api.isDesktop())) {
return await this.call('isogit', 'currentbranch')
}
@ -426,11 +422,11 @@ class DGitProvider extends Plugin {
input
}
this.call('terminal', 'logHtml', `Cloning ${input.url}... please wait...`)
try{
try {
const result = await this.call('isogit', 'clone', cmd)
this.call('fs', 'openWindow', folder)
return result
}catch(e){
} catch (e){
this.call('notification', 'alert', {
id: 'dgitAlert',
message: 'Unexpected error while cloning the repository: \n' + e.toString(),
@ -516,7 +512,7 @@ class DGitProvider extends Plugin {
for (const module of gitmodules) {
const dir = path.join(currentDir, module.path)
// if url contains git@github.com: convert it
if(module.url && module.url.startsWith('git@github.com:')) {
if (module.url && module.url.startsWith('git@github.com:')) {
module.url = module.url.replace('git@github.com:', 'https://github.com/')
}
try {
@ -530,7 +526,7 @@ class DGitProvider extends Plugin {
this.call('terminal', 'logHtml', `Cloning submodule ${dir}...`)
await git.clone(cmd)
this.call('terminal', 'logHtml', `Cloned successfully submodule ${dir}...`)
const commitHash = await git.resolveRef({
...await this.getGitConfig(currentDir),
ref: 'HEAD'
@ -540,12 +536,12 @@ class DGitProvider extends Plugin {
...await this.getGitConfig(currentDir),
trees: [git.TREE({ ref: commitHash })],
map: async function (filepath, [A]) {
if(filepath === module.path) {
if (filepath === module.path) {
return await A.oid()
}
}
})
if(result && result.length) {
if (result && result.length) {
this.call('terminal', 'logHtml', `Checking out submodule ${dir} to ${result[0]} in directory ${dir}`)
await git.fetch({
...await this.parseInput(input),
@ -558,16 +554,16 @@ class DGitProvider extends Plugin {
...await this.getGitConfig(dir),
ref: result[0]
})
const log = await git.log({
...await this.getGitConfig(dir),
})
if(log[0].oid !== result[0]) {
if (log[0].oid !== result[0]) {
this.call('terminal', 'log', {
type: 'error',
value: `Could not checkout submodule to ${result[0]}`
})} else {
})} else {
this.call('terminal', 'logHtml',`Checked out submodule ${dir} to ${result[0]}`)
}
}

@ -1,6 +1,5 @@
import FileProvider from "./fileProvider"
declare global {
interface Window {
remixFileSystem: any
@ -50,7 +49,6 @@ export class ElectronProvider extends FileProvider {
}
}
// isDirectory is already included
// this is a more efficient version of the default implementation
async resolveDirectory(path, cb) {

@ -4,7 +4,7 @@ import { saveAs } from 'file-saver'
import JSZip from 'jszip'
import { Plugin } from '@remixproject/engine'
import * as packageJson from '../../../../../package.json'
import {Registry} from '@remix-project/remix-lib'
import { Registry } from '@remix-project/remix-lib'
import { fileChangedToastMsg, recursivePasteToastMsg, storageFullMessage } from '@remix-ui/helper'
import helper from '../../lib/helper.js'
import { RemixAppManager } from '../../remixAppManager'
@ -251,7 +251,7 @@ class FileManager extends Plugin {
throw new Error(e)
}
}
/**
* Set the content of a specific file, does nnot rewrite file if it exists but creates a new unique name
* @param {string} path path of the file
@ -265,11 +265,11 @@ class FileManager extends Plugin {
if (await this.exists(path)) {
const newPath = await helper.createNonClashingNameAsync(path, this)
const content = await this.setFileContent(newPath, data)
return {newContent: content, newPath}
return { newContent: content, newPath }
} else {
const ret = await this.setFileContent(path, data)
this.emit('fileAdded', path)
return {newContent: ret, newpath: path}
return { newContent: ret, newpath: path }
}
} catch (e) {
throw new Error(e)
@ -523,7 +523,7 @@ class FileManager extends Plugin {
this._deps.electronExplorer.event.on('fileRenamed', (oldName, newName, isFolder) => { this.fileRenamedEvent(oldName, newName, isFolder) })
this._deps.electronExplorer.event.on('fileRemoved', (path) => { this.fileRemovedEvent(path) })
this._deps.electronExplorer.event.on('fileAdded', (path) => { this.fileAddedEvent(path) })
this.getCurrentFile = this.file
this.getFile = this.readFile
this.getFolder = this.readdir
@ -726,7 +726,7 @@ class FileManager extends Plugin {
}
try {
// This make sure dependencies are loaded in the editor context.
// This ensure monaco is aware of deps artifacts, so it can provide basic features like "go to" symbols.
// This ensure monaco is aware of deps artifacts, so it can provide basic features like "go to" symbols.
await this.editor.handleTypeScriptDependenciesOf(file, content, path => this.readFile(path), path => this.exists(path))
} catch (e) {
console.log('unable to handle TypeScript dependencies of', file)
@ -927,7 +927,6 @@ class FileManager extends Plugin {
return exists
}
async moveFileIsAllowed (src: string, dest: string) {
try {
src = this.normalize(src)
@ -970,7 +969,7 @@ class FileManager extends Plugin {
if (provider.isSubDirectory(src, dest)) {
this.call('notification', 'toast', recursivePasteToastMsg())
return false
}
}
return true
} catch (e) {
console.log(e)
@ -1033,7 +1032,7 @@ class FileManager extends Plugin {
if (provider.isSubDirectory(src, dest)) {
this.call('notification', 'toast', recursivePasteToastMsg())
return false
}
}
await this.inDepthCopy(src, dest, dirName)
await this.remove(src)
@ -1047,7 +1046,7 @@ class FileManager extends Plugin {
if (provider && provider.copyFolderToJson) {
return await provider.copyFolderToJson(folder)
}
throw new Error('copyFolderToJson not available')
throw new Error('copyFolderToJson not available')
}
}

@ -5,7 +5,6 @@ import EventManager from 'events'
import { Storage } from '@remix-project/remix-lib'
import pathModule from 'path'
export default class FileProvider {
event: any
type: any
@ -189,7 +188,7 @@ export default class FileProvider {
return await this.removeFile(path)
} else {
await window.remixFileSystem.unlink(path)
this.event.emit('fileRemoved', this._normalizePath(path))
this.event.emit('fileRemoved', this._normalizePath(path))
}
} catch (e) {
console.log(e)

@ -67,6 +67,5 @@ export class fileSystems {
return null
}
}

@ -72,7 +72,6 @@ export class fileSystemUtility {
}
}
/**
* copy the folder recursively
* @param {string} path is the folder to be copied over
@ -150,7 +149,6 @@ export class fileSystemUtility {
}
}
/* eslint-disable no-template-curly-in-string */
export const migrationTestData = {
'.workspaces': {

@ -47,7 +47,6 @@ export class IndexedDBStorage extends LightningFS {
}
}
export class indexedDBFileSystem extends fileSystem {
constructor() {
super()

@ -48,7 +48,7 @@ export class localStorageFS extends fileSystem {
localStorage.setItem(test, test);
localStorage.removeItem(test);
resolve(true)
} catch(e) {
} catch (e) {
reject(e)
}
})

@ -34,6 +34,7 @@ const profile = {
methods: [
'createNewFile',
'uploadFile',
'echoCall',
'getCurrentWorkspace',
'getAvailableWorkspaceName',
'getWorkspaces',
@ -43,7 +44,7 @@ const profile = {
'registerContextMenuItem',
'renameWorkspace',
'deleteWorkspace',
'loadTemplate',
'loadTemplate',
'clone',
'isExpanded',
'isGist'
@ -154,10 +155,10 @@ module.exports = class Filepanel extends ViewPlugin {
return this.workspaces
}
getAvailableWorkspaceName(name) {
getAvailableWorkspaceName(name) {
if (!this.workspaces) return name
let index = 1
let workspace = this.workspaces.find((workspace) => workspace.name === name + ' - ' + index)
let workspace = this.workspaces.find((workspace) => workspace.name === name + ' - ' + index)
while (workspace) {
index++
workspace = this.workspaces.find((workspace) => workspace.name === name + ' - ' + index)

@ -6,7 +6,7 @@ import { QueryParams } from '@remix-project/remix-lib'
const profile: Profile = {
name: 'layout',
description: 'layout',
methods: ['minimize', 'maximiseSidePanel', 'resetSidePanel', 'maximizeTerminal']
methods: ['minimize', 'maximiseSidePanel', 'resetSidePanel', 'maximizeTerminal', 'maximisePinnedPanel', 'resetPinnedPanel']
}
interface panelState {
@ -74,6 +74,16 @@ export class Layout extends Plugin {
this.event.emit('resetsidepanel')
}
})
this.on('pinnedPanel', 'pinnedPlugin', async (name) => {
const current = await this.call('pinnedPanel', 'currentFocus')
if (this.maximised[current]) {
this.event.emit('maximisepinnedpanel')
} else {
this.event.emit('resetpinnedpanel')
}
})
document.addEventListener('keypress', e => {
if (e.shiftKey && e.ctrlKey) {
if (e.code === 'KeyF') {
@ -110,6 +120,12 @@ export class Layout extends Plugin {
this.maximised[current] = true
}
async maximisePinnedPanel () {
this.event.emit('maximisepinnedpanel')
const current = await this.call('pinnedPanel', 'currentFocus')
this.maximised[current] = true
}
async maximizeTerminal() {
this.panels.terminal.minimized = false
this.event.emit('change', this.panels)
@ -121,4 +137,10 @@ export class Layout extends Plugin {
const current = await this.call('sidePanel', 'currentFocus')
this.maximised[current] = false
}
async resetPinnedPanel () {
this.event.emit('resetpinnedpanel')
const current = await this.call('pinnedPanel', 'currentFocus')
this.maximised[current] = false
}
}

@ -174,7 +174,7 @@ export class TabProxy extends Plugin {
this.on('fileDecorator', 'fileDecoratorsChanged', async (items) => {
this.tabsApi.setFileDecorations(items)
})
try {
this.themeQuality = (await this.call('theme', 'currentTheme') ).quality
} catch (e) {
@ -240,6 +240,11 @@ export class TabProxy extends Plugin {
if ((name.endsWith('.vy') && icon === undefined) || title.includes('Vyper')) {
icon = 'assets/img/vyperLogo2.webp'
}
if (title === 'Solidity Compile Details') {
icon = 'assets/img/solidity.webp'
}
var slash = name.split('/')
const tabPath = slash.reverse()
@ -357,7 +362,9 @@ export class TabProxy extends Plugin {
const onZoomIn = () => this.editor.editorFontSize(1)
const onZoomOut = () => this.editor.editorFontSize(-1)
const onReady = (api) => { this.tabsApi = api }
const onReady = (api) => {
this.tabsApi = api
}
this.dispatch({
plugin: this,

@ -3,7 +3,7 @@ import React from 'react' // eslint-disable-line
import { RemixUiTerminal, RemixUITerminalWrapper } from '@remix-ui/terminal' // eslint-disable-line
import { Plugin } from '@remixproject/engine'
import * as packageJson from '../../../../../package.json'
import {Registry} from '@remix-project/remix-lib'
import { Registry } from '@remix-project/remix-lib'
import { PluginViewWrapper } from '@remix-ui/helper'
import vm from 'vm'
import EventManager from '../../lib/events'
@ -11,7 +11,6 @@ import EventManager from '../../lib/events'
import { CompilerImports } from '@remix-project/core-plugin' // eslint-disable-line
import { RemixUiXterminals } from '@remix-ui/xterm'
const KONSOLES = []
function register(api) { KONSOLES.push(api) }
@ -113,7 +112,6 @@ class Terminal extends Plugin {
}
onActivation() {
this.renderComponent()
}
@ -142,7 +140,7 @@ class Terminal extends Plugin {
}
updateComponent(state) {
return(
return (
<RemixUITerminalWrapper
plugin={state.plugin}
onReady={state.onReady}

@ -210,8 +210,6 @@ export class CodeFormat extends Plugin {
this.call('notification', 'toast', `Error parsing prettier config file: ${prettierConfigFile}`)
}
// merge options
if (parsed) {
options = {
@ -251,7 +249,6 @@ export class CodeFormat extends Plugin {
}
}
const result = this.prettier.format(content, {
plugins: [sol as any, this.ts, this.babel, this.espree, this.yml],
parser: parserName,

@ -194,4 +194,3 @@ export function parse(text, _parsers, options) {
return parsed;
}

@ -1,6 +1,6 @@
import React from 'react'
import { ViewPlugin } from '@remixproject/engine-web'
import {PluginViewWrapper} from '@remix-ui/helper'
import { PluginViewWrapper } from '@remix-ui/helper'
import { RemixAppManager } from '../../remixAppManager'
import { RemixUiCompileDetails } from '@remix-ui/solidity-compile-details'
@ -45,7 +45,6 @@ export class CompilationDetailsPlugin extends ViewPlugin {
async showDetails(sentPayload: any) {
await this.call('tabs', 'focus', 'compilationDetails')
setTimeout(() => {
// TODO: use the react API to render when the tab is focused and the plugin in the view.
this.payload = sentPayload
this.renderComponent()
}, 2000)

@ -1,6 +1,6 @@
import { Plugin } from '@remixproject/engine'
import { QueryParams } from '@remix-project/remix-lib'
import {Registry} from '@remix-project/remix-lib'
import { Registry } from '@remix-project/remix-lib'
const profile = {
name: 'config',

@ -1,8 +1,9 @@
/* eslint-disable prefer-const */
import React from 'react'
import {Plugin} from '@remixproject/engine'
import {customAction} from '@remixproject/plugin-api'
import {concatSourceFiles, getDependencyGraph, normalizeContractPath} from '@remix-ui/solidity-compiler'
import type {CompilerInput, CompilationSource } from '@remix-project/remix-solidity'
import { Plugin } from '@remixproject/engine'
import { customAction } from '@remixproject/plugin-api'
import { concatSourceFiles, getDependencyGraph, normalizeContractPath } from '@remix-ui/solidity-compiler'
import type { CompilerInput, CompilationSource } from '@remix-project/remix-solidity'
const _paq = (window._paq = window._paq || [])
@ -57,11 +58,12 @@ export class ContractFlattener extends Plugin {
let sorted
let result
let sources
let order: string[] = []
try {
dependencyGraph = getDependencyGraph(ast, filePath, input.settings.remappings)
dependencyGraph = getDependencyGraph(ast, filePath, input.settings.remappings, order)
sorted = dependencyGraph.isEmpty() ? [filePath] : dependencyGraph.sort().reverse()
sources = source.sources
result = concatSourceFiles(sorted, sources)
result = concatSourceFiles(sorted, sources, order)
} catch (err) {
console.warn(err)
}

@ -1,7 +1,7 @@
import { ElectronPlugin } from '@remixproject/engine-electron';
import { Plugin } from '@remixproject/engine';
import { baseURLBin, baseURLWasm } from '@remix-project/remix-solidity'
import axios, {AxiosResponse} from 'axios'
import axios, { AxiosResponse } from 'axios'
import { iSolJsonBinData } from '@remix-project/remix-lib'
const profile = {
@ -55,7 +55,7 @@ export class compilerLoaderPluginDesktop extends ElectronPlugin {
}
async onActivation(): Promise<void> {
this.on('solidity', 'loadingCompiler', async (url) => {
await this.call('compilerloader', 'downloadCompiler', url)
})

@ -78,7 +78,7 @@ export class fsPlugin extends ElectronPlugin {
try {
path = fixPath(path)
const stat = await this.call('fs', 'stat', path)
if(!stat) return undefined
if (!stat) return undefined
stat.isDirectory = () => stat.isDirectoryValue
stat.isFile = () => !stat.isDirectoryValue
return stat
@ -90,7 +90,7 @@ export class fsPlugin extends ElectronPlugin {
try {
path = fixPath(path)
const stat = await this.call('fs', 'lstat', path)
if(!stat) return undefined
if (!stat) return undefined
stat.isDirectory = () => stat.isDirectoryValue
stat.isFile = () => !stat.isDirectoryValue
return stat
@ -116,7 +116,7 @@ export class fsPlugin extends ElectronPlugin {
await this.call('fileManager', 'refresh')
})
this.on('fs', 'error', async (error: string) => {
if(error === 'ENOSPC'){
if (error === 'ENOSPC'){
this.call('notification', 'alert', {
id: 'fsError',
message: 'Cannot watch file changes. There are too many files in your project.'

@ -55,8 +55,8 @@ export class FileDecorator extends Plugin {
if (!from) return
const filteredState = this._fileStates.filter((state) => {
if(state.owner != from) return true
if(path && state.path != path) return true
if (state.owner != from) return true
if (path && state.path != path) return true
})
const newState = [...filteredState].sort(sortByPath)

@ -1,8 +1,8 @@
import {Plugin} from '@remixproject/engine'
import {LibraryProfile, MethodApi, StatusEvents} from '@remixproject/plugin-utils'
import {AppModal} from '@remix-ui/app'
import {AlertModal} from '@remix-ui/app'
import {dispatchModalInterface} from '@remix-ui/app'
import { Plugin } from '@remixproject/engine'
import { LibraryProfile, MethodApi, StatusEvents } from '@remixproject/plugin-utils'
import { AppModal } from '@remix-ui/app'
import { AlertModal } from '@remix-ui/app'
import { dispatchModalInterface } from '@remix-ui/app'
interface INotificationApi {
events: StatusEvents

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save