diff --git a/apps/remix-ide/src/app.js b/apps/remix-ide/src/app.js
index a3722c7572..17a84f0dc4 100644
--- a/apps/remix-ide/src/app.js
+++ b/apps/remix-ide/src/app.js
@@ -69,6 +69,7 @@ const remixLib = require('@remix-project/remix-lib')
import { QueryParams } from '@remix-project/remix-lib'
import { SearchPlugin } from './app/tabs/search'
+import { ScriptRunnerUIPlugin } from './app/tabs/script-runner-ui'
import { ElectronProvider } from './app/files/electronProvider'
const Storage = remixLib.Storage
@@ -221,6 +222,9 @@ class AppComponent {
//----- search
const search = new SearchPlugin()
+ //---------------- Script Runner UI Plugin -------------------------
+ const scriptRunnerUI = new ScriptRunnerUIPlugin(this.engine)
+
//---- templates
const templates = new TemplatesPlugin()
@@ -371,7 +375,8 @@ class AppComponent {
git,
pluginStateLogger,
matomo,
- templateSelection
+ templateSelection,
+ scriptRunnerUI
])
//---- fs plugin
@@ -611,7 +616,7 @@ class AppComponent {
})
// activate solidity plugin
- this.appManager.activatePlugin(['solidity', 'udapp', 'deploy-libraries', 'link-libraries', 'openzeppelin-proxy'])
+ this.appManager.activatePlugin(['solidity', 'udapp', 'deploy-libraries', 'link-libraries', 'openzeppelin-proxy', 'scriptRunnerBridge'])
}
}
diff --git a/apps/remix-ide/src/app/panels/terminal.tsx b/apps/remix-ide/src/app/panels/terminal.tsx
index 2cb89e3fcb..a30cf085bd 100644
--- a/apps/remix-ide/src/app/panels/terminal.tsx
+++ b/apps/remix-ide/src/app/panels/terminal.tsx
@@ -117,10 +117,10 @@ class Terminal extends Plugin {
}
onDeactivation() {
- this.off('scriptRunner', 'log')
- this.off('scriptRunner', 'info')
- this.off('scriptRunner', 'warn')
- this.off('scriptRunner', 'error')
+ this.off('scriptRunnerBridge', 'log')
+ this.off('scriptRunnerBridge', 'info')
+ this.off('scriptRunnerBridge', 'warn')
+ this.off('scriptRunnerBridge', 'error')
}
logHtml(html) {
diff --git a/apps/remix-ide/src/app/plugins/matomo.ts b/apps/remix-ide/src/app/plugins/matomo.ts
index 8aa8f61f70..688139d113 100644
--- a/apps/remix-ide/src/app/plugins/matomo.ts
+++ b/apps/remix-ide/src/app/plugins/matomo.ts
@@ -11,7 +11,7 @@ const profile = {
version: '1.0.0'
}
-const allowedPlugins = ['LearnEth', 'etherscan', 'vyper', 'circuit-compiler', 'doc-gen', 'doc-viewer', 'solhint', 'walletconnect', 'scriptRunner', 'dgit']
+const allowedPlugins = ['LearnEth', 'etherscan', 'vyper', 'circuit-compiler', 'doc-gen', 'doc-viewer', 'solhint', 'walletconnect', 'scriptRunner', 'scriptRunnerBridge', 'dgit']
export class Matomo extends Plugin {
diff --git a/apps/remix-ide/src/app/tabs/compile-and-run.ts b/apps/remix-ide/src/app/tabs/compile-and-run.ts
index 63952747c9..9643cd78e9 100644
--- a/apps/remix-ide/src/app/tabs/compile-and-run.ts
+++ b/apps/remix-ide/src/app/tabs/compile-and-run.ts
@@ -62,7 +62,7 @@ export class CompileAndRun extends Plugin {
if (clearAllInstances) {
await this.call('udapp', 'clearAllInstances')
}
- await this.call('scriptRunner', 'execute', content, fileName)
+ await this.call('scriptRunnerBridge', 'execute', content, fileName)
} catch (e) {
this.call('notification', 'toast', e.message || e)
}
diff --git a/apps/remix-ide/src/app/tabs/script-runner-ui.tsx b/apps/remix-ide/src/app/tabs/script-runner-ui.tsx
new file mode 100644
index 0000000000..d5072b80cd
--- /dev/null
+++ b/apps/remix-ide/src/app/tabs/script-runner-ui.tsx
@@ -0,0 +1,87 @@
+import { IframePlugin, IframeProfile, ViewPlugin } from '@remixproject/engine-web'
+import * as packageJson from '../../../../../package.json'
+import React from 'react' // eslint-disable-line
+import { ScriptRunnerUI } from '@remix-scriptrunner' // eslint-disable-line
+import { Profile } from '@remixproject/plugin-utils'
+import { Engine } from '@remixproject/engine'
+const profile = {
+ name: 'scriptRunnerBridge',
+ displayName: 'Script Bridge',
+ methods: ['execute'],
+ events: ['log', 'info', 'warn', 'error'],
+ icon: 'assets/img/settings.webp',
+ description: 'Set up a script runner',
+ kind: '',
+ location: 'sidePanel',
+ version: packageJson.version,
+ maintainedBy: 'Remix'
+}
+
+export class ScriptRunnerUIPlugin extends ViewPlugin {
+ engine: Engine
+ current: string
+ constructor(engine: Engine) {
+ super(profile)
+ console.log('ScriptRunnerUIPlugin', this)
+ this.engine = engine
+ }
+
+ async onActivation () {
+ console.log('onActivation', this)
+ }
+
+ async loadScriptRunner(name: string) {
+ console.log('loadScriptRunner', name, this)
+ const profile: IframeProfile = await this.call('manager', 'getProfile', 'scriptRunner')
+ const newProfile: IframeProfile = {
+ ...profile,
+ name: profile.name + name,
+ url: 'http://localhost:3000?template=' + name
+ }
+ console.log('loadScriptRunner', newProfile)
+ const plugin: IframePlugin = new IframePlugin(newProfile)
+ await this.engine.register(plugin)
+
+ await this.call('manager', 'activatePlugin', newProfile.name)
+ this.current = newProfile.name
+ this.on(newProfile.name, 'log', this.log.bind(this))
+ this.on(newProfile.name, 'info', this.log.bind(this))
+ this.on(newProfile.name, 'warn', this.log.bind(this))
+ this.on(newProfile.name, 'error', this.log.bind(this))
+ }
+
+ async execute (script: string, filePath: string) {
+ if(!this.current) await this.loadScriptRunner('default')
+ console.log('execute', script, filePath)
+ this.call(this.current, 'execute', script, filePath)
+ }
+
+ async log(data: any){
+ console.log('log', data)
+ this.emit('log', data)
+ }
+
+ async warn(data: any){
+ console.log('warn', data)
+ this.emit('warn', data)
+ }
+
+ async error(data: any){
+ console.log('error', data)
+ this.emit('error', data)
+ }
+
+ async info(data: any){
+ console.log('info', data)
+ this.emit('info', data)
+ }
+
+
+ render() {
+ return (
+
+
+
+ )
+ }
+}
\ No newline at end of file
diff --git a/apps/remix-ide/src/assets/list.json b/apps/remix-ide/src/assets/list.json
index 6a55fff4f7..82f8fe17bb 100644
--- a/apps/remix-ide/src/assets/list.json
+++ b/apps/remix-ide/src/assets/list.json
@@ -1022,9 +1022,21 @@
"urls": [
"dweb:/ipfs/QmS5JdeXtYhGBvdgNTLWuBNHupyP623X4sf43fRbrgiTaA"
]
+ },
+ {
+ "path": "soljson-v0.8.27+commit.40a35a09.js",
+ "version": "0.8.27",
+ "build": "commit.40a35a09",
+ "longVersion": "0.8.27+commit.40a35a09",
+ "keccak256": "0x68c7a06651a847fc9a60886a6ba590a2b20d87f2d4f9570bf70fbb2b901e7713",
+ "sha256": "0xd91c08277f801321af4e80958015aea18b41c01d2c6a38310a23014485b0e51c",
+ "urls": [
+ "dweb:/ipfs/QmVTALD1WUQwRvEL19jgwrEFyBJMQmy9z32zvT6TAtYPY1"
+ ]
}
],
"releases": {
+ "0.8.27": "soljson-v0.8.27+commit.40a35a09.js",
"0.8.26": "soljson-v0.8.26+commit.8a97fa7a.js",
"0.8.25": "soljson-v0.8.25+commit.b61c2a91.js",
"0.8.24": "soljson-v0.8.24+commit.e11b9ed9.js",
@@ -1119,5 +1131,5 @@
"0.4.0": "soljson-v0.4.0+commit.acd334c9.js",
"0.3.6": "soljson-v0.3.6+commit.3fc68da5.js"
},
- "latestRelease": "0.8.26"
+ "latestRelease": "0.8.27"
}
\ No newline at end of file
diff --git a/apps/remix-ide/src/remixAppManager.js b/apps/remix-ide/src/remixAppManager.js
index f823069585..bf70a26fdb 100644
--- a/apps/remix-ide/src/remixAppManager.js
+++ b/apps/remix-ide/src/remixAppManager.js
@@ -24,6 +24,7 @@ let requiredModules = [ // services + layout views + system views
'blockchain',
'web3Provider',
'scriptRunner',
+ 'scriptRunnerBridge',
'fetchAndCompile',
'mainPanel',
'hiddenPanel',
@@ -107,6 +108,10 @@ const isVM = (name) => {
return name.startsWith('vm')
}
+const isScriptRunner = (name) => {
+ return name.startsWith('scriptRunner')
+}
+
export function isNative(name) {
// nativePlugin allows to bypass the permission request
@@ -139,7 +144,7 @@ export function isNative(name) {
'templateSelection',
'walletconnect'
]
- return nativePlugins.includes(name) || requiredModules.includes(name) || isInjectedProvider(name) || isVM(name)
+ return nativePlugins.includes(name) || requiredModules.includes(name) || isInjectedProvider(name) || isVM(name) || isScriptRunner(name)
}
/**
@@ -192,6 +197,8 @@ export class RemixAppManager extends PluginManager {
}
}
await this.toggleActive(name)
+ }else{
+ console.log('cannot deactivate', name)
}
}
@@ -294,6 +301,7 @@ export class RemixAppManager extends PluginManager {
return plugins.map(plugin => {
if (plugin.name === 'dgit' && Registry.getInstance().get('platform').api.isDesktop()) { plugin.url = 'https://dgit4-76cc9.web.app/' } // temporary fix
if (plugin.name === testPluginName) plugin.url = testPluginUrl
+ //console.log('plugin', plugin)
return new IframePlugin(plugin)
})
}
diff --git a/libs/remix-ui/scriptrunner/src/index.ts b/libs/remix-ui/scriptrunner/src/index.ts
new file mode 100644
index 0000000000..be8e8bb09c
--- /dev/null
+++ b/libs/remix-ui/scriptrunner/src/index.ts
@@ -0,0 +1 @@
+export { ScriptRunnerUI } from './lib/script-runner-ui';
\ No newline at end of file
diff --git a/libs/remix-ui/scriptrunner/src/lib/script-runner-ui.tsx b/libs/remix-ui/scriptrunner/src/lib/script-runner-ui.tsx
new file mode 100644
index 0000000000..5fe5ad0bf4
--- /dev/null
+++ b/libs/remix-ui/scriptrunner/src/lib/script-runner-ui.tsx
@@ -0,0 +1,83 @@
+import React, { useEffect, useState } from "react";
+import { Accordion, Card, Button } from "react-bootstrap";
+import axios from "axios";
+import { ProjectConfiguration } from "./types";
+import { FormattedMessage } from "react-intl";
+import { faCheck, faToggleOn } from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { Profile } from "@remixproject/plugin-utils";
+import { IframeProfile, ViewProfile } from "@remixproject/engine-web";
+import { Plugin } from "@remixproject/engine";
+
+export interface ScriptRunnerUIProps {
+ // Add your props here
+ loadScriptRunner: (name: string) => void;
+}
+
+export const ScriptRunnerUI = (props: ScriptRunnerUIProps) => {
+ const { loadScriptRunner } = props;
+ const [configurations, setConfigurations] = useState([]);
+ const [activeKey, setActiveKey] = useState('default');
+ const [activeConfig, setActiveConfig] = useState('default');
+
+ useEffect(() => {
+ // Fetch the JSON data from the localhost server using Axios
+ const fetchData = async () => {
+ try {
+ const response = await axios.get('http://localhost:3000/projects.json');
+ setConfigurations(response.data);
+ } catch (error) {
+ console.error("Error fetching the projects data:", error);
+ }
+ };
+
+ fetchData();
+ }, []); // Empty array ensures this effect runs once when the component mounts
+
+ const handleSelect = (key) => {
+ console.log("Selected key:", key, activeKey);
+ setActiveConfig(key);
+ console.log(loadScriptRunner)
+ loadScriptRunner(key)
+ };
+
+ // Filter out unpublished configurations
+ const publishedConfigurations = configurations.filter((config) => config.publish);
+
+ return (
+
+
+ {publishedConfigurations.map((config: ProjectConfiguration, index) => (
+
+
+
+ {config.name}
+
+
handleSelect(config.name)} className="pointer px-2">
+ {activeConfig !== config.name ?
+ :
+
+ }
+
+
+
+
+
+ <>
+ Description: {config.description}
+ Dependencies:
+
+ {config.dependencies.map((dep, depIndex) => (
+ -
+ {dep.name} (v{dep.version})
+
+ ))}
+
>
+ ))}
+
+
+
+ );
+};
+
+
diff --git a/libs/remix-ui/scriptrunner/src/lib/types.ts b/libs/remix-ui/scriptrunner/src/lib/types.ts
new file mode 100644
index 0000000000..ff093b428b
--- /dev/null
+++ b/libs/remix-ui/scriptrunner/src/lib/types.ts
@@ -0,0 +1,20 @@
+export interface Dependency {
+ version: string;
+ name: string;
+ alias?: string;
+ import: boolean;
+ require?: boolean;
+ windowImport?: boolean;
+ }
+
+ export interface Replacements {
+ [key: string]: string;
+ }
+
+ export interface ProjectConfiguration {
+ name: string;
+ publish: boolean;
+ description: string;
+ dependencies: Dependency[];
+ replacements: Replacements;
+ }
diff --git a/libs/remix-ui/tabs/src/lib/remix-ui-tabs.tsx b/libs/remix-ui/tabs/src/lib/remix-ui-tabs.tsx
index 311b4c166a..3f57709eca 100644
--- a/libs/remix-ui/tabs/src/lib/remix-ui-tabs.tsx
+++ b/libs/remix-ui/tabs/src/lib/remix-ui-tabs.tsx
@@ -209,7 +209,7 @@ export const TabsUI = (props: TabsUIProps) => {
const path = active().substr(active().indexOf('/') + 1, active().length)
const content = await props.plugin.call('fileManager', 'readFile', path)
if (tabsState.currentExt === 'js' || tabsState.currentExt === 'ts') {
- await props.plugin.call('scriptRunner', 'execute', content, path)
+ await props.plugin.call('scriptRunnerBridge', 'execute', content, path)
_paq.push(['trackEvent', 'editor', 'clickRunFromEditor', tabsState.currentExt])
} else if (tabsState.currentExt === 'sol' || tabsState.currentExt === 'yul') {
await props.plugin.call('solidity', 'compile', path)
diff --git a/libs/remix-ui/terminal/src/lib/actions/terminalAction.ts b/libs/remix-ui/terminal/src/lib/actions/terminalAction.ts
index ceeea496f7..0a8a6b5891 100644
--- a/libs/remix-ui/terminal/src/lib/actions/terminalAction.ts
+++ b/libs/remix-ui/terminal/src/lib/actions/terminalAction.ts
@@ -79,28 +79,29 @@ export const filterFnAction = (name: string, filterFn, dispatch: React.Dispatch<
}
export const registerLogScriptRunnerAction = (on, commandName, commandFn, dispatch: React.Dispatch) => {
- on('scriptRunner', commandName, (msg) => {
+ console.log('registerLogScriptRunnerAction', commandName)
+ on('scriptRunnerBridge', commandName, (msg) => {
commandFn.log.apply(commandFn, msg.data) // eslint-disable-line
dispatch({ type: commandName, payload: { commandFn, message: msg.data } })
})
}
export const registerInfoScriptRunnerAction = (on, commandName, commandFn, dispatch: React.Dispatch) => {
- on('scriptRunner', commandName, (msg) => {
+ on('scriptRunnerBridge', commandName, (msg) => {
commandFn.info.apply(commandFn, msg.data) // eslint-disable-line
dispatch({ type: commandName, payload: { commandFn, message: msg.data } })
})
}
export const registerWarnScriptRunnerAction = (on, commandName, commandFn, dispatch: React.Dispatch) => {
- on('scriptRunner', commandName, (msg) => {
+ on('scriptRunnerBridge', commandName, (msg) => {
commandFn.warn.apply(commandFn, msg.data) // eslint-disable-line
dispatch({ type: commandName, payload: { commandFn, message: msg.data } })
})
}
export const registerErrorScriptRunnerAction = (on, commandName, commandFn, dispatch: React.Dispatch) => {
- on('scriptRunner', commandName, (msg) => {
+ on('scriptRunnerBridge', commandName, (msg) => {
commandFn.error.apply(commandFn, msg.data) // eslint-disable-line
dispatch({ type: commandName, payload: { commandFn, message: msg.data } })
})
diff --git a/libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx b/libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx
index 29f471be3a..b88b7da73e 100644
--- a/libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx
+++ b/libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx
@@ -245,7 +245,7 @@ export const RemixUiTerminal = (props: RemixUiTerminalProps) => {
await call('solcoder', 'solidity_answer', script)
_paq.push(['trackEvent', 'ai', 'solcoder', 'askFromTerminal'])
} else {
- await call('scriptRunner', 'execute', script)
+ await call('scriptRunnerBridge', 'execute', script)
}
done()
} catch (error) {
diff --git a/libs/remix-ui/workspace/src/lib/actions/index.ts b/libs/remix-ui/workspace/src/lib/actions/index.ts
index e10fa20d43..23b9598ce4 100644
--- a/libs/remix-ui/workspace/src/lib/actions/index.ts
+++ b/libs/remix-ui/workspace/src/lib/actions/index.ts
@@ -506,7 +506,7 @@ export const runScript = async (path: string) => {
if (error) {
return dispatch(displayPopUp(error))
}
- plugin.call('scriptRunner', 'execute', content, path)
+ plugin.call('scriptRunnerBridge', 'execute', content, path)
})
}
diff --git a/tsconfig.paths.json b/tsconfig.paths.json
index 3b4433ee92..c1c11be318 100644
--- a/tsconfig.paths.json
+++ b/tsconfig.paths.json
@@ -180,7 +180,10 @@
],
"@remix-api": [
"libs/remix-api/src/index.ts"
- ]
+ ],
+ "@remix-scriptrunner": [
+ "libs/remix-ui/scriptrunner/src/index.ts"
+ ],
}
}
}