parent
df4a0a35cd
commit
cb62de2ffe
@ -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' |
||||
} |
||||
*/ |
||||
} |
Loading…
Reference in new issue