2017-12-16 20:39:30 +00:00
let async = require ( '../../utils/async_extend.js' ) ;
let SolcW = require ( './solcW.js' ) ;
class Solidity {
constructor ( embark , options ) {
this . logger = embark . logger ;
2017-12-30 21:48:53 +00:00
this . events = embark . events ;
2017-12-16 20:39:30 +00:00
this . contractDirectories = options . contractDirectories ;
embark . registerCompiler ( ".sol" , this . compile _solidity . bind ( this ) ) ;
}
compile _solidity ( contractFiles , cb ) {
let self = this ;
let input = { } ;
let solcW ;
async . waterfall ( [
function prepareInput ( callback ) {
async . each ( contractFiles ,
function ( file , fileCb ) {
let filename = file . filename ;
for ( let directory of self . contractDirectories ) {
filename = filename . replace ( directory , '' ) ;
}
file . content ( function ( fileContent ) {
input [ filename ] = fileContent ;
fileCb ( ) ;
} ) ;
} ,
function ( err ) {
callback ( err ) ;
}
) ;
} ,
function loadCompiler ( callback ) {
// TODO: there ino need to load this twice
2017-12-30 21:48:53 +00:00
solcW = new SolcW ( { logger : self . logger , events : self . events } ) ;
2017-12-16 20:39:30 +00:00
if ( solcW . isCompilerLoaded ( ) ) {
return callback ( ) ;
}
self . logger . info ( "loading solc compiler.." ) ;
solcW . load _compiler ( function ( err ) {
callback ( err ) ;
} ) ;
} ,
function compileContracts ( callback ) {
self . logger . info ( "compiling contracts..." ) ;
solcW . compile ( { sources : input } , 1 , function ( output ) {
if ( output . errors ) {
2017-12-27 18:07:13 +00:00
for ( let i = 0 ; i < output . errors . length ; i ++ ) {
2017-12-16 20:39:30 +00:00
if ( output . errors [ i ] . indexOf ( 'Warning:' ) >= 0 ) {
2017-12-27 18:07:13 +00:00
//return callback(new Error("Solidity errors: " + output.errors).message);
}
if ( output . errors [ i ] . indexOf ( 'Error:' ) >= 0 ) {
2017-12-16 20:39:30 +00:00
return callback ( new Error ( "Solidity errors: " + output . errors ) . message ) ;
}
}
self . logger . warn ( output . errors . join ( '\n' ) ) ;
}
callback ( null , output ) ;
} ) ;
} ,
function createCompiledObject ( output , callback ) {
let json = output . contracts ;
2018-01-17 20:09:19 +00:00
if ( ! output || ! output . contracts ) {
return callback ( new Error ( "error compiling for unknown reasons" ) ) ;
}
2017-12-27 18:07:13 +00:00
if ( Object . keys ( output . contracts ) . length === 0 && output . sourceList . length > 0 ) {
return callback ( new Error ( "error compiling. There are sources available but no code could be compiled, likely due to fatal errors in the solidity code" ) . message ) ;
}
2017-12-16 20:39:30 +00:00
let compiled _object = { } ;
for ( let contractName in json ) {
let contract = json [ contractName ] ;
// Pull out filename:classname
// [0] filename:classname
// [1] filename
// [2] classname
const regex = /(.*):(.*)/ ;
const className = contractName . match ( regex ) [ 2 ] ;
const filename = contractName . match ( regex ) [ 1 ] ;
compiled _object [ className ] = { } ;
compiled _object [ className ] . code = contract . bytecode ;
compiled _object [ className ] . runtimeBytecode = contract . runtimeBytecode ;
compiled _object [ className ] . realRuntimeBytecode = contract . runtimeBytecode . slice ( 0 , - 68 ) ;
compiled _object [ className ] . swarmHash = contract . runtimeBytecode . slice ( - 68 ) . slice ( 0 , 64 ) ;
compiled _object [ className ] . gasEstimates = contract . gasEstimates ;
compiled _object [ className ] . functionHashes = contract . functionHashes ;
compiled _object [ className ] . abiDefinition = JSON . parse ( contract . interface ) ;
compiled _object [ className ] . filename = filename ;
}
callback ( null , compiled _object ) ;
}
] , function ( err , result ) {
cb ( err , result ) ;
} ) ;
}
}
module . exports = Solidity ;