add solidity script

pull/3549/head
yann300 2 years ago committed by Aniket
parent 5c9f5dfe1e
commit aca95d02ef
  1. 7
      apps/remix-ide/src/app.js
  2. 82
      apps/remix-ide/src/app/plugins/solidity-script.tsx
  3. 7
      apps/remix-ide/src/app/tabs/compile-tab.js
  4. 2
      apps/remix-ide/src/blockchain/blockchain.js
  5. 2
      apps/remix-ide/src/remixAppManager.js
  6. 28
      libs/remix-solidity/src/compiler/compiler-helpers.ts
  7. 73
      libs/remix-solidity/src/compiler/compiler-worker.ts
  8. 5
      libs/remix-ui/tabs/src/lib/remix-ui-tabs.tsx

@ -16,6 +16,7 @@ import { PermissionHandlerPlugin } from './app/plugins/permission-handler-plugin
import { AstWalker } from '@remix-project/remix-astwalker'
import { LinkLibraries, DeployLibraries, OpenZeppelinProxy } from '@remix-project/core-plugin'
import { CodeParser } from './app/plugins/parser/code-parser'
import { SolidityScript } from './app/plugins/solidity-script'
import { WalkthroughService } from './walkthroughService'
@ -246,7 +247,7 @@ class AppComponent {
)
const codeParser = new CodeParser(new AstWalker())
const solidityScript = new SolidityScript()
this.notification = new NotificationPlugin()
@ -298,7 +299,8 @@ class AppComponent {
this.walkthroughService,
search,
solidityumlgen,
contractFlattener
contractFlattener,
solidityScript
])
// LAYOUT & SYSTEM VIEWS
@ -414,6 +416,7 @@ class AppComponent {
await this.appManager.activatePlugin(['hiddenPanel', 'pluginManager', 'codeParser', 'codeFormatter', 'fileDecorator', 'terminal', 'blockchain', 'fetchAndCompile', 'contentImport', 'gistHandler'])
await this.appManager.activatePlugin(['settings'])
await this.appManager.activatePlugin(['walkthrough', 'storage', 'search', 'compileAndRun', 'recorder'])
await this.appManager.activatePlugin(['solidity-script'])
this.appManager.on(
'filePanel',

@ -0,0 +1,82 @@
import React from 'react' // eslint-disable-line
import { format } from 'util'
import { Plugin } from '@remixproject/engine'
import { compile } from '@remix-project/remix-solidity'
import { TransactionConfig } from 'web3-core'
const _paq = window._paq = window._paq || [] //eslint-disable-line
const profile = {
name: 'solidity-script',
displayName: 'solidity-script',
description: 'solidity-script',
methods: ['execute']
}
export class SolidityScript extends Plugin {
constructor () {
super(profile)
}
async execute (path: string) {
_paq.push(['trackEvent', 'SolidityScript', 'execute', 'script'])
let content = await this.call('fileManager', 'readFile', path)
const params = await this.call('solidity', 'getCompilerParameters')
content = `
import "hardhat/console.sol";
contract SolidityScript {
${content}
}`
const targets = { 'script.sol': { content } }
// compile
const compiler = await this.call('solidity', 'getCompiler')
const compilation = await compile(targets, params, async (url, cb) => {
await this.call('contentImport', 'resolveAndSave', url).then((result) => cb(null, result)).catch((error) => cb(error.message))
}, compiler.state.worker)
// get the vm provider
const contract = compilation.getContract('SolidityScript')
const bytecode = '0x' + contract.object.evm.bytecode.object
const web3 = await this.call('blockchain', 'web3VM')
const accounts = await this.call('blockchain', 'getAccounts')
if (!accounts || accounts.length === 0) {
throw new Error('no account available')
}
// deploy the contract
let tx: TransactionConfig = {
from: accounts[0],
data: bytecode
}
const receipt = await web3.eth.sendTransaction(tx)
tx = {
from: accounts[0],
to: receipt.contractAddress,
data: '0x504917d1'
}
const receiptCall = await web3.eth.sendTransaction(tx)
const hhlogs = await web3.eth.getHHLogsForTx(receiptCall.transactionHash)
if (hhlogs && hhlogs.length) {
let finalLogs = <div><div><b>console.log:</b></div>
{
hhlogs.map((log) => {
let formattedLog
// Hardhat implements the same formatting options that can be found in Node.js' console.log,
// which in turn uses util.format: https://nodejs.org/dist/latest-v12.x/docs/api/util.html#util_util_format_format_args
// For example: console.log("Name: %s, Age: %d", remix, 6) will log 'Name: remix, Age: 6'
// We check first arg to determine if 'util.format' is needed
if (typeof log[0] === 'string' && (log[0].includes('%s') || log[0].includes('%d'))) {
formattedLog = format(log[0], ...log.slice(1))
} else {
formattedLog = log.join(' ')
}
return <div>{formattedLog}</div>
})}
</div>
_paq.push(['trackEvent', 'udapp', 'hardhat', 'console.log'])
this.call('terminal', 'logHtml', finalLogs)
}
}
}

@ -21,7 +21,7 @@ const profile = {
documentation: 'https://remix-ide.readthedocs.io/en/latest/compile.html',
version: packageJson.version,
maintainedBy: 'Remix',
methods: ['getCompilationResult', 'compile', 'compileWithParameters', 'setCompilerConfig', 'compileFile', 'getCompilerState']
methods: ['getCompilationResult', 'compile', 'compileWithParameters', 'setCompilerConfig', 'compileFile', 'getCompilerState', 'getCompilerParameters', 'getCompiler']
}
// EditorApi:
@ -133,8 +133,13 @@ class CompileTab extends CompilerApiMixin(ViewPlugin) { // implements ICompilerA
}
}
getCompiler () {
return this.compileTabLogic.compiler
}
getCompilerParameters () {
const params = this.queryParams.get()
params.evmVersion = params.evmVersion === 'null' || params.evmVersion === 'undefined' ? null : params.evmVersion
params.optimize = (params.optimize === 'false' || params.optimize === null || params.optimize === undefined) ? false : params.optimize
params.optimize = params.optimize === 'true' ? true : params.optimize
return params

@ -23,7 +23,7 @@ const profile = {
name: 'blockchain',
displayName: 'Blockchain',
description: 'Blockchain - Logic',
methods: ['getCode', 'getTransactionReceipt', 'addProvider', 'removeProvider', 'getCurrentFork', 'web3VM', 'getProvider'],
methods: ['getCode', 'getTransactionReceipt', 'addProvider', 'removeProvider', 'getCurrentFork', 'getAccounts', 'web3VM', 'getProvider'],
version: packageJson.version
}

@ -11,7 +11,7 @@ const requiredModules = [ // services + layout views + system views
'filePanel', 'terminal', 'settings', 'pluginManager', 'tabs', 'udapp', 'dGitProvider', 'solidity', 'solidity-logic', 'gistHandler', 'layout',
'notification', 'permissionhandler', 'walkthrough', 'storage', 'restorebackupzip', 'link-libraries', 'deploy-libraries', 'openzeppelin-proxy',
'hardhat-provider', 'ganache-provider', 'foundry-provider', 'basic-http-provider', 'injected', 'injected-trustwallet', 'injected-optimism-provider', 'injected-arbitrum-one-provider', 'vm-custom-fork', 'vm-goerli-fork', 'vm-mainnet-fork', 'vm-sepolia-fork', 'vm-merge', 'vm-london', 'vm-berlin',
'compileAndRun', 'search', 'recorder', 'fileDecorator', 'codeParser', 'codeFormatter', 'solidityumlgen', 'contractflattener', 'doc-gen', 'doc-viewer']
'compileAndRun', 'search', 'recorder', 'fileDecorator', 'codeParser', 'codeFormatter', 'solidityumlgen', 'contractflattener', 'doc-gen', 'doc-viewer', 'solidity-script']
// dependentModules shouldn't be manually activated (e.g hardhat is activated by remixd)
const dependentModules = ['foundry', 'hardhat', 'truffle', 'slither']

@ -3,21 +3,17 @@ import { canUseWorker, urlFromVersion } from './compiler-utils'
import { CompilerAbstract } from './compiler-abstract'
import { Compiler } from './compiler'
export const compile = async (compilationTargets, settings, contentResolverCallback) => {
const res = await (() => {
return new Promise((resolve, reject) => {
console.log('compilationTargets', compilationTargets)
const compiler = new Compiler(contentResolverCallback)
compiler.set('evmVersion', settings.evmVersion)
compiler.set('optimize', settings.optimize)
compiler.set('language', settings.language)
compiler.set('runs', settings.runs)
compiler.loadVersion(canUseWorker(settings.version), urlFromVersion(settings.version))
compiler.event.register('compilationFinished', (success, compilationData, source, input, version) => {
resolve(new CompilerAbstract(settings.version, compilationData, source, input))
})
compiler.event.register('compilerLoaded', _ => compiler.compile(compilationTargets, ''))
export const compile = (compilationTargets, settings, contentResolverCallback, worker?: any): Promise<CompilerAbstract> => {
return new Promise((resolve, reject) => {
const compiler = new Compiler(contentResolverCallback)
compiler.set('evmVersion', settings.evmVersion)
compiler.set('optimize', settings.optimize)
compiler.set('language', settings.language)
compiler.set('runs', settings.runs)
compiler.loadVersion(canUseWorker(settings.version), urlFromVersion(settings.version), worker)
compiler.event.register('compilationFinished', (success, compilationData, source, input, version) => {
resolve(new CompilerAbstract(settings.version, compilationData, source, input))
})
})()
return res
compiler.event.register('compilerLoaded', _ => compiler.compile(compilationTargets, ''))
})
}

@ -0,0 +1,73 @@
'use strict'
import * as solc from 'solc/wrapper'
import { CompilerInput, MessageToWorker } from './types'
let compileJSON: ((input: CompilerInput) => string) | null = (input) => { return '' }
const missingInputs: string[] = []
// 'DedicatedWorkerGlobalScope' object (the Worker global scope) is accessible through the self keyword
// 'dom' and 'webworker' library files can't be included together https://github.com/microsoft/TypeScript/issues/20595
export default function (self) { // eslint-disable-line @typescript-eslint/explicit-module-boundary-types
self.addEventListener('message', (e) => {
const data: MessageToWorker = e.data
switch (data.cmd) {
case 'loadVersion':
{
delete self.Module
// NOTE: workaround some browsers?
self.Module = undefined
compileJSON = null
// importScripts() method of synchronously imports one or more scripts into the worker's scope
self.importScripts(data.data)
const compiler: solc = solc(self.Module)
compileJSON = (input) => {
try {
const missingInputsCallback = (path) => {
missingInputs.push(path)
return { error: 'Deferred import' }
}
return compiler.compile(input, { import: missingInputsCallback })
} catch (exception) {
return JSON.stringify({ error: 'Uncaught JavaScript exception:\n' + exception })
}
}
self.postMessage({
cmd: 'versionLoaded',
data: compiler.version(),
license: compiler.license()
})
break
}
case 'compile': {
missingInputs.length = 0
if (data.input && compileJSON) {
self.postMessage({
cmd: 'compiled',
job: data.job,
timestamp: data.timestamp,
data: compileJSON(data.input),
input: data.input,
missingInputs: missingInputs
})
}
break
}
case 'standalone-compile':
missingInputs.length = 0
if (data.input && compileJSON) {
self.postMessage({
cmd: 'standalone-compiled',
job: data.job,
timestamp: data.timestamp,
data: compileJSON(data.input),
input: data.input,
missingInputs: missingInputs
})
}
break
}
}, false)
}

@ -167,10 +167,13 @@ export const TabsUI = (props: TabsUIProps) => {
if (tabsState.currentExt === 'js' || tabsState.currentExt === 'ts') {
await props.plugin.call('scriptRunner', 'execute', content, path)
_paq.push(['trackEvent', 'editor', 'clickRunFromEditor', tabsState.currentExt])
} else if (path.endsWith('.script.sol')) {
await props.plugin.call('solidity-script', 'execute', path)
_paq.push(['trackEvent', 'editor', 'clickRunFromEditor', tabsState.currentExt])
} else if (tabsState.currentExt === 'sol' || tabsState.currentExt === 'yul') {
await props.plugin.call('solidity', 'compile', path)
_paq.push(['trackEvent', 'editor', 'clickRunFromEditor', tabsState.currentExt])
}
}
}}
>
<CustomTooltip

Loading…
Cancel
Save