Merge pull request #1398 from ethereum/extensionRefactor

Plugin Manager (former #1260)
pull/1/head
yann300 6 years ago committed by GitHub
commit 60e5c4ba47
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      src/app.js
  2. 6
      src/app/debugger/debugger.js
  3. 2
      src/app/editor/contextView.js
  4. 2
      src/app/editor/contextualListener.js
  5. 56
      src/app/panels/righthand-panel.js
  6. 2
      src/app/panels/terminal.js
  7. 41
      src/app/plugin/plugin.md
  8. 48
      src/app/plugin/pluginAPI.js
  9. 65
      src/app/plugin/pluginManager.js
  10. 8
      src/app/plugin/plugins.js
  11. 5
      src/app/staticanalysis/staticAnalysisView.js
  12. 5
      src/app/tabs/plugin-tab.js
  13. 14
      src/app/tabs/settings-tab.js
  14. 24
      src/app/tabs/tabbed-menu.js
  15. 6
      src/lib/offsetToLineColumnConverter.js
  16. 23
      src/universal-dapp.js
  17. 43
      test-browser/plugin/remix.js

@ -578,6 +578,14 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
if (queryParams.get().debugtx) {
self.startdebugging(queryParams.get().debugtx)
}
if (queryParams.get().pluginurl) {
var title = queryParams.get().plugintitle
var url = queryParams.get().pluginurl
modalDialogCustom.confirm(null, `Remix is going to load the extension "${title}" located at ${queryParams.get().pluginurl}. Are you sure to load this external extension?`, () => {
self._components.righthandpanel.loadPlugin({title, url})
})
}
})
// chrome app

