2017-03-29 15:37:30 +00:00
let async = require ( 'async' ) ;
2018-01-05 20:10:47 +00:00
//require("../utils/debug_util.js")(__filename, async);
2017-03-29 15:37:30 +00:00
let Deploy = require ( './deploy.js' ) ;
2017-12-21 16:21:36 +00:00
let RunCode = require ( '../core/runCode.js' ) ;
2017-03-01 01:42:03 +00:00
2017-03-30 11:12:39 +00:00
class DeployManager {
constructor ( options ) {
this . config = options . config ;
this . logger = options . logger ;
this . blockchainConfig = this . config . blockchainConfig ;
2017-12-21 16:21:36 +00:00
2017-03-31 11:34:43 +00:00
this . events = options . events ;
2017-03-30 11:12:39 +00:00
this . plugins = options . plugins ;
2018-05-18 22:31:47 +00:00
this . blockchain = options . blockchain ;
this . web3 = this . blockchain . web3 ;
2017-03-30 11:12:39 +00:00
this . chainConfig = ( options . trackContracts !== false ) ? this . config . chainTracker : false ;
2018-02-21 23:43:34 +00:00
this . contractsManager = options . contractsManager ;
2018-01-13 16:38:10 +00:00
this . gasLimit = false ;
this . fatalErrors = false ;
2018-03-11 12:28:03 +00:00
this . deployOnlyOnConfig = false ;
2018-03-22 19:09:01 +00:00
this . onlyCompile = options . onlyCompile !== undefined ? options . onlyCompile : false ;
2017-03-01 01:42:03 +00:00
}
2017-03-30 11:12:39 +00:00
deployContracts ( done ) {
let self = this ;
if ( self . blockchainConfig === { } || self . blockchainConfig . enabled === false ) {
2018-05-08 21:49:46 +00:00
self . logger . info ( _ _ ( "Blockchain component is disabled in the config" ) . underline ) ;
2017-03-31 11:34:43 +00:00
this . events . emit ( 'blockchainDisabled' , { } ) ;
2017-03-30 11:12:39 +00:00
return done ( ) ;
2017-03-11 15:29:45 +00:00
}
2017-03-30 11:12:39 +00:00
async . waterfall ( [
function buildContracts ( callback ) {
2018-03-11 12:28:03 +00:00
self . contractsManager . deployOnlyOnConfig = self . deployOnlyOnConfig ; // temporary, should refactor
2018-02-21 23:43:34 +00:00
self . contractsManager . build ( callback ) ;
2017-03-30 11:12:39 +00:00
} ,
2018-03-22 19:09:01 +00:00
function checkCompileOnly ( contractsManager , callback ) {
if ( self . onlyCompile ) {
self . events . emit ( 'contractsDeployed' , contractsManager ) ;
return done ( ) ;
}
2018-04-13 18:54:46 +00:00
return callback ( null , contractsManager ) ;
2018-03-22 19:09:01 +00:00
} ,
2018-05-20 10:46:12 +00:00
// TODO: remove this
// instead it can make a request to check if it's connected to a node
2017-03-30 11:12:39 +00:00
function checkWeb3IsConnected ( contractsManager , callback ) {
if ( ! self . web3 ) {
return callback ( Error ( "no web3 instance found" ) ) ;
}
2018-01-05 20:10:47 +00:00
if ( self . web3 . currentProvider === undefined ) {
2018-05-08 21:49:46 +00:00
self . logger . error ( _ _ ( "Couldn't connect to an Ethereum node are you sure it's on?" ) . red ) ;
self . logger . info ( _ _ ( "make sure you have an Ethereum node or simulator running. e.g '%s'" , 'embark blockchain' ) . magenta ) ;
2017-03-11 15:29:45 +00:00
return callback ( Error ( "error connecting to blockchain node" ) ) ;
}
2018-01-05 20:10:47 +00:00
2018-05-18 22:31:47 +00:00
self . blockchain . getAccounts ( function ( err , _accounts ) {
2018-01-05 20:10:47 +00:00
if ( err ) {
2018-05-08 21:49:46 +00:00
self . logger . error ( _ _ ( "Couldn't connect to an Ethereum node are you sure it's on?" ) . red ) ;
self . logger . info ( _ _ ( "make sure you have an Ethereum node or simulator running. e.g '%s'" , 'embark blockchain' ) . magenta ) ;
2018-01-05 20:10:47 +00:00
return callback ( Error ( "error connecting to blockchain node" ) ) ;
}
2017-03-30 11:12:39 +00:00
return callback ( null , contractsManager , self . web3 ) ;
2018-01-05 20:10:47 +00:00
} ) ;
2017-03-30 11:12:39 +00:00
} ,
function setDefaultAccount ( contractsManager , web3 , callback ) {
2018-05-18 22:31:47 +00:00
self . blockchain . getAccounts ( function ( err , accounts ) {
2017-03-30 11:12:39 +00:00
if ( err ) {
2017-12-20 19:54:47 +00:00
self . logger . error ( err ) ;
2017-03-30 11:12:39 +00:00
return callback ( new Error ( err ) ) ;
}
let accountConfig = self . config . blockchainConfig . account ;
let selectedAccount = accountConfig && accountConfig . address ;
2018-05-18 22:31:47 +00:00
self . blockchain . setDefaultAccount ( selectedAccount || accounts [ 0 ] ) ;
2017-03-30 11:12:39 +00:00
callback ( null , contractsManager , web3 ) ;
} ) ;
} ,
2018-05-20 10:46:12 +00:00
2017-03-30 11:12:39 +00:00
function deployAllContracts ( contractsManager , web3 , callback ) {
let deploy = new Deploy ( {
2018-05-18 22:31:47 +00:00
blockchain : self . blockchain ,
2017-03-30 11:12:39 +00:00
contractsManager : contractsManager ,
logger : self . logger ,
2018-02-27 20:40:05 +00:00
events : self . events ,
2017-03-30 11:12:39 +00:00
chainConfig : self . chainConfig ,
2018-01-13 16:38:10 +00:00
env : self . config . env ,
2018-01-17 23:04:19 +00:00
plugins : self . plugins ,
2018-01-13 16:38:10 +00:00
gasLimit : self . gasLimit
2017-03-30 11:12:39 +00:00
} ) ;
2018-01-05 20:10:47 +00:00
2018-05-19 02:40:47 +00:00
deploy . deployAll ( function ( err ) {
if ( ! err ) {
self . events . emit ( 'contractsDeployed' , contractsManager ) ;
}
if ( err && self . fatalErrors ) {
return callback ( err ) ;
}
callback ( null , contractsManager , web3 ) ;
2017-03-30 11:12:39 +00:00
} ) ;
2017-12-21 16:21:36 +00:00
} ,
function runAfterDeployCommands ( contractsManager , web3 , callback ) {
2018-05-20 10:46:12 +00:00
// TODO: should instead emit a afterDeploy event and/or run a afterDeploy plugin
2017-12-21 16:21:36 +00:00
let afterDeployCmds = self . config . contractsConfig . afterDeploy || [ ] ;
let withErrors = false ;
let regex = /\$\w+/g ;
let onDeployCode = afterDeployCmds . map ( ( cmd ) => {
let realCmd = cmd . replace ( regex , ( match ) => {
let referedContractName = match . slice ( 1 ) ;
let referedContract = contractsManager . getContract ( referedContractName ) ;
if ( ! referedContract ) {
self . logger . error ( referedContractName + ' does not exist' ) ;
2018-05-08 21:49:46 +00:00
self . logger . error ( _ _ ( "error running afterDeploy: " ) + cmd ) ;
2017-12-21 16:21:36 +00:00
withErrors = true ;
return ;
}
if ( referedContract && referedContract . deploy === false ) {
self . logger . error ( referedContractName + " exists but has been set to not deploy" ) ;
2018-05-08 21:49:46 +00:00
self . logger . error ( _ _ ( "error running afterDeploy: " ) + cmd ) ;
2017-12-21 16:21:36 +00:00
withErrors = true ;
return ;
}
if ( referedContract && ! referedContract . deployedAddress ) {
self . logger . error ( "couldn't find a valid address for " + referedContractName + ". has it been deployed?" ) ;
2018-05-08 21:49:46 +00:00
self . logger . error ( _ _ ( "error running afterDeploy: " ) + cmd ) ;
2017-12-21 16:21:36 +00:00
withErrors = true ;
return ;
}
return referedContract . deployedAddress ;
} ) ;
return realCmd ;
} ) ;
if ( withErrors ) {
return callback ( new Error ( "error running afterDeploy" ) ) ;
}
2017-12-27 18:07:13 +00:00
// TODO: convert to for to avoid repeated callback
2017-12-28 12:30:41 +00:00
for ( let cmd of onDeployCode ) {
2018-05-08 21:49:46 +00:00
self . logger . info ( _ _ ( "executing" ) + ": " + cmd ) ;
2017-12-27 18:07:13 +00:00
try {
2018-05-18 19:55:34 +00:00
RunCode . doEval ( cmd , { web3 : web3 } ) ;
2017-12-27 18:07:13 +00:00
} catch ( e ) {
if ( e . message . indexOf ( "invalid opcode" ) >= 0 ) {
2018-05-08 21:49:46 +00:00
self . logger . error ( _ _ ( 'the transaction was rejected; this usually happens due to a throw or a require, it can also happen due to an invalid operation' ) ) ;
2017-12-27 18:07:13 +00:00
}
return callback ( new Error ( e ) ) ;
}
2017-12-28 12:30:41 +00:00
}
2017-12-21 16:21:36 +00:00
callback ( null , contractsManager ) ;
2017-03-30 11:12:39 +00:00
}
] , function ( err , result ) {
2017-02-24 13:20:03 +00:00
if ( err ) {
2017-03-30 11:12:39 +00:00
done ( err , null ) ;
} else {
done ( null , result ) ;
2017-02-24 13:20:03 +00:00
}
} ) ;
}
2017-03-30 11:12:39 +00:00
}
2017-02-24 13:20:03 +00:00
module . exports = DeployManager ;