@ -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 {
< / d i v >
`
// DOM ELEMENT
var el = yo `
< div class = "${css.settings}" >
$ { environmentEl }
@ -98,40 +112,47 @@ class SettingsUI {
< / d i v >
`
// 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 }
< / o p t i o n > ` )
tootip ( ` ${ network . name } [ ${ network . url } ] added ` )
addTool tip( ` ${ 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 ` )
addTool tip( ` ${ 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 modalDialog Custom . 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 ) {
var promptCb = ( passphrase ) => {
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 ) => {
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 ++
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 || '-' } ) `
}
} )
} ) ( networkcallid )
this . settings . updateNetwork ( ( err , { id , name } = { } ) => {
if ( err ) {
this . netUI . innerHTML = 'can\'t detect network '
return
}
this . netUI . innerHTML = ` <i class=" ${ css . networkItem } fa fa-plug" aria-hidden="true"></i> ${ name } ( ${ id || '-' } ) `
} )
}
}
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