|
|
|
@ -11,168 +11,167 @@ var modalCustom = require('../../ui/modal-dialog-custom') |
|
|
|
|
var tootip = require('../../ui/tooltip') |
|
|
|
|
var helper = require('../../../lib/helper.js') |
|
|
|
|
|
|
|
|
|
function settings (container, self) { |
|
|
|
|
// VARIABLES
|
|
|
|
|
var net = yo`<span class=${css.network}></span>` |
|
|
|
|
var networkcallid = 0 |
|
|
|
|
const updateNetwork = (cb) => { |
|
|
|
|
networkcallid++ |
|
|
|
|
(function (callid) { |
|
|
|
|
executionContext.detectNetwork((err, { id, name } = {}) => { |
|
|
|
|
if (networkcallid > callid) return |
|
|
|
|
networkcallid++ |
|
|
|
|
if (err) { |
|
|
|
|
console.error(err) |
|
|
|
|
net.innerHTML = 'can\'t detect network ' |
|
|
|
|
} else { |
|
|
|
|
net.innerHTML = `<i class="${css.networkItem} fa fa-plug" aria-hidden="true"></i> ${name} (${id || '-'})` |
|
|
|
|
} |
|
|
|
|
if (cb) cb(err, {id, name}) |
|
|
|
|
}) |
|
|
|
|
})(networkcallid) |
|
|
|
|
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) => { |
|
|
|
|
if (error) return |
|
|
|
|
if (!lookupOnly) this.el.querySelector('#value').value = '0' |
|
|
|
|
updateAccountBalances(this.container, this.parentSelf) |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
var environmentEl = yo` |
|
|
|
|
<div class="${css.crow}"> |
|
|
|
|
<div id="selectExEnv" class="${css.col1_1}"> |
|
|
|
|
Environment |
|
|
|
|
|
|
|
|
|
render () { |
|
|
|
|
this.netUI = yo`<span class=${css.network}></span>` |
|
|
|
|
|
|
|
|
|
var environmentEl = yo` |
|
|
|
|
<div class="${css.crow}"> |
|
|
|
|
<div id="selectExEnv" class="${css.col1_1}"> |
|
|
|
|
Environment |
|
|
|
|
</div> |
|
|
|
|
<div class=${css.environment}> |
|
|
|
|
${this.netUI} |
|
|
|
|
<select id="selectExEnvOptions" onchange=${() => { this.updateNetwork() }} class="${css.select}"> |
|
|
|
|
<option id="vm-mode" |
|
|
|
|
title="Execution environment does not connect to any node, everything is local and in memory only." |
|
|
|
|
value="vm" checked name="executionContext"> JavaScript VM |
|
|
|
|
</option> |
|
|
|
|
<option id="injected-mode" |
|
|
|
|
title="Execution environment has been provided by Metamask or similar provider." |
|
|
|
|
value="injected" checked name="executionContext"> Injected Web3 |
|
|
|
|
</option> |
|
|
|
|
<option id="web3-mode" |
|
|
|
|
title="Execution environment connects to node at localhost (or via IPC if available), transactions will be sent to the network and can cause loss of money or worse! |
|
|
|
|
If this page is served via https and you access your node via http, it might not work. In this case, try cloning the repository and serving it via http." |
|
|
|
|
value="web3" name="executionContext"> Web3 Provider |
|
|
|
|
</option> |
|
|
|
|
</select> |
|
|
|
|
<a href="https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md" target="_blank"><i class="${css.icon} fa fa-info"></i></a> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
<div class=${css.environment}> |
|
|
|
|
${net} |
|
|
|
|
<select id="selectExEnvOptions" onchange=${() => { updateNetwork() }} class="${css.select}"> |
|
|
|
|
<option id="vm-mode" |
|
|
|
|
title="Execution environment does not connect to any node, everything is local and in memory only." |
|
|
|
|
value="vm" checked name="executionContext"> JavaScript VM |
|
|
|
|
</option> |
|
|
|
|
<option id="injected-mode" |
|
|
|
|
title="Execution environment has been provided by Metamask or similar provider." |
|
|
|
|
value="injected" checked name="executionContext"> Injected Web3 |
|
|
|
|
</option> |
|
|
|
|
<option id="web3-mode" |
|
|
|
|
title="Execution environment connects to node at localhost (or via IPC if available), transactions will be sent to the network and can cause loss of money or worse! |
|
|
|
|
If this page is served via https and you access your node via http, it might not work. In this case, try cloning the repository and serving it via http." |
|
|
|
|
value="web3" name="executionContext"> Web3 Provider |
|
|
|
|
</option> |
|
|
|
|
</select> |
|
|
|
|
<a href="https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md" target="_blank"><i class="${css.icon} fa fa-info"></i></a> |
|
|
|
|
` |
|
|
|
|
|
|
|
|
|
var accountEl = yo` |
|
|
|
|
<div class="${css.crow}"> |
|
|
|
|
<div class="${css.col1_1}"> |
|
|
|
|
Account |
|
|
|
|
<i class="fa fa-plus-circle ${css.icon}" aria-hidden="true" onclick=${this.newAccount.bind(this)} title="Create a new account"></i> |
|
|
|
|
</div> |
|
|
|
|
<div class=${css.account}> |
|
|
|
|
<select name="txorigin" class="${css.select}" id="txorigin"></select> |
|
|
|
|
${copyToClipboard(() => document.querySelector('#runTabView #txorigin').value)} |
|
|
|
|
<i class="fa fa-pencil-square-o ${css.icon}" aria-hiden="true" onclick=${this.signMessage.bind(this)} title="Sign a message using this account key"></i> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
` |
|
|
|
|
var accountEl = yo` |
|
|
|
|
<div class="${css.crow}"> |
|
|
|
|
<div class="${css.col1_1}"> |
|
|
|
|
Account |
|
|
|
|
<i class="fa fa-plus-circle ${css.icon}" aria-hidden="true" onclick=${newAccount} title="Create a new account"></i> |
|
|
|
|
` |
|
|
|
|
|
|
|
|
|
var gasPriceEl = yo` |
|
|
|
|
<div class="${css.crow}"> |
|
|
|
|
<div class="${css.col1_1}">Gas limit</div> |
|
|
|
|
<input type="number" class="${css.col2}" id="gasLimit" value="3000000"> |
|
|
|
|
</div> |
|
|
|
|
<div class=${css.account}> |
|
|
|
|
<select name="txorigin" class="${css.select}" id="txorigin"></select> |
|
|
|
|
${copyToClipboard(() => document.querySelector('#runTabView #txorigin').value)} |
|
|
|
|
<i class="fa fa-pencil-square-o ${css.icon}" aria-hiden="true" onclick=${signMessage} title="Sign a message using this account key"></i> |
|
|
|
|
` |
|
|
|
|
|
|
|
|
|
var valueEl = yo` |
|
|
|
|
<div class="${css.crow}"> |
|
|
|
|
<div class="${css.col1_1}">Value</div> |
|
|
|
|
<input type="text" class="${css.col2_1}" id="value" value="0" title="Enter the value and choose the unit"> |
|
|
|
|
<select name="unit" class="${css.col2_2}" id="unit"> |
|
|
|
|
<option data-unit="wei">wei</option> |
|
|
|
|
<option data-unit="gwei">gwei</option> |
|
|
|
|
<option data-unit="finney">finney</option> |
|
|
|
|
<option data-unit="ether">ether</option> |
|
|
|
|
</select> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
` |
|
|
|
|
var gasPriceEl = yo` |
|
|
|
|
<div class="${css.crow}"> |
|
|
|
|
<div class="${css.col1_1}">Gas limit</div> |
|
|
|
|
<input type="number" class="${css.col2}" id="gasLimit" value="3000000"> |
|
|
|
|
</div> |
|
|
|
|
` |
|
|
|
|
var valueEl = yo` |
|
|
|
|
<div class="${css.crow}"> |
|
|
|
|
<div class="${css.col1_1}">Value</div> |
|
|
|
|
<input type="text" class="${css.col2_1}" id="value" value="0" title="Enter the value and choose the unit"> |
|
|
|
|
<select name="unit" class="${css.col2_2}" id="unit"> |
|
|
|
|
<option data-unit="wei">wei</option> |
|
|
|
|
<option data-unit="gwei">gwei</option> |
|
|
|
|
<option data-unit="finney">finney</option> |
|
|
|
|
<option data-unit="ether">ether</option> |
|
|
|
|
</select> |
|
|
|
|
</div> |
|
|
|
|
` |
|
|
|
|
// DOM ELEMENT
|
|
|
|
|
var el = yo` |
|
|
|
|
<div class="${css.settings}"> |
|
|
|
|
${environmentEl} |
|
|
|
|
${accountEl} |
|
|
|
|
${gasPriceEl} |
|
|
|
|
${valueEl} |
|
|
|
|
</div> |
|
|
|
|
` |
|
|
|
|
// HELPER FUNCTIONS AND EVENTS
|
|
|
|
|
self._deps.udapp.event.register('transactionExecuted', (error, from, to, data, lookupOnly, txResult) => { |
|
|
|
|
if (error) return |
|
|
|
|
if (!lookupOnly) el.querySelector('#value').value = '0' |
|
|
|
|
updateAccountBalances(container, self) |
|
|
|
|
}) |
|
|
|
|
` |
|
|
|
|
|
|
|
|
|
// DROPDOWN
|
|
|
|
|
var selectExEnv = environmentEl.querySelector('#selectExEnvOptions') |
|
|
|
|
// DOM ELEMENT
|
|
|
|
|
var el = yo` |
|
|
|
|
<div class="${css.settings}"> |
|
|
|
|
${environmentEl} |
|
|
|
|
${accountEl} |
|
|
|
|
${gasPriceEl} |
|
|
|
|
${valueEl} |
|
|
|
|
</div> |
|
|
|
|
` |
|
|
|
|
|
|
|
|
|
function setFinalContext () { |
|
|
|
|
// set the final context. Cause it is possible that this is not the one we've originaly selected
|
|
|
|
|
selectExEnv.value = executionContext.getProvider() |
|
|
|
|
self.event.trigger('clearInstance', []) |
|
|
|
|
updateNetwork() |
|
|
|
|
fillAccountsList(el, self) |
|
|
|
|
} |
|
|
|
|
// DROPDOWN
|
|
|
|
|
var selectExEnv = environmentEl.querySelector('#selectExEnvOptions') |
|
|
|
|
this.selectExEnv = selectExEnv |
|
|
|
|
|
|
|
|
|
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) |
|
|
|
|
}) |
|
|
|
|
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) |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
executionContext.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`) |
|
|
|
|
}) |
|
|
|
|
executionContext.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`) |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
executionContext.event.register('removeProvider', (name) => { |
|
|
|
|
var env = selectExEnv.querySelector(`option[value="${name}"]`) |
|
|
|
|
if (env) { |
|
|
|
|
selectExEnv.removeChild(env) |
|
|
|
|
tootip(`${name} removed`) |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
executionContext.event.register('removeProvider', (name) => { |
|
|
|
|
var env = selectExEnv.querySelector(`option[value="${name}"]`) |
|
|
|
|
if (env) { |
|
|
|
|
selectExEnv.removeChild(env) |
|
|
|
|
tootip(`${name} removed`) |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
selectExEnv.addEventListener('change', function (event) { |
|
|
|
|
let context = selectExEnv.options[selectExEnv.selectedIndex].value |
|
|
|
|
executionContext.executionContextChange(context, null, () => { |
|
|
|
|
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) => { |
|
|
|
|
if (alertMsg) { |
|
|
|
|
modalDialogCustom.alert(alertMsg) |
|
|
|
|
} |
|
|
|
|
setFinalContext() |
|
|
|
|
}) |
|
|
|
|
}, setFinalContext) |
|
|
|
|
}, setFinalContext) |
|
|
|
|
}, (alertMsg) => { |
|
|
|
|
modalDialogCustom.alert(alertMsg) |
|
|
|
|
}, setFinalContext) |
|
|
|
|
}) |
|
|
|
|
selectExEnv.addEventListener('change', (event) => { |
|
|
|
|
let context = selectExEnv.options[selectExEnv.selectedIndex].value |
|
|
|
|
executionContext.executionContextChange(context, null, () => { |
|
|
|
|
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) => { |
|
|
|
|
if (alertMsg) { |
|
|
|
|
modalDialogCustom.alert(alertMsg) |
|
|
|
|
} |
|
|
|
|
this.setFinalContext() |
|
|
|
|
}) |
|
|
|
|
}, this.setFinalContext.bind(this)) |
|
|
|
|
}, this.setFinalContext.bind(this)) |
|
|
|
|
}, (alertMsg) => { |
|
|
|
|
modalDialogCustom.alert(alertMsg) |
|
|
|
|
}, this.setFinalContext.bind(this)) |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
selectExEnv.value = executionContext.getProvider() |
|
|
|
|
executionContext.event.register('contextChanged', (context, silent) => { |
|
|
|
|
setFinalContext() |
|
|
|
|
}) |
|
|
|
|
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) |
|
|
|
|
|
|
|
|
|
setInterval(() => { |
|
|
|
|
updateNetwork() |
|
|
|
|
fillAccountsList(el, self) |
|
|
|
|
}, 5000) |
|
|
|
|
this.el = el |
|
|
|
|
return el |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
setInterval(() => { |
|
|
|
|
updateAccountBalances(container, self) |
|
|
|
|
}, 10000) |
|
|
|
|
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.updateNetwork() |
|
|
|
|
fillAccountsList(this.el, this.parentSelf) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function newAccount () { |
|
|
|
|
self._deps.udapp.newAccount('', |
|
|
|
|
newAccount () { |
|
|
|
|
this.parentSelf._deps.udapp.newAccount('', |
|
|
|
|
(cb) => { |
|
|
|
|
modalCustom.promptPassphraseCreation((error, passphrase) => { |
|
|
|
|
if (error) { |
|
|
|
@ -190,11 +189,12 @@ function settings (container, self) { |
|
|
|
|
} |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
function signMessage (event) { |
|
|
|
|
self._deps.udapp.getAccounts((err, accounts) => { |
|
|
|
|
|
|
|
|
|
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 = container.querySelector('#txorigin') |
|
|
|
|
var $txOrigin = this.container.querySelector('#txorigin') |
|
|
|
|
var account = $txOrigin.selectedOptions[0].value |
|
|
|
|
var isVM = executionContext.isVM() |
|
|
|
|
var isInjected = executionContext.getProvider() === 'injected' |
|
|
|
@ -209,7 +209,7 @@ function settings (container, self) { |
|
|
|
|
if (isVM) { |
|
|
|
|
modalDialogCustom.promptMulti(signMessageDialog, (message) => { |
|
|
|
|
const personalMsg = ethJSUtil.hashPersonalMessage(Buffer.from(message)) |
|
|
|
|
var privKey = self._deps.udapp.accounts[account].privateKey |
|
|
|
|
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) |
|
|
|
@ -252,7 +252,27 @@ function settings (container, self) { |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return el |
|
|
|
|
// TODO: cb param doesn't seem to be used
|
|
|
|
|
updateNetwork (cb) { |
|
|
|
|
let self = this |
|
|
|
|
var networkcallid = 0 |
|
|
|
|
networkcallid++ |
|
|
|
|
(function (callid) { |
|
|
|
|
executionContext.detectNetwork((err, { id, name } = {}) => { |
|
|
|
|
if (networkcallid > callid) return |
|
|
|
|
networkcallid++ |
|
|
|
|
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 || '-'})` |
|
|
|
|
} |
|
|
|
|
// TODO: cb param doesn't seem to be used
|
|
|
|
|
if (cb) cb(err, {id, name}) |
|
|
|
|
}) |
|
|
|
|
})(networkcallid) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var accountListCallId = 0 |
|
|
|
@ -296,4 +316,4 @@ function updateAccountBalances (container, self) { |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
module.exports = settings |
|
|
|
|
module.exports = SettingsUI |
|
|
|
|