make fetchAndCompileAPlugin

pull/5370/head
yann300 5 years ago
parent f2f43b82c5
commit f4bdad42d0
  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 { 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)

@ -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 { 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

@ -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 {
<div id="debugger" class="${css.debugger}"></div>
</div>`
let compilers = globalRegistry.get('compilersartefacts').api
fetchAndCompile.event.on('compiling', (settings) => {
this.on('fetchAndCompile', 'compiling', (settings) => {
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>`)
})
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>`)
})
fetchAndCompile.event.on('usingLocalCompilation', (contractAddress) => {
this.on('fetchAndCompile', 'usingLocalCompilation', (contractAddress) => {
toaster(yo`<div><b>Using compilation result from Solidity module</b></div>`)
})
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')

@ -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']

Loading…
Cancel
Save