make fetchAndCompileAPlugin

pull/1/head
yann300 5 years ago
parent b354154f5e
commit ee5c9a7fa9
  1. 8
      src/app.js
  2. 20
      src/app/compiler/compiler-helpers.js
  3. 84
      src/app/compiler/compiler-sourceVerifier-fetchAndCompile.js
  4. 14
      src/app/tabs/debugger-tab.js
  5. 2
      src/remixAppManager.js

@ -54,6 +54,7 @@ import { HiddenPanel } from './app/components/hidden-panel'
import { VerticalIcons } from './app/components/vertical-icons' import { VerticalIcons } from './app/components/vertical-icons'
import { LandingPage } from './app/ui/landing-page/landing-page' import { LandingPage } from './app/ui/landing-page/landing-page'
import { MainPanel } from './app/components/main-panel' import { MainPanel } from './app/components/main-panel'
import FetchAndCompile from './app/compiler/compiler-sourceVerifier-fetchAndCompile'
import migrateFileSystem from './migrateFileSystem' 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) const compilersArtefacts = new CompilersArtefacts() // store all the compilation results (key represent a compiler name)
registry.put({api: compilersArtefacts, name: 'compilersartefacts'}) 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) ----- // ----------------- network service (resolve network id / name) -----
const networkModule = new NetworkModule(blockchain) const networkModule = new NetworkModule(blockchain)
// ----------------- represent the current selected web3 provider ---- // ----------------- 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, offsetToLineColumnConverter,
contextualListener, contextualListener,
terminal, terminal,
web3Provider web3Provider,
fetchAndCompile
]) ])
// LAYOUT & SYSTEM VIEWS // 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(['contentImport', 'theme', 'editor', 'fileManager', 'compilerMetadata', 'compilerArtefacts', 'network', 'web3Provider', 'offsetToLineColumnConverter'])
await appManager.activatePlugin(['mainPanel', 'menuicons']) 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 // Set workspace after initial activation
if (Array.isArray(workspace)) await appManager.activatePlugin(workspace) if (Array.isArray(workspace)) await appManager.activatePlugin(workspace)

@ -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, ''))
})
})()
}