@ -36,7 +36,7 @@ function Debugger (id, sourceHighlighter, localRegistry) {
this.isActive = false
this.breakPointManager = new remixCore.code.BreakpointManager(this.debugger, (sourceLocation) => {
return self._deps.offsetToLineColumnConverter.offsetToLineColumn(sourceLocation, sourceLocation.file, this._deps.compiler.lastCompilationResult.data)
return self._deps.offsetToLineColumnConverter.offsetToLineColumn(sourceLocation, sourceLocation.file, this._deps.compiler.lastCompilationResult.source.sources)
})
this.debugger.setBreakpointManager(this.breakPointManager)
@ -74,8 +74,8 @@ function Debugger (id, sourceHighlighter, localRegistry) {
this.debugger.codeManager.event.register('changed', this, function (code, address, index) {
if (self._deps.compiler.lastCompilationResult) {
self.debugger.callTree.sourceLocationTracker.getSourceLocationFromInstructionIndex(address, index, self._deps.compiler.lastCompilationResult.data.contracts, function (error, rawLocation) {
if (!error) {
var lineColumnPos = self._deps.offsetToLineColumnConverter.offsetToLineColumn(rawLocation, rawLocation.file, self._deps.compiler.lastCompilationResult)
if (!error && self._deps.compiler.lastCompilationResult && self._deps.compiler.lastCompilationResult.data) {
var lineColumnPos = self._deps.offsetToLineColumnConverter.offsetToLineColumn(rawLocation, rawLocation.file, self._deps.compiler.lastCompilationResult.source.sources)
self._components.sourceHighlighter.currentSourceLocation(lineColumnPos, rawLocation)
} else {
self._components.sourceHighlighter.currentSourceLocation(null)

@ -98,7 +98,7 @@ class ContextView {
}
}
if (self._deps.compiler.lastCompilationResult && self._deps.compiler.lastCompilationResult.data) {
var lineColumn = self._deps.offsetToLineColumnConverter.offsetToLineColumn(position, position.file, self._deps.compiler.lastCompilationResult)
var lineColumn = self._deps.offsetToLineColumnConverter.offsetToLineColumn(position, position.file, self._deps.compiler.lastCompilationResult.source.sources)
var filename = self._deps.compiler.getSourceName(position.file)
// TODO: refactor with rendererAPI.errorClick
if (filename !== self._deps.config.get('currentFile')) {

@ -114,7 +114,7 @@ class ContextualListener {
_highlightInternal (position, node) {
var self = this
if (self._deps.compiler.lastCompilationResult && self._deps.compiler.lastCompilationResult.data) {
var lineColumn = self._deps.offsetToLineColumnConverter.offsetToLineColumn(position, position.file, self._deps.compiler.lastCompilationResult)
var lineColumn = self._deps.offsetToLineColumnConverter.offsetToLineColumn(position, position.file, self._deps.compiler.lastCompilationResult.source.sources)
var css = 'highlightreference'
if (node.children && node.children.length) {
// If node has children, highlight the entire line. if not, just highlight the current source position of the node.

@ -15,7 +15,10 @@ const SupportTab = require('../tabs/support-tab')
const PluginTab = require('../tabs/plugin-tab')
const TestTab = require('../tabs/test-tab')
const RunTab = require('../tabs/run-tab')
const PluginAPI = require('../plugin/pluginAPI')
const plugins = require('../plugin/plugins')
var toolTip = require('../ui/tooltip')
const EventManager = remixLib.EventManager
const styles = styleguide.chooser()
@ -24,6 +27,7 @@ module.exports = class RighthandPanel {
const self = this
self._components = {}
self._components.registry = localRegistry || globalRegistry
self._components.registry.put({api: this, name: 'righthandpanel'})
self.event = new EventManager()
self._view = {
element: null,
@ -32,11 +36,32 @@ module.exports = class RighthandPanel {
dragbar: null
}
self._components.registry.put({api: this, name: 'righthandpanel'})
self._deps = {
fileProviders: self._components.registry.get('fileproviders').api,
compiler: self._components.registry.get('compiler').api,
udapp: self._components.registry.get('udapp').api,
app: self._components.registry.get('app').api,
txlistener: self._components.registry.get('txlistener').api
}
var tabbedMenu = new TabbedMenu(self._components.registry)
var pluginAPI = new PluginAPI(
self._deps.fileProviders,
self._deps.compiler,
self._deps.udapp,
tabbedMenu
)
var pluginManager = new PluginManager(
pluginAPI,
self._deps.app,
self._deps.compiler,
self._deps.txlistener)
self._components = {
pluginManager: new PluginManager(self._components.registry),
tabbedMenu: new TabbedMenu(self._components.registry),
pluginManager: pluginManager,
tabbedMenu: tabbedMenu,
compile: new CompileTab(self._components.registry),
run: new RunTab(self._components.registry),
settings: new SettingsTab(self._components.registry),
@ -47,12 +72,29 @@ module.exports = class RighthandPanel {
}
self.event.register('plugin-loadRequest', json => {
const tab = new PluginTab({}, self._events, json)
const content = tab.render()
self._components.tabbedMenu.addTab(json.title, 'plugin', content)
self._components.pluginManager.register(json, content)
self.loadPlugin(json)
})
self.event.register('plugin-name-loadRequest', name => {
if (plugins[name]) {
self.loadPlugin(plugins[name])
} else {
toolTip('unknown plugin ' + name)
}
})
self.loadPlugin = function (json) {
if (self._components.pluginManager.plugins[json.title]) {
self._components.tabbedMenu.removeTabByTitle(json.title)
self._components.pluginManager.unregister(json)
} else {
var tab = new PluginTab(json)
var content = tab.render()
self._components.tabbedMenu.addTab(json.title, json.title + ' plugin', content)
self._components.pluginManager.register(json, content)
}
}
self._view.dragbar = yo`<div id="dragbar" class=${css.dragbar}></div>`
self._view.element = yo`
<div id="righthand-panel" class=${css.righthandpanel}>

@ -74,7 +74,7 @@ class Terminal {
self.registerCommand('script', function execute (args, scopedCommands, append) {
var script = String(args[0])
scopedCommands.log(`> ${script}`)
if (self._opts.cmdInterpreter && self.opts.cmdInterpreter.interpret(script)) return
if (self._opts.cmdInterpreter && self._opts.cmdInterpreter.interpret(script)) return
self._shell(script, scopedCommands, function (error, output) {
if (error) scopedCommands.error(error)
else scopedCommands.log(output)

@ -0,0 +1,41 @@
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)`
- updateTitle `@param {String} title`
### 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)`

@ -1,25 +1,61 @@
'use strict'
var executionContext = require('../../execution-context')
/*
Defines available API. `key` / `type`
*/
module.exports = (registry) => {
module.exports = (fileProviders, compiler, udapp, tabbedMenu) => {
return {
app: {
getExecutionContextProvider: (mod, cb) => {
cb(null, executionContext.getProvider())
},
updateTitle: (mod, title, cb) => {
tabbedMenu.updateTabTitle(mod, title)
}
},
config: {
setConfig: (mod, path, content, cb) => {
registry.get('fileproviders/config').api.set(mod + '/' + path, content)
fileProviders['config'].set(mod + '/' + path, content)
cb()
},
getConfig: (mod, path, cb) => {
cb(null, registry.get('fileproviders/config').get(mod + '/' + path))
cb(null, fileProviders['config'].get(mod + '/' + path))
},
removeConfig: (mod, path, cb) => {
cb(null, registry.get('fileproviders/config').api.remove(mod + '/' + path))
cb(null, fileProviders['config'].remove(mod + '/' + path))
if (cb) cb()
}
},
compiler: {
getCompilationResult: () => {
return registry.get('compiler').api.lastCompilationResult
getCompilationResult: (mod, cb) => {
cb(null, compiler.lastCompilationResult)
}
},
udapp: {
runTx: (mod, tx, cb) => {
if (executionContext.getProvider() !== 'vm') return cb('plugin API does not allow sending a transaction through a web3 connection. Only vm mode is allowed')
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) => {
if (executionContext.getProvider() !== 'vm') return cb('plugin API does not allow retrieving accounts through a web3 connection. Only vm mode is allowed')
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)
})
}
}
}

@ -1,7 +1,5 @@
'use strict'
var globalRegistry = require('../../global/registry')
var PluginAPI = require('./pluginAPI')
var executionContext = require('../../execution-context')
/**
* Register and Manage plugin:
*
@ -79,19 +77,13 @@ var PluginAPI = require('./pluginAPI')
*
*/
module.exports = class PluginManager {
constructor (localRegistry) {
constructor (pluginAPI, app, compiler, txlistener) {
const self = this
self.plugins = {}
self._components = {}
self._components.registry = localRegistry || globalRegistry
self._components.pluginAPI = new PluginAPI(self._components.registry)
self._deps = {
compiler: self._components.registry.get('compiler').api,
app: self._components.registry.get('app').api
}
self.origins = {}
self.inFocus
self.allowedapi = {'setConfig': 1, 'getConfig': 1, 'removeConfig': 1}
self._deps.compiler.event.register('compilationFinished', (success, data, source) => {
compiler.event.register('compilationFinished', (success, data, source) => {
if (self.inFocus) {
// trigger to the current focus
self.post(self.inFocus, JSON.stringify({
@ -103,7 +95,17 @@ module.exports = class PluginManager {
}
})
self._deps.app.event.register('tabChanged', (tabName) => {
txlistener.event.register('newTransaction', (tx) => {
if (executionContext.getProvider() !== 'vm') return
self.broadcast(JSON.stringify({
action: 'notification',
key: 'txlistener',
type: 'newTransaction',
value: [tx]
}))
})
app.event.register('tabChanged', (tabName) => {
if (self.inFocus && self.inFocus !== tabName) {
// trigger unfocus
self.post(self.inFocus, JSON.stringify({
@ -122,18 +124,25 @@ module.exports = class PluginManager {
value: []
}))
self.inFocus = tabName
pluginAPI.compiler.getCompilationResult(tabName, (error, data) => {
if (!error) return
self.post(tabName, JSON.stringify({
action: 'notification',
key: 'compiler',
type: 'compilationData',
value: [self._deps.compiler.getCompilationResult()]
value: [data]
}))
})
}
})
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.post(self.inFocus, JSON.stringify({
self.postToOrigin(event.origin, JSON.stringify({
id: callid,
action: 'response',
key: key,
@ -142,21 +151,35 @@ module.exports = class PluginManager {
value: [ result ]
}))
}
if (event.type === 'message' && self.inFocus && self.plugins[self.inFocus] && self.plugins[self.inFocus].origin === event.origin) {
var data = JSON.parse(event.data)
data.value.unshift(self.inFocus)
if (self.allowedapi[data.type]) {
data.value.unshift(extension)
// if (self.allowedapi[data.type]) {
data.value.push((error, result) => {
response(data.key, data.type, data.id, error, result)
})
self._components.pluginAPI[data.key][data.type].apply({}, data.value)
}
}
pluginAPI[data.key][data.type].apply({}, data.value)
// }
}, false)
}
unregister (desc) {
const self = this
delete self.plugins[desc.title]
delete self.origins[desc.url]
}
register (desc, content) {
const self = this
self.plugins[desc.title] = {content, 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)
}
}
post (name, value) {
const self = this

@ -0,0 +1,8 @@
'use strict'
module.exports = {
'oraclize': {
url: 'https://remix-plugin.oraclize.it',
title: 'Oraclize'
}
}

@ -20,6 +20,7 @@ function staticAnalysisView (localRegistry) {
this.runner = new StaticAnalysisRunner()
this.modulesView = renderModules(this.runner.modules())
this.lastCompilationResult = null
this.lastCompilationSource = null
self._components = {}
self._components.registry = localRegistry || globlalRegistry
// dependencies
@ -31,9 +32,11 @@ function staticAnalysisView (localRegistry) {
self._deps.compiler.event.register('compilationFinished', function (success, data, source) {
self.lastCompilationResult = null
self.lastCompilationSource = null
$('#staticanalysisresult').empty()
if (success) {
self.lastCompilationResult = data
self.lastCompilationSource = source
if (self.view.querySelector('#autorunstaticanalysis').checked) {
self.run()
}
@ -94,7 +97,7 @@ staticAnalysisView.prototype.run = function () {
start: parseInt(split[0]),
length: parseInt(split[1])
}
location = self._deps.offsetToLineColumnConverter.offsetToLineColumn(location, file)
location = self._deps.offsetToLineColumnConverter.offsetToLineColumn(location, file, self.lastCompilationSource.sources)
location = Object.keys(self.lastCompilationResult.contracts)[file] + ':' + (location.start.line + 1) + ':' + (location.start.column + 1) + ':'
}
warningCount++

@ -6,10 +6,11 @@ var globalRegistry = require('../../global/registry')
var EventManager = remixLib.EventManager
module.exports = class plugintab {
constructor (localRegistry) {
constructor (json, localRegistry) {
const self = this
self.event = new EventManager()
self._view = { el: null }
self.data = { json }
self._components = {}
self._components.registry = localRegistry || globalRegistry
}
@ -18,7 +19,7 @@ module.exports = class plugintab {
if (self._view.el) return self._view.el
self._view.el = yo`
<div class="${css.pluginTabView}" id="pluginView">
<iframe class="${css.iframe}" src="${self._opts.url}/index.html"></iframe>
<iframe class="${css.iframe}" src="${self.data.json.url}/index.html"></iframe>
</div>`
return self._view.el
}

@ -26,7 +26,8 @@ module.exports = class SettingsTab {
compiler: self._components.registry.get('compiler').api,
config: self._components.registry.get('config').api,
editorPanel: self._components.registry.get('editorpanel').api,
editor: self._components.registry.get('editor').api
editor: self._components.registry.get('editor').api,
righthandpanel: self._components.registry.get('righthandpanel').api
}
self._view = { /* eslint-disable */
el: null,
@ -155,8 +156,9 @@ module.exports = class SettingsTab {
</div>
<div>
${self._view.pluginInput}
<input onclick=${onloadPlugin} type="button" value="Load" class="${css.pluginLoad}">
<input onclick=${onloadPluginJson} type="button" value="Load" class="${css.pluginLoad}">
</div>
<input onclick=${() => { onLoadPlugin('oraclize') }} type="button" value="Oraclize" class="${css.pluginLoad}">
</div>
</div>`
self._view.config.remixd = yo`
@ -197,14 +199,18 @@ module.exports = class SettingsTab {
function onchangeOption (event) {
self._deps.config.set('settings/always-use-vm', !self._deps.config.get('settings/always-use-vm'))
}
function onloadPlugin (event) {
function onLoadPlugin (name) {
// @TODO: BAD! REFACTOR: no module should trigger events of another modules emitter
self._deps.righthandpanel.event.trigger('plugin-name-loadRequest', [name])
}
function onloadPluginJson (event) {
try {
var json = JSON.parse(self._view.pluginInput.value)
} catch (e) {
return modal.alert('cannot parse the plugin definition to JSON')
}
// @TODO: BAD! REFACTOR: no module should trigger events of another modules emitter
self._events.rhp.trigger('plugin-loadRequest', [json])
self._deps.righthandpanel.event.trigger('plugin-loadRequest', [json])
}
function onswitch2darkTheme (event) {
styleGuide.switchTheme('dark')

@ -46,13 +46,35 @@ module.exports = class TabbedMenu {
if (self._view.el) self._view.el.appendChild(self._view.tabs[title])
if (self._view.viewport) self._view.viewport.appendChild(self._view.contents[title])
}
removeTabByTitle (title) {
const self = this
if (self._view.tabs[title]) {
self._view.tabs[title].parentNode.removeChild(self._view.tabs[title])
}
if (self._view.contents[title]) {
self._view.contents[title].parentNode.removeChild(self._view.contents[title])
}
delete self._view.contents[title]
delete self._view.tabs[title]
}
getTabByClass (tabClass) {
const self = this
return self._view.el.querySelector(`li.${tabClass}`)
}
updateTabTitle (tabClass, title) {
const self = this
var tab = self.getTabByClass(tabClass)
if (tab) tab.innerHTML = title
}
selectTabByTitle (title) {
const self = this
self.selectTab(self._view.tabs[title])
}
selectTabByClassName (tabClass) {
const self = this
self.selectTab(self._view.el.querySelector(`li.${tabClass}`))
var tab = self.getTabByClass(tabClass)
if (tab) self.selectTab(tab)
return tab
}
selectTab (el) {
const self = this

@ -10,10 +10,10 @@ function offsetToColumnConverter (compilerEvent) {
})
}
offsetToColumnConverter.prototype.offsetToLineColumn = function (rawLocation, file, compilationResult) {
offsetToColumnConverter.prototype.offsetToLineColumn = function (rawLocation, file, sources) {
if (!this.lineBreakPositionsByContent[file]) {
var filename = Object.keys(compilationResult.data.sources)[file]
this.lineBreakPositionsByContent[file] = this.sourceMappingDecoder.getLinebreakPositions(compilationResult.source.sources[filename].content)
var filename = Object.keys(sources)[file]
this.lineBreakPositionsByContent[file] = this.sourceMappingDecoder.getLinebreakPositions(sources[filename].content)
}
return this.sourceMappingDecoder.convertOffsetToLineColumn(rawLocation, this.lineBreakPositionsByContent[file])
}

@ -80,6 +80,12 @@ UniversalDApp.prototype.resetAPI = function (transactionContextAPI) {
this.transactionContextAPI = transactionContextAPI
}
UniversalDApp.prototype.createVMAccount = function (privateKey, balance, cb) {
this._addAccount(privateKey, balance)
privateKey = new Buffer(privateKey, 'hex')
cb(null, '0x' + ethJSUtil.privateToAddress(privateKey).toString('hex'))
}
UniversalDApp.prototype.newAccount = function (password, cb) {
if (!executionContext.isVM()) {
if (!this._deps.config.get('settings/personal-mode')) {
@ -282,6 +288,23 @@ UniversalDApp.prototype.getInputs = function (funABI) {
return txHelper.inputParametersDeclarationToString(funABI.inputs)
}
/**
* This function send a tx without alerting the user (if mainnet or if gas estimation too high).
* SHOULD BE TAKEN CAREFULLY!
*
* @param {Object} tx - transaction.
* @param {Function} callback - callback.
*/
UniversalDApp.prototype.silentRunTx = function (tx, cb) {
if (!executionContext.isVM()) return cb('Cannot silently send transaction through a web3 provider')
this.txRunner.rawRun(
tx,
(network, tx, gasEstimation, continueTxExecution, cancelCb) => { continueTxExecution() },
(error, continueTxExecution, cancelCb) => { if (error) { cb(error) } else { continueTxExecution() } },
(okCb, cancelCb) => { okCb() },
cb)
}
UniversalDApp.prototype.runTx = function (args, cb) {
const self = this
async.waterfall([

@ -1,4 +1,17 @@
/*
test contract creation
*/
var addrResolverByteCode = '0x6060604052341561000f57600080fd5b33600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061033c8061005f6000396000f300606060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806338cc483114610067578063767800de146100bc578063a6f9dae114610111578063d1d80fdf1461014a575b600080fd5b341561007257600080fd5b61007a610183565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156100c757600080fd5b6100cf6101ac565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561011c57600080fd5b610148600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506101d1565b005b341561015557600080fd5b610181600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610271565b005b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561022d57600080fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156102cd57600080fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505600a165627a7a723058201b23355f578cb9a23c0a43a440ab2631b62df7be0a8e759812a70f01344224da0029'
const addrResolverTx = {
gasLimit: '0x2710',
from: '0xca35b7d915458ef540ade6068dfe2f44e8fa733c',
data: addrResolverByteCode,
value: '0x00',
useCall: false
}
function receiveMessage (event) {
console.log('receiveMessage', event.data, event.source, event.origin)
document.getElementById('compilationdata').innerHTML += event.data + '<br>'
@ -35,4 +48,34 @@ window.onload = function () {
id: 36
}), '*')
})
document.querySelector('input#testcontractcreation').addEventListener('click', function () {
window.parent.postMessage(JSON.stringify({
action: 'request',
key: 'udapp',
type: 'runTx',
value: [addrResolverTx],
id: 37
}), '*')
})
document.querySelector('input#testaccountcreation').addEventListener('click', function () {
window.parent.postMessage(JSON.stringify({
action: 'request',
key: 'udapp',
type: 'createVMAccount',
value: ['71975fbf7fe448e004ac7ae54cad0a383c3906055a75468714156a07385e96ce', '0x56BC75E2D63100000'],
id: 38
}), '*')
})
var k = 0
document.querySelector('input#testchangetitle').addEventListener('click', function () {
window.parent.postMessage(JSON.stringify({
action: 'request',
key: 'app',
type: 'updateTitle',
value: ['changed title ' + k++],
id: 39
}), '*')
})
}

Loading…
Cancel
Save