@ -1,89 +1,67 @@
'use strict'
'use strict'
import { Plugin } from '@remixproject/engine'
import { Plugin } from '@remixproject/engine'
import { util } from '@remix-project/remix-lib'
import { util } from '@remix-project/remix-lib'
import { CompilerAbstract } from '@remix-project/remix-solidity'
import { CompilerAbstract } from '@remix-project/remix-solidity'
const profile = {
const profile = {
name : 'compilerArtefacts' ,
name : 'compilerArtefacts' ,
methods : [ 'get' , 'addResolvedContract' , 'getCompilerAbstract' , 'getAllContractDatas' , 'getLastCompilationResult' , 'getArtefactsByContractName' , 'getContractDataFromAddress' , 'getContractDataFromByteCode' , 'saveCompilerAbstract' ] ,
methods : [ 'get' , 'addResolvedContract' , 'getCompilerAbstract' , 'getAllContractDatas' , 'getLastCompilationResult' , 'getArtefactsByContractName' , 'getContractDataFromAddress' , 'getContractDataFromByteCode' , 'saveCompilerAbstract' , 'getAllCompilerAbstracts' ] ,
events : [ ] ,
events : [ ] ,
version : '0.0.1'
version : '0.0.1' ,
}
}
export class CompilerArtefacts extends Plugin {
export class CompilerArtefacts extends Plugin {
compilersArtefactsPerFile : any
compilersArtefactsPerFile : any
compilersArtefacts : any
compilersArtefacts : any
constructor ( ) {
constructor ( ) {
super ( profile )
super ( profile )
this . compilersArtefacts = { }
this . compilersArtefacts = { }
this . compilersArtefactsPerFile = { }
this . compilersArtefactsPerFile = { }
}
}
clear ( ) {
clear() {
this . compilersArtefacts = { }
this . compilersArtefacts = { }
this . compilersArtefactsPerFile = { }
this . compilersArtefactsPerFile = { }
}
}
saveCompilerAbstract ( file : string , compilerAbstract : CompilerAbstract ) {
saveCompilerAbstract ( file : string , compilerAbstract : CompilerAbstract ) {
this . compilersArtefactsPerFile [ file ] = compilerAbstract
this . compilersArtefactsPerFile [ file ] = compilerAbstract
}
}
onActivation ( ) {
getAllCompilerAbstracts() {
const saveCompilationPerFileResult = ( file , source , languageVersion , data , input ? ) = > {
return this . compilersArtefactsPerFile
}
onActivation() {
const saveCompilationResult = ( file , source , languageVersion , data , input ? ) = > {
this . compilersArtefacts . __last = new CompilerAbstract ( languageVersion , data , source , input )
this . compilersArtefactsPerFile [ file ] = new CompilerAbstract ( languageVersion , data , source , input )
this . compilersArtefactsPerFile [ file ] = new CompilerAbstract ( languageVersion , data , source , input )
}
}
this . on ( 'solidity' , 'compilationFinished' , ( file , source , languageVersion , data , input , version ) = > {
this . on ( 'solidity' , 'compilationFinished' , saveCompilationResult )
this . compilersArtefacts . __last = new CompilerAbstract ( languageVersion , data , source , input )
saveCompilationPerFileResult ( file , source , languageVersion , data )
} )
this . on ( 'vyper' , 'compilationFinished' , ( file , source , languageVersion , data ) = > {
this . on ( 'vyper' , 'compilationFinished' , saveCompilationResult )
this . compilersArtefacts . __last = new CompilerAbstract ( languageVersion , data , source )
saveCompilationPerFileResult ( file , source , languageVersion , data )
} )
this . on ( 'lexon' , 'compilationFinished' , ( file , source , languageVersion , data ) = > {
this . on ( 'lexon' , 'compilationFinished' , saveCompilationResult )
this . compilersArtefacts . __last = new CompilerAbstract ( languageVersion , data , source )
saveCompilationPerFileResult ( file , source , languageVersion , data )
} )
this . on ( 'yulp' , 'compilationFinished' , ( file , source , languageVersion , data ) = > {
this . on ( 'yulp' , 'compilationFinished' , saveCompilationResult )
this . compilersArtefacts . __last = new CompilerAbstract ( languageVersion , data , source )
saveCompilationPerFileResult ( file , source , languageVersion , data )
} )
this . on ( 'solidityUnitTesting' , 'compilationFinished' , ( file , source , languageVersion , data , input , version ) = > {
this . on ( 'solidityUnitTesting' , 'compilationFinished' , saveCompilationResult )
this . compilersArtefacts . __last = new CompilerAbstract ( languageVersion , data , source , input )
saveCompilationPerFileResult ( file , source , languageVersion , data , input )
} )
this . on ( 'nahmii-compiler' , 'compilationFinished' , ( file , source , languageVersion , data ) = > {
this . on ( 'nahmii-compiler' , 'compilationFinished' , saveCompilationResult )
this . compilersArtefacts . __last = new CompilerAbstract ( languageVersion , data , source )
saveCompilationPerFileResult ( file , source , languageVersion , data )
} )
this . on ( 'hardhat' , 'compilationFinished' , ( file , source , languageVersion , data ) = > {
this . on ( 'hardhat' , 'compilationFinished' , saveCompilationResult )
this . compilersArtefacts . __last = new CompilerAbstract ( languageVersion , data , source )
saveCompilationPerFileResult ( file , source , languageVersion , data )
} )
this . on ( 'truffle' , 'compilationFinished' , ( file , source , languageVersion , data ) = > {
this . on ( 'truffle' , 'compilationFinished' , saveCompilationResult )
this . compilersArtefacts . __last = new CompilerAbstract ( languageVersion , data , source )
saveCompilationPerFileResult ( file , source , languageVersion , data )
} )
this . on ( 'foundry' , 'compilationFinished' , ( file , source , languageVersion , data ) = > {
this . on ( 'foundry' , 'compilationFinished' , saveCompilationResult )
this . compilersArtefacts . __last = new CompilerAbstract ( languageVersion , data , source )
saveCompilationPerFileResult ( file , source , languageVersion , data )
} )
}
}
/ * *
/ * *
* Get artefacts for last compiled contract
* Get artefacts for last compiled contract
* * @returns last compiled contract compiler abstract
* * @returns last compiled contract compiler abstract
* /
* /
getLastCompilationResult ( ) {
getLastCompilationResult() {
return this . compilersArtefacts . __last
return this . compilersArtefacts . __last
}
}
@ -91,7 +69,7 @@ export class CompilerArtefacts extends Plugin {
* Get compilation output for contracts compiled during a session of Remix IDE
* Get compilation output for contracts compiled during a session of Remix IDE
* @returns compilatin output
* @returns compilatin output
* /
* /
getAllContractDatas ( ) {
getAllContractDatas() {
return this . filterAllContractDatas ( ( ) = > true )
return this . filterAllContractDatas ( ( ) = > true )
}
}
@ -99,7 +77,7 @@ export class CompilerArtefacts extends Plugin {
* filter compilation output for contracts compiled during a session of Remix IDE
* filter compilation output for contracts compiled during a session of Remix IDE
* @returns compilatin output
* @returns compilatin output
* /
* /
filterAllContractDatas ( filter ) {
filterAllContractDatas ( filter ) {
const contractsData = { }
const contractsData = { }
Object . keys ( this . compilersArtefactsPerFile ) . map ( ( targetFile ) = > {
Object . keys ( this . compilersArtefactsPerFile ) . map ( ( targetFile ) = > {
const artefact = this . compilersArtefactsPerFile [ targetFile ]
const artefact = this . compilersArtefactsPerFile [ targetFile ]
@ -124,7 +102,7 @@ export class CompilerArtefacts extends Plugin {
* @param contractName contract name
* @param contractName contract name
* @returns arefacts object , with fully qualified name ( e . g ; contracts / 1_Storage.sol :Storage ) as key
* @returns arefacts object , with fully qualified name ( e . g ; contracts / 1_Storage.sol :Storage ) as key
* /
* /
_getAllContractArtefactsfromOutput ( compilerOutput , contractName ) {
_getAllContractArtefactsfromOutput ( compilerOutput , contractName ) {
const contractArtefacts = { }
const contractArtefacts = { }
for ( const filename in compilerOutput ) {
for ( const filename in compilerOutput ) {
if ( Object . keys ( compilerOutput [ filename ] ) . includes ( contractName ) ) contractArtefacts [ filename + ':' + contractName ] = compilerOutput [ filename ] [ contractName ]
if ( Object . keys ( compilerOutput [ filename ] ) . includes ( contractName ) ) contractArtefacts [ filename + ':' + contractName ] = compilerOutput [ filename ] [ contractName ]
@ -139,12 +117,12 @@ export class CompilerArtefacts extends Plugin {
* @param contractArtefacts populated resultant artefacts object , with fully qualified name ( e.g : contracts / 1_Storage.sol :Storage ) as key
* @param contractArtefacts populated resultant artefacts object , with fully qualified name ( e.g : contracts / 1_Storage.sol :Storage ) as key
* Once method execution completes , contractArtefacts object will hold all possible artefacts for contract
* Once method execution completes , contractArtefacts object will hold all possible artefacts for contract
* /
* /
async _populateAllContractArtefactsFromFE ( path , contractName , contractArtefacts ) {
async _populateAllContractArtefactsFromFE ( path , contractName , contractArtefacts ) {
const dirList = await this . call ( 'fileManager' , 'dirList' , path )
const dirList = await this . call ( 'fileManager' , 'dirList' , path )
if ( dirList && dirList . length ) {
if ( dirList && dirList . length ) {
for ( const dirPath of dirList ) {
for ( const dirPath of dirList ) {
// check if directory contains an 'artifacts' folder and a 'build-info' folder inside 'artifacts'
// check if directory contains an 'artifacts' folder and a 'build-info' folder inside 'artifacts'
if ( dirPath === path + '/artifacts' && await this . call ( 'fileManager' , 'exists' , dirPath + '/build-info' ) ) {
if ( dirPath === path + '/artifacts' && ( await this . call ( 'fileManager' , 'exists' , dirPath + '/build-info' ) ) ) {
const buildFileList = await this . call ( 'fileManager' , 'fileList' , dirPath + '/build-info' )
const buildFileList = await this . call ( 'fileManager' , 'fileList' , dirPath + '/build-info' )
// process each build-info file to populate the artefacts for contractName
// process each build-info file to populate the artefacts for contractName
for ( const buildFile of buildFileList ) {
for ( const buildFile of buildFileList ) {
@ -155,7 +133,7 @@ export class CompilerArtefacts extends Plugin {
// populate the resultant object with artefacts
// populate the resultant object with artefacts
Object . assign ( contractArtefacts , artefacts )
Object . assign ( contractArtefacts , artefacts )
}
}
} else await this . _populateAllContractArtefactsFromFE ( dirPath , contractName , contractArtefacts )
} else await this . _populateAllContractArtefactsFromFE ( dirPath , contractName , contractArtefacts )
}
}
} else return
} else return
}
}
@ -165,7 +143,7 @@ export class CompilerArtefacts extends Plugin {
* @param name contract name or fully qualified name i . e . < filename > : < contractname > e.g : contracts / 1_Storage.sol :Storage
* @param name contract name or fully qualified name i . e . < filename > : < contractname > e.g : contracts / 1_Storage.sol :Storage
* @returns artefacts for the contract
* @returns artefacts for the contract
* /
* /
async getArtefactsByContractName ( name ) {
async getArtefactsByContractName ( name ) {
const contractsDataByFilename = this . getAllContractDatas ( )
const contractsDataByFilename = this . getAllContractDatas ( )
// check if name is a fully qualified name
// check if name is a fully qualified name
if ( name . includes ( ':' ) ) {
if ( name . includes ( ':' ) ) {
@ -173,12 +151,11 @@ export class CompilerArtefacts extends Plugin {
const nameArr = fullyQualifiedName . split ( ':' )
const nameArr = fullyQualifiedName . split ( ':' )
const filename = nameArr [ 0 ]
const filename = nameArr [ 0 ]
const contract = nameArr [ 1 ]
const contract = nameArr [ 1 ]
if ( Object . keys ( contractsDataByFilename ) . includes ( filename ) && contractsDataByFilename [ filename ] [ contract ] )
if ( Object . keys ( contractsDataByFilename ) . includes ( filename ) && contractsDataByFilename [ filename ] [ contract ] ) return contractsDataByFilename [ filename ] [ contract ]
return contractsDataByFilename [ filename ] [ contract ]
else {
else {
const allContractsData = { }
const allContractsData = { }
await this . _populateAllContractArtefactsFromFE ( 'contracts' , contract , allContractsData )
await this . _populateAllContractArtefactsFromFE ( 'contracts' , contract , allContractsData )
if ( allContractsData [ fullyQualifiedName ] ) return { fullyQualifiedName , artefact : allContractsData [ fullyQualifiedName ] }
if ( allContractsData [ fullyQualifiedName ] ) return { fullyQualifiedName , artefact : allContractsData [ fullyQualifiedName ] }
else throw new Error ( ` Could not find artifacts for ${ fullyQualifiedName } . Compile contract to generate artifacts. ` )
else throw new Error ( ` Could not find artifacts for ${ fullyQualifiedName } . Compile contract to generate artifacts. ` )
}
}
} else {
} else {
@ -186,10 +163,10 @@ export class CompilerArtefacts extends Plugin {
const contractArtefacts = this . _getAllContractArtefactsfromOutput ( contractsDataByFilename , contractName )
const contractArtefacts = this . _getAllContractArtefactsfromOutput ( contractsDataByFilename , contractName )
let keys = Object . keys ( contractArtefacts )
let keys = Object . keys ( contractArtefacts )
if ( ! keys . length ) {
if ( ! keys . length ) {
await this . _populateAllContractArtefactsFromFE ( 'contracts' , contractName , contractArtefacts )
await this . _populateAllContractArtefactsFromFE ( 'contracts' , contractName , contractArtefacts )
keys = Object . keys ( contractArtefacts )
keys = Object . keys ( contractArtefacts )
}
}
if ( keys . length === 1 ) return { fullyQualifiedName : keys [ 0 ] , artefact : contractArtefacts [ keys [ 0 ] ] }
if ( keys . length === 1 ) return { fullyQualifiedName : keys [ 0 ] , artefact : contractArtefacts [ keys [ 0 ] ] }
else if ( keys . length > 1 ) {
else if ( keys . length > 1 ) {
throw new Error ( ` There are multiple artifacts for contract " ${ contractName } ", please use a fully qualified name. \ n
throw new Error ( ` There are multiple artifacts for contract " ${ contractName } ", please use a fully qualified name. \ n
Please replace $ { contractName } for one of these options wherever you are trying to read its artifact : \ n
Please replace $ { contractName } for one of these options wherever you are trying to read its artifact : \ n
@ -199,7 +176,7 @@ export class CompilerArtefacts extends Plugin {
}
}
}
}
async getCompilerAbstract ( file ) {
async getCompilerAbstract ( file ) {
if ( ! file ) return null
if ( ! file ) return null
if ( this . compilersArtefactsPerFile [ file ] ) return this . compilersArtefactsPerFile [ file ]
if ( this . compilersArtefactsPerFile [ file ] ) return this . compilersArtefactsPerFile [ file ]
const path = await this . call ( 'fileManager' , 'getPathFromUrl' , file )
const path = await this . call ( 'fileManager' , 'getPathFromUrl' , file )
@ -215,30 +192,30 @@ export class CompilerArtefacts extends Plugin {
return artefact
return artefact
}
}
addResolvedContract ( address : string , compilerData : CompilerAbstract ) {
addResolvedContract ( address : string , compilerData : CompilerAbstract ) {
this . compilersArtefacts [ address ] = compilerData
this . compilersArtefacts [ address ] = compilerData
}
}
isResolved ( address ) {
isResolved ( address ) {
return this . compilersArtefacts [ address ] !== undefined
return this . compilersArtefacts [ address ] !== undefined
}
}
get ( key ) {
get ( key ) {
return this . compilersArtefacts [ key ]
return this . compilersArtefacts [ key ]
}
}
async getContractDataFromAddress ( address ) {
async getContractDataFromAddress ( address ) {
const code = await this . call ( 'blockchain' , 'getCode' , address )
const code = await this . call ( 'blockchain' , 'getCode' , address )
return this . getContractDataFromByteCode ( code )
return this . getContractDataFromByteCode ( code )
}
}
async getContractDataFromByteCode ( code ) {
async getContractDataFromByteCode ( code ) {
let found
let found
this . filterAllContractDatas ( ( file , contractsData ) = > {
this . filterAllContractDatas ( ( file , contractsData ) = > {
for ( const name of Object . keys ( contractsData ) ) {
for ( const name of Object . keys ( contractsData ) ) {
const contract = contractsData [ name ]
const contract = contractsData [ name ]
if ( util . compareByteCode ( code , '0x' + contract . evm . deployedBytecode . object ) ) {
if ( util . compareByteCode ( code , '0x' + contract . evm . deployedBytecode . object ) ) {
found = { name , contract , file }
found = { name , contract , file }
return true
return true
}
}
}
}