@ -1,13 +1,21 @@
import { EventEmitter } from 'events' import * as packageJson from '../../../package.json'
import { Compiler } from 'remix-solidity' import { Plugin } from '@remixproject/engine'
import { canUseWorker, urlFromVersion } from './compiler-utils' import { urlFromVersion } from './compiler-utils'
import CompilerAbstract from './compiler-abstract' import { compile } from './compiler-helpers'
import globalRegistry from '../../global/registry'
import remixLib from 'remix-lib' import remixLib from 'remix-lib'
class FetchAndCompile { const profile = {
name: 'fetchAndCompile',
methods: ['resolve'],
version: packageJson.version
}
export default class FetchAndCompile extends Plugin {
constructor () { constructor () {
this.event = new EventEmitter() super(profile)
this.compiler = null this.compiler = null
this.unresolvedAddresses = [] this.unresolvedAddresses = []
this.firstResolvedAddress = null 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 * 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. * if no contract address are passed, we default to the first resolved address.
* *
* @param {string} contractAddress - Address of the contrac to resolve * @param {string} contractAddress - Address of the contrac to resolve
* @param {string} compilersartefacts - Object containing a mapping of compilation results (byContractAddress and __last) * @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 * @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 contractAddress = contractAddress || this.firstResolvedAddress
const compilersartefacts = globalRegistry.get('compilersartefacts').api
const localCompilation = () => compilersartefacts.get('__last') ? compilersartefacts.get('__last') : null const localCompilation = () => compilersartefacts.get('__last') ? compilersartefacts.get('__last') : null
const resolved = compilersartefacts.get(contractAddress) const resolved = compilersartefacts.get(contractAddress)
@ -39,7 +50,7 @@ class FetchAndCompile {
let network let network
try { try {
network = await pluginAccess.call('network', 'detectNetwork') network = await this.call('network', 'detectNetwork')
} catch (e) { } catch (e) {
return localCompilation() return localCompilation()
} }
@ -58,38 +69,39 @@ class FetchAndCompile {
if (found) { if (found) {
compilersartefacts.addResolvedContract(contractAddress, compilation) compilersartefacts.addResolvedContract(contractAddress, compilation)
this.firstResolvedAddress = contractAddress this.firstResolvedAddress = contractAddress
setTimeout(_ => this.event.emit('usingLocalCompilation', contractAddress), 0) setTimeout(_ => this.emit('usingLocalCompilation', contractAddress), 0)
return compilation return compilation
} }
} }
let name = network.name.toLowerCase() let name = network.name.toLowerCase()
name === 'main' ? 'mainnet' : name // source-verifier api expect "mainnet" and not "main" name === 'main' ? 'mainnet' : name // source-verifier api expect "mainnet" and not "main"
await pluginAccess.call('manager', 'activatePlugin', 'source-verification') await this.call('manager', 'activatePlugin', 'source-verification')
const data = await pluginAccess.call('source-verification', 'fetch', contractAddress, name.toLowerCase()) const data = await this.call('source-verification', 'fetch', contractAddress, name.toLowerCase())
if (!data || !data.metadata) { if (!data || !data.metadata) {
setTimeout(_ => this.event.emit('notFound', contractAddress), 0) setTimeout(_ => this.emit('notFound', contractAddress), 0)
this.unresolvedAddresses.push(contractAddress) this.unresolvedAddresses.push(contractAddress)
return localCompilation() return localCompilation()
} }
// set the solidity contract code using metadata // 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 = {} let compilationTargets = {}
for (let file in data.metadata.sources) { for (let file in data.metadata.sources) {
const urls = data.metadata.sources[file].urls const urls = data.metadata.sources[file].urls
for (let url of urls) { for (let url of urls) {
if (url.includes('ipfs')) { if (url.includes('ipfs')) {
let stdUrl = `ipfs://${url.split('/')[2]}` 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. file = file.replace('browser/', '') // should be fixed in the remix IDE end.
const path = `${targetPath}/${contractAddress}/${file}` 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 } compilationTargets[path] = { content: source.content }
break break
} }
} }
} }
// compile // compile
const settings = { const settings = {
version: data.metadata.compiler.version, version: data.metadata.compiler.version,
@ -98,32 +110,16 @@ class FetchAndCompile {
optimize: data.metadata.settings.optimizer.enabled, optimize: data.metadata.settings.optimizer.enabled,
compilerUrl: urlFromVersion(data.metadata.compiler.version) compilerUrl: urlFromVersion(data.metadata.compiler.version)
} }
return await (() => { try {
return new Promise((resolve, reject) => { setTimeout(_ => this.emit('compiling', settings), 0)
setTimeout(_ => this.event.emit('compiling', settings), 0) const compData = await compile(compilationTargets, settings)
if (!this.compiler) this.compiler = new Compiler(() => {}) compilersartefacts.addResolvedContract(contractAddress, compData)
this.compiler.set('evmVersion', settings.evmVersion) this.firstResolvedAddress = contractAddress
this.compiler.set('optimize', settings.optimize) return compData
this.compiler.loadVersion(canUseWorker(settings.version), settings.compilerUrl) } catch (e) {
this.compiler.event.register('compilationFinished', (success, compilationData, source) => { this.unresolvedAddresses.push(contractAddress)
if (!success) { setTimeout(_ => this.emit('compilationFailed'), 0)
this.unresolvedAddresses.push(contractAddress) return localCompilation()
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, '')
})
})
})()
} }
} }
const fetchAndCompile = new FetchAndCompile()
export default fetchAndCompile

@ -1,7 +1,5 @@
const yo = require('yo-yo') const yo = require('yo-yo')
const css = require('./styles/debugger-tab-styles') const css = require('./styles/debugger-tab-styles')
var globalRegistry = require('../../global/registry')
import fetchAndCompile from '../compiler/compiler-sourceVerifier-fetchAndCompile'
import toaster from '../ui/tooltip' import toaster from '../ui/tooltip'
const DebuggerUI = require('./debugger/debuggerUI') const DebuggerUI = require('./debugger/debuggerUI')
import { ViewPlugin } from '@remixproject/engine' import { ViewPlugin } from '@remixproject/engine'
@ -36,28 +34,26 @@ class DebuggerTab extends ViewPlugin {
<div id="debugger" class="${css.debugger}"></div> <div id="debugger" class="${css.debugger}"></div>
</div>` </div>`
let compilers = globalRegistry.get('compilersartefacts').api this.on('fetchAndCompile', 'compiling', (settings) => {
fetchAndCompile.event.on('compiling', (settings) => {
toaster(yo`<div><b>Recompiling and debugging with params</b><pre>${JSON.stringify(settings, null, '\t')}</pre></div>`) toaster(yo`<div><b>Recompiling and debugging with params</b><pre>${JSON.stringify(settings, null, '\t')}</pre></div>`)
}) })
fetchAndCompile.event.on('compilationFailed', (data) => { this.on('fetchAndCompile', 'compilationFailed', (data) => {
toaster(yo`<div><b>Compilation failed...</b> continuing <i>without</i> source code debugging.</div>`) toaster(yo`<div><b>Compilation failed...</b> continuing <i>without</i> source code debugging.</div>`)
}) })
fetchAndCompile.event.on('notFound', (contractAddress) => { this.on('fetchAndCompile', 'notFound', (contractAddress) => {
toaster(yo`<div><b>Contract ${contractAddress} not found in source code repository</b> continuing <i>without</i> source code debugging.</div>`) toaster(yo`<div><b>Contract ${contractAddress} not found in source code repository</b> continuing <i>without</i> source code debugging.</div>`)
}) })
fetchAndCompile.event.on('usingLocalCompilation', (contractAddress) => { this.on('fetchAndCompile', 'usingLocalCompilation', (contractAddress) => {
toaster(yo`<div><b>Using compilation result from Solidity module</b></div>`) toaster(yo`<div><b>Using compilation result from Solidity module</b></div>`)
}) })
this.debuggerUI = new DebuggerUI( this.debuggerUI = new DebuggerUI(
this.el.querySelector('#debugger'), this.el.querySelector('#debugger'),
this.blockchain, 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') this.call('manager', 'activatePlugin', 'udapp')

@ -5,7 +5,7 @@ import QueryParams from './lib/query-params'
import { PermissionHandler } from './app/ui/persmission-handler' import { PermissionHandler } from './app/ui/persmission-handler'
const requiredModules = [ // services + layout views + system views 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', 'mainPanel', 'hiddenPanel', 'sidePanel', 'menuicons', 'fileExplorers',
'terminal', 'settings', 'pluginManager'] 'terminal', 'settings', 'pluginManager']

Loading…
Cancel
Save