Merge branch 'homepage2' of https://github.com/ethereum/remix-ide into homepage2

pull/1/head
Rob Stupay 6 years ago
commit 69f85d5833
  1. 2
      extensions/etherscan-general/index.js
  2. 2
      package.json
  3. 103
      src/app.js
  4. 30
      src/app/components/plugin-manager-component.js
  5. 24
      src/app/editor/SourceHighlighters.js
  6. 7
      src/app/editor/editor.js
  7. 28
      src/app/files/browser-files-tree.js
  8. 31
      src/app/files/fileManager.js
  9. 42
      src/app/files/remixd-handle.js
  10. 30
      src/app/panels/file-panel.js
  11. 4
      src/app/panels/tab-proxy.js
  12. 13
      src/app/panels/terminal.js
  13. 94
      src/app/plugin/bundle.js
  14. 55
      src/app/plugin/index.js
  15. 71
      src/app/plugin/package.json
  16. 53
      src/app/plugin/plugin.md
  17. 150
      src/app/plugin/pluginAPI.js
  18. 179
      src/app/plugin/pluginManager.js
  19. 38
      src/app/plugin/plugins.js
  20. 22
      src/app/tabs/analysis-tab.js
  21. 34
      src/app/tabs/compile-tab.js
  22. 18
      src/app/tabs/debugger-tab.js
  23. 66
      src/app/tabs/network-module.js
  24. 30
      src/app/tabs/run-tab.js
  25. 30
      src/app/tabs/settings-tab.js
  26. 30
      src/app/tabs/test-tab.js
  27. 2
      src/app/tabs/testTab/testTab.js
  28. 20
      src/app/tabs/theme-module.js
  29. 23
      src/app/tabs/txlistener-module.js
  30. 20
      src/app/ui/landing-page/landing-page.js
  31. 6
      src/app/ui/landing-page/section.js
  32. 2
      src/app/ui/landing-page/workspace.js
  33. 5
      src/remixAppManager.js
  34. 31
      src/universal-dapp.js
  35. 2
      test-browser/plugin/index.html
  36. 10
      test-browser/plugin/plugin.js

