77const Web3 = require ( 'web3' )
88const solc = require ( 'solc' )
99const { getRemoteCompiler } = require ( './remoteCompiler.js' )
10+ const { readFileCallback} = require ( './utils.js' )
11+ const path = require ( 'path' ) ;
1012
1113/** CONST */
1214const rexTypeError = / R e t u r n a r g u m e n t t y p e ( .* ) i s n o t i m p l i c i t l y c o n v e r t i b l e t o e x p e c t e d t y p e \( t y p e o f f i r s t r e t u r n v a r i a b l e \) / ;
@@ -30,25 +32,26 @@ const SCOPE = {
3032function getBestSolidityVersion ( source ) {
3133 var rx = / ^ p r a g m a s o l i d i t y ( \^ ? [ ^ ; ] + ) ; $ / gm;
3234 let allVersions = source . match ( rx ) . map ( e => {
33- try {
34- return e . match ( / ( \d + ) \. ( \d + ) \. ( \d + ) / ) . splice ( 1 , 3 ) . map ( a => parseInt ( a ) )
35- } catch { }
35+ try {
36+ return e . match ( / ( \d + ) \. ( \d + ) \. ( \d + ) / ) . splice ( 1 , 3 ) . map ( a => parseInt ( a ) )
37+ } catch { }
3638 } )
37- let lastVersion = allVersions [ allVersions . length - 1 ] ;
38- if ( ! lastVersion ) {
39+ let lastVersion = allVersions [ allVersions . length - 1 ] ;
40+ if ( ! lastVersion ) {
3941 return undefined ;
4042 }
4143 return `^${ lastVersion . join ( '.' ) } ` ;
4244}
4345
46+
4447/** CLASS */
4548class SolidityStatement {
4649
4750 constructor ( rawCommand , scope ) {
4851 this . rawCommand = rawCommand ? rawCommand . trim ( ) : "" ;
49- this . hasNoReturnValue = ( rexAssign . test ( this . rawCommand ) )
50- || ( this . rawCommand . startsWith ( 'delete' ) )
51- || ( this . rawCommand . startsWith ( 'assembly' ) )
52+ this . hasNoReturnValue = ( rexAssign . test ( this . rawCommand ) )
53+ || ( this . rawCommand . startsWith ( 'delete' ) )
54+ || ( this . rawCommand . startsWith ( 'assembly' ) )
5255 || ( this . rawCommand . startsWith ( 'revert' ) )
5356 || ( rexTypeDecl . test ( this . rawCommand ) )
5457
@@ -78,7 +81,7 @@ class SolidityStatement {
7881 } else {
7982 this . scope = SCOPE . MAIN ;
8083 this . rawCommand = this . fixStatement ( this . rawCommand ) ;
81- if ( this . rawCommand === ';' ) {
84+ if ( this . rawCommand === ';' ) {
8285 this . hasNoReturnValue = true ;
8386 }
8487 }
@@ -134,34 +137,34 @@ class InteractiveSolidityShell {
134137 this . cache = {
135138 compiler : { } /** compilerVersion:object */
136139 }
137-
140+
138141 this . cache . compiler [ this . settings . installedSolidityVersion . startsWith ( "^" ) ? this . settings . installedSolidityVersion . substring ( 1 ) : this . settings . installedSolidityVersion ] = solc ;
139142 this . reset ( )
140143
141144 this . blockchain = new Blockchain ( this . settings , this . log )
142145 this . blockchain . connect ( )
143146 }
144147
145- loadSession ( stmts ) {
146- if ( ! stmts ) {
148+ loadSession ( stmts ) {
149+ if ( ! stmts ) {
147150 this . session . statements = [ ]
148151 } else {
149152 this . session . statements = stmts . map ( s => new SolidityStatement ( s [ 0 ] , s [ 1 ] ) ) ;
150153 }
151154 }
152155
153- dumpSession ( ) {
156+ dumpSession ( ) {
154157 return this . session . statements . map ( s => s . toList ( ) ) ;
155158 }
156159
157- setSetting ( key , value ) {
158- switch ( key ) {
160+ setSetting ( key , value ) {
161+ switch ( key ) {
159162 case 'installedSolidityVersion' : return ;
160163 case 'ganacheArgs' :
161- if ( ! value ) {
164+ if ( ! value ) {
162165 value = [ ] ;
163166 }
164- else if ( ! Array . isArray ( value ) ) {
167+ else if ( ! Array . isArray ( value ) ) {
165168 value = value . split ( ' ' ) ;
166169 }
167170 break ;
@@ -194,10 +197,10 @@ class InteractiveSolidityShell {
194197 const lastVersionPragma = this . session . statements . filter ( stm => stm . scope === SCOPE . VERSION_PRAGMA ) . pop ( ) ;
195198
196199 /* prepare body and return statement */
197- var lastStatement = this . session . statements [ this . session . statements . length - 1 ] || { }
198- if ( lastStatement . scope !== SCOPE . MAIN || lastStatement . hasNoReturnValue === true ) {
200+ var lastStatement = this . session . statements [ this . session . statements . length - 1 ] || { }
201+ if ( lastStatement . scope !== SCOPE . MAIN || lastStatement . hasNoReturnValue === true ) {
199202 /* not a main statement, put everything in the body and use a dummy as returnexpression */
200- var mainBody = mainStatements ;
203+ var mainBody = mainStatements ;
201204 lastStatement = new SolidityStatement ( ) // add dummy w/o return value
202205 } else {
203206 var mainBody = mainStatements . slice ( 0 , mainStatements . length - 1 )
@@ -218,7 +221,7 @@ contract ${this.settings.templateContractName} {
218221 return ${ lastStatement . returnExpression }
219222 }
220223}` . trim ( ) ;
221- if ( this . settings . debugShowContract ) this . log ( ret )
224+ if ( this . settings . debugShowContract ) this . log ( ret )
222225 return ret ;
223226 }
224227
@@ -230,7 +233,7 @@ contract ${this.settings.templateContractName} {
230233 /** load remote version - (maybe cache?) */
231234
232235 return new Promise ( ( resolve , reject ) => {
233- if ( that . cache . compiler [ solidityVersion ] ) {
236+ if ( that . cache . compiler [ solidityVersion ] ) {
234237 return resolve ( that . cache . compiler [ solidityVersion ] ) ;
235238 }
236239
@@ -245,15 +248,14 @@ contract ${this.settings.templateContractName} {
245248 return reject ( err )
246249 } )
247250 } ) ;
248-
251+
249252 }
250253
251254 compile ( source , cbWarning ) {
252255 let solidityVersion = getBestSolidityVersion ( source ) ;
253-
254256 return new Promise ( ( resolve , reject ) => {
255257
256- if ( ! solidityVersion ) {
258+ if ( ! solidityVersion ) {
257259 return reject ( new Error ( `No valid solidity version found in source code (e.g. pragma solidity 0.8.10).` ) ) ;
258260 }
259261 this . loadCachedCompiler ( solidityVersion ) . then ( solcSelected => {
@@ -274,31 +276,37 @@ contract ${this.settings.templateContractName} {
274276 } ,
275277 }
276278 input . settings . outputSelection [ '*' ] [ '*' ] = [ 'abi' , 'evm.bytecode' ]
277-
278- let ret = JSON . parse ( solcSelected . compile ( JSON . stringify ( input ) ) )
279+
280+ function readFileCallbackLambda ( sourcePath ) {
281+ return readFileCallback ( sourcePath , { basePath : process . cwd ( ) , includePath : [ path . join ( process . cwd ( ) , "./node_modules/" ) ] } ) ;
282+ }
283+
284+ const callbacks = { 'import' : readFileCallbackLambda } ;
285+
286+ let ret = JSON . parse ( solcSelected . compile ( JSON . stringify ( input ) , callbacks ) )
279287 if ( ret . errors ) {
280288 let realErrors = ret . errors . filter ( err => err . type !== 'Warning' ) ;
281289 if ( realErrors . length ) {
282290 return reject ( realErrors ) ;
283291 }
284292 // print handle warnings
285293 let warnings = ret . errors . filter ( err => err . type === 'Warning' && ! IGNORE_WARNINGS . some ( target => err . message . includes ( target ) ) ) ;
286- if ( warnings . length ) cbWarning ( warnings ) ;
287-
294+ if ( warnings . length ) cbWarning ( warnings ) ;
295+
288296 }
289297 return resolve ( ret ) ;
290298 } )
291- . catch ( err => {
292- return reject ( err ) ;
293- } ) ;
294-
299+ . catch ( err => {
300+ return reject ( err ) ;
301+ } ) ;
302+
295303
296304 } ) ;
297305
298-
299-
300306
301-
307+
308+
309+
302310 }
303311
304312 run ( statement ) {
@@ -323,8 +331,8 @@ contract ${this.settings.templateContractName} {
323331 } )
324332 } ) . catch ( errors => {
325333 // frownie face
326-
327- if ( ! Array . isArray ( errors ) ) { //handle single error
334+
335+ if ( ! Array . isArray ( errors ) ) { //handle single error
328336 this . revert ( ) ;
329337 return reject ( errors ) ;
330338 }
@@ -393,7 +401,7 @@ class Blockchain {
393401 this . web3 = new Web3 ( this . provider ) ;
394402
395403 this . web3 . eth . net . isListening ( ) . then ( ) . catch ( err => {
396- if ( ! this . settings . autostartGanache ) {
404+ if ( ! this . settings . autostartGanache ) {
397405 console . warn ( "⚠️ ganache autostart is disabled" )
398406 return ;
399407 }
@@ -429,7 +437,7 @@ class Blockchain {
429437 async deploy ( contracts , callback ) {
430438 //sort deploy other contracts first
431439 Object . entries ( contracts ) . sort ( ( a , b ) => a [ 1 ] . main ? 10 : - 1 ) . forEach ( ( [ templateContractName , o ] ) => {
432- if ( o . evm . bytecode . object . length === 0 ) {
440+ if ( o . evm . bytecode . object . length === 0 ) {
433441 return ; //no bytecode, probably an interface
434442 }
435443
@@ -444,22 +452,22 @@ class Blockchain {
444452
445453 this . deployed [ templateContractName ] = thisContract ;
446454 this . getAccounts ( )
447- . then ( accounts => {
448- thisContract . accounts = accounts ;
449- let instance = thisContract . proxy . deploy ( { data : thisContract . bytecode } ) . send ( { from : accounts [ 0 ] , gas : 3e6 } )
450- thisContract . instance = instance ;
451- return instance ;
452- } )
453- . then ( contract => {
454- if ( thisContract . main ) {
455- contract . methods [ thisContract . main ] ( ) . call ( { from : thisContract . accounts [ 0 ] , gas : 3e6 } , callback ) ;
456- }
457- return ;
458- } )
459- . catch ( err => {
460- callback ( `💥 ganache not yet ready. Please try again. (👉 ${ err } 👈)` )
461- } )
462-
455+ . then ( accounts => {
456+ thisContract . accounts = accounts ;
457+ let instance = thisContract . proxy . deploy ( { data : thisContract . bytecode } ) . send ( { from : accounts [ 0 ] , gas : 3e6 } )
458+ thisContract . instance = instance ;
459+ return instance ;
460+ } )
461+ . then ( contract => {
462+ if ( thisContract . main ) {
463+ contract . methods [ thisContract . main ] ( ) . call ( { from : thisContract . accounts [ 0 ] , gas : 3e6 } , callback ) ;
464+ }
465+ return ;
466+ } )
467+ . catch ( err => {
468+ callback ( `💥 ganache not yet ready. Please try again. (👉 ${ err } 👈)` )
469+ } )
470+
463471 } , this ) ;
464472 }
465473}
0 commit comments