refactor rhpp

pull/1/head
yann300 7 years ago
parent 317801bfca
commit 911ba041fa
  1. 189
      src/app.js
  2. 9
      src/app/editor/editor.js
  3. 4
      src/app/panels/editor-panel.js
  4. 32
      src/app/panels/righthand-panel.js
  5. 10
      src/app/plugin/pluginAPI.js
  6. 23
      src/app/plugin/pluginManager.js
  7. 6
      src/app/tabs/analysis-tab.js
  8. 74
      src/app/tabs/compile-tab.js
  9. 6
      src/app/tabs/debugger-tab.js
  10. 7
      src/app/tabs/plugin-tab.js
  11. 119
      src/app/tabs/run-tab.js
  12. 47
      src/app/tabs/settings-tab.js
  13. 11
      src/app/tabs/support-tab.js
  14. 15
      src/app/tabs/tabbed-menu.js
  15. 23
      src/app/tabs/test-tab.js
  16. 11
      src/universal-dapp.js

@ -46,7 +46,6 @@ var BasicReadOnlyExplorer = require('./app/files/basicReadOnlyExplorer')
var NotPersistedExplorer = require('./app/files/NotPersistedExplorer') var NotPersistedExplorer = require('./app/files/NotPersistedExplorer')
var toolTip = require('./app/ui/tooltip') var toolTip = require('./app/ui/tooltip')
var CommandInterpreter = require('./lib/cmdInterpreter') var CommandInterpreter = require('./lib/cmdInterpreter')
var PluginAPI = require('./app/plugin/pluginAPI')
var styleGuide = require('./app/ui/styles-guide/theme-chooser') var styleGuide = require('./app/ui/styles-guide/theme-chooser')
var styles = styleGuide.chooser() var styles = styleGuide.chooser()
@ -117,16 +116,26 @@ class App {
constructor (api = {}, events = {}, opts = {}) { constructor (api = {}, events = {}, opts = {}) {
var self = this var self = this
self._api = {} self._api = {}
registry.put({api: self, name: 'app'})
var fileStorage = new Storage('sol:') var fileStorage = new Storage('sol:')
registry.put({api: fileStorage, name: 'fileStorage'})
var configStorage = new Storage('config:') var configStorage = new Storage('config:')
registry.put({api: configStorage, name: 'configStorage'})
self._api.config = new Config(fileStorage) self._api.config = new Config(fileStorage)
registry.put({api: self._api.config, name: 'config'})
executionContext.init(self._api.config) executionContext.init(self._api.config)
executionContext.listenOnLastBlock() executionContext.listenOnLastBlock()
self._api.filesProviders = {} self._api.filesProviders = {}
self._api.filesProviders['browser'] = new Browserfiles(fileStorage) self._api.filesProviders['browser'] = new Browserfiles(fileStorage)
self._api.filesProviders['config'] = new BrowserfilesTree('config', configStorage) self._api.filesProviders['config'] = new BrowserfilesTree('config', configStorage)
self._api.filesProviders['config'].init() self._api.filesProviders['config'].init()
registry.put({api: self._api.filesProviders['browser'], name: 'fileProviders/browser'})
registry.put({api: self._api.filesProviders['config'], name: 'fileProviders/config'})
var remixd = new Remixd() var remixd = new Remixd()
registry.put({api: remixd, name: 'remixd/config'})
remixd.event.register('system', (message) => { remixd.event.register('system', (message) => {
if (message.error) toolTip(message.error) if (message.error) toolTip(message.error)
}) })
@ -135,9 +144,15 @@ class App {
self._api.filesProviders['github'] = new BasicReadOnlyExplorer('github') self._api.filesProviders['github'] = new BasicReadOnlyExplorer('github')
self._api.filesProviders['gist'] = new NotPersistedExplorer('gist') self._api.filesProviders['gist'] = new NotPersistedExplorer('gist')
self._api.filesProviders['ipfs'] = new BasicReadOnlyExplorer('ipfs') self._api.filesProviders['ipfs'] = new BasicReadOnlyExplorer('ipfs')
registry.put({api: self._api.filesProviders['localhost'], name: 'fileProviders/localhost'})
registry.put({api: self._api.filesProviders['swarm'], name: 'fileProviders/swarm'})
registry.put({api: self._api.filesProviders['github'], name: 'fileProviders/github'})
registry.put({api: self._api.filesProviders['gist'], name: 'fileProviders/gist'})
registry.put({api: self._api.filesProviders['ipfs'], name: 'fileProviders/ipfs'})
self._view = {} self._view = {}
self._components = {} self._components = {}
self._components.compilerImport = new CompilerImport() self._components.compilerImport = new CompilerImport()
registry.put({api: self._components.compilerImport, name: 'compilerImport'})
self.data = { self.data = {
_layout: { _layout: {
right: { right: {
@ -207,6 +222,34 @@ class App {
self._adjustLayout('right', self.data._layout.right.offset) self._adjustLayout('right', self.data._layout.right.offset)
return self._view.el return self._view.el
} }
runCompiler () {
const self = this
if (self._view.transactionDebugger.isActive) return
self._components.fileManager.saveCurrentFile()
self._components.editor.clearAnnotations()
var currentFile = self._api.config.get('currentFile')
if (currentFile) {
if (/.(.sol)$/.exec(currentFile)) {
// only compile *.sol file.
var target = currentFile
var sources = {}
var provider = self._components.fileManager.fileProviderOf(currentFile)
if (provider) {
provider.get(target, (error, content) => {
if (error) {
console.log(error)
} else {
sources[target] = { content }
self._components.compiler.compile(sources, target)
}
})
} else {
console.log('cannot compile ' + currentFile + '. Does not belong to any explorer')
}
}
}
}
} }
module.exports = App module.exports = App
@ -242,7 +285,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
// ctrl+s or command+s // ctrl+s or command+s
if ((e.metaKey || e.ctrlKey) && e.keyCode === 83) { if ((e.metaKey || e.ctrlKey) && e.keyCode === 83) {
e.preventDefault() e.preventDefault()
runCompiler() self.runCompiler()
} }
}) })
@ -293,7 +336,8 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
} }
// ----------------- Compiler ----------------- // ----------------- Compiler -----------------
var compiler = new Compiler(importFileCb) self._components.compiler = new Compiler(importFileCb)
var compiler = self._components.compiler
registry.put({api: compiler, name: 'compiler'}) registry.put({api: compiler, name: 'compiler'})
var offsetToLineColumnConverter = new OffsetToLineColumnConverter(compiler.event) var offsetToLineColumnConverter = new OffsetToLineColumnConverter(compiler.event)
@ -327,6 +371,8 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
cb(null, $('#gasLimit').val()) cb(null, $('#gasLimit').val())
} }
} }
// @TODO should put this in runtab
registry.put({api: transactionContextAPI, name: 'transactionContextAPI'})
var udapp = new UniversalDApp({ var udapp = new UniversalDApp({
api: { api: {
@ -346,10 +392,12 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
}, },
opt: { removable: false, removable_instances: true } opt: { removable: false, removable_instances: true }
}) })
registry.put({api: udapp, name: 'udapp'})
var udappUI = new UniversalDAppUI(udapp) var udappUI = new UniversalDAppUI(udapp)
registry.put({api: udappUI, name: 'udappUI'})
udapp.reset({}, transactionContextAPI) udapp.reset({})
udappUI.reset() udappUI.reset()
udapp.event.register('debugRequested', this, function (txResult) { udapp.event.register('debugRequested', this, function (txResult) {
startdebugging(txResult.transactionHash) startdebugging(txResult.transactionHash)
@ -389,6 +437,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
event: { event: {
udapp: udapp.event udapp: udapp.event
}}) }})
registry.put({api: txlistener, name: 'txlistener'})
var eventsDecoder = new EventsDecoder({ var eventsDecoder = new EventsDecoder({
api: { api: {
@ -397,6 +446,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
} }
} }
}) })
registry.put({api: eventsDecoder, name: 'eventsDecoder'})
txlistener.startListening() txlistener.startListening()
@ -467,6 +517,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
// ----------------- editor ---------------------------- // ----------------- editor ----------------------------
this._components.editor = new Editor({}) // @TODO: put into editorpanel this._components.editor = new Editor({}) // @TODO: put into editorpanel
var editor = self._components.editor // shortcut for the editor var editor = self._components.editor // shortcut for the editor
registry.put({api: editor, name: 'editor'})
// ---------------- ContextualListener ----------------------- // ---------------- ContextualListener -----------------------
this._components.contextualListener = new ContextualListener({ this._components.contextualListener = new ContextualListener({
@ -557,6 +608,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
udapp: () => { return udapp } udapp: () => { return udapp }
} }
}) })
registry.put({ api: this._components.editorpanel, name: 'editorpanel' })
this._components.editorpanel.event.register('resize', direction => self._adjustLayout(direction)) this._components.editorpanel.event.register('resize', direction => self._adjustLayout(direction))
this._view.centerpanel.appendChild(this._components.editorpanel.render()) this._view.centerpanel.appendChild(this._components.editorpanel.render())
@ -580,12 +632,14 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
var config = self._api.config var config = self._api.config
var filesProviders = self._api.filesProviders var filesProviders = self._api.filesProviders
var fileManager = new FileManager({ self._components.fileManager = new FileManager({
config: config, config: config,
editor: editor, editor: editor,
filesProviders: filesProviders, filesProviders: filesProviders,
compilerImport: self._components.compilerImport compilerImport: self._components.compilerImport
}) })
var fileManager = self._components.fileManager
registry.put({api: fileManager, name: 'filemanager'})
// Add files received from remote instance (i.e. another remix-ide) // Add files received from remote instance (i.e. another remix-ide)
function loadFiles (filesSet, fileProvider, callback) { function loadFiles (filesSet, fileProvider, callback) {
@ -715,6 +769,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
} }
} }
var renderer = new Renderer(rendererAPI) var renderer = new Renderer(rendererAPI)
registry.put({api: renderer, name: 'renderer'})
// ----------------- StaticAnalysis ----------------- // ----------------- StaticAnalysis -----------------
@ -727,84 +782,10 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
} }
} }
var staticanalysis = new StaticAnalysis(staticAnalysisAPI, compiler.event) var staticanalysis = new StaticAnalysis(staticAnalysisAPI, compiler.event)
registry.put({api: staticanalysis, name: 'staticanalysis'})
// ---------------- Righthand-panel -------------------- // ---------------- Righthand-panel --------------------
self._components.righthandpanel = new RighthandPanel()
var rhpAPI = {
importFileCb: importFileCb,
filesFromPath: (path, cb) => {
fileManager.filesFromPath(path, cb)
},
newAccount: (pass, cb) => {
udapp.newAccount(pass, cb)
},
setEditorSize (delta) {
$('#righthand-panel').css('width', delta)
self._view.centerpanel.style.right = delta + 'px'
document.querySelector(`.${css.dragbar2}`).style.right = delta + 'px'
onResize()
},
switchFile: function (path) {
fileManager.switchFile(path)
},
filesProviders: filesProviders,
fileProviderOf: (path) => {
return fileManager.fileProviderOf(path)
},
fileProvider: (name) => {
return self._api.filesProviders[name]
},
currentPath: function () {
return fileManager.currentPath()
},
getBalance: (address, callback) => {
udapp.getBalance(address, (error, balance) => {
if (error) {
callback(error)
} else {
callback(null, executionContext.web3().fromWei(balance, 'ether'))
}
})
},
currentCompiledSourceCode: () => {
if (compiler.lastCompilationResult.source) {
return compiler.lastCompilationResult.source.sources[compiler.lastCompilationResult.source.target]
}
return ''
},
resetDapp: (contracts) => {
udapp.reset(contracts, transactionContextAPI)
udappUI.reset()
},
setOptimize: (optimize, runCompilation) => {
compiler.setOptimize(optimize)
if (runCompilation) runCompiler()
},
runCompiler: () => {
runCompiler()
},
logMessage: (msg) => {
self._components.editorpanel.log({type: 'log', value: msg})
}
}
var rhpEvents = {
compiler: compiler.event,
app: self.event,
udapp: udapp.event,
editor: editor.event,
staticAnalysis: staticanalysis.event
}
var rhpOpts = {
pluginAPI: new PluginAPI(self, compiler),
udapp: udapp,
udappUI: udappUI,
compiler: compiler,
renderer: renderer,
editor: editor,
config: config
}
self._components.righthandpanel = new RighthandPanel(rhpAPI, rhpEvents, rhpOpts)
self._view.rightpanel.appendChild(self._components.righthandpanel.render()) self._view.rightpanel.appendChild(self._components.righthandpanel.render())
self._components.righthandpanel.init() self._components.righthandpanel.init()
self._components.righthandpanel.event.register('resize', delta => self._adjustLayout('right', delta)) self._components.righthandpanel.event.register('resize', delta => self._adjustLayout('right', delta))
@ -861,11 +842,11 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
return offsetToLineColumnConverter.offsetToLineColumn(location, file, compiler.lastCompilationResult) return offsetToLineColumnConverter.offsetToLineColumn(location, file, compiler.lastCompilationResult)
} }
} }
var transactionDebugger = new Debugger('#debugger', debugAPI, editor.event) self._view.transactionDebugger = new Debugger('#debugger', debugAPI, editor.event)
transactionDebugger.addProvider('vm', executionContext.vm()) self._view.transactionDebugger.addProvider('vm', executionContext.vm())
transactionDebugger.addProvider('injected', executionContext.internalWeb3()) self._view.transactionDebugger.addProvider('injected', executionContext.internalWeb3())
transactionDebugger.addProvider('web3', executionContext.internalWeb3()) self._view.transactionDebugger.addProvider('web3', executionContext.internalWeb3())
transactionDebugger.switchProvider(executionContext.getProvider()) self._view.transactionDebugger.switchProvider(executionContext.getProvider())
var txLogger = new TxLogger({ var txLogger = new TxLogger({
api: { api: {
@ -889,34 +870,6 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
startdebugging(hash) startdebugging(hash)
}) })
function runCompiler () {
if (transactionDebugger.isActive) return
fileManager.saveCurrentFile()
editor.clearAnnotations()
var currentFile = config.get('currentFile')
if (currentFile) {
if (/.(.sol)$/.exec(currentFile)) {
// only compile *.sol file.
var target = currentFile
var sources = {}
var provider = fileManager.fileProviderOf(currentFile)
if (provider) {
provider.get(target, (error, content) => {
if (error) {
console.log(error)
} else {
sources[target] = { content }
compiler.compile(sources, target)
}
})
} else {
console.log('cannot compile ' + currentFile + '. Does not belong to any explorer')
}
}
}
}
var previousInput = '' var previousInput = ''
var saveTimeout = null var saveTimeout = null
@ -950,16 +903,16 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
editor.event.register('sessionSwitched', editorOnChange) editor.event.register('sessionSwitched', editorOnChange)
executionContext.event.register('contextChanged', this, function (context) { executionContext.event.register('contextChanged', this, function (context) {
runCompiler() self.runCompiler()
}) })
executionContext.event.register('web3EndpointChanged', this, function (context) { executionContext.event.register('web3EndpointChanged', this, function (context) {
runCompiler() self.runCompiler()
}) })
compiler.event.register('compilerLoaded', this, function (version) { compiler.event.register('compilerLoaded', this, function (version) {
previousInput = '' previousInput = ''
runCompiler() self.runCompiler()
if (queryParams.get().context) { if (queryParams.get().context) {
let context = queryParams.get().context let context = queryParams.get().context
@ -987,6 +940,6 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
function startdebugging (txHash) { function startdebugging (txHash) {
self.event.trigger('debuggingRequested', []) self.event.trigger('debuggingRequested', [])
transactionDebugger.debug(txHash) self._view.transactionDebugger.debug(txHash)
} }
} }

@ -65,7 +65,6 @@ document.head.appendChild(yo`
function Editor (opts = {}) { function Editor (opts = {}) {
var self = this var self = this
var el = yo`<div id="input"></div>` var el = yo`<div id="input"></div>`
var editor = ace.edit(el) var editor = ace.edit(el)
if (styles.appProperties.aceTheme) { if (styles.appProperties.aceTheme) {
@ -104,14 +103,14 @@ function Editor (opts = {}) {
var breakpoints = e.editor.session.getBreakpoints() var breakpoints = e.editor.session.getBreakpoints()
for (var k in breakpoints) { for (var k in breakpoints) {
if (k === row.toString()) { if (k === row.toString()) {
self.event.trigger('breakpointCleared', [currentSession, row]) event.trigger('breakpointCleared', [currentSession, row])
e.editor.session.clearBreakpoint(row) e.editor.session.clearBreakpoint(row)
e.stop() e.stop()
return return
} }
} }
self.setBreakpoint(row) self.setBreakpoint(row)
self.event.trigger('breakpointAdded', [currentSession, row]) event.trigger('breakpointAdded', [currentSession, row])
e.stop() e.stop()
}) })
@ -278,10 +277,10 @@ function Editor (opts = {}) {
// Do setup on initialisation here // Do setup on initialisation here
editor.on('changeSession', function () { editor.on('changeSession', function () {
self.event.trigger('sessionSwitched', []) event.trigger('sessionSwitched', [])
editor.getSession().on('change', function () { editor.getSession().on('change', function () {
self.event.trigger('contentChanged', []) event.trigger('contentChanged', [])
}) })
}) })

@ -96,6 +96,10 @@ class EditorPanel {
var command = self._components.terminal.commands[data.type] var command = self._components.terminal.commands[data.type]
if (typeof command === 'function') command(data.value) if (typeof command === 'function') command(data.value)
} }
logMessage (msg) {
var self = this
self.log({type: 'log', value: msg})
}
render () { render () {
var self = this var self = this
if (self._view.el) return self._view.el if (self._view.el) return self._view.el

@ -2,6 +2,8 @@ const yo = require('yo-yo')
const csjs = require('csjs-inject') const csjs = require('csjs-inject')
const remixLib = require('remix-lib') const remixLib = require('remix-lib')
var globalRegistry = require('../../global/registry')
const styleguide = require('../ui/styles-guide/theme-chooser') const styleguide = require('../ui/styles-guide/theme-chooser')
const PluginManager = require('../plugin/pluginManager') const PluginManager = require('../plugin/pluginManager')
const TabbedMenu = require('../tabs/tabbed-menu') const TabbedMenu = require('../tabs/tabbed-menu')
@ -18,32 +20,28 @@ const EventManager = remixLib.EventManager
const styles = styleguide.chooser() const styles = styleguide.chooser()
module.exports = class RighthandPanel { module.exports = class RighthandPanel {
constructor (api = {}, events = {}, opts = {}) { constructor (localRegistry) {
const self = this const self = this
self._components = {}
self._components.registry = localRegistry || globalRegistry
self.event = new EventManager() self.event = new EventManager()
self._api = api
self._api.switchTab = x => { // @TODO: refactor
if (self._components.tabbedMenu) self._components.tabbedMenu.selectTabByClassName(x)
}
self._events = events
self._events.rhp = self.event // @TODO: refactor
self._opts = opts
self._view = { self._view = {
element: null, element: null,
tabbedMenu: null, tabbedMenu: null,
tabbedMenuViewport: null, tabbedMenuViewport: null,
dragbar: null dragbar: null
} }
self._components = { self._components = {
pluginManager: new PluginManager(self._opts.pluginAPI, self._events), pluginManager: new PluginManager(),
tabbedMenu: new TabbedMenu(self._api, self._events), tabbedMenu: new TabbedMenu(),
compile: new CompileTab(self._api, self._events, self._opts), compile: new CompileTab(),
run: new RunTab(self._api, self._events, self._opts), run: new RunTab(),
settings: new SettingsTab(self._api, self._events, self._opts), settings: new SettingsTab(),
analysis: new AnalysisTab(self._api, self._events, self._opts), analysis: new AnalysisTab(),
debug: new DebuggerTab(self._api, self._events, self._opts), debug: new DebuggerTab(),
support: new SupportTab(self._api, self._events, self._opts), support: new SupportTab(),
test: new TestTab(self._api, self._events, self._opts) test: new TestTab()
} }
self.event.register('plugin-loadRequest', json => { self.event.register('plugin-loadRequest', json => {

@ -2,24 +2,24 @@
/* /*
Defines available API. `key` / `type` Defines available API. `key` / `type`
*/ */
module.exports = (app, compiler) => { module.exports = (registry) => {
return { return {
config: { config: {
setConfig: (mod, path, content, cb) => { setConfig: (mod, path, content, cb) => {
app._api.filesProviders['config'].set(mod + '/' + path, content) registry.get('fileProviders/config').api.set(mod + '/' + path, content)
cb() cb()
}, },
getConfig: (mod, path, cb) => { getConfig: (mod, path, cb) => {
cb(null, app._api.filesProviders['config'].get(mod + '/' + path)) cb(null, registry.get('fileProviders/config').get(mod + '/' + path))
}, },
removeConfig: (mod, path, cb) => { removeConfig: (mod, path, cb) => {
cb(null, app._api.filesProviders['config'].remove(mod + '/' + path)) cb(null, registry.get('fileProviders/config').api.remove(mod + '/' + path))
if (cb) cb() if (cb) cb()
} }
}, },
compiler: { compiler: {
getCompilationResult: () => { getCompilationResult: () => {
return compiler.lastCompilationResult return registry.get('compiler').api.lastCompilationResult
} }
} }
} }

@ -1,4 +1,7 @@
'use strict' 'use strict'
var globalRegistry = require('../../global/registry')
var PluginAPI = require('./pluginAPI')
/** /**
* Register and Manage plugin: * Register and Manage plugin:
* *
@ -76,15 +79,19 @@
* *
*/ */
module.exports = class PluginManager { module.exports = class PluginManager {
constructor (api = {}, events = {}, opts = {}) { constructor (localRegistry) {
const self = this const self = this
self._opts = opts
self._api = api
self._events = events
self.plugins = {} self.plugins = {}
self._components = {}
self._components.registry = localRegistry || globalRegistry
self._components.pluginAPI = new PluginAPI(self._components.registry)
self._deps = {
compiler: self._components.registry.get('compiler').api,
app: self._components.registry.get('app').api
}
self.inFocus self.inFocus
self.allowedapi = {'setConfig': 1, 'getConfig': 1, 'removeConfig': 1} self.allowedapi = {'setConfig': 1, 'getConfig': 1, 'removeConfig': 1}
self._events.compiler.register('compilationFinished', (success, data, source) => { self._deps.compiler.event.register('compilationFinished', (success, data, source) => {
if (self.inFocus) { if (self.inFocus) {
// trigger to the current focus // trigger to the current focus
self.post(self.inFocus, JSON.stringify({ self.post(self.inFocus, JSON.stringify({
@ -96,7 +103,7 @@ module.exports = class PluginManager {
} }
}) })
self._events.app.register('tabChanged', (tabName) => { self._deps.app.event.register('tabChanged', (tabName) => {
if (self.inFocus && self.inFocus !== tabName) { if (self.inFocus && self.inFocus !== tabName) {
// trigger unfocus // trigger unfocus
self.post(self.inFocus, JSON.stringify({ self.post(self.inFocus, JSON.stringify({
@ -119,7 +126,7 @@ module.exports = class PluginManager {
action: 'notification', action: 'notification',
key: 'compiler', key: 'compiler',
type: 'compilationData', type: 'compilationData',
value: [api.compiler.getCompilationResult()] value: [self._deps.compiler.getCompilationResult()]
})) }))
} }
}) })
@ -142,7 +149,7 @@ module.exports = class PluginManager {
data.value.push((error, result) => { data.value.push((error, result) => {
response(data.key, data.type, data.id, error, result) response(data.key, data.type, data.id, error, result)
}) })
api[data.key][data.type].apply({}, data.value) self._components.pluginAPI[data.key][data.type].apply({}, data.value)
} }
} }
}, false) }, false)

@ -2,17 +2,17 @@ var yo = require('yo-yo')
var csjs = require('csjs-inject') var csjs = require('csjs-inject')
var remixLib = require('remix-lib') var remixLib = require('remix-lib')
var globalRegistry = require('../../global/registry')
var EventManager = remixLib.EventManager var EventManager = remixLib.EventManager
module.exports = class AnalysisTab { module.exports = class AnalysisTab {
constructor (opts = { api: {}, events: {} }) { constructor (localRegistry) {
const self = this const self = this
self.event = new EventManager() self.event = new EventManager()
self._api = opts.api
self._events = opts.events
self._view = { el: null } self._view = { el: null }
self.data = {} self.data = {}
self._components = {} self._components = {}
self._components.registry = localRegistry || globalRegistry
} }
render () { render () {
const self = this const self = this

@ -2,6 +2,7 @@ const yo = require('yo-yo')
const csjs = require('csjs-inject') const csjs = require('csjs-inject')
const copy = require('clipboard-copy') const copy = require('clipboard-copy')
var globalRegistry = require('../../global/registry')
const TreeView = require('../ui/TreeView') const TreeView = require('../ui/TreeView')
const modalDialog = require('../ui/modaldialog') const modalDialog = require('../ui/modaldialog')
const copyToClipboard = require('../ui/copy-to-clipboard') const copyToClipboard = require('../ui/copy-to-clipboard')
@ -14,11 +15,8 @@ const addTooltip = require('../ui/tooltip')
const styles = styleGuide.chooser() const styles = styleGuide.chooser()
module.exports = class CompileTab { module.exports = class CompileTab {
constructor (api = {}, events = {}, opts = {}) { constructor (localRegistry) {
const self = this const self = this
self._opts = opts
self._api = api
self._events = events
self._view = { self._view = {
el: null, el: null,
autoCompile: null, autoCompile: null,
@ -30,22 +28,36 @@ module.exports = class CompileTab {
contractNames: null, contractNames: null,
contractEl: null contractEl: null
} }
self._components = {}
self._components.registry = localRegistry || globalRegistry
// dependencies
self._deps = {
app: self._components.registry.get('app').api,
udapp: self._components.registry.get('udapp').api,
udappUI: self._components.registry.get('udappUI').api,
editor: self._components.registry.get('editor').api,
config: self._components.registry.get('config').api,
compiler: self._components.registry.get('compiler').api,
staticAnalysis: self._components.registry.get('staticanalysis').api,
renderer: self._components.registry.get('renderer').api,
transactionContextAPI: self._components.registry.get('transactionContextAPI').api
}
self.data = { self.data = {
hideWarnings: self._opts.config.get('hideWarnings') || false, hideWarnings: self._deps.config.get('hideWarnings') || false,
autoCompile: self._opts.config.get('autoCompile'), autoCompile: self._deps.config.get('autoCompile'),
compileTimeout: null, compileTimeout: null,
contractsDetails: {}, contractsDetails: {},
maxTime: 1000, maxTime: 1000,
timeout: 300 timeout: 300
} }
self._events.editor.register('contentChanged', scheduleCompilation) self._deps.editor.event.register('contentChanged', scheduleCompilation)
self._events.editor.register('sessionSwitched', scheduleCompilation) self._deps.editor.event.register('sessionSwitched', scheduleCompilation)
function scheduleCompilation () { function scheduleCompilation () {
if (!self._opts.config.get('autoCompile')) return if (!self._deps.config.get('autoCompile')) return
if (self.data.compileTimeout) window.clearTimeout(self.data.compileTimeout) if (self.data.compileTimeout) window.clearTimeout(self.data.compileTimeout)
self.data.compileTimeout = window.setTimeout(() => self._api.runCompiler(), self.data.timeout) self.data.compileTimeout = window.setTimeout(() => self._deps.app.runCompiler(), self.data.timeout)
} }
self._events.compiler.register('compilationDuration', function tabHighlighting (speed) { self._deps.compiler.event.register('compilationDuration', function tabHighlighting (speed) {
if (!self._view.warnCompilationSlow) return if (!self._view.warnCompilationSlow) return
if (speed > self.data.maxTime) { if (speed > self.data.maxTime) {
const msg = `Last compilation took ${speed}ms. We suggest to turn off autocompilation.` const msg = `Last compilation took ${speed}ms. We suggest to turn off autocompilation.`
@ -55,31 +67,31 @@ module.exports = class CompileTab {
self._view.warnCompilationSlow.style.display = 'none' self._view.warnCompilationSlow.style.display = 'none'
} }
}) })
self._events.editor.register('contentChanged', function changedFile () { self._deps.editor.event.register('contentChanged', function changedFile () {
if (!self._view.compileIcon) return if (!self._view.compileIcon) return
const compileTab = document.querySelector('.compileView') // @TODO: compileView tab const compileTab = document.querySelector('.compileView') // @TODO: compileView tab
compileTab.style.color = styles.colors.red // @TODO: compileView tab compileTab.style.color = styles.colors.red // @TODO: compileView tab
self._view.compileIcon.classList.add(`${css.bouncingIcon}`) // @TODO: compileView tab self._view.compileIcon.classList.add(`${css.bouncingIcon}`) // @TODO: compileView tab
}) })
self._events.compiler.register('loadingCompiler', function start () { self._deps.compiler.event.register('loadingCompiler', function start () {
if (!self._view.compileIcon) return if (!self._view.compileIcon) return
self._view.compileIcon.classList.add(`${css.spinningIcon}`) self._view.compileIcon.classList.add(`${css.spinningIcon}`)
self._view.warnCompilationSlow.style.display = 'none' self._view.warnCompilationSlow.style.display = 'none'
self._view.compileIcon.setAttribute('title', 'compiler is loading, please wait a few moments.') self._view.compileIcon.setAttribute('title', 'compiler is loading, please wait a few moments.')
}) })
self._events.compiler.register('compilationStarted', function start () { self._deps.compiler.event.register('compilationStarted', function start () {
if (!self._view.compileIcon) return if (!self._view.compileIcon) return
self._view.errorContainer.innerHTML = '' self._view.errorContainer.innerHTML = ''
self._view.compileIcon.classList.remove(`${css.bouncingIcon}`) self._view.compileIcon.classList.remove(`${css.bouncingIcon}`)
self._view.compileIcon.classList.add(`${css.spinningIcon}`) self._view.compileIcon.classList.add(`${css.spinningIcon}`)
self._view.compileIcon.setAttribute('title', 'compiling...') self._view.compileIcon.setAttribute('title', 'compiling...')
}) })
self._events.compiler.register('compilerLoaded', function loaded () { self._deps.compiler.event.register('compilerLoaded', function loaded () {
if (!self._view.compileIcon) return if (!self._view.compileIcon) return
self._view.compileIcon.classList.remove(`${css.spinningIcon}`) self._view.compileIcon.classList.remove(`${css.spinningIcon}`)
self._view.compileIcon.setAttribute('title', '') self._view.compileIcon.setAttribute('title', '')
}) })
self._events.compiler.register('compilationFinished', function finish (success, data, source) { self._deps.compiler.event.register('compilationFinished', function finish (success, data, source) {
if (self._view.compileIcon) { if (self._view.compileIcon) {
const compileTab = document.querySelector('.compileView') const compileTab = document.querySelector('.compileView')
compileTab.style.color = styles.colors.black compileTab.style.color = styles.colors.black
@ -94,15 +106,17 @@ module.exports = class CompileTab {
self._view.contractNames.innerHTML = '' self._view.contractNames.innerHTML = ''
if (success) { if (success) {
self._view.contractNames.removeAttribute('disabled') self._view.contractNames.removeAttribute('disabled')
self._opts.compiler.visitContracts(contract => { self._deps.compiler.visitContracts(contract => {
self.data.contractsDetails[contract.name] = parseContracts(contract.name, contract.object, self._opts.compiler.getSource(contract.file)) self.data.contractsDetails[contract.name] = parseContracts(contract.name, contract.object, self._deps.compiler.getSource(contract.file))
var contractName = yo`<option>${contract.name}</option>` var contractName = yo`<option>${contract.name}</option>`
self._view.contractNames.appendChild(contractName) self._view.contractNames.appendChild(contractName)
}) })
self._api.resetDapp(self.data.contractsDetails) self._deps.udapp.reset(self.data.contractsDetails, self._deps.transactionContextAPI)
self._deps.udappUI.reset()
} else { } else {
self._view.contractNames.setAttribute('disabled', true) self._view.contractNames.setAttribute('disabled', true)
self._api.resetDapp({}) self._deps.udapp.reset({}, self._deps.transactionContextAPI)
self._deps.udappUI.reset()
} }
// hightlight the tab if error // hightlight the tab if error
if (success) document.querySelector('.compileView').style.color = '' // @TODO: compileView tab if (success) document.querySelector('.compileView').style.color = '' // @TODO: compileView tab
@ -111,31 +125,31 @@ module.exports = class CompileTab {
var error = false var error = false
if (data['error']) { if (data['error']) {
error = true error = true
self._opts.renderer.error(data['error'].formattedMessage, self._view.errorContainer, {type: data['error'].severity}) self._deps.renderer.error(data['error'].formattedMessage, self._view.errorContainer, {type: data['error'].severity})
} }
if (data.errors && data.errors.length) { if (data.errors && data.errors.length) {
error = true error = true
data.errors.forEach(function (err) { data.errors.forEach(function (err) {
if (self._opts.config.get('hideWarnings')) { if (self._deps.config.get('hideWarnings')) {
if (err.severity !== 'warning') { if (err.severity !== 'warning') {
self._opts.renderer.error(err.formattedMessage, self._view.errorContainer, {type: err.severity}) self._deps.renderer.error(err.formattedMessage, self._view.errorContainer, {type: err.severity})
} }
} else { } else {
self._opts.renderer.error(err.formattedMessage, self._view.errorContainer, {type: err.severity}) self._deps.renderer.error(err.formattedMessage, self._view.errorContainer, {type: err.severity})
} }
}) })
} }
if (!error && data.contracts) { if (!error && data.contracts) {
self._opts.compiler.visitContracts((contract) => { self._deps.compiler.visitContracts((contract) => {
self._opts.renderer.error(contract.name, self._view.errorContainer, {type: 'success'}) self._deps.renderer.error(contract.name, self._view.errorContainer, {type: 'success'})
}) })
} }
}) })
self._events.staticAnalysis.register('staticAnaysisWarning', (count) => { self._deps.staticAnalysis.event.register('staticAnaysisWarning', (count) => {
if (count) { if (count) {
const msg = `Static Analysis raised ${count} warning(s) that requires your attention. Click here to show the warning(s).` const msg = `Static Analysis raised ${count} warning(s) that requires your attention. Click here to show the warning(s).`
const settings = { type: 'staticAnalysisWarning', click: () => self._api.switchTab('staticanalysisView'), useSpan: true } const settings = { type: 'staticAnalysisWarning', click: () => self._api.switchTab('staticanalysisView'), useSpan: true }
self._opts.renderer.error(msg, self._view.errorContainer, settings) self._deps.renderer.error(msg, self._view.errorContainer, settings)
} }
}) })
} }
@ -202,8 +216,8 @@ module.exports = class CompileTab {
'swarmLocation': 'Swarm url where all metadata information can be found (contract needs to be published first)', 'swarmLocation': 'Swarm url where all metadata information can be found (contract needs to be published first)',
'web3Deploy': 'Copy/paste this code to any JavaScript/Web3 console to deploy this contract' 'web3Deploy': 'Copy/paste this code to any JavaScript/Web3 console to deploy this contract'
} }
function updateAutoCompile (event) { self._opts.config.set('autoCompile', self._view.autoCompile.checked) } function updateAutoCompile (event) { self._deps.config.set('autoCompile', self._view.autoCompile.checked) }
function compile (event) { self._api.runCompiler() } function compile (event) { self._deps.app.runCompiler() }
function hideWarnings (event) { function hideWarnings (event) {
self._opts.config.set('hideWarnings', self._view.hideWarningsBox.checked) self._opts.config.set('hideWarnings', self._view.hideWarningsBox.checked)
self._api.runCompiler() self._api.runCompiler()

@ -2,18 +2,18 @@ var yo = require('yo-yo')
var csjs = require('csjs-inject') var csjs = require('csjs-inject')
var remixLib = require('remix-lib') var remixLib = require('remix-lib')
var globalRegistry = require('../../global/registry')
var EventManager = remixLib.EventManager var EventManager = remixLib.EventManager
var styles = require('../ui/styles-guide/theme-chooser').chooser() var styles = require('../ui/styles-guide/theme-chooser').chooser()
module.exports = class DebuggerTab { module.exports = class DebuggerTab {
constructor (opts = { api: {}, events: {} }) { constructor (localRegistry) {
const self = this const self = this
self.event = new EventManager() self.event = new EventManager()
self._api = opts.api
self._events = opts.events
self._view = { el: null } self._view = { el: null }
self.data = {} self.data = {}
self._components = {} self._components = {}
self._components.registry = localRegistry || globalRegistry
} }
render () { render () {
const self = this const self = this

@ -2,17 +2,16 @@ var yo = require('yo-yo')
var csjs = require('csjs-inject') var csjs = require('csjs-inject')
var remixLib = require('remix-lib') var remixLib = require('remix-lib')
var globalRegistry = require('../../global/registry')
var EventManager = remixLib.EventManager var EventManager = remixLib.EventManager
module.exports = class plugintab { module.exports = class plugintab {
constructor (api = {}, events = {}, opts = {}) { constructor (localRegistry) {
const self = this const self = this
self.event = new EventManager() self.event = new EventManager()
self._opts = opts
self._api = api
self._events = events
self._view = { el: null } self._view = { el: null }
self._components = {} self._components = {}
self._components.registry = localRegistry || globalRegistry
} }
render () { render () {
const self = this const self = this

@ -8,6 +8,7 @@ var txExecution = remixLib.execution.txExecution
var txFormat = remixLib.execution.txFormat var txFormat = remixLib.execution.txFormat
var txHelper = remixLib.execution.txHelper var txHelper = remixLib.execution.txHelper
var EventManager = remixLib.EventManager var EventManager = remixLib.EventManager
var globlalRegistry = require('../../global/registry')
var helper = require('../../lib/helper.js') var helper = require('../../lib/helper.js')
var executionContext = require('../../execution-context') var executionContext = require('../../execution-context')
var modalDialogCustom = require('../ui/modal-dialog-custom') var modalDialogCustom = require('../ui/modal-dialog-custom')
@ -18,13 +19,12 @@ var addTooltip = require('../ui/tooltip')
var css = require('./styles/run-tab-styles') var css = require('./styles/run-tab-styles')
var MultiParamManager = require('../../multiParamManager') var MultiParamManager = require('../../multiParamManager')
function runTab (appAPI = {}, appEvents = {}, opts = {}) { function runTab (localRegistry) {
/* ------------------------- /* -------------------------
VARIABLES VARIABLES
--------------------------- */ --------------------------- */
var self = this var self = this
var event = new EventManager() var event = new EventManager()
appEvents.eventManager = event
self._view = {} self._view = {}
self.data = { self.data = {
count: 0, count: 0,
@ -33,7 +33,18 @@ function runTab (appAPI = {}, appEvents = {}, opts = {}) {
another environment. e.g Transactions created in another environment. e.g Transactions created in
Javascript VM can be replayed in the Injected Web3.` Javascript VM can be replayed in the Injected Web3.`
} }
self._components = {}
self._components.registry = localRegistry || globlalRegistry
// dependencies
self._deps = {
compiler: self._components.registry.get('compiler').api,
udapp: self._components.registry.get('udapp').api,
udappUI: self._components.registry.get('udappUI').api,
config: self._components.registry.get('config').api,
fileManager: self._components.registry.get('filemanager').api,
editorPanel: self._components.registry.get('editorpanel').api,
editor: self._components.registry.get('editor').api
}
self._view.recorderCount = yo`<span>0</span>` self._view.recorderCount = yo`<span>0</span>`
self._view.instanceContainer = yo`<div class="${css.instanceContainer}"></div>` self._view.instanceContainer = yo`<div class="${css.instanceContainer}"></div>`
self._view.clearInstanceElement = yo` self._view.clearInstanceElement = yo`
@ -52,7 +63,7 @@ function runTab (appAPI = {}, appEvents = {}, opts = {}) {
</div>` </div>`
var container = yo`<div class="${css.runTabView}" id="runTabView" ></div>` var container = yo`<div class="${css.runTabView}" id="runTabView" ></div>`
var recorderInterface = makeRecorder(appAPI, appEvents, opts, self) var recorderInterface = makeRecorder(localRegistry, event, self)
self._view.collapsedView = yo` self._view.collapsedView = yo`
<div class=${css.recorderCollapsedView}> <div class=${css.recorderCollapsedView}>
@ -92,8 +103,8 @@ function runTab (appAPI = {}, appEvents = {}, opts = {}) {
--------------------------- */ --------------------------- */
var el = yo` var el = yo`
<div> <div>
${settings(container, appAPI, appEvents, opts)} ${settings(container, self)}
${contractDropdown(event, appAPI, appEvents, opts, self)} ${contractDropdown(event, self)}
${recorderCard.render()} ${recorderCard.render()}
${self._view.instanceContainer} ${self._view.instanceContainer}
</div> </div>
@ -114,7 +125,7 @@ function runTab (appAPI = {}, appEvents = {}, opts = {}) {
function setFinalContext () { function setFinalContext () {
// set the final context. Cause it is possible that this is not the one we've originaly selected // set the final context. Cause it is possible that this is not the one we've originaly selected
selectExEnv.value = executionContext.getProvider() selectExEnv.value = executionContext.getProvider()
fillAccountsList(appAPI, opts, el) fillAccountsList(el, self)
event.trigger('clearInstance', []) event.trigger('clearInstance', [])
} }
@ -141,9 +152,9 @@ function runTab (appAPI = {}, appEvents = {}, opts = {}) {
setFinalContext() setFinalContext()
}) })
fillAccountsList(appAPI, opts, el) fillAccountsList(el, self)
setInterval(() => { setInterval(() => {
updateAccountBalances(container, appAPI) updateAccountBalances(container, self)
}, 10000) }, 10000)
event.register('clearInstance', () => { event.register('clearInstance', () => {
@ -156,10 +167,10 @@ function runTab (appAPI = {}, appEvents = {}, opts = {}) {
return { render () { return container } } return { render () { return container } }
} }
function fillAccountsList (appAPI, opts, container) { function fillAccountsList (container, self) {
var $txOrigin = $(container.querySelector('#txorigin')) var $txOrigin = $(container.querySelector('#txorigin'))
$txOrigin.empty() $txOrigin.empty()
opts.udapp.getAccounts((err, accounts) => { self._deps.udapp.getAccounts((err, accounts) => {
if (err) { addTooltip(`Cannot get account list: ${err}`) } if (err) { addTooltip(`Cannot get account list: ${err}`) }
if (accounts && accounts[0]) { if (accounts && accounts[0]) {
for (var a in accounts) { $txOrigin.append($('<option />').val(accounts[a]).text(accounts[a])) } for (var a in accounts) { $txOrigin.append($('<option />').val(accounts[a]).text(accounts[a])) }
@ -170,11 +181,11 @@ function fillAccountsList (appAPI, opts, container) {
}) })
} }
function updateAccountBalances (container, appAPI) { function updateAccountBalances (container, self) {
var accounts = $(container.querySelector('#txorigin')).children('option') var accounts = $(container.querySelector('#txorigin')).children('option')
accounts.each(function (index, value) { accounts.each(function (index, value) {
(function (acc) { (function (acc) {
appAPI.getBalance(accounts[acc].value, function (err, res) { self._deps.udapp.getBalanceInEther(accounts[acc].value, function (err, res) {
if (!err) { if (!err) {
accounts[acc].innerText = helper.shortenAddress(accounts[acc].value, res) accounts[acc].innerText = helper.shortenAddress(accounts[acc].value, res)
} }
@ -186,15 +197,15 @@ function updateAccountBalances (container, appAPI) {
/* ------------------------------------------------ /* ------------------------------------------------
RECORDER RECORDER
------------------------------------------------ */ ------------------------------------------------ */
function makeRecorder (appAPI, appEvents, opts, self) { function makeRecorder (registry, runTabEvent, self) {
var recorder = new Recorder(opts.compiler, opts.udapp, { var recorder = new Recorder(self._deps.compiler, self._deps.udapp, {
events: { events: {
udapp: appEvents.udapp, udapp: self._deps.udapp.event,
executioncontext: executionContext.event, executioncontext: executionContext.event,
runtab: appEvents.eventManager runtab: runTabEvent
}, }
api: appAPI
}) })
recorder.event.register('newTxRecorded', (count) => { recorder.event.register('newTxRecorded', (count) => {
self.data.count = count self.data.count = count
self._view.recorderCount.innerText = count self._view.recorderCount.innerText = count
@ -217,9 +228,10 @@ function makeRecorder (appAPI, appEvents, opts, self) {
function triggerRecordButton () { function triggerRecordButton () {
var txJSON = JSON.stringify(recorder.getAll(), null, 2) var txJSON = JSON.stringify(recorder.getAll(), null, 2)
var path = appAPI.currentPath() var fileManager = self._deps.fileManager
var path = fileManager.currentPath()
modalDialogCustom.prompt(null, 'Transactions will be saved in a file under ' + path, 'scenario.json', input => { modalDialogCustom.prompt(null, 'Transactions will be saved in a file under ' + path, 'scenario.json', input => {
var fileProvider = appAPI.fileProviderOf(path) var fileProvider = fileManager.fileProviderOf(path)
if (fileProvider) { if (fileProvider) {
var newFile = path + input var newFile = path + input
helper.createNonClashingName(newFile, fileProvider, (error, newFile) => { helper.createNonClashingName(newFile, fileProvider, (error, newFile) => {
@ -227,7 +239,7 @@ function makeRecorder (appAPI, appEvents, opts, self) {
if (!fileProvider.set(newFile, txJSON)) { if (!fileProvider.set(newFile, txJSON)) {
modalDialogCustom.alert('Failed to create file ' + newFile) modalDialogCustom.alert('Failed to create file ' + newFile)
} else { } else {
appAPI.switchFile(newFile) fileManager.switchFile(newFile)
} }
}) })
} }
@ -240,8 +252,10 @@ function makeRecorder (appAPI, appEvents, opts, self) {
update account address in scenario.json update account address in scenario.json
popup if scenario.json not open - "Open a file with transactions you want to replay and click play again" popup if scenario.json not open - "Open a file with transactions you want to replay and click play again"
*/ */
var currentFile = opts.config.get('currentFile') var currentFile = self._deps.config.get('currentFile').api
appAPI.fileProviderOf(currentFile).get(currentFile, (error, json) => { var udappUI = self._deps.config.get('udappUI').api
var fileManager = self._deps.config.get('fileManager').api
fileManager.fileProviderOf(currentFile).get(currentFile, (error, json) => {
if (error) { if (error) {
modalDialogCustom.alert('Invalid Scenario File ' + error) modalDialogCustom.alert('Invalid Scenario File ' + error)
} else { } else {
@ -259,8 +273,8 @@ function makeRecorder (appAPI, appEvents, opts, self) {
if (txArray.length) { if (txArray.length) {
var noInstancesText = self._view.noInstancesText var noInstancesText = self._view.noInstancesText
if (noInstancesText.parentNode) { noInstancesText.parentNode.removeChild(noInstancesText) } if (noInstancesText.parentNode) { noInstancesText.parentNode.removeChild(noInstancesText) }
recorder.run(txArray, accounts, options, abis, linkReferences, opts.udapp, (abi, address, contractName) => { recorder.run(txArray, accounts, options, abis, linkReferences, udapp, (abi, address, contractName) => {
self._view.instanceContainer.appendChild(opts.udappUI.renderInstanceFromABI(abi, address, contractName)) self._view.instanceContainer.appendChild(udappUI.renderInstanceFromABI(abi, address, contractName))
}) })
} }
} else { } else {
@ -276,13 +290,13 @@ function makeRecorder (appAPI, appEvents, opts, self) {
CONTRACT (deploy or access deployed) CONTRACT (deploy or access deployed)
------------------------------------------------ */ ------------------------------------------------ */
function contractDropdown (events, appAPI, appEvents, opts, self) { function contractDropdown (events, self) {
var instanceContainer = self._view.instanceContainer var instanceContainer = self._view.instanceContainer
var instanceContainerTitle = self._view.instanceContainerTitle var instanceContainerTitle = self._view.instanceContainerTitle
instanceContainer.appendChild(instanceContainerTitle) instanceContainer.appendChild(instanceContainerTitle)
instanceContainer.appendChild(self._view.noInstancesText) instanceContainer.appendChild(self._view.noInstancesText)
var compFails = yo`<i title="Contract compilation failed. Please check the compile tab for more information." class="fa fa-times-circle ${css.errorIcon}" ></i>` var compFails = yo`<i title="Contract compilation failed. Please check the compile tab for more information." class="fa fa-times-circle ${css.errorIcon}" ></i>`
appEvents.compiler.register('compilationFinished', function (success, data, source) { self._deps.compiler.event.register('compilationFinished', function (success, data, source) {
getContractNames(success, data) getContractNames(success, data)
if (success) { if (success) {
compFails.style.display = 'none' compFails.style.display = 'none'
@ -301,12 +315,11 @@ function contractDropdown (events, appAPI, appEvents, opts, self) {
if (contractName) { if (contractName) {
return { return {
name: contractName, name: contractName,
contract: opts.compiler.getContract(contractName) contract: self._deps.compiler.getContract(contractName)
} }
} }
return null return null
} }
appAPI.getSelectedContract = getSelectedContract
var createPanel = yo`<div class="${css.button}"></div>` var createPanel = yo`<div class="${css.button}"></div>`
@ -319,7 +332,7 @@ function contractDropdown (events, appAPI, appEvents, opts, self) {
${createPanel} ${createPanel}
<div class="${css.button}"> <div class="${css.button}">
${atAddressButtonInput} ${atAddressButtonInput}
<div class="${css.atAddress}" onclick=${function () { loadFromAddress(opts.editor, opts.config) }}>At Address</div> <div class="${css.atAddress}" onclick=${function () { loadFromAddress() }}>At Address</div>
</div> </div>
</div> </div>
</div> </div>
@ -327,7 +340,7 @@ function contractDropdown (events, appAPI, appEvents, opts, self) {
function setInputParamsPlaceHolder () { function setInputParamsPlaceHolder () {
createPanel.innerHTML = '' createPanel.innerHTML = ''
if (opts.compiler.getContract && selectContractNames.selectedIndex >= 0 && selectContractNames.children.length > 0) { if (self._deps.compiler.getContract && selectContractNames.selectedIndex >= 0 && selectContractNames.children.length > 0) {
var ctrabi = txHelper.getConstructorInterface(getSelectedContract().contract.object.abi) var ctrabi = txHelper.getConstructorInterface(getSelectedContract().contract.object.abi)
var ctrEVMbc = getSelectedContract().contract.object.evm.bytecode.object var ctrEVMbc = getSelectedContract().contract.object.evm.bytecode.object
var createConstructorInstance = new MultiParamManager(0, ctrabi, (valArray, inputsValues) => { var createConstructorInstance = new MultiParamManager(0, ctrabi, (valArray, inputsValues) => {
@ -352,44 +365,44 @@ function contractDropdown (events, appAPI, appEvents, opts, self) {
} }
var constructor = txHelper.getConstructorInterface(selectedContract.contract.object.abi) var constructor = txHelper.getConstructorInterface(selectedContract.contract.object.abi)
txFormat.buildData(selectedContract.name, selectedContract.contract.object, opts.compiler.getContracts(), true, constructor, args, (error, data) => { txFormat.buildData(selectedContract.name, selectedContract.contract.object, self._deps.compiler.getContracts(), true, constructor, args, (error, data) => {
if (!error) { if (!error) {
appAPI.logMessage(`creation of ${selectedContract.name} pending...`) self._deps.editorPanel.logMessage(`creation of ${selectedContract.name} pending...`)
opts.udapp.createContract(data, (error, txResult) => { self._deps.udapp.createContract(data, (error, txResult) => {
if (error) { if (error) {
appAPI.logMessage(`creation of ${selectedContract.name} errored: ` + error) self._deps.editorPanel.logMessage(`creation of ${selectedContract.name} errored: ` + error)
} else { } else {
var isVM = executionContext.isVM() var isVM = executionContext.isVM()
if (isVM) { if (isVM) {
var vmError = txExecution.checkVMError(txResult) var vmError = txExecution.checkVMError(txResult)
if (vmError.error) { if (vmError.error) {
appAPI.logMessage(vmError.message) self._deps.editorPanel.logMessage(vmError.message)
return return
} }
} }
if (txResult.result.status && txResult.result.status === '0x0') { if (txResult.result.status && txResult.result.status === '0x0') {
appAPI.logMessage(`creation of ${selectedContract.name} errored: transaction execution failed`) self._deps.editorPanel.logMessage(`creation of ${selectedContract.name} errored: transaction execution failed`)
return return
} }
var noInstancesText = self._view.noInstancesText var noInstancesText = self._view.noInstancesText
if (noInstancesText.parentNode) { noInstancesText.parentNode.removeChild(noInstancesText) } if (noInstancesText.parentNode) { noInstancesText.parentNode.removeChild(noInstancesText) }
var address = isVM ? txResult.result.createdAddress : txResult.result.contractAddress var address = isVM ? txResult.result.createdAddress : txResult.result.contractAddress
instanceContainer.appendChild(opts.udappUI.renderInstance(selectedContract.contract.object, address, selectContractNames.value)) instanceContainer.appendChild(self._deps.udappUI.renderInstance(selectedContract.contract.object, address, selectContractNames.value))
} }
}) })
} else { } else {
appAPI.logMessage(`creation of ${selectedContract.name} errored: ` + error) self._deps.editorPanel.logMessage(`creation of ${selectedContract.name} errored: ` + error)
} }
}, (msg) => { }, (msg) => {
appAPI.logMessage(msg) self._deps.editorPanel.logMessage(msg)
}, (data, runTxCallback) => { }, (data, runTxCallback) => {
// called for libraries deployment // called for libraries deployment
opts.udapp.runTx(data, runTxCallback) self._deps.udapp.runTx(data, runTxCallback)
}) })
} }
// ACCESS DEPLOYED INSTANCE // ACCESS DEPLOYED INSTANCE
function loadFromAddress (editor, config) { function loadFromAddress () {
var noInstancesText = self._view.noInstancesText var noInstancesText = self._view.noInstancesText
if (noInstancesText.parentNode) { noInstancesText.parentNode.removeChild(noInstancesText) } if (noInstancesText.parentNode) { noInstancesText.parentNode.removeChild(noInstancesText) }
var contractNames = document.querySelector(`.${css.contractNames.classNames[0]}`) var contractNames = document.querySelector(`.${css.contractNames.classNames[0]}`)
@ -400,19 +413,19 @@ function contractDropdown (events, appAPI, appEvents, opts, self) {
if (/[a-f]/.test(address) && /[A-F]/.test(address) && !ethJSUtil.isValidChecksumAddress(address)) { if (/[a-f]/.test(address) && /[A-F]/.test(address) && !ethJSUtil.isValidChecksumAddress(address)) {
return modalDialogCustom.alert('Invalid checksum address.') return modalDialogCustom.alert('Invalid checksum address.')
} }
if (/.(.abi)$/.exec(config.get('currentFile'))) { if (/.(.abi)$/.exec(self._deps.config.get('currentFile'))) {
modalDialogCustom.confirm(null, 'Do you really want to interact with ' + address + ' using the current ABI definition ?', () => { modalDialogCustom.confirm(null, 'Do you really want to interact with ' + address + ' using the current ABI definition ?', () => {
var abi var abi
try { try {
abi = JSON.parse(editor.currentContent()) abi = JSON.parse(self._deps.editor.currentContent())
} catch (e) { } catch (e) {
return modalDialogCustom.alert('Failed to parse the current file as JSON ABI.') return modalDialogCustom.alert('Failed to parse the current file as JSON ABI.')
} }
instanceContainer.appendChild(opts.udappUI.renderInstanceFromABI(abi, address, address)) instanceContainer.appendChild(self._deps.udappUI.renderInstanceFromABI(abi, address, address))
}) })
} else { } else {
var contract = opts.compiler.getContract(contractNames.children[contractNames.selectedIndex].innerHTML) var contract = self._deps.compiler.getContract(contractNames.children[contractNames.selectedIndex].innerHTML)
instanceContainer.appendChild(opts.udappUI.renderInstance(contract.object, address, selectContractNames.value)) instanceContainer.appendChild(self._deps.udappUI.renderInstance(contract.object, address, selectContractNames.value))
} }
} }
@ -422,7 +435,7 @@ function contractDropdown (events, appAPI, appEvents, opts, self) {
contractNames.innerHTML = '' contractNames.innerHTML = ''
if (success) { if (success) {
selectContractNames.removeAttribute('disabled') selectContractNames.removeAttribute('disabled')
opts.compiler.visitContracts((contract) => { self._deps.compiler.visitContracts((contract) => {
contractNames.appendChild(yo`<option>${contract.name}</option>`) contractNames.appendChild(yo`<option>${contract.name}</option>`)
}) })
} else { } else {
@ -436,7 +449,7 @@ function contractDropdown (events, appAPI, appEvents, opts, self) {
/* ------------------------------------------------ /* ------------------------------------------------
section SETTINGS: Environment, Account, Gas, Value section SETTINGS: Environment, Account, Gas, Value
------------------------------------------------ */ ------------------------------------------------ */
function settings (container, appAPI, appEvents, opts) { function settings (container, self) {
// VARIABLES // VARIABLES
var net = yo`<span class=${css.network}></span>` var net = yo`<span class=${css.network}></span>`
const updateNetwork = () => { const updateNetwork = () => {
@ -511,15 +524,15 @@ function settings (container, appAPI, appEvents, opts) {
</div> </div>
` `
// HELPER FUNCTIONS AND EVENTS // HELPER FUNCTIONS AND EVENTS
appEvents.udapp.register('transactionExecuted', (error, from, to, data, lookupOnly, txResult) => { self._deps.udapp.event.register('transactionExecuted', (error, from, to, data, lookupOnly, txResult) => {
if (error) return if (error) return
if (!lookupOnly) el.querySelector('#value').value = '0' if (!lookupOnly) el.querySelector('#value').value = '0'
updateAccountBalances(container, appAPI) updateAccountBalances(container, self)
}) })
setInterval(updateNetwork, 5000) setInterval(updateNetwork, 5000)
function newAccount () { function newAccount () {
appAPI.newAccount('', (error, address) => { self._deps.udapp.newAccount('', (error, address) => {
if (!error) { if (!error) {
container.querySelector('#txorigin').appendChild(yo`<option value=${address}>${address}</option>`) container.querySelector('#txorigin').appendChild(yo`<option value=${address}>${address}</option>`)
addTooltip(`account ${address} created`) addTooltip(`account ${address} created`)

@ -3,6 +3,8 @@ var yo = require('yo-yo')
var csjs = require('csjs-inject') var csjs = require('csjs-inject')
var minixhr = require('minixhr') var minixhr = require('minixhr')
var remixLib = require('remix-lib') var remixLib = require('remix-lib')
var globalRegistry = require('../../global/registry')
var QueryParams = require('../../lib/query-params') var QueryParams = require('../../lib/query-params')
var helper = require('../../lib/helper') var helper = require('../../lib/helper')
var modal = require('../ui/modal-dialog-custom') var modal = require('../ui/modal-dialog-custom')
@ -15,12 +17,20 @@ var Storage = remixLib.Storage
var EventManager = remixLib.EventManager var EventManager = remixLib.EventManager
module.exports = class SettingsTab { module.exports = class SettingsTab {
constructor (api = {}, events = {}, opts = {}) { constructor (localRegistry) {
const self = this const self = this
self._opts = opts
self._api = api
self._events = events
self._components = {} self._components = {}
self._components.registry = localRegistry || globalRegistry
// dependencies
self._deps = {
compiler: self._components.registry.get('compiler').api,
udapp: self._components.registry.get('udapp').api,
udappUI: self._components.registry.get('udappUI').api,
config: self._components.registry.get('config').api,
fileManager: self._components.registry.get('filemanager').api,
editorPanel: self._components.registry.get('editorpanel').api,
editor: self._components.registry.get('editor').api
}
self._view = { /* eslint-disable */ self._view = { /* eslint-disable */
el: null, el: null,
optionVM: null, personal: null, optimize: null, warnPersonalMode: null, optionVM: null, personal: null, optimize: null, warnPersonalMode: null,
@ -41,9 +51,11 @@ module.exports = class SettingsTab {
self._components.themeStorage = new Storage('style:') self._components.themeStorage = new Storage('style:')
self.data.optimize = !!self._components.queryParams.get().optimize self.data.optimize = !!self._components.queryParams.get().optimize
self._components.queryParams.update({ optimize: self.data.optimize }) self._components.queryParams.update({ optimize: self.data.optimize })
self._api.setOptimize(self.data.optimize, false) self._deps.compiler.setOptimize(self.data.optimize)
self.data.currentTheme = self._components.themeStorage.get('theme') || 'light' self.data.currentTheme = self._components.themeStorage.get('theme') || 'light'
self._events.compiler.register('compilerLoaded', (version) => self.setVersionText(version))
var compilerEvent = self._components.registry.get('compiler').event
compilerEvent.register('compilerLoaded', (version) => self.setVersionText(version))
self.fetchAllVersion((allversions, selectedVersion) => { self.fetchAllVersion((allversions, selectedVersion) => {
self.data.allversions = allversions self.data.allversions = allversions
self.data.selectedVersion = selectedVersion self.data.selectedVersion = selectedVersion
@ -56,16 +68,16 @@ module.exports = class SettingsTab {
// Gist settings // Gist settings
var gistAccessToken = yo`<input id="gistaccesstoken" type="password">` var gistAccessToken = yo`<input id="gistaccesstoken" type="password">`
var token = self._opts.config.get('settings/gist-access-token') var token = self._deps.config.get('settings/gist-access-token')
if (token) gistAccessToken.value = token if (token) gistAccessToken.value = token
var gistAddToken = yo`<input class="${css.savegisttoken}" id="savegisttoken" onclick=${() => { self._opts.config.set('settings/gist-access-token', gistAccessToken.value); tooltip('Access token saved') }} value="Save" type="button">` var gistAddToken = yo`<input class="${css.savegisttoken}" id="savegisttoken" onclick=${() => { self._deps.config.set('settings/gist-access-token', gistAccessToken.value); tooltip('Access token saved') }} value="Save" type="button">`
var gistRemoveToken = yo`<input id="removegisttoken" onclick=${() => { gistAccessToken.value = ''; self._opts.config.set('settings/gist-access-token', ''); tooltip('Access token removed') }} value="Remove" type="button">` var gistRemoveToken = yo`<input id="removegisttoken" onclick=${() => { gistAccessToken.value = ''; self._deps.config.set('settings/gist-access-token', ''); tooltip('Access token removed') }} value="Remove" type="button">`
self._view.gistToken = yo`<div class="${css.checkboxText}">${gistAccessToken}${copyToClipboard(() => self._opts.config.get('settings/gist-access-token'))}${gistAddToken}${gistRemoveToken}</div>` self._view.gistToken = yo`<div class="${css.checkboxText}">${gistAccessToken}${copyToClipboard(() => self._deps.config.get('settings/gist-access-token'))}${gistAddToken}${gistRemoveToken}</div>`
// //
self._view.optionVM = yo`<input onchange=${onchangeOption} id="alwaysUseVM" type="checkbox">` self._view.optionVM = yo`<input onchange=${onchangeOption} id="alwaysUseVM" type="checkbox">`
if (self._opts.config.get('settings/always-use-vm')) self._view.optionVM.setAttribute('checked', '') if (self._deps.config.get('settings/always-use-vm')) self._view.optionVM.setAttribute('checked', '')
self._view.personal = yo`<input onchange=${onchangePersonal} id="personal" type="checkbox">` self._view.personal = yo`<input onchange=${onchangePersonal} id="personal" type="checkbox">`
if (self._opts.config.get('settings/personal-mode')) self._view.personal.setAttribute('checked', '') if (self._deps.config.get('settings/personal-mode')) self._view.personal.setAttribute('checked', '')
self._view.optimize = yo`<input onchange=${onchangeOptimize} id="optimize" type="checkbox">` self._view.optimize = yo`<input onchange=${onchangeOptimize} id="optimize" type="checkbox">`
if (self.data.optimize) self._view.optimize.setAttribute('checked', '') if (self.data.optimize) self._view.optimize.setAttribute('checked', '')
var warnText = `Transaction sent over Web3 will use the web3.personal API - be sure the endpoint is opened before enabling it. var warnText = `Transaction sent over Web3 will use the web3.personal API - be sure the endpoint is opened before enabling it.
@ -187,7 +199,7 @@ module.exports = class SettingsTab {
${self._view.config.localremixd} ${self._view.config.localremixd}
</div>` </div>`
function onchangeOption (event) { function onchangeOption (event) {
self._opts.config.set('settings/always-use-vm', !self._opts.config.get('settings/always-use-vm')) self._deps.config.set('settings/always-use-vm', !self._deps.config.get('settings/always-use-vm'))
} }
function onloadPlugin (event) { function onloadPlugin (event) {
try { try {
@ -209,14 +221,15 @@ module.exports = class SettingsTab {
function onchangeOptimize (event) { function onchangeOptimize (event) {
self.data.optimize = !!self._view.optimize.checked self.data.optimize = !!self._view.optimize.checked
self._components.queryParams.update({ optimize: self.data.optimize }) self._components.queryParams.update({ optimize: self.data.optimize })
self._api.setOptimize(self.data.optimize, true) self._deps.compiler.setOptimize(self.data.optimize)
self._deps.app.runCompiler()
} }
function onchangeLoadVersion (event) { function onchangeLoadVersion (event) {
self.data.selectedVersion = self._view.versionSelector.value self.data.selectedVersion = self._view.versionSelector.value
self._updateVersionSelector() self._updateVersionSelector()
} }
function onchangePersonal (event) { function onchangePersonal (event) {
self._opts.config.set('settings/personal-mode', !self._opts.config.get('settings/personal-mode')) self._deps.config.set('settings/personal-mode', !self._deps.config.get('settings/personal-mode'))
} }
return self._view.el return self._view.el
} }
@ -250,10 +263,10 @@ module.exports = class SettingsTab {
// Workers cannot load js on "file:"-URLs and we get a // Workers cannot load js on "file:"-URLs and we get a
// "Uncaught RangeError: Maximum call stack size exceeded" error on Chromium, // "Uncaught RangeError: Maximum call stack size exceeded" error on Chromium,
// resort to non-worker version in that case. // resort to non-worker version in that case.
self._opts.compiler.loadVersion(true, url) self._deps.compiler.loadVersion(true, url)
self.setVersionText('(loading using worker)') self.setVersionText('(loading using worker)')
} else { } else {
self._opts.compiler.loadVersion(false, url) self._deps.compiler.loadVersion(false, url)
self.setVersionText('(loading)') self.setVersionText('(loading)')
} }
} }

@ -2,21 +2,22 @@ const yo = require('yo-yo')
const csjs = require('csjs-inject') const csjs = require('csjs-inject')
const remixLib = require('remix-lib') const remixLib = require('remix-lib')
var globalRegistry = require('../../global/registry')
const styles = require('../ui/styles-guide/theme-chooser').chooser() const styles = require('../ui/styles-guide/theme-chooser').chooser()
const EventManager = remixLib.EventManager const EventManager = remixLib.EventManager
module.exports = class SupportTab { module.exports = class SupportTab {
constructor (api = {}, events = {}, opts = {}) { constructor (localRegistry) {
const self = this const self = this
self.event = new EventManager() self.event = new EventManager()
self._api = api
self._events = events
self._opts = opts
self._view = { el: null, gitterIframe: '' } self._view = { el: null, gitterIframe: '' }
self.data = { gitterIsLoaded: false } self.data = { gitterIsLoaded: false }
self._components = {} self._components = {}
self._events.app.register('tabChanged', (tabName) => { self._components.registry = localRegistry || globalRegistry
var appEvent = self._components.registry.get('app').event
appEvent.register('tabChanged', (tabName) => {
if (tabName !== 'Support' || self.data.gitterIsLoaded) return if (tabName !== 'Support' || self.data.gitterIsLoaded) return
const iframe = yo`<iframe class="${css.chatIframe}" src='https://gitter.im/ethereum/remix/~embed'>` const iframe = yo`<iframe class="${css.chatIframe}" src='https://gitter.im/ethereum/remix/~embed'>`
self._view.gitterIframe.parentNode.replaceChild(iframe, self._view.gitterIframe) self._view.gitterIframe.parentNode.replaceChild(iframe, self._view.gitterIframe)

@ -2,20 +2,23 @@ var yo = require('yo-yo')
var csjs = require('csjs-inject') var csjs = require('csjs-inject')
var remixLib = require('remix-lib') var remixLib = require('remix-lib')
var globalRegistry = require('../../global/registry')
var helper = require('../../lib/helper') var helper = require('../../lib/helper')
var styles = require('../ui/styles-guide/theme-chooser').chooser() var styles = require('../ui/styles-guide/theme-chooser').chooser()
var EventManager = remixLib.EventManager var EventManager = remixLib.EventManager
module.exports = class TabbedMenu { module.exports = class TabbedMenu {
constructor (api = {}, events = {}, opts = {}) { constructor (localRegistry) {
const self = this const self = this
self.event = new EventManager() self.event = new EventManager()
self._opts = opts self._components = {}
self._api = api self._components.registry = localRegistry || globalRegistry
self._events = events self._deps = {
app: self._components.registry.get('app').api
}
self._view = { el: null, viewport: null, tabs: {}, contents: {} } self._view = { el: null, viewport: null, tabs: {}, contents: {} }
events.app.register('debuggingRequested', () => { self._deps.app.event.register('debuggingRequested', () => {
self.selectTabByTitle('Debugger') self.selectTabByTitle('Debugger')
}) })
} }
@ -63,7 +66,7 @@ module.exports = class TabbedMenu {
var title = el.getAttribute('title') var title = el.getAttribute('title')
self._view.contents[el.getAttribute('title')].style.display = 'block' self._view.contents[el.getAttribute('title')].style.display = 'block'
el.classList.add(css.active) el.classList.add(css.active)
self._events.app.trigger('tabChanged', [title]) self._deps.app.event.trigger('tabChanged', [title])
} }
} }

@ -1,21 +1,24 @@
var yo = require('yo-yo') var yo = require('yo-yo')
var async = require('async') var async = require('async')
var globalRegistry = require('../../global/registry')
var css = require('./styles/test-tab-styles') var css = require('./styles/test-tab-styles')
var remixTests = require('remix-tests') var remixTests = require('remix-tests')
module.exports = class TestTab { module.exports = class TestTab {
constructor (api = {}, events = {}, opts = {}) { constructor (localRegistry) {
const self = this const self = this
self._opts = opts
self._api = api
self._events = events
self._view = { el: null } self._view = { el: null }
self._components = {} self._components = {}
self._components.registry = localRegistry || globalRegistry
// dependencies
self._deps = {
fileManager: self._components.registry.get('filemanager').api
}
self.data = {} self.data = {}
self._view.el = self.render() self._view.el = self.render()
var appEvent = self._components.registry.get('app').event
events.app.register('tabChanged', tabName => { appEvent.register('tabChanged', tabName => {
if (tabName !== 'test') return if (tabName !== 'test') return
yo.update(self._view.el, self.render()) yo.update(self._view.el, self.render())
self._view.el.style.display = 'block' self._view.el.style.display = 'block'
@ -24,8 +27,6 @@ module.exports = class TestTab {
return { render () { return self._view.el } } return { render () { return self._view.el } }
} }
render () { render () {
const self = this
const api = self._api
var container = yo`<div class="tests" id="tests"></div>` var container = yo`<div class="tests" id="tests"></div>`
function append (container, txt) { function append (container, txt) {
@ -67,7 +68,7 @@ module.exports = class TestTab {
} }
function runTest (testFilePath, callback) { function runTest (testFilePath, callback) {
var provider = api.fileProviderOf(testFilePath) var provider = this._deps.fileManager.fileProviderOf(testFilePath)
provider.get(testFilePath, (error, content) => { provider.get(testFilePath, (error, content) => {
if (!error) { if (!error) {
var runningTest = {} var runningTest = {}
@ -75,14 +76,14 @@ module.exports = class TestTab {
remixTests.runTestSources(runningTest, testCallback, resultsCallback, (error, result) => { remixTests.runTestSources(runningTest, testCallback, resultsCallback, (error, result) => {
updateFinalResult(error, result) updateFinalResult(error, result)
callback(error) callback(error)
}, api.importFileCb) }, this._deps.fileManager.importFileCb)
} }
}) })
} }
let runTests = function () { let runTests = function () {
container.innerHTML = '' container.innerHTML = ''
var path = api.currentPath() var path = this._deps.fileManager.currentPath()
var tests = [] var tests = []
api.filesFromPath(path, (error, files) => { api.filesFromPath(path, (error, files) => {
if (!error) { if (!error) {

@ -148,6 +148,17 @@ UniversalDApp.prototype.getBalance = function (address, cb) {
} }
} }
UniversalDApp.prototype.getBalanceInEther = function (address, callback) {
var self = this
self.getBalance(address, (error, balance) => {
if (error) {
callback(error)
} else {
callback(null, executionContext.web3().fromWei(balance, 'ether'))
}
})
}
UniversalDApp.prototype.pendingTransactions = function () { UniversalDApp.prototype.pendingTransactions = function () {
return this.txRunner.pendingTxs return this.txRunner.pendingTxs
} }

Loading…
Cancel
Save