From f4bdad42d07dce129cc454deccdfee94ae013bb2 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 24 Apr 2020 13:09:04 +0200 Subject: [PATCH] make fetchAndCompileAPlugin --- src/app.js | 8 +- src/app/compiler/compiler-helpers.js | 20 +++++ ...compiler-sourceVerifier-fetchAndCompile.js | 84 +++++++++---------- src/app/tabs/debugger-tab.js | 14 ++-- src/remixAppManager.js | 2 +- 5 files changed, 72 insertions(+), 56 deletions(-) create mode 100644 src/app/compiler/compiler-helpers.js diff --git a/src/app.js b/src/app.js index 5d21483e25..afbcae5d40 100644 --- a/src/app.js +++ b/src/app.js @@ -54,6 +54,7 @@ import { HiddenPanel } from './app/components/hidden-panel' import { VerticalIcons } from './app/components/vertical-icons' import { LandingPage } from './app/ui/landing-page/landing-page' import { MainPanel } from './app/components/main-panel' +import FetchAndCompile from './app/compiler/compiler-sourceVerifier-fetchAndCompile' import migrateFileSystem from './migrateFileSystem' @@ -267,6 +268,8 @@ Please make a backup of your contracts and start using http://remix.ethereum.org const compilersArtefacts = new CompilersArtefacts() // store all the compilation results (key represent a compiler name) registry.put({api: compilersArtefacts, name: 'compilersartefacts'}) + // service which fetch contract artifacts from sourve-verify, put artifacts in remix and compile it + const fetchAndCompile = new FetchAndCompile() // ----------------- network service (resolve network id / name) ----- const networkModule = new NetworkModule(blockchain) // ----------------- represent the current selected web3 provider ---- @@ -305,7 +308,8 @@ Please make a backup of your contracts and start using http://remix.ethereum.org offsetToLineColumnConverter, contextualListener, terminal, - web3Provider + web3Provider, + fetchAndCompile ]) // LAYOUT & SYSTEM VIEWS @@ -391,7 +395,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org await appManager.activatePlugin(['contentImport', 'theme', 'editor', 'fileManager', 'compilerMetadata', 'compilerArtefacts', 'network', 'web3Provider', 'offsetToLineColumnConverter']) await appManager.activatePlugin(['mainPanel', 'menuicons']) - await appManager.activatePlugin(['home', 'sidePanel', 'hiddenPanel', 'pluginManager', 'fileExplorers', 'settings', 'contextualListener', 'scriptRunner', 'terminal']) + await appManager.activatePlugin(['home', 'sidePanel', 'hiddenPanel', 'pluginManager', 'fileExplorers', 'settings', 'contextualListener', 'scriptRunner', 'terminal', 'fetchAndCompile']) // Set workspace after initial activation if (Array.isArray(workspace)) await appManager.activatePlugin(workspace) diff --git a/src/app/compiler/compiler-helpers.js b/src/app/compiler/compiler-helpers.js new file mode 100644 index 0000000000..a20ffa13b1 --- /dev/null +++ b/src/app/compiler/compiler-helpers.js @@ -0,0 +1,20 @@ +'use strict' +import { canUseWorker } from './compiler-utils' +import { Compiler } from 'remix-solidity' +import CompilerAbstract from './compiler-abstract' + +export const compile = async (compilationTargets, settings) => { + return await (() => { + return new Promise((resolve, reject) => { + const compiler = new Compiler(() => {}) + compiler.set('evmVersion', settings.evmVersion) + compiler.set('optimize', settings.optimize) + compiler.loadVersion(canUseWorker(settings.version), settings.compilerUrl) + compiler.event.register('compilationFinished', (success, compilationData, source) => { + if (!success) return reject(compilationData) + resolve(new CompilerAbstract(settings.version, compilationData, source)) + }) + compiler.event.register('compilerLoaded', _ => compiler.compile(compilationTargets, '')) + }) + })() +} diff --git a/src/app/compiler/compiler-sourceVerifier-fetchAndCompile.js b/src/app/compiler/compiler-sourceVerifier-fetchAndCompile.js index 7a01768caa..8356939d38 100644 --- a/src/app/compiler/compiler-sourceVerifier-fetchAndCompile.js +++ b/src/app/compiler/compiler-sourceVerifier-fetchAndCompile.js @@ -1,13 +1,21 @@ -import { EventEmitter } from 'events' -import { Compiler } from 'remix-solidity' -import { canUseWorker, urlFromVersion } from './compiler-utils' -import CompilerAbstract from './compiler-abstract' +import * as packageJson from '../../../package.json' +import { Plugin } from '@remixproject/engine' +import { urlFromVersion } from './compiler-utils' +import { compile } from './compiler-helpers' +import globalRegistry from '../../global/registry' + import remixLib from 'remix-lib' -class FetchAndCompile { +const profile = { + name: 'fetchAndCompile', + methods: ['resolve'], + version: packageJson.version +} + +export default class FetchAndCompile extends Plugin { constructor () { - this.event = new EventEmitter() + super(profile) this.compiler = null this.unresolvedAddresses = [] this.firstResolvedAddress = null @@ -16,17 +24,20 @@ class FetchAndCompile { /** * Fetch compiliation metadata from source-Verify from a given @arg contractAddress - https://github.com/ethereum/source-verify - * Compile the code using Solidity compiler. + * Put the artifacts in the file explorer + * Compile the code using Solidity compiler + * Returns compilation data * if no contract address are passed, we default to the first resolved address. * * @param {string} contractAddress - Address of the contrac to resolve * @param {string} compilersartefacts - Object containing a mapping of compilation results (byContractAddress and __last) - * @param {object} pluginAccess - any registered plugin (for making the calls) * @return {CompilerAbstract} - compilation data targeting the given @arg contractAddress */ - async resolve (contractAddress, compilersartefacts, pluginAccess, targetPath, web3) { + async resolve (contractAddress, targetPath, web3) { contractAddress = contractAddress || this.firstResolvedAddress + const compilersartefacts = globalRegistry.get('compilersartefacts').api + const localCompilation = () => compilersartefacts.get('__last') ? compilersartefacts.get('__last') : null const resolved = compilersartefacts.get(contractAddress) @@ -39,7 +50,7 @@ class FetchAndCompile { let network try { - network = await pluginAccess.call('network', 'detectNetwork') + network = await this.call('network', 'detectNetwork') } catch (e) { return localCompilation() } @@ -58,38 +69,39 @@ class FetchAndCompile { if (found) { compilersartefacts.addResolvedContract(contractAddress, compilation) this.firstResolvedAddress = contractAddress - setTimeout(_ => this.event.emit('usingLocalCompilation', contractAddress), 0) + setTimeout(_ => this.emit('usingLocalCompilation', contractAddress), 0) return compilation } } let name = network.name.toLowerCase() name === 'main' ? 'mainnet' : name // source-verifier api expect "mainnet" and not "main" - await pluginAccess.call('manager', 'activatePlugin', 'source-verification') - const data = await pluginAccess.call('source-verification', 'fetch', contractAddress, name.toLowerCase()) + await this.call('manager', 'activatePlugin', 'source-verification') + const data = await this.call('source-verification', 'fetch', contractAddress, name.toLowerCase()) if (!data || !data.metadata) { - setTimeout(_ => this.event.emit('notFound', contractAddress), 0) + setTimeout(_ => this.emit('notFound', contractAddress), 0) this.unresolvedAddresses.push(contractAddress) return localCompilation() } // set the solidity contract code using metadata - await pluginAccess.call('fileManager', 'setFile', `${targetPath}/${contractAddress}/metadata.json`, JSON.stringify(data.metadata, null, '\t')) + await this.call('fileManager', 'setFile', `${targetPath}/${contractAddress}/metadata.json`, JSON.stringify(data.metadata, null, '\t')) let compilationTargets = {} for (let file in data.metadata.sources) { const urls = data.metadata.sources[file].urls for (let url of urls) { if (url.includes('ipfs')) { let stdUrl = `ipfs://${url.split('/')[2]}` - const source = await pluginAccess.call('contentImport', 'resolve', stdUrl) + const source = await this.call('contentImport', 'resolve', stdUrl) file = file.replace('browser/', '') // should be fixed in the remix IDE end. const path = `${targetPath}/${contractAddress}/${file}` - await pluginAccess.call('fileManager', 'setFile', path, source.content) + await this.call('fileManager', 'setFile', path, source.content) compilationTargets[path] = { content: source.content } break } } } + // compile const settings = { version: data.metadata.compiler.version, @@ -98,32 +110,16 @@ class FetchAndCompile { optimize: data.metadata.settings.optimizer.enabled, compilerUrl: urlFromVersion(data.metadata.compiler.version) } - return await (() => { - return new Promise((resolve, reject) => { - setTimeout(_ => this.event.emit('compiling', settings), 0) - if (!this.compiler) this.compiler = new Compiler(() => {}) - this.compiler.set('evmVersion', settings.evmVersion) - this.compiler.set('optimize', settings.optimize) - this.compiler.loadVersion(canUseWorker(settings.version), settings.compilerUrl) - this.compiler.event.register('compilationFinished', (success, compilationData, source) => { - if (!success) { - this.unresolvedAddresses.push(contractAddress) - setTimeout(_ => this.event.emit('compilationFailed', compilationData), 0) - return resolve(null) - } - const compilerData = new CompilerAbstract(settings.version, compilationData, source) - compilersartefacts.addResolvedContract(contractAddress, compilerData) - this.firstResolvedAddress = contractAddress - resolve(compilerData) - }) - this.compiler.event.register('compilerLoaded', (version) => { - this.compiler.compile(compilationTargets, '') - }) - }) - })() + try { + setTimeout(_ => this.emit('compiling', settings), 0) + const compData = await compile(compilationTargets, settings) + compilersartefacts.addResolvedContract(contractAddress, compData) + this.firstResolvedAddress = contractAddress + return compData + } catch (e) { + this.unresolvedAddresses.push(contractAddress) + setTimeout(_ => this.emit('compilationFailed'), 0) + return localCompilation() + } } } - -const fetchAndCompile = new FetchAndCompile() - -export default fetchAndCompile diff --git a/src/app/tabs/debugger-tab.js b/src/app/tabs/debugger-tab.js index 157483e510..63fc792ea4 100644 --- a/src/app/tabs/debugger-tab.js +++ b/src/app/tabs/debugger-tab.js @@ -1,7 +1,5 @@ const yo = require('yo-yo') const css = require('./styles/debugger-tab-styles') -var globalRegistry = require('../../global/registry') -import fetchAndCompile from '../compiler/compiler-sourceVerifier-fetchAndCompile' import toaster from '../ui/tooltip' const DebuggerUI = require('./debugger/debuggerUI') import { ViewPlugin } from '@remixproject/engine' @@ -36,28 +34,26 @@ class DebuggerTab extends ViewPlugin {
` - let compilers = globalRegistry.get('compilersartefacts').api - - fetchAndCompile.event.on('compiling', (settings) => { + this.on('fetchAndCompile', 'compiling', (settings) => { toaster(yo`
Recompiling and debugging with params
${JSON.stringify(settings, null, '\t')}
`) }) - fetchAndCompile.event.on('compilationFailed', (data) => { + this.on('fetchAndCompile', 'compilationFailed', (data) => { toaster(yo`
Compilation failed... continuing without source code debugging.
`) }) - fetchAndCompile.event.on('notFound', (contractAddress) => { + this.on('fetchAndCompile', 'notFound', (contractAddress) => { toaster(yo`
Contract ${contractAddress} not found in source code repository continuing without source code debugging.
`) }) - fetchAndCompile.event.on('usingLocalCompilation', (contractAddress) => { + this.on('fetchAndCompile', 'usingLocalCompilation', (contractAddress) => { toaster(yo`
Using compilation result from Solidity module
`) }) this.debuggerUI = new DebuggerUI( this.el.querySelector('#debugger'), this.blockchain, - adddress => fetchAndCompile.resolve(adddress, compilers, this, '.debug', this.blockchain.web3())) + adddress => this.call('fetchAndCompile', 'resolve', adddress, '.debug', this.blockchain.web3())) this.call('manager', 'activatePlugin', 'udapp') diff --git a/src/remixAppManager.js b/src/remixAppManager.js index 36b53d2c31..9d008ff582 100644 --- a/src/remixAppManager.js +++ b/src/remixAppManager.js @@ -5,7 +5,7 @@ import QueryParams from './lib/query-params' import { PermissionHandler } from './app/ui/persmission-handler' const requiredModules = [ // services + layout views + system views - 'manager', 'compilerArtefacts', 'compilerMetadata', 'contextualListener', 'editor', 'offsetToLineColumnConverter', 'network', 'theme', 'fileManager', 'contentImport', 'web3Provider', 'scriptRunner', + 'manager', 'compilerArtefacts', 'compilerMetadata', 'contextualListener', 'editor', 'offsetToLineColumnConverter', 'network', 'theme', 'fileManager', 'contentImport', 'web3Provider', 'scriptRunner', 'fetchAndCompile', 'mainPanel', 'hiddenPanel', 'sidePanel', 'menuicons', 'fileExplorers', 'terminal', 'settings', 'pluginManager']