@ -40,7 +40,7 @@ function load () {
} }
}) })
setInterval(function () { setInterval(function () {
remix.call('app', 'detectNetWork', [], function (error, result) { remix.call('network', 'detectNetWork', [], function (error, result) {
if (error) console.log(error) if (error) console.log(error)
if (network.innerHTML !== result[0].name + ' - ' + result[0].id) { if (network.innerHTML !== result[0].name + ' - ' + result[0].id) {
currentNetWork = result[0].name currentNetWork = result[0].name

@ -65,7 +65,7 @@
}, },
"dependencies": { "dependencies": {
"http-server": "0.9.0", "http-server": "0.9.0",
"remix-plugin": "0.0.1-alpha.43", "remix-plugin": "0.0.2-alpha.3",
"remixd": "0.1.8-alpha.6" "remixd": "0.1.8-alpha.6"
}, },
"repository": { "repository": {

@ -6,7 +6,6 @@ var yo = require('yo-yo')
var async = require('async') var async = require('async')
var request = require('request') var request = require('request')
var remixLib = require('remix-lib') var remixLib = require('remix-lib')
var EventManager = require('./lib/events')
var registry = require('./global/registry') var registry = require('./global/registry')
var UniversalDApp = require('./universal-dapp.js') var UniversalDApp = require('./universal-dapp.js')
var UniversalDAppUI = require('./universal-dapp-ui.js') var UniversalDAppUI = require('./universal-dapp-ui.js')
@ -54,9 +53,8 @@ import { EntityStore } from './lib/store'
import { RemixAppManager } from './remixAppManager' import { RemixAppManager } from './remixAppManager'
import { LandingPage } from './app/ui/landing-page/landing-page' import { LandingPage } from './app/ui/landing-page/landing-page'
import framingService from './framingService' import framingService from './framingService'
import { ApiFactory } from 'remix-plugin'
import { TxListenerModule } from './app/tabs/txlistener-module'
import { ThemeModule } from './app/tabs/theme-module' import { ThemeModule } from './app/tabs/theme-module'
import { NetworkModule } from './app/tabs/network-module'
var css = csjs` var css = csjs`
html { box-sizing: border-box; } html { box-sizing: border-box; }
@ -116,11 +114,9 @@ var css = csjs`
} }
` `
class App extends ApiFactory { class App {
constructor (api = {}, events = {}, opts = {}) { constructor (api = {}, events = {}, opts = {}) {
super()
var self = this var self = this
this.event = new EventManager()
self._components = {} self._components = {}
registry.put({api: self, name: 'app'}) registry.put({api: self, name: 'app'})
@ -171,14 +167,6 @@ class App extends ApiFactory {
run.apply(self) run.apply(self)
} }
get profile () {
return {
name: 'app',
description: 'service - provides information about current context (network).',
methods: ['getExecutionContextProvider', 'getProviderEndpoint', 'detectNetWork', 'addProvider', 'removeProvider']
}
}
render () { render () {
var self = this var self = this
if (self._view.el) return self._view.el if (self._view.el) return self._view.el
@ -250,45 +238,6 @@ class App extends ApiFactory {
if (callback) callback(error) if (callback) callback(error)
}) })
} }
getExecutionContextProvider () {
return new Promise((resolve, reject) => {
resolve(executionContext.getProvider())
})
}
getProviderEndpoint () {
return new Promise((resolve, reject) => {
if (executionContext.getProvider() === 'web3') {
resolve(executionContext.web3().currentProvider.host)
} else {
reject('no endpoint: current provider is either injected or vm')
}
})
}
detectNetWork () {
return new Promise((resolve, reject) => {
executionContext.detectNetwork((error, network) => {
if (error) return reject(error)
resolve(network)
})
})
}
addProvider (name, url) {
return new Promise((resolve, reject) => {
executionContext.addProvider({ name, url })
resolve()
})
}
removeProvider (name) {
return new Promise((resolve, reject) => {
executionContext.removeProvider(name)
resolve()
})
}
} }
module.exports = App module.exports = App
@ -329,7 +278,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
registry.put({api: self._components.compilersArtefacts, name: 'compilersartefacts'}) registry.put({api: self._components.compilersArtefacts, name: 'compilersartefacts'})
// ----------------- UniversalDApp ----------------- // ----------------- UniversalDApp -----------------
var udapp = new UniversalDApp(registry) const udapp = new UniversalDApp(registry)
// TODO: to remove when possible // TODO: to remove when possible
registry.put({api: udapp, name: 'udapp'}) registry.put({api: udapp, name: 'udapp'})
udapp.event.register('transactionBroadcasted', (txhash, networkName) => { udapp.event.register('transactionBroadcasted', (txhash, networkName) => {
@ -337,14 +286,14 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
if (txLink) registry.get('logCallback').api.logCallback(yo`<a href="${txLink}" target="_blank">${txLink}</a>`) if (txLink) registry.get('logCallback').api.logCallback(yo`<a href="${txLink}" target="_blank">${txLink}</a>`)
}) })
var udappUI = new UniversalDAppUI(udapp, registry) const udappUI = new UniversalDAppUI(udapp, registry)
// TODO: to remove when possible // TODO: to remove when possible
registry.put({api: udappUI, name: 'udappUI'}) registry.put({api: udappUI, name: 'udappUI'})
// ----------------- Tx listener ----------------- // ----------------- Tx listener -----------------
var transactionReceiptResolver = new TransactionReceiptResolver() const transactionReceiptResolver = new TransactionReceiptResolver()
var txlistener = new Txlistener({ const txlistener = new Txlistener({
api: { api: {
contracts: function () { contracts: function () {
if (self._components.compilersArtefacts['__last']) return self._components.compilersArtefacts['__last'].getContracts() if (self._components.compilersArtefacts['__last']) return self._components.compilersArtefacts['__last'].getContracts()
@ -358,8 +307,9 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
udapp: udapp.event udapp: udapp.event
}}) }})
registry.put({api: txlistener, name: 'txlistener'}) registry.put({api: txlistener, name: 'txlistener'})
udapp.startListening(txlistener)
var eventsDecoder = new EventsDecoder({ const eventsDecoder = new EventsDecoder({
api: { api: {
resolveReceipt: function (tx, cb) { resolveReceipt: function (tx, cb) {
transactionReceiptResolver.resolve(tx, cb) transactionReceiptResolver.resolve(tx, cb)
@ -368,11 +318,6 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
}) })
registry.put({api: eventsDecoder, name: 'eventsdecoder'}) registry.put({api: eventsDecoder, name: 'eventsdecoder'})
/*
that proxy is used by appManager to broadcast new transaction event
*/
const txListenerModule = new TxListenerModule(txlistener)
txlistener.startListening() txlistener.startListening()
// TODO: There are still a lot of dep between editorpanel and filemanager // TODO: There are still a lot of dep between editorpanel and filemanager
@ -385,9 +330,13 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
// ----------------- file manager ---------------------------- // ----------------- file manager ----------------------------
self._components.fileManager = new FileManager() self._components.fileManager = new FileManager()
var fileManager = self._components.fileManager const fileManager = self._components.fileManager
registry.put({api: fileManager, name: 'filemanager'}) registry.put({api: fileManager, name: 'filemanager'})
// ----------------- Network ----------------------------
const networkModule = new NetworkModule()
registry.put({api: networkModule, name: 'network'})
// ----------------- theme module ---------------------------- // ----------------- theme module ----------------------------
const themeModule = new ThemeModule() const themeModule = new ThemeModule()
registry.put({api: themeModule, name: 'themeModule'}) registry.put({api: themeModule, name: 'themeModule'})
@ -397,7 +346,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
registry.put({ api: self._components.editorpanel, name: 'editorpanel' }) registry.put({ api: self._components.editorpanel, name: 'editorpanel' })
// ----------------- Renderer ----------------- // ----------------- Renderer -----------------
var renderer = new Renderer() const renderer = new Renderer()
registry.put({api: renderer, name: 'renderer'}) registry.put({api: renderer, name: 'renderer'})
// ----------------- app manager ---------------------------- // ----------------- app manager ----------------------------
@ -413,17 +362,18 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
const pluginManagerComponent = new PluginManagerComponent() const pluginManagerComponent = new PluginManagerComponent()
const swapPanelComponent = new SwapPanelComponent('swapPanel', appStore, appManager, { default: true, displayHeader: true }) const swapPanelComponent = new SwapPanelComponent('swapPanel', appStore, appManager, { default: true, displayHeader: true })
registry.put({api: appManager.proxy(), name: 'pluginmanager'})
pluginManagerComponent.setApp(appManager)
pluginManagerComponent.setStore(appStore)
// ----------------- Vertical Icon ----------------------------
const verticalIconsComponent = new VerticalIconsComponent('swapPanel', appStore) const verticalIconsComponent = new VerticalIconsComponent('swapPanel', appStore)
const swapPanelApi = new SwapPanelApi(swapPanelComponent, verticalIconsComponent) // eslint-disable-line const swapPanelApi = new SwapPanelApi(swapPanelComponent, verticalIconsComponent) // eslint-disable-line
const mainPanelApi = new SwapPanelApi(mainPanelComponent, verticalIconsComponent) // eslint-disable-line const mainPanelApi = new SwapPanelApi(mainPanelComponent, verticalIconsComponent) // eslint-disable-line
const verticalIconsApi = new VerticalIconsApi(verticalIconsComponent) // eslint-disable-line const verticalIconsApi = new VerticalIconsApi(verticalIconsComponent) // eslint-disable-line
registry.put({api: appManager.proxy(), name: 'pluginmanager'})
registry.put({api: verticalIconsApi, name: 'verticalicon'}) registry.put({api: verticalIconsApi, name: 'verticalicon'})
pluginManagerComponent.setApp(appManager)
pluginManagerComponent.setStore(appStore)
self._components.editorpanel.init() self._components.editorpanel.init()
self._components.fileManager.init() self._components.fileManager.init()
@ -469,16 +419,15 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
let sourceHighlighters = registry.get('editor').api.sourceHighlighters let sourceHighlighters = registry.get('editor').api.sourceHighlighters
appManager.init([ appManager.init([
this.api(),
landingPage.api(), landingPage.api(),
udapp.api(), udapp.api(),
fileManager.api(), fileManager.api(),
sourceHighlighters.api(), sourceHighlighters.api(),
txListenerModule.api(),
filePanel.api(), filePanel.api(),
// { profile: support.profile(), api: support }, // { profile: support.profile(), api: support },
settings.api(), settings.api(),
pluginManagerComponent.api(), pluginManagerComponent.api(),
networkModule.api(),
themeModule.api() themeModule.api()
]) ])
@ -496,8 +445,8 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
// The event listener needs to be registered as early as possible, because the // The event listener needs to be registered as early as possible, because the
// parent will send the message upon the "load" event. // parent will send the message upon the "load" event.
var filesToLoad = null let filesToLoad = null
var loadFilesCallback = function (files) { filesToLoad = files } // will be replaced later let loadFilesCallback = function (files) { filesToLoad = files } // will be replaced later
window.addEventListener('message', function (ev) { window.addEventListener('message', function (ev) {
if (typeof ev.data === typeof [] && ev.data[0] === 'loadFiles') { if (typeof ev.data === typeof [] && ev.data[0] === 'loadFiles') {
@ -515,7 +464,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
self.loadFiles(filesToLoad) self.loadFiles(filesToLoad)
} }
var txLogger = new TxLogger() // eslint-disable-line const txLogger = new TxLogger() // eslint-disable-line
txLogger.event.register('debuggingRequested', (hash) => { txLogger.event.register('debuggingRequested', (hash) => {
if (!appStore.isActive('debugger')) appManager.activateOne('debugger') if (!appStore.isActive('debugger')) appManager.activateOne('debugger')
debug.debugger().debug(hash) debug.debugger().debug(hash)
@ -547,9 +496,9 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
} }
udapp.resetAPI(transactionContextAPI) udapp.resetAPI(transactionContextAPI)
var queryParams = new QueryParams() const queryParams = new QueryParams()
var loadingFromGist = self.loadFromGist(queryParams.get()) const loadingFromGist = self.loadFromGist(queryParams.get())
if (!loadingFromGist) { if (!loadingFromGist) {
// insert ballot contract if there are no files to show // insert ballot contract if there are no files to show
self._components.filesProviders['browser'].resolveDirectory('browser', (error, filesList) => { self._components.filesProviders['browser'].resolveDirectory('browser', (error, filesList) => {

@ -2,7 +2,7 @@ const yo = require('yo-yo')
const csjs = require('csjs-inject') const csjs = require('csjs-inject')
const EventEmitter = require('events') const EventEmitter = require('events')
const LocalPlugin = require('./local-plugin') const LocalPlugin = require('./local-plugin')
import { Plugin, ApiFactory } from 'remix-plugin' import { Plugin, BaseApi } from 'remix-plugin'
const css = csjs` const css = csjs`
.pluginSearch { .pluginSearch {
@ -34,21 +34,7 @@ const css = csjs`
} }
` `
class PluginManagerComponent extends ApiFactory { const profile = {
constructor () {
super()
this.event = new EventEmitter()
this.views = {
root: null,
items: {}
}
this.localPlugin = new LocalPlugin()
this.filter = ''
}
get profile () {
return {
displayName: 'plugin manager', displayName: 'plugin manager',
name: 'pluginManager', name: 'pluginManager',
methods: [], methods: [],
@ -58,6 +44,18 @@ class PluginManagerComponent extends ApiFactory {
kind: 'settings', kind: 'settings',
location: 'swapPanel' location: 'swapPanel'
} }
class PluginManagerComponent extends BaseApi {
constructor () {
super(profile)
this.event = new EventEmitter()
this.views = {
root: null,
items: {}
}
this.localPlugin = new LocalPlugin()
this.filter = ''
} }
setApp (appManager) { setApp (appManager) {

@ -1,22 +1,22 @@
'use strict' 'use strict'
const SourceHighlighter = require('./sourceHighlighter') const SourceHighlighter = require('./sourceHighlighter')
import { ApiFactory } from 'remix-plugin' import { EditorApi } from 'remix-plugin'
class SourceHighlighters extends ApiFactory { const profile = {
constructor () {
super()
this.highlighters = {}
}
get profile () {
return {
displayName: 'source highlighters', displayName: 'source highlighters',
name: 'sourceHighlighters', name: 'editor',
methods: ['highlight', 'discardHighlight'],
description: 'service - highlight source code' description: 'service - highlight source code'
} }
// EditorApi:
// - methods: ['highlight', 'discardHighlight'],
class SourceHighlighters extends EditorApi {
constructor () {
super(profile)
this.highlighters = {}
} }
highlight (lineColumnPos, filePath, hexColor) { highlight (lineColumnPos, filePath, hexColor) {

@ -99,8 +99,11 @@ class Editor {
this.editor = ace.edit(el) this.editor = ace.edit(el)
ace.acequire('ace/ext/language_tools') ace.acequire('ace/ext/language_tools')
// Unmap ctrl-t & ctrl-f // Unmap ctrl-l & cmd-l
this.editor.commands.bindKeys({ 'ctrl-t': null }) this.editor.commands.bindKeys({
'ctrl-L': null,
'Command-L': null
})
// shortcuts for "Ctrl-"" and "Ctrl+"" to increase/decrease font size of the editor // shortcuts for "Ctrl-"" and "Ctrl+"" to increase/decrease font size of the editor
this.editor.commands.addCommand({ this.editor.commands.addCommand({

@ -2,12 +2,16 @@
var EventManager = require('../../lib/events') var EventManager = require('../../lib/events')
import { ApiFactory } from 'remix-plugin' import { BaseApi } from 'remix-plugin'
class FilesTree extends ApiFactory {
class FilesTree extends BaseApi {
constructor (name, storage) { constructor (name, storage) {
super() super({
name: name,
methods: ['get', 'set', 'remove'],
description:
'service - read/write file to the `config` explorer without need of additionnal permission.'
})
this.event = new EventManager() this.event = new EventManager()
this.storage = storage this.storage = storage
this.type = name this.type = name
@ -15,15 +19,6 @@ class FilesTree extends ApiFactory {
this.tree = {} this.tree = {}
} }
get profile () {
// TODO should make them promisable
return {
name: this.type,
methods: ['get', 'set', 'remove'],
description: 'service - read/write file to the `config` explorer without need of additionnal permission.'
}
}
exists (path, cb) { exists (path, cb) {
cb(null, this._exists(path)) cb(null, this._exists(path))
} }
@ -114,7 +109,11 @@ class FilesTree extends ApiFactory {
if (!this.storage.rename(unprefixedoldPath, unprefixednewPath)) { if (!this.storage.rename(unprefixedoldPath, unprefixednewPath)) {
return false return false
} }
this.event.trigger('fileRenamed', [this.type + '/' + unprefixedoldPath, this.type + '/' + unprefixednewPath, isFolder]) this.event.trigger('fileRenamed', [
this.type + '/' + unprefixedoldPath,
this.type + '/' + unprefixednewPath,
isFolder
])
return true return true
} }
return false return false
@ -143,7 +142,6 @@ class FilesTree extends ApiFactory {
if (path[0] === '/') return path.substring(1) if (path[0] === '/') return path.substring(1)
return path return path
} }
} }
module.exports = FilesTree module.exports = FilesTree

@ -1,20 +1,31 @@
'use strict' 'use strict'
import { ApiFactory } from 'remix-plugin'
import yo from 'yo-yo' import yo from 'yo-yo'
const EventEmitter = require('events') const EventEmitter = require('events')
var globalRegistry = require('../../global/registry') var globalRegistry = require('../../global/registry')
var CompilerImport = require('../compiler/compiler-imports') var CompilerImport = require('../compiler/compiler-imports')
var toaster = require('../ui/tooltip') var toaster = require('../ui/tooltip')
import { FileSystemApi } from 'remix-plugin'
/* /*
attach to files event (removed renamed) attach to files event (removed renamed)
trigger: currentFileChanged trigger: currentFileChanged
*/ */
class FileManager extends ApiFactory { const profile = {
displayName: 'file manager',
name: 'fileManager',
description: 'service - read/write to any files or folders, require giving permissions',
permission: true
}
// File System profile
// - events: ['currentFileChanged']
// - methods: ['getFolder', 'getCurrentFile', 'getFile', 'setFile']
class FileManager extends FileSystemApi {
constructor (localRegistry) { constructor (localRegistry) {
super() super(profile)
this.openedFiles = {} // list all opened files this.openedFiles = {} // list all opened files
this.events = new EventEmitter() this.events = new EventEmitter()
this._components = {} this._components = {}
@ -42,18 +53,6 @@ class FileManager extends ApiFactory {
this._deps.localhostExplorer.event.register('closed', (event) => { this.removeTabsOf(this._deps.localhostExplorer) }) this._deps.localhostExplorer.event.register('closed', (event) => { this.removeTabsOf(this._deps.localhostExplorer) })
} }
get profile () {
return {
displayName: 'file manager',
name: 'fileManager',
methods: ['getFilesFromPath', 'getCurrentFile', 'getFile', 'setFile'],
events: ['currentFileChanged'],
description: 'service - read/write to any files or folders, require giving permissions',
permission: true,
icon: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iMTc5MiIgaGVpZ2h0PSIxNzkyIiB2aWV3Qm94PSIwIDAgMTc5MiAxNzkyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik0xNjk2IDM4NHE0MCAwIDY4IDI4dDI4IDY4djEyMTZxMCA0MC0yOCA2OHQtNjggMjhoLTk2MHEtNDAgMC02OC0yOHQtMjgtNjh2LTI4OGgtNTQ0cS00MCAwLTY4LTI4dC0yOC02OHYtNjcycTAtNDAgMjAtODh0NDgtNzZsNDA4LTQwOHEyOC0yOCA3Ni00OHQ4OC0yMGg0MTZxNDAgMCA2OCAyOHQyOCA2OHYzMjhxNjgtNDAgMTI4LTQwaDQxNnptLTU0NCAyMTNsLTI5OSAyOTloMjk5di0yOTl6bS02NDAtMzg0bC0yOTkgMjk5aDI5OXYtMjk5em0xOTYgNjQ3bDMxNi0zMTZ2LTQxNmgtMzg0djQxNnEwIDQwLTI4IDY4dC02OCAyOGgtNDE2djY0MGg1MTJ2LTI1NnEwLTQwIDIwLTg4dDQ4LTc2em05NTYgODA0di0xMTUyaC0zODR2NDE2cTAgNDAtMjggNjh0LTY4IDI4aC00MTZ2NjQwaDg5NnoiLz48L3N2Zz4='
}
}
fileRenamedEvent (oldName, newName, isFolder) { fileRenamedEvent (oldName, newName, isFolder) {
if (!isFolder) { if (!isFolder) {
this._deps.config.set('currentFile', '') this._deps.config.set('currentFile', '')
@ -223,7 +222,7 @@ class FileManager extends ApiFactory {
} }
} }
getFilesFromPath (path) { getFolder (path) {
// TODO : Change provider with promise // TODO : Change provider with promise
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const provider = this.fileProviderOf(path) const provider = this.fileProviderOf(path)

@ -1,7 +1,9 @@
import { ApiFactory } from 'remix-plugin' let globalRegistry = require('../../global/registry')
import { BaseApi } from 'remix-plugin'
var yo = require('yo-yo') var yo = require('yo-yo')
var modalDialog = require('../ui/modaldialog') var modalDialog = require('../ui/modaldialog')
var modalDialogCustom = require('../ui/modal-dialog-custom')
var csjs = require('csjs-inject') var csjs = require('csjs-inject')
@ -16,21 +18,19 @@ var css = csjs`
} }
` `
export class RemixdHandle extends ApiFactory { const profile = {
constructor (fileSystemExplorer, locahostProvider) {
super()
this.fileSystemExplorer = fileSystemExplorer
this.locahostProvider = locahostProvider
}
get profile () {
return {
name: 'remixd', name: 'remixd',
methods: [], methods: [],
events: [], events: [],
description: 'using Remixd daemon, allow to access file system', description: 'using Remixd daemon, allow to access file system',
kind: 'other' kind: 'other'
} }
export class RemixdHandle extends BaseApi {
constructor (fileSystemExplorer, locahostProvider) {
super(profile)
this.fileSystemExplorer = fileSystemExplorer
this.locahostProvider = locahostProvider
} }
deactivate () { deactivate () {
@ -43,6 +43,11 @@ export class RemixdHandle extends ApiFactory {
this.connectToLocalhost() this.connectToLocalhost()
} }
canceled () {
let appManager = globalRegistry.get('appmanager').api
appManager.ensureDeactivated('remixd')
}
/** /**
* connect to localhost if no connection and render the explorer * connect to localhost if no connection and render the explorer
* disconnect from localhost if connected and remove the explorer * disconnect from localhost if connected and remove the explorer
@ -55,17 +60,30 @@ export class RemixdHandle extends ApiFactory {
if (error) console.log(error) if (error) console.log(error)
}) })
} else { } else {
modalDialog('Connect to localhost', remixdDialog(), modalDialog(
'Connect to localhost',
remixdDialog(),
{ label: 'Connect', { label: 'Connect',
fn: () => { fn: () => {
this.locahostProvider.init((error) => { this.locahostProvider.init((error) => {
if (error) { if (error) {
console.log(error) console.log(error)
modalDialogCustom.alert(
'Cannot connect to the remixd daemon.' +
'Please make sure you have the remixd running in the background.'
)
this.canceled()
} else { } else {
this.fileSystemExplorer.ensureRoot() this.fileSystemExplorer.ensureRoot()
} }
}) })
}} }
},
{ label: 'Cancel',
fn: () => {
this.canceled()
}
}
) )
} }
} }

@ -6,7 +6,7 @@ var { RemixdHandle } = require('../files/remixd-handle.js')
var globalRegistry = require('../../global/registry') var globalRegistry = require('../../global/registry')
var css = require('./styles/file-panel-styles') var css = require('./styles/file-panel-styles')
import { ApiFactory } from 'remix-plugin' import { BaseApi } from 'remix-plugin'
var canUpload = window.File || window.FileReader || window.FileList || window.Blob var canUpload = window.File || window.FileReader || window.FileList || window.Blob
@ -27,10 +27,21 @@ var canUpload = window.File || window.FileReader || window.FileList || window.Bl
- call fileProvider API - call fileProvider API
*/ */
module.exports = class Filepanel extends ApiFactory { const profile = {
name: 'fileExplorers',
displayName: 'file explorers',
methods: [],
events: [],
icon: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iMTc5MiIgaGVpZ2h0PSIxNzkyIiB2aWV3Qm94PSIwIDAgMTc5MiAxNzkyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik0xNjk2IDM4NHE0MCAwIDY4IDI4dDI4IDY4djEyMTZxMCA0MC0yOCA2OHQtNjggMjhoLTk2MHEtNDAgMC02OC0yOHQtMjgtNjh2LTI4OGgtNTQ0cS00MCAwLTY4LTI4dC0yOC02OHYtNjcycTAtNDAgMjAtODh0NDgtNzZsNDA4LTQwOHEyOC0yOCA3Ni00OHQ4OC0yMGg0MTZxNDAgMCA2OCAyOHQyOCA2OHYzMjhxNjgtNDAgMTI4LTQwaDQxNnptLTU0NCAyMTNsLTI5OSAyOTloMjk5di0yOTl6bS02NDAtMzg0bC0yOTkgMjk5aDI5OXYtMjk5em0xOTYgNjQ3bDMxNi0zMTZ2LTQxNmgtMzg0djQxNnEwIDQwLTI4IDY4dC02OCAyOGgtNDE2djY0MGg1MTJ2LTI1NnEwLTQwIDIwLTg4dDQ4LTc2em05NTYgODA0di0xMTUyaC0zODR2NDE2cTAgNDAtMjggNjh0LTY4IDI4aC00MTZ2NjQwaDg5NnoiLz48L3N2Zz4=',
description: ' - ',
kind: 'fileexplorer',
location: 'swapPanel'
}
module.exports = class Filepanel extends BaseApi {
constructor (localRegistry) { constructor (localRegistry) {
super() super(profile)
var self = this var self = this
self._components = {} self._components = {}
self._components.registry = localRegistry || globalRegistry self._components.registry = localRegistry || globalRegistry
@ -132,18 +143,5 @@ module.exports = class Filepanel extends ApiFactory {
self.render = function render () { return element } self.render = function render () { return element }
} }
get profile () {
return {
name: 'fileExplorers',
displayName: 'file explorers',
methods: [],
events: [],
icon: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iMTc5MiIgaGVpZ2h0PSIxNzkyIiB2aWV3Qm94PSIwIDAgMTc5MiAxNzkyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik0xNjk2IDM4NHE0MCAwIDY4IDI4dDI4IDY4djEyMTZxMCA0MC0yOCA2OHQtNjggMjhoLTk2MHEtNDAgMC02OC0yOHQtMjgtNjh2LTI4OGgtNTQ0cS00MCAwLTY4LTI4dC0yOC02OHYtNjcycTAtNDAgMjAtODh0NDgtNzZsNDA4LTQwOHEyOC0yOCA3Ni00OHQ4OC0yMGg0MTZxNDAgMCA2OCAyOHQyOCA2OHYzMjhxNjgtNDAgMTI4LTQwaDQxNnptLTU0NCAyMTNsLTI5OSAyOTloMjk5di0yOTl6bS02NDAtMzg0bC0yOTkgMjk5aDI5OXYtMjk5em0xOTYgNjQ3bDMxNi0zMTZ2LTQxNmgtMzg0djQxNnEwIDQwLTI4IDY4dC02OCAyOGgtNDE2djY0MGg1MTJ2LTI1NnEwLTQwIDIwLTg4dDQ4LTc2em05NTYgODA0di0xMTUyaC0zODR2NDE2cTAgNDAtMjggNjh0LTY4IDI4aC00MTZ2NjQwaDg5NnoiLz48L3N2Zz4=',
description: ' - ',
kind: 'fileexplorer',
location: 'swapPanel'
}
}
} }

@ -105,6 +105,8 @@ export class TabProxy {
} }
addTab (name, switchTo, close, kind) { addTab (name, switchTo, close, kind) {
if (this._handlers[name]) return
var slash = name.split('/') var slash = name.split('/')
let title = name.indexOf('/') !== -1 ? slash[slash.length - 1] : name let title = name.indexOf('/') !== -1 ? slash[slash.length - 1] : name
this._view.filetabs.addTab({ this._view.filetabs.addTab({
@ -117,7 +119,7 @@ export class TabProxy {
} }
removeTab (name) { removeTab (name) {
this._view.filetabs.closeTab(name) this._view.filetabs.removeTab(name)
delete this._handlers[name] delete this._handlers[name]
} }

@ -132,6 +132,7 @@ class Terminal {
<div onmousedown=${mousedown} class=${css.dragbarHorizontal}></div>` <div onmousedown=${mousedown} class=${css.dragbarHorizontal}></div>`
self._view.dropdown = self._components.dropdown.render() self._view.dropdown = self._components.dropdown.render()
self._view.pendingTxCount = yo`<div class=${css.pendingTx} title='Pending Transactions'>0</div>` self._view.pendingTxCount = yo`<div class=${css.pendingTx} title='Pending Transactions'>0</div>`
self._view.inputSearch = yo`<input spellcheck="false" type="text" class="${css.filter} form-control" id="input" onkeydown=${filter} placeholder="Search transactions"></input>`
self._view.bar = yo` self._view.bar = yo`
<div class="${css.bar}"> <div class="${css.bar}">
${self._view.dragbar} ${self._view.dragbar}
@ -151,7 +152,7 @@ class Terminal {
${self._view.dropdown} ${self._view.dropdown}
<div class=${css.search}> <div class=${css.search}>
<i class="fa fa-search ${css.searchIcon} bg-light" aria-hidden="true"></i> <i class="fa fa-search ${css.searchIcon} bg-light" aria-hidden="true"></i>
<input spellcheck="false" type="text" class="${css.filter} form-control" onkeydown=${filter} placeholder="Search transactions"> ${self._view.inputSearch}
</div> </div>
</div> </div>
</div> </div>
@ -280,7 +281,7 @@ class Terminal {
if (inserted) { if (inserted) {
text.innerText = '' text.innerText = ''
background.onclick = undefined background.onclick = undefined
self._view.journal.removeChild(placeholder) if (placeholder.parentElement) self._view.journal.removeChild(placeholder)
} }
inserted = false inserted = false
delete self.scroll2bottom delete self.scroll2bottom
@ -347,7 +348,7 @@ class Terminal {
clearTimeout(filtertimeout) clearTimeout(filtertimeout)
} }
filtertimeout = setTimeout(() => { filtertimeout = setTimeout(() => {
self.updateJournal({ type: 'search', value: document.querySelector('.' + event.target.className).value }) self.updateJournal({ type: 'search', value: self._view.inputSearch.value })
}, 500) }, 500)
} }
function clear (event) { function clear (event) {
@ -499,8 +500,8 @@ class Terminal {
commands[value] = false commands[value] = false
if (!self._INDEX.commandsMain[value]) return if (!self._INDEX.commandsMain[value]) return
self._INDEX.commandsMain[value].forEach(item => { self._INDEX.commandsMain[value].forEach(item => {
item.root.steps.forEach(item => { self._JOURNAL[item.gidx] = undefined }) item.root.steps.forEach(item => { self._JOURNAL[item.gidx].hide = true })
self._JOURNAL[item.gidx] = undefined self._JOURNAL[item.gidx].hide = true
}) })
} else if (filterEvent.type === 'search') { } else if (filterEvent.type === 'search') {
if (value !== self.data.activeFilters.input) { if (value !== self.data.activeFilters.input) {
@ -535,7 +536,7 @@ class Terminal {
self._jobs = [] self._jobs = []
}) })
} }
self._jobs.push(el) if (self.data.activeFilters.commands[item.cmd]) self._jobs.push(el)
} }
scroll2bottom () { scroll2bottom () {
var self = this var self = this

@ -1,94 +0,0 @@
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
'use strict';
var _createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);
}
}return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;
};
}();
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
var RemixExtension = function () {
function RemixExtension() {
var _this = this;
_classCallCheck(this, RemixExtension);
this._notifications = {};
this._pendingRequests = {};
this._id = 0;
window.addEventListener('message', function (event) {
return _this._newMessage(event);
}, false);
}
_createClass(RemixExtension, [{
key: 'listen',
value: function listen(key, type, callback) {
if (!this._notifications[key]) this._notifications[key] = {};
this._notifications[key][type] = callback;
}
}, {
key: 'call',
value: function call(key, type, params, callback) {
this._id++;
this._pendingRequests[this._id] = callback;
window.parent.postMessage(JSON.stringify({
action: 'request',
key: key,
type: type,
value: params,
id: this._id
}), '*');
}
}, {
key: '_newMessage',
value: function _newMessage(event) {
if (!event.data) return;
if (typeof event.data !== 'string') return;
var msg;
try {
msg = JSON.parse(event.data);
} catch (e) {
return console.log('unable to parse data');
}
var _msg = msg,
action = _msg.action,
key = _msg.key,
type = _msg.type,
value = _msg.value;
if (action === 'notification') {
if (this._notifications[key] && this._notifications[key][type]) {
this._notifications[key][type](value);
}
} else if (action === 'response') {
var _msg2 = msg,
id = _msg2.id,
error = _msg2.error;
if (this._pendingRequests[id]) {
this._pendingRequests[id](error, value);
delete this._pendingRequests[id];
}
}
}
}]);
return RemixExtension;
}();
if (window) window.RemixExtension = RemixExtension;
if (module && module.exports) module.exports = RemixExtension;
},{}]},{},[1]);

@ -1,55 +0,0 @@
'use strict'
class RemixExtension {
constructor () {
this._notifications = {}
this._pendingRequests = {}
this._id = 0
window.addEventListener('message', (event) => this._newMessage(event), false)
}
listen (key, type, callback) {
if (!this._notifications[key]) this._notifications[key] = {}
this._notifications[key][type] = callback
}
call (key, type, params, callback) {
this._id++
this._pendingRequests[this._id] = callback
window.parent.postMessage(JSON.stringify({
action: 'request',
key,
type,
value: params,
id: this._id
}), '*')
}
_newMessage (event) {
if (!event.data) return
if (typeof event.data !== 'string') return
var msg
try {
msg = JSON.parse(event.data)
} catch (e) {
return console.log('unable to parse data')
}
const {action, key, type, value} = msg
if (action === 'notification') {
if (this._notifications[key] && this._notifications[key][type]) {
this._notifications[key][type](value)
}
} else if (action === 'response') {
const {id, error} = msg
if (this._pendingRequests[id]) {
this._pendingRequests[id](error, value)
delete this._pendingRequests[id]
}
}
}
}
if (window) window.RemixExtension = RemixExtension
if (module && module.exports) module.exports = RemixExtension

@ -1,71 +0,0 @@
{
"name": "remix-extension",
"version": "0.0.1",
"description": "Ethereum IDE and tools for the web",
"contributors": [
{
"name": "Yann Levreau",
"email": "yann@ethdev.com"
}
],
"main": "./index.js",
"dependencies": {
"babel-eslint": "^7.1.1",
"babel-plugin-transform-object-assign": "^6.22.0",
"babel-preset-es2015": "^6.24.0",
"babelify": "^7.3.0",
"standard": "^7.0.1",
"tape": "^4.6.0"
},
"scripts": {
"browserify": "browserify index.js -o bundle.js"
},
"standard": {
"ignore": [
"node_modules/*"
],
"parser": "babel-eslint"
},
"repository": {
"type": "git",
"url": "git+https://github.com/ethereum/remix-ide.git"
},
"author": "cpp-ethereum team",
"license": "MIT",
"bugs": {
"url": "https://github.com/ethereum/remix-ide/issues"
},
"homepage": "https://github.com/ethereum/remix-ide#readme",
"browserify": {
"transform": [
[
"babelify",
{
"plugins": [
[
"fast-async",
{
"runtimePatten": null,
"compiler": {
"promises": true,
"es7": true,
"noRuntime": true,
"wrapAwait": true
}
}
],
"transform-object-assign"
]
}
],
[
"babelify",
{
"presets": [
"es2015"
]
}
]
]
}
}

@ -1,53 +0,0 @@
plugin api
# current APIs:
## 1) notifications
### app (key: app)
- unfocus `[]`
- focus `[]`
### compiler (key: compiler)
- compilationFinished `[success (bool), data (obj), source (obj)]`
- compilationData `[compilationResult]`
### transaction listener (key: txlistener)
- newTransaction `tx (obj)`
## 2) interactions
### app
- getExecutionContextProvider `@return {String} provider (injected | web3 | vm)`
- getProviderEndpoint `@return {String} url`
- updateTitle `@param {String} title`
- detectNetWork `@return {Object} {name, id}`
- addProvider `@param {String} name, @param {String} url`
- removeProvider `@return {String} name`
### config
- setConfig `@param {String} path, @param {String} content`
- getConfig `@param {String} path`
- removeConfig `@param {String} path`
### compiler
- getCompilationResult `@return {Object} compilation result`
### udapp (only VM)
- runTx `@param {Object} tx`
- getAccounts `@return {Array} acccounts`
- createVMAccount `@param {String} privateKey, @param {String} balance (hex)`
### editor
- getFilesFromPath `@param {Array} [path]`
- getCurrentFile `@return {String} path`
- getFile `@param {String} path`
- setFile `@param {String} path, @param {String} content`
- highlight `@param {Object} lineColumnPos {start: {line, column}, end: {line, column}}, @param {String} path, @param {String} hexColor`
- discardHighlight

@ -1,150 +0,0 @@
'use strict'
var executionContext = require('../../execution-context')
var SourceHighlighter = require('../editor/sourceHighlighter')
/*
Defines available API. `key` / `type`
*/
module.exports = (pluginManager, fileProviders, fileManager, compilesrArtefacts, udapp) => {
let highlighters = {}
return {
app: {
getExecutionContextProvider: (mod, cb) => {
cb(null, executionContext.getProvider())
},
getProviderEndpoint: (mod, cb) => {
if (executionContext.getProvider() === 'web3') {
cb(null, executionContext.web3().currentProvider.host)
} else {
cb('no endpoint: current provider is either injected or vm')
}
},
updateTitle: (mod, title, cb) => {
pluginManager.plugins[mod].modal.setTitle(title)
if (cb) cb()
},
detectNetWork: (mod, cb) => {
executionContext.detectNetwork((error, network) => {
cb(error, network)
})
},
addProvider: (mod, name, url, cb) => {
executionContext.addProvider({ name, url })
cb()
},
removeProvider: (mod, name, cb) => {
executionContext.removeProvider(name)
cb()
}
},
config: {
setConfig: (mod, path, content, cb) => {
fileProviders['config'].set(mod + '/' + path, content)
cb()
},
getConfig: (mod, path, cb) => {
cb(null, fileProviders['config'].get(mod + '/' + path))
},
removeConfig: (mod, path, cb) => {
cb(null, fileProviders['config'].remove(mod + '/' + path))
if (cb) cb()
}
},
compiler: {
getCompilationResult: (mod, cb) => {
cb(null, compilesrArtefacts['__last'])
},
sendCompilationResult: (mod, file, source, languageVersion, data, cb) => {
pluginManager.receivedDataFrom('sendCompilationResult', mod, [file, source, languageVersion, data])
}
},
udapp: {
runTx: (mod, tx, cb) => {
executionContext.detectNetwork((error, network) => {
if (error) return cb(error)
if (network.name === 'Main' && network.id === '1') {
return cb('It is not allowed to make this action against mainnet')
}
udapp.silentRunTx(tx, (error, result) => {
if (error) return cb(error)
cb(null, {
transactionHash: result.transactionHash,
status: result.result.status,
gasUsed: '0x' + result.result.gasUsed.toString('hex'),
error: result.result.vm.exceptionError,
return: result.result.vm.return ? '0x' + result.result.vm.return.toString('hex') : '0x',
createdAddress: result.result.createdAddress ? '0x' + result.result.createdAddress.toString('hex') : undefined
})
})
})
},
getAccounts: (mod, cb) => {
executionContext.detectNetwork((error, network) => {
if (error) return cb(error)
if (network.name === 'Main' && network.id === '1') {
return cb('It is not allowed to make this action against mainnet')
}
udapp.getAccounts(cb)
})
},
createVMAccount: (mod, privateKey, balance, cb) => {
if (executionContext.getProvider() !== 'vm') return cb('plugin API does not allow creating a new account through web3 connection. Only vm mode is allowed')
udapp.createVMAccount(privateKey, balance, (error, address) => {
cb(error, address)
})
}
},
editor: {
getFilesFromPath: (mod, path, cb) => {
fileManager.filesFromPath(path, cb)
},
getCurrentFile: (mod, cb) => {
var path = fileManager.currentFile()
if (!path) {
cb('no file selected')
} else {
cb(null, path)
}
},
getFile: (mod, path, cb) => {
var provider = fileManager.fileProviderOf(path)
if (provider) {
// TODO add approval to user for external plugin to get the content of the given `path`
provider.get(path, (error, content) => {
cb(error, content)
})
} else {
cb(path + ' not available')
}
},
setFile: (mod, path, content, cb) => {
var provider = fileManager.fileProviderOf(path)
if (provider) {
// TODO add approval to user for external plugin to set the content of the given `path`
provider.set(path, content, (error) => {
if (error) return cb(error)
fileManager.syncEditor(path)
cb()
})
} else {
cb(path + ' not available')
}
},
highlight: (mod, lineColumnPos, filePath, hexColor, cb) => {
var position
try {
position = JSON.parse(lineColumnPos)
} catch (e) {
return cb(e.message)
}
if (!highlighters[mod]) highlighters[mod] = new SourceHighlighter()
highlighters[mod].currentSourceLocation(null)
highlighters[mod].currentSourceLocationFromfileName(position, filePath, hexColor)
cb()
},
discardHighlight: (mod, cb) => {
if (highlighters[mod]) highlighters[mod].currentSourceLocation(null)
cb()
}
}
}
}

@ -1,179 +0,0 @@
'use strict'
var remixLib = require('remix-lib')
var EventManager = remixLib.EventManager
const PluginAPI = require('./pluginAPI')
/**
* Register and Manage plugin:
*
* Plugin registration is done in the settings tab,
* using the following format:
* {
* "title": "<plugin name>",
* "url": "<plugin url>"
* }
*
* structure of messages:
*
* - Notification sent by Remix:
*{
* action: 'notification',
* key: <string>,
* type: <string>,
* value: <array>
*}
*
* - Request sent by the plugin:
*{
* id: <number>,
* action: 'request',
* key: <string>,
* type: <string>,
* value: <array>
*}
*
* - Response sent by Remix and receive by the plugin:
*{
* id: <number>,
* action: 'response',
* key: <string>,
* type: <string>,
* value: <array>,
* error: (see below)
*}
* => The `error` property is `undefined` if no error happened.
* => In case of error (due to permission, system error, API error, etc...):
* error: { code, msg (optional), data (optional), stack (optional)
* => possible error code are still to be defined, but the generic one would be 500.
*
* Plugin receive 4 types of message:
* - focus (when he get focus)
* - unfocus (when he loose focus - is hidden)
* - compilationData (that is triggered just after a focus - and send the current compilation data or null)
* - compilationFinished (that is only sent to the plugin that has focus)
*
* Plugin can emit messages and receive response.
*
* CONFIG:
* - getConfig(filename). The data to send should be formatted like:
* {
* id: <requestid>,
* action: 'request',
* key: 'config',
* type: 'getConfig',
* value: ['filename.ext']
* }
* the plugin will reveice a response like:
* {
* id: <requestid>,
* action: 'response',
* key: 'config',
* type: 'getConfig',
* error,
* value: ['content of filename.ext']
* }
* same apply for the other call
* - setConfig(filename, content)
* - removeConfig
*
* See index.html and remix.js in test-browser folder for sample
*
*/
module.exports = class PluginManager {
constructor (app, compilersArtefacts, txlistener, fileProviders, fileManager, udapp) {
const self = this
self.event = new EventManager()
var pluginAPI = new PluginAPI(
this,
fileProviders,
fileManager,
compilersArtefacts,
udapp
)
self._components = { pluginAPI }
self.plugins = {}
self.origins = {}
self.inFocus
fileManager.events.on('currentFileChanged', (file) => {
self.broadcast(JSON.stringify({
action: 'notification',
key: 'editor',
type: 'currentFileChanged',
value: [ file ]
}))
})
txlistener.event.register('newTransaction', (tx) => {
self.broadcast(JSON.stringify({
action: 'notification',
key: 'txlistener',
type: 'newTransaction',
value: [tx]
}))
})
window.addEventListener('message', (event) => {
if (event.type !== 'message') return
var extension = self.origins[event.origin]
if (!extension) return
function response (key, type, callid, error, result) {
self.postToOrigin(event.origin, JSON.stringify({
id: callid,
action: 'response',
key: key,
type: type,
error: error,
value: [ result ]
}))
}
var data = JSON.parse(event.data)
data.value.unshift(extension)
data.value.push((error, result) => {
response(data.key, data.type, data.id, error, result)
})
if (pluginAPI[data.key] && pluginAPI[data.key][data.type]) {
pluginAPI[data.key][data.type].apply({}, data.value)
} else {
response(data.key, data.type, data.id, `Endpoint ${data.key}/${data.type} not present`, null)
}
}, false)
}
unregister (desc) {
const self = this
self._components.pluginAPI.editor.discardHighlight(desc.title, () => {})
delete self.plugins[desc.title]
delete self.origins[desc.url]
}
register (desc, modal, content) {
const self = this
self.plugins[desc.title] = { content, modal, origin: desc.url }
self.origins[desc.url] = desc.title
}
broadcast (value) {
for (var plugin in this.plugins) {
this.post(plugin, value)
}
}
postToOrigin (origin, value) {
if (this.origins[origin]) {
this.post(this.origins[origin], value)
}
}
receivedDataFrom (methodName, mod, argumentsArray) {
// TODO check whether 'mod' as right to do that
console.log(argumentsArray)
this.event.trigger(methodName, argumentsArray) // forward to internal modules
this.broadcast(JSON.stringify({ // forward to plugins
action: 'notification',
key: mod,
type: methodName,
value: argumentsArray
}))
}
post (name, value) {
const self = this
if (self.plugins[name]) {
self.plugins[name].content.querySelector('iframe').contentWindow.postMessage(value, self.plugins[name].origin)
}
}
}

@ -1,38 +0,0 @@
'use strict'
module.exports = {
'oraclize': {
url: 'https://remix-plugin.oraclize.it',
title: 'Oraclize'
},
'solium': {
url: 'https://two-water.surge.sh',
title: 'Solium'
},
'ethdoc': {
url: 'https://30400.swarm-gateways.net/bzz:/ethdoc.remixide.eth',
title: 'Ethdoc'
},
'openzeppelin snippet': {
url: 'https://left-edge.surge.sh',
title: 'Openzeppelin snippet'
},
'vyper': {
url: 'https://plugin.vyper.live',
title: 'Vyper'
},
'slither/mythril': {
url: 'http://jittery-space.surge.sh',
title: 'Slither/Mythril'
},
'pipeline': {
url: 'https://pipeline.pipeos.one',
title: 'Pipeline'
}
/*
'etherscan-general': {
url: 'http://127.0.0.1:8081',
title: 'Etherscan-general'
}
*/
}

@ -3,20 +3,10 @@ var StaticAnalysis = require('../staticanalysis/staticAnalysisView')
var EventManager = require('../../lib/events') var EventManager = require('../../lib/events')
var css = require('./styles/analysis-tab-styles') var css = require('./styles/analysis-tab-styles')
import { ApiFactory } from 'remix-plugin' import { BaseApi } from 'remix-plugin'
import { EventEmitter } from 'events' import { EventEmitter } from 'events'
class AnalysisTab extends ApiFactory { const profile = {
constructor (registry) {
super()
this.event = new EventManager()
this.events = new EventEmitter()
this.registry = registry
}
get profile () {
return {
name: 'solidityStaticAnalysis', name: 'solidityStaticAnalysis',
displayName: 'solidity static analysis', displayName: 'solidity static analysis',
methods: [], methods: [],
@ -26,6 +16,14 @@ class AnalysisTab extends ApiFactory {
kind: 'analysis', kind: 'analysis',
location: 'swapPanel' location: 'swapPanel'
} }
class AnalysisTab extends BaseApi {
constructor (registry) {
super(profile)
this.event = new EventManager()
this.events = new EventEmitter()
this.registry = registry
} }
render () { render () {

@ -17,12 +17,26 @@ var css = require('./styles/compile-tab-styles')
const CompileTabLogic = require('./compileTab/compileTab.js') const CompileTabLogic = require('./compileTab/compileTab.js')
const CompilerContainer = require('./compileTab/compilerContainer.js') const CompilerContainer = require('./compileTab/compilerContainer.js')
import { ApiFactory } from 'remix-plugin' import { CompilerApi } from 'remix-plugin'
class CompileTab extends ApiFactory { const profile = {
displayName: 'solidity compiler',
name: 'solidity',
icon: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE2LjAuMywgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zOnNrZXRjaD0iaHR0cDovL3d3dy5ib2hlbWlhbmNvZGluZy5jb20vc2tldGNoL25zIgoJIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iMTMwMHB4IiBoZWlnaHQ9IjEzMDBweCIKCSB2aWV3Qm94PSIwIDAgMTMwMCAxMzAwIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAxMzAwIDEzMDAiIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8dGl0bGU+VmVjdG9yIDE8L3RpdGxlPgo8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4KPGcgaWQ9IlBhZ2UtMSIgc2tldGNoOnR5cGU9Ik1TUGFnZSI+Cgk8ZyBpZD0ic29saWRpdHkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDQwMi4wMDAwMDAsIDExOC4wMDAwMDApIiBza2V0Y2g6dHlwZT0iTVNMYXllckdyb3VwIj4KCQk8ZyBpZD0iR3JvdXAiIHNrZXRjaDp0eXBlPSJNU1NoYXBlR3JvdXAiPgoJCQk8cGF0aCBpZD0iU2hhcGUiIG9wYWNpdHk9IjAuNDUiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgICAgIiBkPSJNMzcxLjc3MiwxMzUuMzA4TDI0MS4wNjgsMzY3LjYxSC0yMC4xNThsMTMwLjYxNC0yMzIuMzAyCgkJCQlIMzcxLjc3MiIvPgoJCQk8cGF0aCBpZD0iU2hhcGVfMV8iIG9wYWNpdHk9IjAuNiIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAgICAiIGQ9Ik0yNDEuMDY4LDM2Ny42MWgyNjEuMzE4TDM3MS43NzIsMTM1LjMwOEgxMTAuNDU2CgkJCQlMMjQxLjA2OCwzNjcuNjF6Ii8+CgkJCTxwYXRoIGlkPSJTaGFwZV8yXyIgb3BhY2l0eT0iMC44IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3ICAgICIgZD0iTTExMC40NTYsNTk5LjgyMkwyNDEuMDY4LDM2Ny42MUwxMTAuNDU2LDEzNS4zMDgKCQkJCUwtMjAuMTU4LDM2Ny42MUwxMTAuNDU2LDU5OS44MjJ6Ii8+CgkJCTxwYXRoIGlkPSJTaGFwZV8zXyIgb3BhY2l0eT0iMC40NSIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAgICAiIGQ9Ik0xMTEuNzIxLDk0OC4yNzVsMTMwLjcwNC0yMzIuMzAzaDI2MS4zMThMMzczLjAzOCw5NDguMjc1CgkJCQlIMTExLjcyMSIvPgoJCQk8cGF0aCBpZD0iU2hhcGVfNF8iIG9wYWNpdHk9IjAuNiIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAgICAiIGQ9Ik0yNDIuNDI0LDcxNS45NzNILTE4Ljg5M2wxMzAuNjEzLDIzMi4zMDNoMjYxLjMxNwoJCQkJTDI0Mi40MjQsNzE1Ljk3M3oiLz4KCQkJPHBhdGggaWQ9IlNoYXBlXzVfIiBvcGFjaXR5PSIwLjgiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgICAgIiBkPSJNMzczLjAzOCw0ODMuNzYxTDI0Mi40MjQsNzE1Ljk3M2wxMzAuNjE0LDIzMi4zMDMKCQkJCWwxMzAuNzA0LTIzMi4zMDNMMzczLjAzOCw0ODMuNzYxeiIvPgoJCTwvZz4KCTwvZz4KPC9nPgo8L3N2Zz4K',
description: 'compile solidity contracts',
kind: 'compile',
permission: true,
location: 'swapPanel'
}
// EditorApi:
// - events: ['compilationFinished'],
// - methods: ['getCompilationResult']
class CompileTab extends CompilerApi {
constructor (editor, config, renderer, swarmfileProvider, fileManager, fileProviders, pluginManager) { constructor (editor, config, renderer, swarmfileProvider, fileManager, fileProviders, pluginManager) {
super() super(profile)
this.events = new EventEmitter() this.events = new EventEmitter()
this._view = { this._view = {
el: null, el: null,
@ -57,20 +71,6 @@ class CompileTab extends ApiFactory {
) )
} }
get profile () {
return {
displayName: 'solidity compiler',
name: 'solidity',
methods: ['getCompilationResult'],
events: ['compilationFinished'],
icon: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE2LjAuMywgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zOnNrZXRjaD0iaHR0cDovL3d3dy5ib2hlbWlhbmNvZGluZy5jb20vc2tldGNoL25zIgoJIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iMTMwMHB4IiBoZWlnaHQ9IjEzMDBweCIKCSB2aWV3Qm94PSIwIDAgMTMwMCAxMzAwIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAxMzAwIDEzMDAiIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8dGl0bGU+VmVjdG9yIDE8L3RpdGxlPgo8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4KPGcgaWQ9IlBhZ2UtMSIgc2tldGNoOnR5cGU9Ik1TUGFnZSI+Cgk8ZyBpZD0ic29saWRpdHkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDQwMi4wMDAwMDAsIDExOC4wMDAwMDApIiBza2V0Y2g6dHlwZT0iTVNMYXllckdyb3VwIj4KCQk8ZyBpZD0iR3JvdXAiIHNrZXRjaDp0eXBlPSJNU1NoYXBlR3JvdXAiPgoJCQk8cGF0aCBpZD0iU2hhcGUiIG9wYWNpdHk9IjAuNDUiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgICAgIiBkPSJNMzcxLjc3MiwxMzUuMzA4TDI0MS4wNjgsMzY3LjYxSC0yMC4xNThsMTMwLjYxNC0yMzIuMzAyCgkJCQlIMzcxLjc3MiIvPgoJCQk8cGF0aCBpZD0iU2hhcGVfMV8iIG9wYWNpdHk9IjAuNiIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAgICAiIGQ9Ik0yNDEuMDY4LDM2Ny42MWgyNjEuMzE4TDM3MS43NzIsMTM1LjMwOEgxMTAuNDU2CgkJCQlMMjQxLjA2OCwzNjcuNjF6Ii8+CgkJCTxwYXRoIGlkPSJTaGFwZV8yXyIgb3BhY2l0eT0iMC44IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3ICAgICIgZD0iTTExMC40NTYsNTk5LjgyMkwyNDEuMDY4LDM2Ny42MUwxMTAuNDU2LDEzNS4zMDgKCQkJCUwtMjAuMTU4LDM2Ny42MUwxMTAuNDU2LDU5OS44MjJ6Ii8+CgkJCTxwYXRoIGlkPSJTaGFwZV8zXyIgb3BhY2l0eT0iMC40NSIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAgICAiIGQ9Ik0xMTEuNzIxLDk0OC4yNzVsMTMwLjcwNC0yMzIuMzAzaDI2MS4zMThMMzczLjAzOCw5NDguMjc1CgkJCQlIMTExLjcyMSIvPgoJCQk8cGF0aCBpZD0iU2hhcGVfNF8iIG9wYWNpdHk9IjAuNiIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAgICAiIGQ9Ik0yNDIuNDI0LDcxNS45NzNILTE4Ljg5M2wxMzAuNjEzLDIzMi4zMDNoMjYxLjMxNwoJCQkJTDI0Mi40MjQsNzE1Ljk3M3oiLz4KCQkJPHBhdGggaWQ9IlNoYXBlXzVfIiBvcGFjaXR5PSIwLjgiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgICAgIiBkPSJNMzczLjAzOCw0ODMuNzYxTDI0Mi40MjQsNzE1Ljk3M2wxMzAuNjE0LDIzMi4zMDMKCQkJCWwxMzAuNzA0LTIzMi4zMDNMMzczLjAzOCw0ODMuNzYxeiIvPgoJCTwvZz4KCTwvZz4KPC9nPgo8L3N2Zz4K',
description: 'compile solidity contracts',
kind: 'compile',
permission: true,
location: 'swapPanel'
}
}
/************ /************
* EVENTS * EVENTS
*/ */

@ -3,17 +3,9 @@ var css = require('./styles/debugger-tab-styles')
var DebuggerUI = require('../debugger/debuggerUI') var DebuggerUI = require('../debugger/debuggerUI')
import { ApiFactory } from 'remix-plugin' import { BaseApi } from 'remix-plugin'
class DebuggerTab extends ApiFactory { const profile = {
constructor () {
super()
this.el = null
}
get profile () {
return {
displayName: 'debugger', displayName: 'debugger',
name: 'debugger', name: 'debugger',
methods: [], methods: [],
@ -23,6 +15,12 @@ class DebuggerTab extends ApiFactory {
kind: 'debugging', kind: 'debugging',
location: 'swapPanel' location: 'swapPanel'
} }
class DebuggerTab extends BaseApi {
constructor () {
super(profile)
this.el = null
} }
render () { render () {

@ -0,0 +1,66 @@
const executionContext = require('../../execution-context')
import { NetworkApi } from 'remix-plugin'
export const profile = {
name: 'network',
description: 'Manage the network (mainnet, ropsten, goerli...) and the provider (web3, vm, injected)'
}
// Network API has :
// - events: ['providerChanged']
// - methods: ['getNetworkProvider', 'getEndpoint', 'detectNetwork', 'addNetwork', 'removeNetwork']
export class NetworkModule extends NetworkApi {
constructor () {
super(profile)
// TODO: See with remix-lib to make sementic coherent
executionContext.event.register('contextChanged', (provider) => {
this.events.emit('providerChanged', provider)
})
/*
// Events that could be implemented later
executionContext.event.register('removeProvider', (provider) => {
this.events.emit('networkRemoved', provider)
})
executionContext.event.register('addProvider', (provider) => {
this.events.emit('networkAdded', provider)
})
executionContext.event.register('web3EndpointChanged', (provider) => {
this.events.emit('web3EndpointChanged', provider)
})
*/
}
/** Return the current network provider (web3, vm, injected) */
getNetworkProvider () {
return executionContext.getProvider()
}
/** Return the current network */
detectNetwork () {
return new Promise((resolve, reject) => {
executionContext.detectNetwork((error, network) => {
error ? reject(error) : resolve(network)
})
})
}
/** Return the url only if network provider is 'web3' */
getEndpoint () {
const provider = executionContext.getProvider()
if (provider !== 'web3') {
throw new Error('no endpoint: current provider is either injected or vm')
}
return provider.web3().currentProvider.host
}
/** Add a custom network to the list of available networks */
addNetwork (customNetwork) {
executionContext.addProvider(customNetwork)
}
/** Remove a network to the list of availble networks */
removeNetwork (name) {
executionContext.removeProvider(name)
}
}

@ -12,12 +12,23 @@ var ContractDropdownUI = require('./runTab/contractDropdown.js')
var Recorder = require('./runTab/model/recorder.js') var Recorder = require('./runTab/model/recorder.js')
var RecorderUI = require('./runTab/recorder.js') var RecorderUI = require('./runTab/recorder.js')
import { ApiFactory } from 'remix-plugin' import { BaseApi } from 'remix-plugin'
class RunTab extends ApiFactory { const profile = {
name: 'run',
displayName: 'run transactions',
methods: [],
events: [],
icon: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iMTc5MiIgaGVpZ2h0PSIxNzkyIiB2aWV3Qm94PSIwIDAgMTc5MiAxNzkyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik0xNTc2IDkyN2wtMTMyOCA3MzhxLTIzIDEzLTM5LjUgM3QtMTYuNS0zNnYtMTQ3MnEwLTI2IDE2LjUtMzZ0MzkuNSAzbDEzMjggNzM4cTIzIDEzIDIzIDMxdC0yMyAzMXoiLz48L3N2Zz4=',
description: 'execute and save transactions',
kind: 'run',
location: 'swapPanel'
}
class RunTab extends BaseApi {
constructor (udapp, udappUI, config, fileManager, editor, logCallback, filePanel, pluginManager, compilersArtefacts) { constructor (udapp, udappUI, config, fileManager, editor, logCallback, filePanel, pluginManager, compilersArtefacts) {
super() super(profile)
this.event = new EventManager() this.event = new EventManager()
this.renderInstanceContainer() this.renderInstanceContainer()
@ -28,19 +39,6 @@ class RunTab extends ApiFactory {
this.renderContainer() this.renderContainer()
} }
get profile () {
return {
name: 'run',
displayName: 'run transactions',
methods: [],
events: [],
icon: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iMTc5MiIgaGVpZ2h0PSIxNzkyIiB2aWV3Qm94PSIwIDAgMTc5MiAxNzkyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik0xNTc2IDkyN2wtMTMyOCA3MzhxLTIzIDEzLTM5LjUgM3QtMTYuNS0zNnYtMTQ3MnEwLTI2IDE2LjUtMzZ0MzkuNSAzbDEzMjggNzM4cTIzIDEzIDIzIDMxdC0yMyAzMXoiLz48L3N2Zz4=',
description: 'execute and save transactions',
kind: 'run',
location: 'swapPanel'
}
}
renderContainer () { renderContainer () {
this.container = yo`<div class="${css.runTabView}" id="runTabView" ></div>` this.container = yo`<div class="${css.runTabView}" id="runTabView" ></div>`

@ -4,11 +4,22 @@ var tooltip = require('../ui/tooltip')
var copyToClipboard = require('../ui/copy-to-clipboard') var copyToClipboard = require('../ui/copy-to-clipboard')
var EventManager = require('../../lib/events') var EventManager = require('../../lib/events')
var css = require('./styles/settings-tab-styles') var css = require('./styles/settings-tab-styles')
import { ApiFactory } from 'remix-plugin' import { BaseApi } from 'remix-plugin'
module.exports = class SettingsTab extends ApiFactory { const profile = {
displayName: 'settings',
name: 'settings',
methods: [],
events: [],
icon: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iMTc5MiIgaGVpZ2h0PSIxNzkyIiB2aWV3Qm94PSIwIDAgMTc5MiAxNzkyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik0xMTUyIDg5NnEwLTEwNi03NS0xODF0LTE4MS03NS0xODEgNzUtNzUgMTgxIDc1IDE4MSAxODEgNzUgMTgxLTc1IDc1LTE4MXptNTEyLTEwOXYyMjJxMCAxMi04IDIzdC0yMCAxM2wtMTg1IDI4cS0xOSA1NC0zOSA5MSAzNSA1MCAxMDcgMTM4IDEwIDEyIDEwIDI1dC05IDIzcS0yNyAzNy05OSAxMDh0LTk0IDcxcS0xMiAwLTI2LTlsLTEzOC0xMDhxLTQ0IDIzLTkxIDM4LTE2IDEzNi0yOSAxODYtNyAyOC0zNiAyOGgtMjIycS0xNCAwLTI0LjUtOC41dC0xMS41LTIxLjVsLTI4LTE4NHEtNDktMTYtOTAtMzdsLTE0MSAxMDdxLTEwIDktMjUgOS0xNCAwLTI1LTExLTEyNi0xMTQtMTY1LTE2OC03LTEwLTctMjMgMC0xMiA4LTIzIDE1LTIxIDUxLTY2LjV0NTQtNzAuNXEtMjctNTAtNDEtOTlsLTE4My0yN3EtMTMtMi0yMS0xMi41dC04LTIzLjV2LTIyMnEwLTEyIDgtMjN0MTktMTNsMTg2LTI4cTE0LTQ2IDM5LTkyLTQwLTU3LTEwNy0xMzgtMTAtMTItMTAtMjQgMC0xMCA5LTIzIDI2LTM2IDk4LjUtMTA3LjV0OTQuNS03MS41cTEzIDAgMjYgMTBsMTM4IDEwN3E0NC0yMyA5MS0zOCAxNi0xMzYgMjktMTg2IDctMjggMzYtMjhoMjIycTE0IDAgMjQuNSA4LjV0MTEuNSAyMS41bDI4IDE4NHE0OSAxNiA5MCAzN2wxNDItMTA3cTktOSAyNC05IDEzIDAgMjUgMTAgMTI5IDExOSAxNjUgMTcwIDcgOCA3IDIyIDAgMTItOCAyMy0xNSAyMS01MSA2Ni41dC01NCA3MC41cTI2IDUwIDQxIDk4bDE4MyAyOHExMyAyIDIxIDEyLjV0OCAyMy41eiIvPjwvc3ZnPg==',
description: ' - ',
kind: 'settings',
location: 'swapPanel'
}
module.exports = class SettingsTab extends BaseApi {
constructor (config, editor, appManager) { constructor (config, editor, appManager) {
super() super(profile)
this.config = config this.config = config
this.editor = editor this.editor = editor
this.appManager = appManager this.appManager = appManager
@ -30,18 +41,7 @@ module.exports = class SettingsTab extends ApiFactory {
initTheme () { initTheme () {
this.currentTheme = this._deps.themeModule.currentTheme() this.currentTheme = this._deps.themeModule.currentTheme()
} }
get profile () {
return {
displayName: 'settings',
name: 'settings',
methods: [],
events: [],
icon: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iMTc5MiIgaGVpZ2h0PSIxNzkyIiB2aWV3Qm94PSIwIDAgMTc5MiAxNzkyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik0xMTUyIDg5NnEwLTEwNi03NS0xODF0LTE4MS03NS0xODEgNzUtNzUgMTgxIDc1IDE4MSAxODEgNzUgMTgxLTc1IDc1LTE4MXptNTEyLTEwOXYyMjJxMCAxMi04IDIzdC0yMCAxM2wtMTg1IDI4cS0xOSA1NC0zOSA5MSAzNSA1MCAxMDcgMTM4IDEwIDEyIDEwIDI1dC05IDIzcS0yNyAzNy05OSAxMDh0LTk0IDcxcS0xMiAwLTI2LTlsLTEzOC0xMDhxLTQ0IDIzLTkxIDM4LTE2IDEzNi0yOSAxODYtNyAyOC0zNiAyOGgtMjIycS0xNCAwLTI0LjUtOC41dC0xMS41LTIxLjVsLTI4LTE4NHEtNDktMTYtOTAtMzdsLTE0MSAxMDdxLTEwIDktMjUgOS0xNCAwLTI1LTExLTEyNi0xMTQtMTY1LTE2OC03LTEwLTctMjMgMC0xMiA4LTIzIDE1LTIxIDUxLTY2LjV0NTQtNzAuNXEtMjctNTAtNDEtOTlsLTE4My0yN3EtMTMtMi0yMS0xMi41dC04LTIzLjV2LTIyMnEwLTEyIDgtMjN0MTktMTNsMTg2LTI4cTE0LTQ2IDM5LTkyLTQwLTU3LTEwNy0xMzgtMTAtMTItMTAtMjQgMC0xMCA5LTIzIDI2LTM2IDk4LjUtMTA3LjV0OTQuNS03MS41cTEzIDAgMjYgMTBsMTM4IDEwN3E0NC0yMyA5MS0zOCAxNi0xMzYgMjktMTg2IDctMjggMzYtMjhoMjIycTE0IDAgMjQuNSA4LjV0MTEuNSAyMS41bDI4IDE4NHE0OSAxNiA5MCAzN2wxNDItMTA3cTktOSAyNC05IDEzIDAgMjUgMTAgMTI5IDExOSAxNjUgMTcwIDcgOCA3IDIyIDAgMTItOCAyMy0xNSAyMS01MSA2Ni41dC01NCA3MC41cTI2IDUwIDQxIDk4bDE4MyAyOHExMyAyIDIxIDEyLjV0OCAyMy41eiIvPjwvc3ZnPg==',
description: ' - ',
kind: 'settings',
location: 'swapPanel'
}
}
createThemeCheckies () { createThemeCheckies () {
let themes = this._deps.themeModule.getThemes() let themes = this._deps.themeModule.getThemes()
const onswitchTheme = (event, name) => { const onswitchTheme = (event, name) => {

@ -3,13 +3,23 @@ var async = require('async')
var tooltip = require('../ui/tooltip') var tooltip = require('../ui/tooltip')
var css = require('./styles/test-tab-styles') var css = require('./styles/test-tab-styles')
var remixTests = require('remix-tests') var remixTests = require('remix-tests')
import { ApiFactory } from 'remix-plugin' import { BaseApi } from 'remix-plugin'
const TestTabLogic = require('./testTab/testTab') const TestTabLogic = require('./testTab/testTab')
module.exports = class TestTab extends ApiFactory { const profile = {
name: 'solidityUnitTesting',
displayName: 'solidity unit testing',
methods: [],
events: [],
icon: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iMjMwNCIgaGVpZ2h0PSIxNzkyIiB2aWV3Qm94PSIwIDAgMjMwNCAxNzkyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik0xNzI4IDQ0OGwtMzg0IDcwNGg3Njh6bS0xMjgwIDBsLTM4NCA3MDRoNzY4em04MjEtMTkycS0xNCA0MC00NS41IDcxLjV0LTcxLjUgNDUuNXYxMjkxaDYwOHExNCAwIDIzIDl0OSAyM3Y2NHEwIDE0LTkgMjN0LTIzIDloLTEzNDRxLTE0IDAtMjMtOXQtOS0yM3YtNjRxMC0xNCA5LTIzdDIzLTloNjA4di0xMjkxcS00MC0xNC03MS41LTQ1LjV0LTQ1LjUtNzEuNWgtNDkxcS0xNCAwLTIzLTl0LTktMjN2LTY0cTAtMTQgOS0yM3QyMy05aDQ5MXEyMS01NyA3MC05Mi41dDExMS0zNS41IDExMSAzNS41IDcwIDkyLjVoNDkxcTE0IDAgMjMgOXQ5IDIzdjY0cTAgMTQtOSAyM3QtMjMgOWgtNDkxem0tMTgxIDE2cTMzIDAgNTYuNS0yMy41dDIzLjUtNTYuNS0yMy41LTU2LjUtNTYuNS0yMy41LTU2LjUgMjMuNS0yMy41IDU2LjUgMjMuNSA1Ni41IDU2LjUgMjMuNXptMTA4OCA4ODBxMCA3My00Ni41IDEzMXQtMTE3LjUgOTEtMTQ0LjUgNDkuNS0xMzkuNSAxNi41LTEzOS41LTE2LjUtMTQ0LjUtNDkuNS0xMTcuNS05MS00Ni41LTEzMXEwLTExIDM1LTgxdDkyLTE3NC41IDEwNy0xOTUuNSAxMDItMTg0IDU2LTEwMHExOC0zMyA1Ni0zM3Q1NiAzM3E0IDcgNTYgMTAwdDEwMiAxODQgMTA3IDE5NS41IDkyIDE3NC41IDM1IDgxem0tMTI4MCAwcTAgNzMtNDYuNSAxMzF0LTExNy41IDkxLTE0NC41IDQ5LjUtMTM5LjUgMTYuNS0xMzkuNS0xNi41LTE0NC41LTQ5LjUtMTE3LjUtOTEtNDYuNS0xMzFxMC0xMSAzNS04MXQ5Mi0xNzQuNSAxMDctMTk1LjUgMTAyLTE4NCA1Ni0xMDBxMTgtMzMgNTYtMzN0NTYgMzNxNCA3IDU2IDEwMHQxMDIgMTg0IDEwNyAxOTUuNSA5MiAxNzQuNSAzNSA4MXoiLz48L3N2Zz4=',
description: ' - ',
location: 'swapPanel'
}
module.exports = class TestTab extends BaseApi {
constructor (fileManager, filePanel, compileTab) { constructor (fileManager, filePanel, compileTab) {
super() super(profile)
this.compileTab = compileTab this.compileTab = compileTab
this._view = { el: null } this._view = { el: null }
this.compileTab = compileTab this.compileTab = compileTab
@ -20,18 +30,6 @@ module.exports = class TestTab extends ApiFactory {
this.testList = yo`<div class=${css.testList}></div>` this.testList = yo`<div class=${css.testList}></div>`
} }
get profile () {
return {
name: 'solidityUnitTesting',
displayName: 'solidity unit testing',
methods: [],
events: [],
icon: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iMjMwNCIgaGVpZ2h0PSIxNzkyIiB2aWV3Qm94PSIwIDAgMjMwNCAxNzkyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik0xNzI4IDQ0OGwtMzg0IDcwNGg3Njh6bS0xMjgwIDBsLTM4NCA3MDRoNzY4em04MjEtMTkycS0xNCA0MC00NS41IDcxLjV0LTcxLjUgNDUuNXYxMjkxaDYwOHExNCAwIDIzIDl0OSAyM3Y2NHEwIDE0LTkgMjN0LTIzIDloLTEzNDRxLTE0IDAtMjMtOXQtOS0yM3YtNjRxMC0xNCA5LTIzdDIzLTloNjA4di0xMjkxcS00MC0xNC03MS41LTQ1LjV0LTQ1LjUtNzEuNWgtNDkxcS0xNCAwLTIzLTl0LTktMjN2LTY0cTAtMTQgOS0yM3QyMy05aDQ5MXEyMS01NyA3MC05Mi41dDExMS0zNS41IDExMSAzNS41IDcwIDkyLjVoNDkxcTE0IDAgMjMgOXQ5IDIzdjY0cTAgMTQtOSAyM3QtMjMgOWgtNDkxem0tMTgxIDE2cTMzIDAgNTYuNS0yMy41dDIzLjUtNTYuNS0yMy41LTU2LjUtNTYuNS0yMy41LTU2LjUgMjMuNS0yMy41IDU2LjUgMjMuNSA1Ni41IDU2LjUgMjMuNXptMTA4OCA4ODBxMCA3My00Ni41IDEzMXQtMTE3LjUgOTEtMTQ0LjUgNDkuNS0xMzkuNSAxNi41LTEzOS41LTE2LjUtMTQ0LjUtNDkuNS0xMTcuNS05MS00Ni41LTEzMXEwLTExIDM1LTgxdDkyLTE3NC41IDEwNy0xOTUuNSAxMDItMTg0IDU2LTEwMHExOC0zMyA1Ni0zM3Q1NiAzM3E0IDcgNTYgMTAwdDEwMiAxODQgMTA3IDE5NS41IDkyIDE3NC41IDM1IDgxem0tMTI4MCAwcTAgNzMtNDYuNSAxMzF0LTExNy41IDkxLTE0NC41IDQ5LjUtMTM5LjUgMTYuNS0xMzkuNS0xNi41LTE0NC41LTQ5LjUtMTE3LjUtOTEtNDYuNS0xMzFxMC0xMSAzNS04MXQ5Mi0xNzQuNSAxMDctMTk1LjUgMTAyLTE4NCA1Ni0xMDBxMTgtMzMgNTYtMzN0NTYgMzNxNCA3IDU2IDEwMHQxMDIgMTg0IDEwNyAxOTUuNSA5MiAxNzQuNSAzNSA4MXoiLz48L3N2Zz4=',
description: ' - ',
location: 'swapPanel'
}
}
activate () { activate () {
this.listenToEvents() this.listenToEvents()
} }
@ -173,7 +171,7 @@ module.exports = class TestTab extends ApiFactory {
<br/> <br/>
For more details, see For more details, see
How to test smart contracts guide in our documentation. How to test smart contracts guide in our documentation.
<div class="${css.generateTestFile} btn btn-primary m-1" onclick="${this.testTabLogic.generateTestFile(this)}">Generate test file</div> <div class="${css.generateTestFile} btn btn-primary m-1" onclick="${this.testTabLogic.generateTestFile.bind(this.testTabLogic)}">Generate test file</div>
</div> </div>
<div class="${css.tests}"> <div class="${css.tests}">
<div class="${css.buttons}"> <div class="${css.buttons}">

@ -26,7 +26,7 @@ class TestTabLogic {
var tests = [] var tests = []
let files let files
try { try {
files = await this.fileManager.getFilesFromPath(path) files = await this.fileManager.getFolder(path)
} catch (e) { } catch (e) {
cb(e.message) cb(e.message)
} }

@ -1,4 +1,4 @@
import { ApiFactory } from 'remix-plugin' import { BaseApi } from 'remix-plugin'
import { EventEmitter } from 'events' import { EventEmitter } from 'events'
const Storage = require('remix-lib').Storage const Storage = require('remix-lib').Storage
@ -17,24 +17,22 @@ const themes = [
{name: 'Superhero', quality: 'dark', url: 'https://stackpath.bootstrapcdn.com/bootswatch/4.3.1/superhero/bootstrap.min.css'} {name: 'Superhero', quality: 'dark', url: 'https://stackpath.bootstrapcdn.com/bootswatch/4.3.1/superhero/bootstrap.min.css'}
] ]
export class ThemeModule extends ApiFactory { const profile = {
name: 'theme',
events: ['themeChanged'],
methods: ['switchTheme', 'getThemes', 'currentTheme']
}
export class ThemeModule extends BaseApi {
constructor () { constructor () {
super() super(profile)
this.events = new EventEmitter() this.events = new EventEmitter()
this.storage = new Storage('style:') this.storage = new Storage('style:')
this.themes = themes.reduce((acc, theme) => ({ ...acc, [theme.name]: theme }), {}) this.themes = themes.reduce((acc, theme) => ({ ...acc, [theme.name]: theme }), {})
this.active = this.storage.exists('theme') ? this.storage.get('theme') : 'Cerulean' this.active = this.storage.exists('theme') ? this.storage.get('theme') : 'Cerulean'
} }
get profile () {
return {
name: 'theme',
events: ['themeChanged'],
methods: ['switchTheme', 'getThemes', 'currentTheme']
}
}
/** Return the active theme */ /** Return the active theme */
currentTheme () { currentTheme () {
return this.themes[this.active] return this.themes[this.active]

@ -1,23 +0,0 @@
import { ApiFactory } from 'remix-plugin'
import { EventEmitter } from 'events'
export class TxListenerModule extends ApiFactory {
constructor (txlistener) {
super()
this.events = new EventEmitter()
txlistener.event.register('newTransaction', (tx) => {
this.events.emit('newTransaction', tx)
})
}
get profile () {
return {
name: 'txListener',
displayName: 'transaction listener',
events: ['newTransaction'],
description: 'service - notify new transactions',
permission: true
}
}
}

@ -100,18 +100,9 @@ let css = csjs`
} }
` `
import { ApiFactory } from 'remix-plugin' import { BaseApi } from 'remix-plugin'
export class LandingPage extends ApiFactory { const profile = {
constructor (appManager, appStore) {
super()
this.appStore = appStore
this.appManager = appManager
}
get profile () {
return {
displayName: 'Home', displayName: 'Home',
name: 'home', name: 'home',
methods: [], methods: [],
@ -120,6 +111,13 @@ export class LandingPage extends ApiFactory {
icon: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjwhRE9DVFlQRSBzdmcgIFBVQkxJQyAnLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4nICAnaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkJz48c3ZnIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDUwIDUwIiBoZWlnaHQ9IjUwcHgiIGlkPSJMYXllcl8xIiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCA1MCA1MCIgd2lkdGg9IjUwcHgiIHhtbDpzcGFjZT0icHJlc2VydmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxyZWN0IGZpbGw9Im5vbmUiIGhlaWdodD0iNTAiIHdpZHRoPSI1MCIvPjxnPjxwYXRoIGQ9IiAgIE0yNSwxQzExLjc0NSwxLDEsMTEuNzQ1LDEsMjVzMTAuNzQ1LDI0LDI0LDI0czI0LTEwLjc0NSwyNC0yNFMzOC4yNTUsMSwyNSwxTDI1LDF6IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBzdHJva2Utd2lkdGg9IjIiLz48L2c+PHBhdGggZD0iICBNNDAuNjk2LDYuODMyYzAsMC0xMy4xNjksOC4yMTItMTEuNTMyLDIyLjMzMmMxLjE0Miw5Ljg1OCwxMS45MzUsMTMuMzc3LDExLjkzNSwxMy4zNzciIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS13aWR0aD0iMi4wNTgzIi8+PHBhdGggZD0iICBNNy4zODUsOC45MTNjMCwwLDMuMDQxLDYuNDc2LDMuMDQxLDE4LjE2OWMwLDkuMjQ2LTMuNTgzLDEyLjkxMS0zLjU4MywxMi45MTEiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS13aWR0aD0iMi4wNTgzIi8+PHBhdGggZD0iICBNMS44NTIsMjIuOTMyYzAsMCw2LjQ5Myw2LjIzMiwyMy4xNDgsNi4yMzJzMjMuNDM4LTYuMjQ2LDIzLjQzOC02LjI0NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgc3Ryb2tlLXdpZHRoPSIyLjA1ODMiLz48cGF0aCBkPSIgIE0yNS42NDgsMS41NDhjMCwwLTYuODk1LDcuOTM1LTYuODk1LDIzLjQ1MkMxOC43NTQsNDAuNTE4LDI1LDQ4LjYyNSwyNSw0OC42MjUiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS13aWR0aD0iMi4wNTgzIi8+PC9zdmc+', icon: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjwhRE9DVFlQRSBzdmcgIFBVQkxJQyAnLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4nICAnaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkJz48c3ZnIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDUwIDUwIiBoZWlnaHQ9IjUwcHgiIGlkPSJMYXllcl8xIiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCA1MCA1MCIgd2lkdGg9IjUwcHgiIHhtbDpzcGFjZT0icHJlc2VydmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxyZWN0IGZpbGw9Im5vbmUiIGhlaWdodD0iNTAiIHdpZHRoPSI1MCIvPjxnPjxwYXRoIGQ9IiAgIE0yNSwxQzExLjc0NSwxLDEsMTEuNzQ1LDEsMjVzMTAuNzQ1LDI0LDI0LDI0czI0LTEwLjc0NSwyNC0yNFMzOC4yNTUsMSwyNSwxTDI1LDF6IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBzdHJva2Utd2lkdGg9IjIiLz48L2c+PHBhdGggZD0iICBNNDAuNjk2LDYuODMyYzAsMC0xMy4xNjksOC4yMTItMTEuNTMyLDIyLjMzMmMxLjE0Miw5Ljg1OCwxMS45MzUsMTMuMzc3LDExLjkzNSwxMy4zNzciIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS13aWR0aD0iMi4wNTgzIi8+PHBhdGggZD0iICBNNy4zODUsOC45MTNjMCwwLDMuMDQxLDYuNDc2LDMuMDQxLDE4LjE2OWMwLDkuMjQ2LTMuNTgzLDEyLjkxMS0zLjU4MywxMi45MTEiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS13aWR0aD0iMi4wNTgzIi8+PHBhdGggZD0iICBNMS44NTIsMjIuOTMyYzAsMCw2LjQ5Myw2LjIzMiwyMy4xNDgsNi4yMzJzMjMuNDM4LTYuMjQ2LDIzLjQzOC02LjI0NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgc3Ryb2tlLXdpZHRoPSIyLjA1ODMiLz48cGF0aCBkPSIgIE0yNS42NDgsMS41NDhjMCwwLTYuODk1LDcuOTM1LTYuODk1LDIzLjQ1MkMxOC43NTQsNDAuNTE4LDI1LDQ4LjYyNSwyNSw0OC42MjUiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS13aWR0aD0iMi4wNTgzIi8+PC9zdmc+',
location: 'mainPanel' location: 'mainPanel'
} }
export class LandingPage extends BaseApi {
constructor (appManager, appStore) {
super(profile)
this.appStore = appStore
this.appManager = appManager
} }
render () { render () {

@ -7,6 +7,7 @@ var css = csjs`
font-weight: normal; font-weight: normal;
max-width: 300px; max-width: 300px;
user-select: none; user-select: none;
padding-left: 14px;
} }
.text:hover { .text:hover {
font-weight: bold; font-weight: bold;
@ -16,6 +17,7 @@ var css = csjs`
font-weight: normal; font-weight: normal;
text-decoration : none; text-decoration : none;
user-select: none; user-select: none;
padding-left: 14px;
} }
.link:hover { .link:hover {
font-weight: bold; font-weight: bold;
@ -40,7 +42,7 @@ class Section {
if (this.actions[i].type === `callback`) { if (this.actions[i].type === `callback`) {
sectionLook.appendChild(yo` sectionLook.appendChild(yo`
<div> <div>
<span class="${css.text} p-3 h6 text-dark" onclick=${this.actions[i].payload} > <span class="${css.text} h6 text-dark" onclick=${this.actions[i].payload} >
${this.actions[i].label} ${this.actions[i].label}
</span> </span>
</div> </div>
@ -48,7 +50,7 @@ class Section {
} else if (this.actions[i].type === `link`) { } else if (this.actions[i].type === `link`) {
sectionLook.appendChild(yo` sectionLook.appendChild(yo`
<div > <div >
<a class="${css.link} text-dark p-3 h6 text-decoration-none" href=${this.actions[i].payload} target="_blank" > <a class="${css.link} text-dark h6 text-decoration-none" href=${this.actions[i].payload} target="_blank" >
${this.actions[i].label} ${this.actions[i].label}
</a> </a>
</div> </div>

@ -21,7 +21,6 @@ export const defaultWorkspaces = (appManager) => {
appManager.ensureActivated('run') appManager.ensureActivated('run')
appManager.ensureActivated('solidityStaticAnalysis') appManager.ensureActivated('solidityStaticAnalysis')
appManager.ensureActivated('solidityUnitTesting') appManager.ensureActivated('solidityUnitTesting')
globalRegistry.get('filemanager').api.switchFile()
globalRegistry.get('verticalicon').api.select('solidity') globalRegistry.get('verticalicon').api.select('solidity')
}, () => {}), }, () => {}),
new Workspace( new Workspace(
@ -31,7 +30,6 @@ export const defaultWorkspaces = (appManager) => {
() => { () => {
appManager.ensureActivated('vyper') appManager.ensureActivated('vyper')
appManager.ensureActivated('run') appManager.ensureActivated('run')
globalRegistry.get('filemanager').api.switchFile()
globalRegistry.get('verticalicon').api.select('vyper') globalRegistry.get('verticalicon').api.select('vyper')
}, () => {}), }, () => {}),
new Workspace('Debugger', 'Debug transactions with remix', false, () => { new Workspace('Debugger', 'Debug transactions with remix', false, () => {

@ -21,6 +21,11 @@ export class RemixAppManager extends AppManagerApi {
this.event.emit('ensureActivated', apiName) this.event.emit('ensureActivated', apiName)
} }
ensureDeactivated (apiName) {
if (this.store.isActive(apiName)) this.deactivateOne(apiName)
this.event.emit('ensureDeactivated', apiName)
}
proxy () { proxy () {
// that's temporary. should be removed when we can have proper notification registration // that's temporary. should be removed when we can have proper notification registration
return this.data.proxy return this.data.proxy

@ -7,16 +7,26 @@ var TxRunner = remixLib.execution.txRunner
var txHelper = remixLib.execution.txHelper var txHelper = remixLib.execution.txHelper
var EventManager = remixLib.EventManager var EventManager = remixLib.EventManager
var executionContext = remixLib.execution.executionContext var executionContext = remixLib.execution.executionContext
import { ApiFactory } from 'remix-plugin' import { UdappApi } from 'remix-plugin'
import { EventEmitter } from 'events'
module.exports = class UniversalDApp extends ApiFactory { const profile = {
name: 'udapp',
displayName: 'universal dapp',
description: 'service - run transaction and access account',
permission: true
}
module.exports = class UniversalDApp extends UdappApi {
constructor (registry) { constructor (registry) {
super() super(profile)
this.events = new EventEmitter()
this.event = new EventManager() this.event = new EventManager()
this._deps = { this._deps = {
config: registry.get('config').api config: registry.get('config').api
} }
this._txRunnerAPI = { this._txRunnerAPI = {
config: this._deps.config, config: this._deps.config,
detectNetwork: (cb) => { detectNetwork: (cb) => {
@ -32,13 +42,12 @@ module.exports = class UniversalDApp extends ApiFactory {
executionContext.event.register('contextChanged', this.resetEnvironment.bind(this)) executionContext.event.register('contextChanged', this.resetEnvironment.bind(this))
} }
get profile () { // TODO : event should be triggered by Udapp instead of TxListener
return { /** Listen on New Transaction. (Cannot be done inside constructor because txlistener doesn't exist yet) */
name: 'udapp', startListening (txlistener) {
displayName: 'universal dapp', txlistener.event.register('newTransaction', (tx) => {
methods: ['runTestTx', 'getAccounts', 'createVMAccount'], this.events.emit('newTransaction', tx)
description: 'service - run transaction and access account' })
}
} }
resetEnvironment () { resetEnvironment () {
@ -242,7 +251,7 @@ module.exports = class UniversalDApp extends ApiFactory {
* *
* @param {Object} tx - transaction. * @param {Object} tx - transaction.
*/ */
runTestTx (tx) { sendTransaction (tx) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
executionContext.detectNetwork((error, network) => { executionContext.detectNetwork((error, network) => {
if (error) return reject(error) if (error) return reject(error)

@ -48,7 +48,7 @@
<input type="button" id="getcontentof">get content of</input> <br> <input type="button" id="getcontentof">get content of</input> <br>
<input type="button" id="getcurrent">get current</input> <br> <input type="button" id="getcurrent">get current</input> <br>
<input type="button" id="sethighlight">set highlight</input> <br> <input type="button" id="sethighlight">set highlight</input> <br>
<input type="button" id="getfilesfrompath">get files from path</input> <br> <input type="button" id="getFolder">get files from path</input> <br>
<input type="button" id="addnetwork">add network</input> <br> <input type="button" id="addnetwork">add network</input> <br>
<input type="button" id="removenetwork">remove network</input> <br> <input type="button" id="removenetwork">remove network</input> <br>
<br> <br>

@ -18,7 +18,7 @@ window.onload = function () {
}) })
setInterval(function () { setInterval(function () {
extension.call('app', 'detectNetWork', [], function (error, result) { extension.call('network', 'detectNetWork', [], function (error, result) {
console.log(error, result) console.log(error, result)
}) })
}, 5000) }, 5000)
@ -74,18 +74,18 @@ window.onload = function () {
function (error, result) { console.log(error, result) }) function (error, result) { console.log(error, result) })
}) })
document.querySelector('input#getfilesfrompath').addEventListener('click', function () { document.querySelector('input#getFolder').addEventListener('click', function () {
extension.call('editor', 'getFilesFromPath', [document.getElementById('filename').value], extension.call('fileManager', 'getFolder', [document.getElementById('filename').value],
function (error, result) { console.log(error, result) }) function (error, result) { console.log(error, result) })
}) })
document.querySelector('input#addnetwork').addEventListener('click', function () { document.querySelector('input#addnetwork').addEventListener('click', function () {
extension.call('app', 'addProvider', [document.getElementById('filename').value, document.getElementById('valuetosend').value], extension.call('network', 'addProvider', [document.getElementById('filename').value, document.getElementById('valuetosend').value],
function (error, result) { console.log(error, result) }) function (error, result) { console.log(error, result) })
}) })
document.querySelector('input#removenetwork').addEventListener('click', function () { document.querySelector('input#removenetwork').addEventListener('click', function () {
extension.call('app', 'removeProvider', [document.getElementById('filename').value], extension.call('network', 'removeProvider', [document.getElementById('filename').value],
function (error, result) { console.log(error, result) }) function (error, result) { console.log(error, result) })
}) })
} }

Loading…
Cancel
Save