@ -43,149 +43,155 @@ TxRunner.prototype.rawRun = function (args, cb) {
run ( this , args , Date . now ( ) , cb )
}
TxRunner . prototype . execute = function ( args , callback ) {
var self = this
function execute ( gasPrice ) {
if ( gasPrice ) tx . gasPrice = executionContext . web3 ( ) . toHex ( gasPrice )
function executeTx ( tx , gasPrice , api , callback ) {
if ( gasPrice ) tx . gasPrice = executionContext . web3 ( ) . toHex ( gasPrice )
if ( self . _api . personalMode ( ) ) {
modal . promptPassphrase ( null , 'Personal mode is enabled. Please provide passphrase of account ' + tx . from , '' , ( value ) => {
sendTransaction ( executionContext . web3 ( ) . personal . sendTransaction , tx , value , callback )
} , ( ) => {
return callback ( 'Canceled by user.' )
} )
} else {
sendTransaction ( executionContext . web3 ( ) . eth . sendTransaction , tx , null , callback )
}
if ( api . personalMode ( ) ) {
modal . promptPassphrase ( null , 'Personal mode is enabled. Please provide passphrase of account ' + tx . from , '' , ( value ) => {
sendTransaction ( executionContext . web3 ( ) . personal . sendTransaction , tx , value , callback )
} , ( ) => {
return callback ( 'Canceled by user.' )
} )
} else {
sendTransaction ( executionContext . web3 ( ) . eth . sendTransaction , tx , null , callback )
}
}
TxRunner . prototype . execute = function ( args , callback ) {
var self = this
var from = args . from
var to = args . to
var data = args . data
if ( data . slice ( 0 , 2 ) !== '0x' ) {
data = '0x' + data
}
var value = args . value
var gasLimit = args . gasLimit
var tx
if ( ! executionContext . isVM ( ) ) {
tx = {
from : from ,
to : to ,
data : data ,
value : value
self . runInNode ( args . from , args . to , data , args . value , args . gasLimit , args . useCall , callback )
} else {
self . runInVm ( args . from , args . to , data , args . value , args . gasLimit , args . useCall , callback )
}
}
TxRunner . prototype . runInVm = function ( from , to , data , value , gasLimit , useCall , callback ) {
const self = this
try {
var account = self . vmaccounts [ from ]
if ( ! account ) {
return callback ( 'Invalid account selected' )
}
var tx = new EthJSTX ( {
nonce : new BN ( account . nonce ++ ) ,
gasPrice : new BN ( 1 ) ,
gasLimit : new BN ( gasLimit , 10 ) ,
to : to ,
value : new BN ( value , 10 ) ,
data : new Buffer ( data . slice ( 2 ) , 'hex' )
} )
tx . sign ( account . privateKey )
if ( args . useCall ) {
tx . gas = gasLimit
executionContext . web3 ( ) . eth . call ( tx , function ( error , result ) {
callback ( error , {
result : result ,
transactionHash : result . transactionHash
} )
} )
const coinbases = [ '0x0e9281e9c6a0808672eaba6bd1220e144c9bb07a' , '0x8945a1288dc78a6d8952a92c77aee6730b414778' , '0x94d76e24f818426ae84aa404140e8d5f60e10e7e' ]
const difficulties = [ new BN ( '69762765929000' , 10 ) , new BN ( '70762765929000' , 10 ) , new BN ( '71762765929000' , 10 ) ]
var block = new EthJSBlock ( {
header : {
timestamp : new Date ( ) . getTime ( ) / 1000 | 0 ,
number : self . blockNumber ,
coinbase : coinbases [ self . blockNumber % coinbases . length ] ,
difficulty : difficulties [ self . blockNumber % difficulties . length ] ,
gasLimit : new BN ( gasLimit , 10 ) . imuln ( 2 )
} ,
transactions : [ ] ,
uncleHeaders : [ ]
} )
if ( ! useCall ) {
++ self . blockNumber
} else {
executionContext . web3 ( ) . eth . estimateGas ( tx , function ( err , gasEstimation ) {
if ( err ) {
return callback ( err , gasEstimation )
}
var blockGasLimit = executionContext . currentblockGasLimit ( )
// NOTE: estimateGas very likely will return a large limit if execution of the code failed
// we want to be able to run the code in order to debug and find the cause for the failure
executionContext . vm ( ) . stateManager . checkpoint ( )
}
var warnEstimation = " An important gas estimation might also be the sign of a problem in the contract code. Please check loops and be sure you did not sent value to a non payable function (that's also the reason of strong gas estimation)."
if ( gasEstimation > gasLimit ) {
return callback ( 'Gas required exceeds limit: ' + gasLimit + '. ' + warnEstimation )
}
if ( gasEstimation > blockGasLimit ) {
return callback ( 'Gas required exceeds block gas limit: ' + gasLimit + '. ' + warnEstimation )
}
executionContext . vm ( ) . runTx ( { block : block , tx : tx , skipBalance : true , skipNonce : true } , function ( err , result ) {
if ( useCall ) {
executionContext . vm ( ) . stateManager . revert ( function ( ) { } )
}
err = err ? err . message : err
result . status = '0x' + result . vm . exception . toString ( 16 )
callback ( err , {
result : result ,
transactionHash : ethJSUtil . bufferToHex ( new Buffer ( tx . hash ( ) ) )
} )
} )
} catch ( e ) {
callback ( e , null )
}
}
tx . gas = gasEstimation
TxRunner . prototype . runInNode = function ( from , to , data , value , gasLimit , useCall , callback ) {
const self = this
var tx = {
from : from ,
to : to ,
data : data ,
value : value
}
if ( ! self . _api . config . getUnpersistedProperty ( 'doNotShowTransactionConfirmationAgain' ) ) {
self . _api . detectNetwork ( ( err , network ) => {
if ( err ) {
console . log ( err )
} else {
if ( network . name === 'Main' ) {
var content = confirmDialog ( tx , gasEstimation , self )
modalDialog ( 'Confirm transaction' , content ,
{ label : 'Confirm' ,
fn : ( ) => {
self . _api . config . setUnpersistedProperty ( 'doNotShowTransactionConfirmationAgain' , content . querySelector ( 'input#confirmsetting' ) . checked )
if ( ! content . gasPriceStatus ) {
callback ( 'Given gas grice is not correct' )
} else {
var gasPrice = executionContext . web3 ( ) . toWei ( content . querySelector ( '#gasprice' ) . value , 'gwei' )
execute ( gasPrice )
}
} } , {
label : 'Cancel' ,
fn : ( ) => {
return callback ( 'Transaction canceled by user.' )
}
} )
} else {
execute ( )
}
}
} )
} else {
execute ( )
}
if ( useCall ) {
tx . gas = gasLimit
executionContext . web3 ( ) . eth . call ( tx , function ( error , result ) {
callback ( error , {
result : result ,
transactionHash : result . transactionHash
} )
}
} )
} else {
try {
var account = self . vmaccounts [ from ]
if ( ! account ) {
return callback ( 'Invalid account selected' )
executionContext . web3 ( ) . eth . estimateGas ( tx , function ( err , gasEstimation ) {
if ( err ) {
return callback ( err , gasEstimation )
}
tx = new EthJSTX ( {
nonce : new BN ( account . nonce ++ ) ,
gasPrice : new BN ( 1 ) ,
gasLimit : new BN ( gasLimit , 10 ) ,
to : to ,
value : new BN ( value , 10 ) ,
data : new Buffer ( data . slice ( 2 ) , 'hex' )
} )
tx . sign ( account . privateKey )
var blockGasLimit = executionContext . currentblockGasLimit ( )
// NOTE: estimateGas very likely will return a large limit if execution of the code failed
// we want to be able to run the code in order to debug and find the cause for the failure
const coinbases = [ '0x0e9281e9c6a0808672eaba6bd1220e144c9bb07a' , '0x8945a1288dc78a6d8952a92c77aee6730b414778' , '0x94d76e24f818426ae84aa404140e8d5f60e10e7e' ]
const difficulties = [ new BN ( '69762765929000' , 10 ) , new BN ( '70762765929000' , 10 ) , new BN ( '71762765929000' , 10 ) ]
var block = new EthJSBlock ( {
header : {
timestamp : new Date ( ) . getTime ( ) / 1000 | 0 ,
number : self . blockNumber ,
coinbase : coinbases [ self . blockNumber % coinbases . length ] ,
difficulty : difficulties [ self . blockNumber % difficulties . length ] ,
gasLimit : new BN ( gasLimit , 10 ) . imuln ( 2 )
} ,
transactions : [ ] ,
uncleHeaders : [ ]
} )
if ( ! args . useCall ) {
++ self . blockNumber
} else {
executionContext . vm ( ) . stateManager . checkpoint ( )
var warnEstimation = " An important gas estimation might also be the sign of a problem in the contract code. Please check loops and be sure you did not sent value to a non payable function (that's also the reason of strong gas estimation)."
if ( gasEstimation > gasLimit ) {
return callback ( 'Gas required exceeds limit: ' + gasLimit + '. ' + warnEstimation )
}
if ( gasEstimation > blockGasLimit ) {
return callback ( 'Gas required exceeds block gas limit: ' + gasLimit + '. ' + warnEstimation )
}
tx . gas = gasEstimation
executionContext . vm ( ) . runTx ( { block : block , tx : tx , skipBalance : true , skipNonce : true } , function ( err , result ) {
if ( args . useCall ) {
executionContext . vm ( ) . stateManager . revert ( function ( ) { } )
}
err = err ? err . message : err
result . status = '0x' + result . vm . exception . toString ( 16 )
callback ( err , {
result : result ,
transactionHash : ethJSUtil . bufferToHex ( new Buffer ( tx . hash ( ) ) )
if ( ! self . _api . config . getUnpersistedProperty ( 'doNotShowTransactionConfirmationAgain' ) ) {
self . _api . detectNetwork ( ( err , network ) => {
if ( err ) {
console . log ( err )
} else {
if ( network . name === 'Main' ) {
var content = confirmDialog ( tx , gasEstimation , self )
modalDialog ( 'Confirm transaction' , content ,
{ label : 'Confirm' ,
fn : ( ) => {
self . _api . config . setUnpersistedProperty ( 'doNotShowTransactionConfirmationAgain' , content . querySelector ( 'input#confirmsetting' ) . checked )
if ( ! content . gasPriceStatus ) {
callback ( 'Given gas grice is not correct' )
} else {
var gasPrice = executionContext . web3 ( ) . toWei ( content . querySelector ( '#gasprice' ) . value , 'gwei' )
executeTx ( tx , gasPrice , self . _api , callback )
}
} } , {
label : 'Cancel' ,
fn : ( ) => {
return callback ( 'Transaction canceled by user.' )
}
} )
} else {
executeTx ( tx , null , self . _api , callback )
}
}
} )
} )
} catch ( e ) {
callback ( e , null )
}
} else {
executeTx ( tx , null , self . _api , callback )
}
} )
}
}