refactor settings; separate logic from view code; refactor code

pull/1/head
Iuri Matias 6 years ago committed by yann300
parent 9a63d0977d
commit 7ff7b8e5bf
  1. 18
      src/app/tabs/run-tab.js
  2. 117
      src/app/tabs/runTab/model/settings.js
  3. 225
      src/app/tabs/runTab/settings.js

@ -6,7 +6,9 @@ var executionContext = require('../../execution-context')
var Card = require('../ui/card')
var css = require('./styles/run-tab-styles')
var Settings = require('./runTab/model/settings.js')
var SettingsUI = require('./runTab/settings.js')
var ContractDropdownUI = require('./runTab/contractDropdown.js')
var Recorder = require('./runTab/model/recorder.js')
@ -126,7 +128,21 @@ function runTab (opts, localRegistry) {
status.appendChild(self._view.collapsedView)
}
})
var settingsUI = new SettingsUI(container, self)
var settings = new Settings(self._deps.udapp)
var settingsUI = new SettingsUI(settings)
self.event.register('clearInstance', () => {
var instanceContainer = self._view.instanceContainer
var instanceContainerTitle = self._view.instanceContainerTitle
instanceContainer.innerHTML = '' // clear the instances list
instanceContainer.appendChild(instanceContainerTitle)
instanceContainer.appendChild(self._view.noInstancesText)
})
settingsUI.event.register('clearInstance', () => {
this.event.trigger('clearInstance', [])
})
var contractDropdownUI = new ContractDropdownUI(self)
var el = yo`
<div>

@ -0,0 +1,117 @@
var ethJSUtil = require('ethereumjs-util')
var Personal = require('web3-eth-personal')
var remixLib = require('remix-lib')
var EventManager = remixLib.EventManager
var executionContext = remixLib.execution.executionContext
class Settings {
constructor (udapp) {
this.udapp = udapp
this.event = new EventManager()
this.udapp.event.register('transactionExecuted', (error, from, to, data, lookupOnly, txResult) => {
this.event.trigger('transactionExecuted', [error, from, to, data, lookupOnly, txResult])
})
executionContext.event.register('contextChanged', (context, silent) => {
this.event.trigger('contextChanged', [context, silent])
})
executionContext.event.register('addProvider', (network) => {
this.event.trigger('addProvider', [network])
})
executionContext.event.register('removeProvider', (name) => {
this.event.trigger('removeProvider', [name])
})
this.networkcallid = 0
}
changeExecutionContext (context, cb) {
return executionContext.executionContextChange(context, null, cb)
}
setProviderFromEndpoint (target, context, cb) {
return executionContext.setProviderFromEndpoint(target, context, cb)
}
getProvider () {
return executionContext.getProvider()
}
getAccountBalanceForAddress (address, cb) {
return this.udapp.getBalanceInEther(address, cb)
}
updateNetwork (cb) {
this.networkcallid++
((callid) => {
executionContext.detectNetwork((err, { id, name } = {}) => {
if (this.networkcallid > callid) return
this.networkcallid++
if (err) {
return cb(err)
}
cb(null, {id, name})
})
})(this.networkcallid)
}
newAccount (passphraseCb, cb) {
return this.udapp.newAccount('', passphraseCb, cb)
}
getAccounts (cb) {
return this.udapp.getAccounts(cb)
}
isWeb3Provider () {
var isVM = executionContext.isVM()
var isInjected = executionContext.getProvider() === 'injected'
return (!isVM && !isInjected)
}
signMessage (message, account, passphrase, cb) {
var isVM = executionContext.isVM()
var isInjected = executionContext.getProvider() === 'injected'
if (isVM) {
const personalMsg = ethJSUtil.hashPersonalMessage(Buffer.from(message))
var privKey = this.udapp.accounts[account].privateKey
try {
var rsv = ethJSUtil.ecsign(personalMsg, privKey)
var signedData = ethJSUtil.toRpcSig(rsv.v, rsv.r, rsv.s)
cb(null, '0x' + personalMsg.toString('hex'), signedData)
} catch (e) {
cb(e.message)
}
return
}
if (isInjected) {
const hashedMsg = executionContext.web3().sha3(message)
try {
executionContext.web3().eth.sign(account, hashedMsg, (error, signedData) => {
cb(error, hashedMsg, signedData)
})
} catch (e) {
cb(e.message)
}
return
}
const hashedMsg = executionContext.web3().sha3(message)
try {
var personal = new Personal(executionContext.web3().currentProvider)
personal.sign(hashedMsg, account, passphrase, (error, signedData) => {
cb(error, hashedMsg, signedData)
})
} catch (e) {
cb(e.message)
}
}
}
module.exports = Settings

@ -1,26 +1,41 @@
var $ = require('jquery')
var yo = require('yo-yo')
var ethJSUtil = require('ethereumjs-util')
var Personal = require('web3-eth-personal')
var remixLib = require('remix-lib')
var EventManager = remixLib.EventManager
var css = require('../styles/run-tab-styles')
var executionContext = require('../../../execution-context')
var copyToClipboard = require('../../ui/copy-to-clipboard')
var modalDialogCustom = require('../../ui/modal-dialog-custom')
var addTooltip = require('../../ui/tooltip')
var modalCustom = require('../../ui/modal-dialog-custom')
var tootip = require('../../ui/tooltip')
var helper = require('../../../lib/helper.js')
class SettingsUI {
constructor (container, parentSelf) {
this.container = container
this.parentSelf = parentSelf
// HELPER FUNCTIONS AND EVENTS
this.parentSelf._deps.udapp.event.register('transactionExecuted', (error, from, to, data, lookupOnly, txResult) => {
constructor (settings) {
this.settings = settings
this.event = new EventManager()
this.settings.event.register('transactionExecuted', (error, from, to, data, lookupOnly, txResult) => {
if (error) return
if (!lookupOnly) this.el.querySelector('#value').value = '0'
updateAccountBalances(this.container, this.parentSelf)
this.updateAccountBalances()
})
setInterval(() => {
this.updateAccountBalances()
}, 10 * 1000)
this.accountListCallId = 0
this.loadedAccounts = {}
}
updateAccountBalances () {
if (!this.el) return
var accounts = $(this.el.querySelector('#txorigin')).children('option')
accounts.each((index, account) => {
this.settings.getAccountBalanceForAddress(account.value, (err, balance) => {
if (err) return
account.innerText = helper.shortenAddress(account.value, balance)
})
})
}
@ -88,7 +103,6 @@ class SettingsUI {
</div>
`
// DOM ELEMENT
var el = yo`
<div class="${css.settings}">
${environmentEl}
@ -98,40 +112,47 @@ class SettingsUI {
</div>
`
// DROPDOWN
var selectExEnv = environmentEl.querySelector('#selectExEnvOptions')
this.selectExEnv = selectExEnv
this.setDropdown(selectExEnv)
this.parentSelf.event.register('clearInstance', () => {
var instanceContainer = this.parentSelf._view.instanceContainer
var instanceContainerTitle = this.parentSelf._view.instanceContainerTitle
instanceContainer.innerHTML = '' // clear the instances list
instanceContainer.appendChild(instanceContainerTitle)
instanceContainer.appendChild(this.parentSelf._view.noInstancesText)
this.settings.event.register('contextChanged', (context, silent) => {
this.setFinalContext()
})
executionContext.event.register('addProvider', (network) => {
setInterval(() => {
this.updateNetwork()
this.fillAccountsList()
}, 5000)
this.el = el
return el
}
setDropdown (selectExEnv) {
this.selectExEnv = selectExEnv
this.settings.event.register('addProvider', (network) => {
selectExEnv.appendChild(yo`<option
title="Manually added environment: ${network.url}"
value="${network.name}" name="executionContext"> ${network.name}
</option>`)
tootip(`${network.name} [${network.url}] added`)
addTooltip(`${network.name} [${network.url}] added`)
})
executionContext.event.register('removeProvider', (name) => {
this.settings.event.register('removeProvider', (name) => {
var env = selectExEnv.querySelector(`option[value="${name}"]`)
if (env) {
selectExEnv.removeChild(env)
tootip(`${name} removed`)
addTooltip(`${name} removed`)
}
})
selectExEnv.addEventListener('change', (event) => {
let context = selectExEnv.options[selectExEnv.selectedIndex].value
executionContext.executionContextChange(context, null, () => {
this.settings.changeExecutionContext(context, () => {
modalDialogCustom.confirm(null, 'Are you sure you want to connect to an ethereum node?', () => {
modalDialogCustom.prompt(null, 'Web3 Provider Endpoint', 'http://localhost:8545', (target) => {
executionContext.setProviderFromEndpoint(target, context, (alertMsg) => {
this.settings.setProviderFromEndpoint(target, context, (alertMsg) => {
if (alertMsg) {
modalDialogCustom.alert(alertMsg)
}
@ -144,38 +165,23 @@ class SettingsUI {
}, this.setFinalContext.bind(this))
})
selectExEnv.value = executionContext.getProvider()
executionContext.event.register('contextChanged', (context, silent) => {
this.setFinalContext()
})
setInterval(() => {
this.updateNetwork()
fillAccountsList(el, this.parentSelf)
}, 5000)
setInterval(() => {
updateAccountBalances(this.container, this.parentSelf)
}, 10000)
this.el = el
return el
selectExEnv.value = this.settings.getProvider()
}
setFinalContext () {
// set the final context. Cause it is possible that this is not the one we've originaly selected
this.selectExEnv.value = executionContext.getProvider()
this.parentSelf.event.trigger('clearInstance', [])
this.selectExEnv.value = this.settings.getProvider()
this.event.trigger('clearInstance', [])
this.updateNetwork()
fillAccountsList(this.el, this.parentSelf)
this.fillAccountsList()
}
newAccount () {
this.parentSelf._deps.udapp.newAccount('',
this.settings.newAccount(
(cb) => {
modalCustom.promptPassphraseCreation((error, passphrase) => {
modalDialogCustom.promptPassphraseCreation((error, passphrase) => {
if (error) {
return modalCustom.alert(error)
return modalDialogCustom.alert(error)
}
cb(passphrase)
}, () => {})
@ -189,127 +195,70 @@ class SettingsUI {
)
}
alertSignedData (error, hash, signedData) {
if (error && error.message !== '') {
console.log(error)
addTooltip(error.message)
} else {
modalDialogCustom.alert(yo`<div><b>hash:</b>${hash}<br><b>signature:</b>${signedData}</div>`)
}
signMessage () {
this.settings.getAccounts((err, accounts) => {
if (err) {
return addTooltip(`Cannot get account list: ${err}`)
}
signMessage (event) {
this.parentSelf._deps.udapp.getAccounts((err, accounts) => {
if (err) { addTooltip(`Cannot get account list: ${err}`) }
var signMessageDialog = { 'title': 'Sign a message', 'text': 'Enter a message to sign', 'inputvalue': 'Message to sign' }
var $txOrigin = this.container.querySelector('#txorigin')
var $txOrigin = this.el.querySelector('#txorigin')
var account = $txOrigin.selectedOptions[0].value
var isVM = executionContext.isVM()
var isInjected = executionContext.getProvider() === 'injected'
if (isVM) {
modalDialogCustom.promptMulti(signMessageDialog, (message) => {
const personalMsg = ethJSUtil.hashPersonalMessage(Buffer.from(message))
var privKey = this.parentSelf._deps.udapp.accounts[account].privateKey
try {
var rsv = ethJSUtil.ecsign(personalMsg, privKey)
var signedData = ethJSUtil.toRpcSig(rsv.v, rsv.r, rsv.s)
this.alertSignedData(null, '0x' + personalMsg.toString('hex'), signedData)
} catch (e) {
addTooltip(e.message)
return
}
}, false)
} else if (isInjected) {
modalDialogCustom.promptMulti(signMessageDialog, (message) => {
const hashedMsg = executionContext.web3().sha3(message)
try {
executionContext.web3().eth.sign(account, hashedMsg, (error, signedData) => {
this.alertSignedData(error, hashedMsg, signedData)
})
} catch (e) {
addTooltip(e.message)
console.log(e)
return
}
})
} else {
modalDialogCustom.promptPassphrase('Passphrase to sign a message', 'Enter your passphrase for this account to sign the message', '', (passphrase) => {
var promptCb = (passphrase) => {
modalDialogCustom.promptMulti(signMessageDialog, (message) => {
const hashedMsg = executionContext.web3().sha3(message)
try {
var personal = new Personal(executionContext.web3().currentProvider)
personal.sign(hashedMsg, account, passphrase, (error, signedData) => {
this.alertSignedData(error, hashedMsg, signedData)
})
} catch (e) {
addTooltip(e.message)
console.log(e)
return
this.settings.signMessage(message, account, passphrase, (err, msgHash, signedData) => {
if (err) {
return addTooltip(err)
}
modalDialogCustom.alert(yo`<div><b>hash:</b>${msgHash}<br><b>signature:</b>${signedData}</div>`)
})
}, false)
}
if (this.settings.isWeb3Provider()) {
return modalDialogCustom.promptPassphrase('Passphrase to sign a message', 'Enter your passphrase for this account to sign the message', '', promptCb, false)
}
promptCb()
})
}
updateNetwork () {
let self = this
var networkcallid = 0
networkcallid++
((callid) => {
executionContext.detectNetwork((err, { id, name } = {}) => {
if (networkcallid > callid) return
networkcallid++
this.settings.updateNetwork((err, {id, name} = {}) => {
if (err) {
console.error(err)
self.netUI.innerHTML = 'can\'t detect network '
} else {
self.netUI.innerHTML = `<i class="${css.networkItem} fa fa-plug" aria-hidden="true"></i> ${name} (${id || '-'})`
this.netUI.innerHTML = 'can\'t detect network '
return
}
this.netUI.innerHTML = `<i class="${css.networkItem} fa fa-plug" aria-hidden="true"></i> ${name} (${id || '-'})`
})
})(networkcallid)
}
}
var accountListCallId = 0
var loadedAccounts = {}
function fillAccountsList (container, self) {
accountListCallId++
((callid) => {
var txOrigin = container.querySelector('#txorigin')
self._deps.udapp.getAccounts((err, accounts) => {
if (accountListCallId > callid) return
accountListCallId++
// TODO: unclear what's the goal of accountListCallId, feels like it can be simplified
fillAccountsList () {
this.accountListCallId++
var callid = this.accountListCallId
var txOrigin = this.el.querySelector('#txorigin')
this.settings.getAccounts((err, accounts) => {
if (this.accountListCallId > callid) return
this.accountListCallId++
if (err) { addTooltip(`Cannot get account list: ${err}`) }
for (var loadedaddress in loadedAccounts) {
for (var loadedaddress in this.loadedAccounts) {
if (accounts.indexOf(loadedaddress) === -1) {
txOrigin.removeChild(txOrigin.querySelector('option[value="' + loadedaddress + '"]'))
delete loadedAccounts[loadedaddress]
delete this.loadedAccounts[loadedaddress]
}
}
for (var i in accounts) {
var address = accounts[i]
if (!loadedAccounts[address]) {
if (!this.loadedAccounts[address]) {
txOrigin.appendChild(yo`<option value="${address}" >${address}</option>`)
loadedAccounts[address] = 1
this.loadedAccounts[address] = 1
}
}
txOrigin.setAttribute('value', accounts[0])
})
})(accountListCallId)
}
}
function updateAccountBalances (container, self) {
var accounts = $(container.querySelector('#txorigin')).children('option')
accounts.each((index, value) => {
((acc) => {
self._deps.udapp.getBalanceInEther(accounts[acc].value, (err, res) => {
if (err) return
accounts[acc].innerText = helper.shortenAddress(accounts[acc].value, res)
})
})(index)
})
}
module.exports = SettingsUI

Loading…
Cancel
Save