diff options
Diffstat (limited to 'packages/sol-compiler')
-rw-r--r-- | packages/sol-compiler/src/compiler.ts | 100 | ||||
-rw-r--r-- | packages/sol-compiler/src/index.ts | 20 |
2 files changed, 85 insertions, 35 deletions
diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 7c76f3e52..3b0bd90f9 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -10,7 +10,7 @@ import { } from '@0xproject/sol-resolver'; import { fetchAsync, logUtils } from '@0xproject/utils'; import chalk from 'chalk'; -import { CompilerOptions, ContractArtifact, ContractVersionData } from 'ethereum-types'; +import { CompilerOptions, ContractArtifact, ContractVersionData, StandardOutput } from 'ethereum-types'; import * as ethUtil from 'ethereumjs-util'; import * as fs from 'fs'; import * as _ from 'lodash'; @@ -110,6 +110,21 @@ export class Compiler { const solcInstance = solc.setupMethods(requireFromString(solcjs, compilerBinFilename)); return { solcInstance, fullSolcVersion }; } + private static _addHexPrefixToContractBytecode(compiledContract: solc.StandardContractOutput): void { + if (!_.isUndefined(compiledContract.evm)) { + if (!_.isUndefined(compiledContract.evm.bytecode) && !_.isUndefined(compiledContract.evm.bytecode.object)) { + compiledContract.evm.bytecode.object = ethUtil.addHexPrefix(compiledContract.evm.bytecode.object); + } + if ( + !_.isUndefined(compiledContract.evm.deployedBytecode) && + !_.isUndefined(compiledContract.evm.deployedBytecode.object) + ) { + compiledContract.evm.deployedBytecode.object = ethUtil.addHexPrefix( + compiledContract.evm.deployedBytecode.object, + ); + } + } + } /** * Instantiates a new instance of the Compiler class. * @param opts Optional compiler options @@ -144,7 +159,22 @@ export class Compiler { public async compileAsync(): Promise<void> { await createDirIfDoesNotExistAsync(this._artifactsDir); await createDirIfDoesNotExistAsync(SOLC_BIN_DIR); - let contractNamesToCompile: string[] = []; + await this._compileContractsAsync(this._getContractNamesToCompile(), true); + } + /** + * Compiles Solidity files specified during instantiation, and returns the + * compiler output given by solc. Return value is an array of outputs: + * Solidity modules are batched together by version required, and each + * element of the returned array corresponds to a compiler version, and + * each element contains the output for all of the modules compiled with + * that version. + */ + public async getCompilerOutputsAsync(): Promise<StandardOutput[]> { + const promisedOutputs = this._compileContractsAsync(this._getContractNamesToCompile(), false); + return promisedOutputs; + } + private _getContractNamesToCompile(): string[] { + let contractNamesToCompile; if (this._specifiedContracts === ALL_CONTRACTS_IDENTIFIER) { const allContracts = this._nameResolver.getAll(); contractNamesToCompile = _.map(allContracts, contractSource => @@ -153,13 +183,14 @@ export class Compiler { } else { contractNamesToCompile = this._specifiedContracts; } - await this._compileContractsAsync(contractNamesToCompile); + return contractNamesToCompile; } /** - * Compiles contract and saves artifact to artifactsDir. + * Compiles contracts, and, if `shouldPersist` is true, saves artifacts to artifactsDir. * @param fileName Name of contract with '.sol' extension. + * @return an array of compiler outputs, where each element corresponds to a different version of solc-js. */ - private async _compileContractsAsync(contractNames: string[]): Promise<void> { + private async _compileContractsAsync(contractNames: string[], shouldPersist: boolean): Promise<StandardOutput[]> { // batch input contracts together based on the version of the compiler that they require. const versionToInputs: VersionToInputs = {}; @@ -200,6 +231,8 @@ export class Compiler { versionToInputs[solcVersion].contractsToCompile.push(contractSource.path); } + const compilerOutputs: StandardOutput[] = []; + const solcVersions = _.keys(versionToInputs); for (const solcVersion of solcVersions) { const input = versionToInputs[solcVersion]; @@ -212,18 +245,34 @@ export class Compiler { const { solcInstance, fullSolcVersion } = await Compiler._getSolcAsync(solcVersion); const compilerOutput = this._compile(solcInstance, input.standardInput); + compilerOutputs.push(compilerOutput); for (const contractPath of input.contractsToCompile) { - await this._verifyAndPersistCompiledContractAsync( - contractPath, - contractPathToData[contractPath].currentArtifactIfExists, - contractPathToData[contractPath].sourceTreeHashHex, - contractPathToData[contractPath].contractName, - fullSolcVersion, - compilerOutput, - ); + const contractName = contractPathToData[contractPath].contractName; + + const compiledContract = compilerOutput.contracts[contractPath][contractName]; + if (_.isUndefined(compiledContract)) { + throw new Error( + `Contract ${contractName} not found in ${contractPath}. Please make sure your contract has the same name as it's file name`, + ); + } + + Compiler._addHexPrefixToContractBytecode(compiledContract); + + if (shouldPersist) { + await this._persistCompiledContractAsync( + contractPath, + contractPathToData[contractPath].currentArtifactIfExists, + contractPathToData[contractPath].sourceTreeHashHex, + contractName, + fullSolcVersion, + compilerOutput, + ); + } } } + + return compilerOutputs; } private _shouldCompile(contractData: ContractData): boolean { if (_.isUndefined(contractData.currentArtifactIfExists)) { @@ -236,7 +285,7 @@ export class Compiler { return !isUserOnLatestVersion || didCompilerSettingsChange || didSourceChange; } } - private async _verifyAndPersistCompiledContractAsync( + private async _persistCompiledContractAsync( contractPath: string, currentArtifactIfExists: ContractArtifact | void, sourceTreeHashHex: string, @@ -244,32 +293,13 @@ export class Compiler { fullSolcVersion: string, compilerOutput: solc.StandardOutput, ): Promise<void> { - const compiledData = compilerOutput.contracts[contractPath][contractName]; - if (_.isUndefined(compiledData)) { - throw new Error( - `Contract ${contractName} not found in ${contractPath}. Please make sure your contract has the same name as it's file name`, - ); - } - if (!_.isUndefined(compiledData.evm)) { - if (!_.isUndefined(compiledData.evm.bytecode) && !_.isUndefined(compiledData.evm.bytecode.object)) { - compiledData.evm.bytecode.object = ethUtil.addHexPrefix(compiledData.evm.bytecode.object); - } - if ( - !_.isUndefined(compiledData.evm.deployedBytecode) && - !_.isUndefined(compiledData.evm.deployedBytecode.object) - ) { - compiledData.evm.deployedBytecode.object = ethUtil.addHexPrefix( - compiledData.evm.deployedBytecode.object, - ); - } - } - + const compiledContract = compilerOutput.contracts[contractPath][contractName]; const sourceCodes = _.mapValues( compilerOutput.sources, (_1, sourceFilePath) => this._resolver.resolve(sourceFilePath).source, ); const contractVersion: ContractVersionData = { - compilerOutput: compiledData, + compilerOutput: compiledContract, sources: compilerOutput.sources, sourceCodes, sourceTreeHashHex, diff --git a/packages/sol-compiler/src/index.ts b/packages/sol-compiler/src/index.ts index f8c2b577a..829e515ff 100644 --- a/packages/sol-compiler/src/index.ts +++ b/packages/sol-compiler/src/index.ts @@ -1,8 +1,28 @@ export { Compiler } from './compiler'; export { + AbiDefinition, CompilerOptions, CompilerSettings, + DataItem, + DevdocOutput, + ErrorSeverity, + ErrorType, + EventAbi, + EventParameter, + EvmBytecodeOutput, + EvmOutput, + FallbackAbi, + FunctionAbi, + MethodAbi, + ConstructorAbi, + ConstructorStateMutability, + ContractAbi, OutputField, CompilerSettingsMetadata, OptimizerSettings, + ParamDescription, + SolcError, + StandardContractOutput, + StandardOutput, + StateMutability, } from 'ethereum-types'; |