Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scriptrunner #5167

Merged
merged 7 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions apps/remix-ide/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()

Expand Down Expand Up @@ -371,7 +375,8 @@ class AppComponent {
git,
pluginStateLogger,
matomo,
templateSelection
templateSelection,
scriptRunnerUI
])

//---- fs plugin
Expand Down Expand Up @@ -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'])
}
}

Expand Down
8 changes: 4 additions & 4 deletions apps/remix-ide/src/app/panels/terminal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion apps/remix-ide/src/app/plugins/matomo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand Down
2 changes: 1 addition & 1 deletion apps/remix-ide/src/app/tabs/compile-and-run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
109 changes: 109 additions & 0 deletions apps/remix-ide/src/app/tabs/script-runner-ui.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
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 configuration',
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
currentTemplate: 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)
const profile: IframeProfile = await this.call('manager', 'getProfile', 'scriptRunner')
const testPluginName = localStorage.getItem('test-plugin-name')
const testPluginUrl = localStorage.getItem('test-plugin-url')
let baseUrl = 'http://localhost:3000'
let url = `${baseUrl}?template=${name}`
if(testPluginName === 'scriptRunner'){
// if testpluginurl has template specified only use that
if(testPluginUrl.indexOf('template')>-1){
url = testPluginUrl
}else{
baseUrl = `//${new URL(testPluginUrl).host}`
url = `${baseUrl}?template=${name}&timestamp=${Date.now()}`
}
}

const newProfile: IframeProfile = {
...profile,
name: profile.name + name,
url: url
}
console.log('loadScriptRunner', newProfile)
try {
const plugin: IframePlugin = new IframePlugin(newProfile)
await this.engine.register(plugin)
await this.call('manager', 'activatePlugin', newProfile.name)
this.current = newProfile.name
this.currentTemplate = name
this.on(newProfile.name, 'log', this.log.bind(this))
this.on(newProfile.name, 'info', this.info.bind(this))
this.on(newProfile.name, 'warn', this.warn.bind(this))
this.on(newProfile.name, 'error', this.error.bind(this))
} catch (e) {
this.current = newProfile.name
this.currentTemplate = name
console.log('Already loaded')
}
}

async execute(script: string, filePath: string) {
if (!this.current) await this.loadScriptRunner('default')
console.log('execute', this.current)
await 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 (
<div id="scriptRunnerTab">
<ScriptRunnerUI loadScriptRunner={this.loadScriptRunner.bind(this)} />
</div>
)
}
}
14 changes: 13 additions & 1 deletion apps/remix-ide/src/assets/list.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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"
}
10 changes: 9 additions & 1 deletion apps/remix-ide/src/remixAppManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ let requiredModules = [ // services + layout views + system views
'blockchain',
'web3Provider',
'scriptRunner',
'scriptRunnerBridge',
'fetchAndCompile',
'mainPanel',
'hiddenPanel',
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
}

/**
Expand Down Expand Up @@ -192,6 +197,8 @@ export class RemixAppManager extends PluginManager {
}
}
await this.toggleActive(name)
}else{
console.log('cannot deactivate', name)
}
}

Expand Down Expand Up @@ -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)
})
}
Expand Down
1 change: 1 addition & 0 deletions libs/remix-ui/scriptrunner/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { ScriptRunnerUI } from './lib/script-runner-ui';
83 changes: 83 additions & 0 deletions libs/remix-ui/scriptrunner/src/lib/script-runner-ui.tsx
Original file line number Diff line number Diff line change
@@ -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?timestamp=' + Date.now());
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 (
<div className="px-1">
<Accordion defaultActiveKey="default">
{publishedConfigurations.map((config: ProjectConfiguration, index) => (
<div key={index}>
<div className="d-flex align-items-baseline justify-content-between">
<Accordion.Toggle as={Button} variant="link" eventKey={config.name}>
<span className="pl-2">{config.name}</span>
</Accordion.Toggle>
<div onClick={() => handleSelect(config.name)} className="pointer px-2">
{activeConfig !== config.name ?
<FontAwesomeIcon icon={faToggleOn}></FontAwesomeIcon> :
<FontAwesomeIcon className="text-success" icon={faCheck}></FontAwesomeIcon>
}
</div>
</div>


<Accordion.Collapse className="px-4" eventKey={config.name}>
<>
<p><strong>Description: </strong>{config.description}</p>
<p><strong>Dependencies:</strong></p>
<ul>
{config.dependencies.map((dep, depIndex) => (
<li key={depIndex}>
<strong>{dep.name}</strong> (v{dep.version})
</li>
))}
</ul></>
</Accordion.Collapse></div>))}
</Accordion>

</div>
);
};


20 changes: 20 additions & 0 deletions libs/remix-ui/scriptrunner/src/lib/types.ts
Original file line number Diff line number Diff line change
@@ -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;
}
2 changes: 1 addition & 1 deletion libs/remix-ui/tabs/src/lib/remix-ui-tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading
Loading