@ -20,6 +20,7 @@
* Ethereum IDE client .
* Ethereum IDE client .
* /
* /
Qt . include ( "QEtherHelper.js" )
Qt . include ( "QEtherHelper.js" )
Qt . include ( "TransactionHelper.js" )
var htmlTemplate = "<html>\n<head>\n<script>\n</script>\n</head>\n<body>\n<script>\n</script>\n</body>\n</html>" ;
var htmlTemplate = "<html>\n<head>\n<script>\n</script>\n</head>\n<body>\n<script>\n</script>\n</body>\n</html>" ;
var contractTemplate = "contract Contract {\n}\n" ;
var contractTemplate = "contract Contract {\n}\n" ;
@ -50,7 +51,8 @@ function saveProject() {
applicationUrlEth : deploymentDialog . applicationUrlEth ,
applicationUrlEth : deploymentDialog . applicationUrlEth ,
applicationUrlHttp : deploymentDialog . applicationUrlHttp ,
applicationUrlHttp : deploymentDialog . applicationUrlHttp ,
packageHash : deploymentDialog . packageHash ,
packageHash : deploymentDialog . packageHash ,
packageBase64 : deploymentDialog . packageBase64
packageBase64 : deploymentDialog . packageBase64 ,
deploymentDir : projectModel . deploymentDir
} ;
} ;
for ( var i = 0 ; i < projectListModel . count ; i ++ )
for ( var i = 0 ; i < projectListModel . count ; i ++ )
projectData . files . push ( projectListModel . get ( i ) . fileName )
projectData . files . push ( projectListModel . get ( i ) . fileName )
@ -68,6 +70,8 @@ function loadProject(path) {
var projectFile = path + projectFileName ;
var projectFile = path + projectFileName ;
var json = fileIo . readFile ( projectFile ) ;
var json = fileIo . readFile ( projectFile ) ;
var projectData = JSON . parse ( json ) ;
var projectData = JSON . parse ( json ) ;
if ( projectData . deploymentDir )
projectModel . deploymentDir = projectData . deploymentDir
if ( projectData . packageHash )
if ( projectData . packageHash )
deploymentDialog . packageHash = projectData . packageHash
deploymentDialog . packageHash = projectData . packageHash
if ( projectData . packageBase64 )
if ( projectData . packageBase64 )
@ -303,49 +307,61 @@ function startDeployProject(erasePrevious)
console . log ( "Deploying " + deploymentId + " to " + jsonRpcUrl ) ;
console . log ( "Deploying " + deploymentId + " to " + jsonRpcUrl ) ;
deploymentStarted ( ) ;
deploymentStarted ( ) ;
var requests = [ ] ;
var ctrNames = Object . keys ( codeModel . contracts ) ;
var requestNames = [ ] ;
var ctrAddresses = { } ;
setDefaultBlock ( 0 , function ( ) {
deployContracts ( 0 , ctrAddresses , ctrNames , function ( ) {
finalizeDeployment ( deploymentId , ctrAddresses ) ;
} ) ;
} ) ;
}
for ( var c in codeModel . contracts ) { //TODO: order based on dependencies
function setDefaultBlock ( val , callBack )
var code = codeModel . contracts [ c ] . codeHex ;
{
requests . push ( {
var requests = [ {
jsonrpc : "2.0" ,
jsonrpc : "2.0" ,
method : "eth_transact" ,
method : "eth_setDefaultBlock" ,
params : [ { "code" : code } ] ,
params : [ val ] ,
id : jsonRpcRequestId ++
id : 0
} ] ;
rpcCall ( requests , function ( httpCall , response ) {
callBack ( ) ;
} ) ;
} ) ;
requestNames . push ( c ) ;
}
}
var rpcRequest = JSON . stringify ( requests ) ;
function deployContracts ( ctrIndex , ctrAddresses , ctrNames , callBack )
var httpRequest = new XMLHttpRequest ( ) ;
{
httpRequest . open ( "POST" , jsonRpcUrl , true ) ;
var code = codeModel . contracts [ ctrNames [ ctrIndex ] ] . codeHex ;
httpRequest . setRequestHeader ( "Content-type" , "application/json" ) ;
var requests = [ {
httpRequest . setRequestHeader ( "Content-length" , rpcRequest . length ) ;
jsonrpc : "2.0" ,
httpRequest . setRequestHeader ( "Connection" , "close" ) ;
method : "eth_transact" ,
httpRequest . onreadystatechange = function ( ) {
params : [ { "from" : deploymentDialog . currentAccount , "gas" : deploymentDialog . gasToUse , "code" : code } ] ,
if ( httpRequest . readyState === XMLHttpRequest . DONE ) {
id : 0
if ( httpRequest . status === 200 ) {
} ] ;
var rpcResponse = JSON . parse ( httpRequest . responseText ) ;
rpcCall ( requests , function ( httpCall , response ) {
if ( rpcResponse . length === requestNames . length ) {
var txt = qsTr ( "Please wait while " + ctrNames [ ctrIndex ] + " is published ..." )
var contractAddresses = { } ;
deploymentStepChanged ( txt ) ;
for ( var r = 0 ; r < rpcResponse . length ; r ++ )
console . log ( txt ) ;
contractAddresses [ requestNames [ r ] ] = rpcResponse [ r ] . result ;
ctrAddresses [ ctrNames [ ctrIndex ] ] = JSON . parse ( response ) [ 0 ] . result
finalizeDeployment ( deploymentId , contractAddresses ) ;
deploymentDialog . waitForTrCountToIncrement ( function ( status ) {
}
if ( status === - 1 )
} else {
{
var errorText = qsTr ( "Deployment error: RPC server HTTP status " ) + httpRequest . status ;
trCountIncrementTimeOut ( ) ;
console . log ( errorText ) ;
return ;
deploymentError ( errorText ) ;
}
}
}
}
httpRequest . send ( rpcRequest ) ;
ctrIndex ++ ;
if ( ctrIndex < ctrNames . length )
deployContracts ( ctrIndex , ctrAddresses , ctrNames , callBack ) ;
else
callBack ( ) ;
} ) ;
} ) ;
}
}
function finalizeDeployment ( deploymentId , addresses ) {
function finalizeDeployment ( deploymentId , addresses ) {
deploymentStepChanged ( qsTr ( "Packaging application ..." ) ) ;
deploymentStepChanged ( qsTr ( "Packaging application ..." ) ) ;
var deploymentDir = projectPath + deploymentId + "/" ;
var deploymentDir = projectPath + deploymentId + "/" ;
projectModel . deploymentDir = deploymentDir ;
fileIo . makeDir ( deploymentDir ) ;
fileIo . makeDir ( deploymentDir ) ;
for ( var i = 0 ; i < projectListModel . count ; i ++ ) {
for ( var i = 0 ; i < projectListModel . count ; i ++ ) {
var doc = projectListModel . get ( i ) ;
var doc = projectListModel . get ( i ) ;
@ -395,138 +411,171 @@ function finalizeDeployment(deploymentId, addresses) {
deploymentDialog . packageBase64 = packageRet [ 1 ] ;
deploymentDialog . packageBase64 = packageRet [ 1 ] ;
var applicationUrlEth = deploymentDialog . applicationUrlEth ;
var applicationUrlEth = deploymentDialog . applicationUrlEth ;
applicationUrlEth = formatAppUrl ( applicationUrlEth ) ;
applicationUrlEth = formatAppUrl ( applicationUrlEth ) ;
deploymentStepChanged ( qsTr ( "Registering application on the Ethereum network ..." ) ) ;
deploymentStepChanged ( qsTr ( "Registering application on the Ethereum network ..." ) ) ;
checkRegistration ( applicationUrlEth , deploymentDialog . e th , function ( ) {
checkEthPath ( applicationUrlEth , function ( ) {
deploymentComplete ( ) ;
deploymentComplete ( ) ;
deployRessourcesDialog . text = qsTr ( "Register Web Application to finalize deployment." ) ;
deployRessourcesDialog . text = qsTr ( "Register Web Application to finalize deployment." ) ;
deployRessourcesDialog . open ( ) ;
deployRessourcesDialog . open ( ) ;
setDefaultBlock ( - 1 , function ( ) { } ) ;
} ) ;
} ) ;
}
}
function rpcCall ( requests , callBack )
function checkEthPath ( dappUrl , callBack )
{
var jsonRpcUrl = "http://localhost:8080" ;
var rpcRequest = JSON . stringify ( requests ) ;
var httpRequest = new XMLHttpRequest ( ) ;
httpRequest . open ( "POST" , jsonRpcUrl , true ) ;
httpRequest . setRequestHeader ( "Content-type" , "application/json" ) ;
httpRequest . setRequestHeader ( "Content-length" , rpcRequest . length ) ;
httpRequest . setRequestHeader ( "Connection" , "close" ) ;
httpRequest . onreadystatechange = function ( ) {
if ( httpRequest . readyState === XMLHttpRequest . DONE ) {
if ( httpRequest . status !== 200 )
{
var errorText = qsTr ( "Deployment error: Error while registering Dapp " ) + httpRequest . status ;
console . log ( errorText ) ;
deploymentError ( errorText ) ;
return ;
}
callBack ( httpRequest . status , httpRequest . responseText )
}
}
httpRequest . send ( rpcRequest ) ;
}
function checkRegistration ( dappUrl , addr , callBack )
{
{
var requests = [ ] ;
if ( dappUrl . length === 1 )
var data = "" ;
registerContentHash ( deploymentDialog . eth , callBack ) ; // we directly create a dapp under the root registrar.
if ( dappUrl . length > 0 )
else
{
{
//checking path (register) .
// the first owned reigstrar must have been created to follow the path.
var str = createString ( dappUrl [ 0 ] ) ;
var str = createString ( dappUrl [ 0 ] ) ;
data = "0x6be16bed" + str . encodeValueAsString ( ) ;
var requests = [ ] ;
console . log ( "checking if path exists (register) => " + JSON . stringify ( dappUrl ) ) ;
requests . push ( {
requests . push ( {
//register()
jsonrpc : "2.0" ,
jsonrpc : "2.0" ,
method : "eth_call" ,
method : "eth_call" ,
params : [ { "to" : '0x' + addr , "data" : data } ] ,
params : [ { "from" : deploymentDialog . currentAccount , "to" : '0x' + deploymentDialog . eth , "data" : "0x6be16bed" + str . encodeValueAsString ( ) } ] ,
id : jsonRpcRequestId ++
id : jsonRpcRequestId ++
} ) ;
} ) ;
rpcCall ( requests , function ( httpRequest , response ) {
rpcCall ( requests , function ( httpRequest , response ) {
var address = JSON . parse ( response ) [ 0 ] . result . replace ( '0x' , '' ) ;
var res = JSON . parse ( response ) ;
if ( address === "" )
var addr = normalizeAddress ( res [ 0 ] . result ) ;
if ( addr . replace ( /0+/g , "" ) === "" )
{
{
var errorTxt = qsTr ( "Path does not exists " + JSON . stringify ( dappUrl ) + " cannot continue " ) ;
var errorTxt = qsTr ( "Path does not exists " + JSON . stringify ( dappUrl ) + ". Please register using Registration Dapp. Aborting." ) ;
deploymentError ( errorTxt ) ;
deploymentError ( errorTxt ) ;
console . log ( errorTxt ) ;
console . log ( errorTxt ) ;
return ;
}
}
else
{
dappUrl . splice ( 0 , 1 ) ;
dappUrl . splice ( 0 , 1 ) ;
checkRegistration ( dappUrl , address , callBack ) ;
checkRegistration ( dappUrl , addr , callBack ) ;
}
} ) ;
} ) ;
}
}
}
function checkRegistration ( dappUrl , addr , callBack )
{
if ( dappUrl . length === 1 )
registerContentHash ( addr , callBack ) ; // We do not create the register for the last part, just registering the content hash.
else
else
{
{
var paramTitle = createString ( projectModel . projectTitle ) ;
var txt = qsTr ( "Checking " + JSON . stringify ( dappUrl ) + " ... in registrar " + addr ) ;
deploymentStepChanged ( txt ) ;
console . log ( txt ) ;
var requests = [ ] ;
var registrar = { }
var str = createString ( dappUrl [ 0 ] ) ;
requests . push ( {
requests . push ( {
//owner()
//getO wner()
jsonrpc : "2.0" ,
jsonrpc : "2.0" ,
method : "eth_call" ,
method : "eth_call" ,
params : [ { "to" : '0x' + addr , "data" : "0xec7b9200" + paramTitle . encodeValueAsString ( ) } ] ,
params : [ { "from" : deploymentDialog . currentAccount , " to" : '0x' + addr , "data" : "0x893d20e8" } ] ,
id : jsonRpcRequestId ++
id : jsonRpcRequestId ++
} ) ;
} ) ;
requests . push ( {
requests . push ( {
//accounts
//register()
jsonrpc : "2.0" ,
jsonrpc : "2.0" ,
method : "eth_accounts " ,
method : "eth_call " ,
params : null ,
params : [ { "from" : deploymentDialog . currentAccount , "to" : '0x' + addr , "data" : "0x6be16bed" + str . encodeValueAsString ( ) } ] ,
id : jsonRpcRequestId ++
id : jsonRpcRequestId ++
} ) ;
} ) ;
rpcCall ( requests , function ( httpRequest , response ) {
rpcCall ( requests , function ( httpRequest , response ) {
requests = [ ] ;
var res = JSON . parse ( response ) ;
var res = JSON . parse ( response ) ;
var currentOwner = res [ 0 ] . result ;
var nextAddr = normalizeAddress ( res [ 1 ] . result ) ;
var noOwner = currentOwner . replace ( '0x' , '' ) . replace ( /0/g , '' ) === '' ;
var errorTxt ;
if ( res [ 1 ] . result === "0x" )
if ( noOwner )
{
{
errorTxt = qsTr ( "Error when creating new owned regsitrar. Please use the regsitration Dapp. Aborting" ) ;
deploymentError ( errorTxt ) ;
console . log ( errorTxt ) ;
}
else if ( normalizeAddress ( deploymentDialog . currentAccount ) !== normalizeAddress ( res [ 0 ] . result ) )
{
errorTxt = qsTr ( "You are not the owner of " + dappUrl [ 0 ] + ". Aborting" ) ;
deploymentError ( errorTxt ) ;
console . log ( errorTxt ) ;
}
else if ( nextAddr . replace ( /0+/g , "" ) !== "" )
{
dappUrl . splice ( 0 , 1 ) ;
checkRegistration ( dappUrl , nextAddr , callBack ) ;
}
else
{
var txt = qsTr ( "Registering sub domain " + dappUrl [ 0 ] + " ..." ) ;
console . log ( txt ) ;
deploymentStepChanged ( txt ) ;
//current registrar is owned => ownedregistrar creation and continue.
requests = [ ] ;
requests . push ( {
requests . push ( {
//reserve()
jsonrpc : "2.0" ,
jsonrpc : "2.0" ,
method : "eth_transact" ,
method : "eth_transact" ,
params : [ { "to" : '0x' + addr , "data" : "0x1c83171b" + paramTitle . encodeValueAsString ( ) } ] ,
params : [ { "from" : deploymentDialog . currentAccount , "gas" : 20000 , "code" : "0x60056013565b61059e8061001d6000396000f35b33600081905550560060003560e060020a90048063019848921461009a578063449c2090146100af5780635d574e32146100cd5780635fd4b08a146100e1578063618242da146100f65780636be16bed1461010b5780636c4489b414610129578063893d20e8146101585780639607730714610173578063c284bc2a14610187578063e50f599a14610198578063e5811b35146101af578063ec7b9200146101cd57005b6100a560043561031b565b8060005260206000f35b6100ba6004356103a0565b80600160a060020a031660005260206000f35b6100db600435602435610537565b60006000f35b6100ec600435610529565b8060005260206000f35b6101016004356103dd565b8060005260206000f35b6101166004356103bd565b80600160a060020a031660005260206000f35b61013460043561034b565b82600160a060020a031660005281600160a060020a03166020528060405260606000f35b610160610341565b80600160a060020a031660005260206000f35b6101816004356024356102b4565b60006000f35b6101926004356103fd565b60006000f35b6101a96004356024356044356101f2565b60006000f35b6101ba6004356101eb565b80600160a060020a031660005260206000f35b6101d8600435610530565b80600160a060020a031660005260206000f35b6000919050565b600054600160a060020a031633600160a060020a031614610212576102af565b8160026000858152602001908152602001600020819055508061023457610287565b81600160a060020a0316837f680ad70765443c2967675ab0fb91a46350c01c6df59bf9a41ff8a8dd097464ec60006000a3826001600084600160a060020a03168152602001908152602001600020819055505b827f18d67da0cd86808336a3aa8912f6ea70c5250f1a98b586d1017ef56fe199d4fc60006000a25b505050565b600054600160a060020a031633600160a060020a0316146102d457610317565b806002600084815260200190815260200160002060010181905550817f18d67da0cd86808336a3aa8912f6ea70c5250f1a98b586d1017ef56fe199d4fc60006000a25b5050565b60006001600083600160a060020a03168152602001908152602001600020549050919050565b6000600054905090565b6000600060006002600085815260200190815260200160002054925060026000858152602001908152602001600020600101549150600260008581526020019081526020016000206002015490509193909250565b600060026000838152602001908152602001600020549050919050565b600060026000838152602001908152602001600020600101549050919050565b600060026000838152602001908152602001600020600201549050919050565b600054600160a060020a031633600160a060020a03161461041d57610526565b80600160006002600085815260200190815260200160002054600160a060020a031681526020019081526020016000205414610458576104d2565b6002600082815260200190815260200160002054600160a060020a0316817f680ad70765443c2967675ab0fb91a46350c01c6df59bf9a41ff8a8dd097464ec60006000a36000600160006002600085815260200190815260200160002054600160a060020a03168152602001908152602001600020819055505b6002600082815260200190815260200160002060008101600090556001810160009055600281016000905550807f18d67da0cd86808336a3aa8912f6ea70c5250f1a98b586d1017ef56fe199d4fc60006000a25b50565b6000919050565b6000919050565b600054600160a060020a031633600160a060020a0316146105575761059a565b806002600084815260200190815260200160002060020181905550817f18d67da0cd86808336a3aa8912f6ea70c5250f1a98b586d1017ef56fe199d4fc60006000a25b505056" } ] ,
id : jsonRpcRequestId ++
id : jsonRpcRequestId ++
} ) ;
} ) ;
}
else
{
var bOwner = false ;
currentOwner = normalizeAddress ( currentOwner ) ;
for ( var u in res [ 1 ] . result )
{
if ( normalizeAddress ( res [ 1 ] . result [ u ] ) === currentOwner )
bOwner = true ;
}
if ( ! bOwner )
rpcCall ( requests , function ( httpRequest , response ) {
var newCtrAddress = normalizeAddress ( JSON . parse ( response ) [ 0 ] . result ) ;
requests = [ ] ;
var txt = qsTr ( "Please wait " + dappUrl [ 0 ] + " is registering ..." ) ;
deploymentStepChanged ( txt ) ;
console . log ( txt ) ;
deploymentDialog . waitForTrCountToIncrement ( function ( status ) {
if ( status === - 1 )
{
{
var errorTxt = qsTr ( "Current user is not the owner of this path. Cannot continue" )
trCountIncrementTimeOut ( ) ;
deploymentError ( errorTxt ) ;
console . log ( errorTxt ) ;
return ;
return ;
}
}
var crLevel = createString ( dappUrl [ 0 ] ) . encodeValueAsString ( ) ;
requests . push ( {
//setRegister()
jsonrpc : "2.0" ,
method : "eth_transact" ,
params : [ { "from" : deploymentDialog . currentAccount , "gas" : 2000 , "to" : '0x' + addr , "data" : "0x96077307" + crLevel + deploymentDialog . pad ( newCtrAddress ) } ] ,
id : jsonRpcRequestId ++
} ) ;
rpcCall ( requests , function ( request , response ) {
dappUrl . splice ( 0 , 1 ) ;
checkRegistration ( dappUrl , newCtrAddress , callBack ) ;
} ) ;
} ) ;
} ) ;
}
}
console . log ( "setContentHash" ) ;
} ) ;
}
}
function trCountIncrementTimeOut ( )
{
var error = qsTr ( "Something went wrong during the deployment. Please verify the amount of gas for this transaction and check your balance." )
console . log ( error ) ;
deploymentError ( error ) ;
}
function registerContentHash ( registrar , callBack )
{
var txt = qsTr ( "Finalizing Dapp registration ..." ) ;
deploymentStepChanged ( txt ) ;
console . log ( txt ) ;
var requests = [ ] ;
var paramTitle = createString ( projectModel . projectTitle ) ;
requests . push ( {
requests . push ( {
//setContent()
//setContent()
jsonrpc : "2.0" ,
jsonrpc : "2.0" ,
method : "eth_transact" ,
method : "eth_transact" ,
params : [ { "to" : '0x' + addr , "data" : "0x5d574e32" + paramTitle . encodeValueAsString ( ) + deploymentDialog . packageHash } ] ,
params : [ { "from" : deploymentDialog . currentAccount , "gas" : 2000 , "gasPrice" : "10" , " to" : '0x' + registr ar, "data" : "0x5d574e32" + paramTitle . encodeValueAsString ( ) + deploymentDialog . packageHash } ] ,
id : jsonRpcRequestId ++
id : jsonRpcRequestId ++
} ) ;
} ) ;
rpcCall ( requests , function ( httpRequest , response ) {
rpcCall ( requests , function ( httpRequest , response ) {
callBack ( ) ;
callBack ( ) ;
} ) ;
} ) ;
} ) ;
}
}
}
function registerToUrlHint ( )
function registerToUrlHint ( )
@ -538,7 +587,7 @@ function registerToUrlHint()
//urlHint => suggestUrl
//urlHint => suggestUrl
jsonrpc : "2.0" ,
jsonrpc : "2.0" ,
method : "eth_transact" ,
method : "eth_transact" ,
params : [ { "to" : '0x' + deploymentDialog . urlHintContract , "data" : "0x4983e19c" + deploymentDialog . packageHash + paramUrlHttp . encodeValueAsString ( ) } ] ,
params : [ { "to" : '0x' + deploymentDialog . urlHintContract , "gas" : 2000 , "data" : "0x4983e19c" + deploymentDialog . packageHash + paramUrlHttp . encodeValueAsString ( ) } ] ,
id : jsonRpcRequestId ++
id : jsonRpcRequestId ++
} ) ;
} ) ;
@ -550,40 +599,35 @@ function registerToUrlHint()
function normalizeAddress ( addr )
function normalizeAddress ( addr )
{
{
addr = addr . replace ( '0x' , '' ) ;
addr = addr . replace ( '0x' , '' ) ;
var i = 0 ;
if ( addr . length <= 40 )
for ( var k in addr )
return addr ;
{
var left = addr . length - 40 ;
if ( addr [ k ] !== "0" )
return addr . substring ( left ) ;
break ;
else
i ++ ;
}
return addr . substring ( i ) ;
}
}
function formatAppUrl ( url )
function formatAppUrl ( url )
{
{
var slash = url . indexOf ( "/" ) ;
if ( url . toLowerCase ( ) . indexOf ( "eth://" ) === 0 )
var dot = url . indexOf ( "." ) ;
url = url . substring ( 6 ) ;
if ( slash === - 1 && dot === - 1 )
if ( url === "" )
return url ;
return [ projectModel . projectTitle ] ;
if ( ( slash !== - 1 && slash < dot ) || dot === - 1 )
return url . split ( "/" ) ;
var ret ;
if ( url . indexOf ( "/" ) === - 1 )
ret = url . split ( '.' ) . reverse ( ) ;
else
else
{
{
var dotted ;
var slash = url . indexOf ( "/" ) ;
var ret = [ ] ;
var left = url . substring ( 0 , slash ) ;
if ( slash !== - 1 )
var leftA = left . split ( "." ) ;
{
leftA . reverse ( ) ;
ret . push ( url . split ( "/" ) ) ;
dotted = ret [ 0 ] . split ( "." ) ;
}
else
dotted = url . split ( "." ) ;
for ( var k in dotted )
var right = url . substring ( slash + 1 ) ;
ret . unshift ( dotted [ k ] ) ;
var rightA = right . split ( '/' ) ;
return ret ;
ret = leftA . concat ( rightA ) ;
}
}
if ( ret [ 0 ] . toLowerCase ( ) === "eth" )
ret . splice ( 0 , 1 ) ;
ret . push ( projectModel . projectTitle ) ;
return ret ;
}
}