diff options
Diffstat (limited to 'packages/deployer/src')
-rw-r--r-- | packages/deployer/src/cli.ts | 34 | ||||
-rw-r--r-- | packages/deployer/src/compiler.ts | 276 | ||||
-rw-r--r-- | packages/deployer/src/utils/compiler.ts | 87 | ||||
-rw-r--r-- | packages/deployer/src/utils/types.ts | 27 |
4 files changed, 128 insertions, 296 deletions
diff --git a/packages/deployer/src/cli.ts b/packages/deployer/src/cli.ts index 7b32187c4..7f1ae708a 100644 --- a/packages/deployer/src/cli.ts +++ b/packages/deployer/src/cli.ts @@ -11,7 +11,7 @@ import * as yargs from 'yargs'; import { commands } from './commands'; import { constants } from './utils/constants'; import { consoleReporter } from './utils/error_reporter'; -import { CliOptions, CompilerOptions, ContractDirectory, DeployerOptions } from './utils/types'; +import { CliOptions, CompilerOptions, DeployerOptions } from './utils/types'; const DEFAULT_OPTIMIZER_ENABLED = false; const DEFAULT_CONTRACTS_DIR = path.resolve('src/contracts'); @@ -27,7 +27,7 @@ const DEFAULT_CONTRACTS_LIST = '*'; */ async function onCompileCommandAsync(argv: CliOptions): Promise<void> { const opts: CompilerOptions = { - contractDirs: getContractDirectoriesFromList(argv.contractDirs), + contractsDir: argv.contractsDir, networkId: argv.networkId, optimizerEnabled: argv.shouldOptimize, artifactsDir: argv.artifactsDir, @@ -45,7 +45,7 @@ async function onDeployCommandAsync(argv: CliOptions): Promise<void> { const web3Wrapper = new Web3Wrapper(provider); const networkId = await web3Wrapper.getNetworkIdAsync(); const compilerOpts: CompilerOptions = { - contractDirs: getContractDirectoriesFromList(argv.contractDirs), + contractsDir: argv.contractsDir, networkId, optimizerEnabled: argv.shouldOptimize, artifactsDir: argv.artifactsDir, @@ -69,29 +69,6 @@ async function onDeployCommandAsync(argv: CliOptions): Promise<void> { } /** * Creates a set of contracts to compile. - * @param contractDirectoriesList Comma separated list of contract directories - * @return Set of contract directories - */ -function getContractDirectoriesFromList(contractDirectoriesList: string): Set<ContractDirectory> { - const directories = new Set(); - const possiblyNamespacedDirectories = contractDirectoriesList.split(','); - _.forEach(possiblyNamespacedDirectories, namespacedDirectory => { - const directoryComponents = namespacedDirectory.split(':'); - if (directoryComponents.length === 1) { - const directory = { namespace: '', path: directoryComponents[0] }; - directories.add(directory); - } else if (directoryComponents.length === 2) { - const directory = { namespace: directoryComponents[0], path: directoryComponents[1] }; - directories.add(directory); - } else { - throw new Error(`Unable to parse contracts directory: '${namespacedDirectory}'`); - } - }); - - return directories; -} -/** - * Creates a set of contracts to compile. * @param contracts Comma separated list of contracts to compile */ function getContractsSetFromList(contracts: string): Set<string> { @@ -126,11 +103,10 @@ function deployCommandBuilder(yargsInstance: any) { (() => { const identityCommandBuilder = _.identity; return yargs - .option('contract-dirs', { + .option('contracts-dir', { type: 'string', default: DEFAULT_CONTRACTS_DIR, - description: - "comma separated list of contract directories.\nTo avoid filename clashes, directories should be prefixed with a namespace as follows: 'namespace:/path/to/dir'.", + description: 'path of contracts directory to compile', }) .option('network-id', { type: 'number', diff --git a/packages/deployer/src/compiler.ts b/packages/deployer/src/compiler.ts index e3ecc6c72..a3c8004ec 100644 --- a/packages/deployer/src/compiler.ts +++ b/packages/deployer/src/compiler.ts @@ -1,5 +1,17 @@ -import { AbiType, ContractAbi, MethodAbi } from '@0xproject/types'; +import { + ContractSource, + ContractSources, + EnumerableResolver, + FallthroughResolver, + FSResolver, + NameResolver, + NPMResolver, + Resolver, + URLResolver, +} from '@0xproject/sol-resolver'; +import { ContractAbi } from '@0xproject/types'; import { logUtils, promisify } from '@0xproject/utils'; +import chalk from 'chalk'; import * as ethUtil from 'ethereumjs-util'; import * as fs from 'fs'; import 'isomorphic-fetch'; @@ -11,10 +23,7 @@ import solc = require('solc'); import { binPaths } from './solc/bin_paths'; import { - constructContractId, - constructUniqueSourceFileId, createDirIfDoesNotExistAsync, - findImportIfExist, getContractArtifactIfExistsAsync, getNormalizedErrMsg, parseDependencies, @@ -25,14 +34,10 @@ import { fsWrapper } from './utils/fs_wrapper'; import { CompilerOptions, ContractArtifact, - ContractDirectory, - ContractIdToSourceFileId, ContractNetworkData, ContractNetworks, - ContractSourceDataByFileId, - ContractSources, + ContractSourceData, ContractSpecificSourceData, - FunctionNameToSeenCount, } from './utils/types'; import { utils } from './utils/utils'; @@ -44,71 +49,32 @@ const SOLC_BIN_DIR = path.join(__dirname, '..', '..', 'solc_bin'); * to artifact files. */ export class Compiler { - private _contractDirs: Set<ContractDirectory>; + private _resolver: Resolver; + private _nameResolver: NameResolver; + private _contractsDir: string; private _networkId: number; private _optimizerEnabled: boolean; private _artifactsDir: string; - // This get's set in the beggining of `compileAsync` function. It's not called from a constructor, but it's the only public method of that class and could as well be. - private _contractSources!: ContractSources; private _specifiedContracts: Set<string> = new Set(); - private _contractSourceDataByFileId: ContractSourceDataByFileId = {}; - - /** - * Recursively retrieves Solidity source code from directory. - * @param dirPath Directory to search. - * @param contractBaseDir Base contracts directory of search tree. - * @return Mapping of sourceFilePath to the contract source. - */ - private static async _getContractSourcesAsync(dirPath: string, contractBaseDir: string): Promise<ContractSources> { - let dirContents: string[] = []; - try { - dirContents = await fsWrapper.readdirAsync(dirPath); - } catch (err) { - throw new Error(`No directory found at ${dirPath}`); - } - let sources: ContractSources = {}; - for (const fileName of dirContents) { - const contentPath = `${dirPath}/${fileName}`; - if (path.extname(fileName) === constants.SOLIDITY_FILE_EXTENSION) { - try { - const opts = { - encoding: 'utf8', - }; - const source = await fsWrapper.readFileAsync(contentPath, opts); - if (!_.startsWith(contentPath, contractBaseDir)) { - throw new Error(`Expected content path '${contentPath}' to begin with '${contractBaseDir}'`); - } - const sourceFilePath = contentPath.slice(contractBaseDir.length); - sources[sourceFilePath] = source; - logUtils.log(`Reading ${sourceFilePath} source...`); - } catch (err) { - logUtils.log(`Could not find file at ${contentPath}`); - } - } else { - try { - const nestedSources = await Compiler._getContractSourcesAsync(contentPath, contractBaseDir); - sources = { - ...sources, - ...nestedSources, - }; - } catch (err) { - logUtils.log(`${contentPath} is not a directory or ${constants.SOLIDITY_FILE_EXTENSION} file`); - } - } - } - return sources; - } /** * Instantiates a new instance of the Compiler class. * @param opts Options specifying directories, network, and optimization settings. * @return An instance of the Compiler class. */ constructor(opts: CompilerOptions) { - this._contractDirs = opts.contractDirs; + this._contractsDir = opts.contractsDir; this._networkId = opts.networkId; this._optimizerEnabled = opts.optimizerEnabled; this._artifactsDir = opts.artifactsDir; this._specifiedContracts = opts.specifiedContracts; + this._nameResolver = new NameResolver(path.resolve(this._contractsDir)); + const resolver = new FallthroughResolver(); + resolver.appendResolver(new URLResolver()); + const packagePath = path.resolve(''); + resolver.appendResolver(new NPMResolver(packagePath)); + resolver.appendResolver(new FSResolver()); + resolver.appendResolver(this._nameResolver); + this._resolver = resolver; } /** * Compiles selected Solidity files found in `contractsDir` and writes JSON artifacts to `artifactsDir`. @@ -116,51 +82,27 @@ export class Compiler { public async compileAsync(): Promise<void> { await createDirIfDoesNotExistAsync(this._artifactsDir); await createDirIfDoesNotExistAsync(SOLC_BIN_DIR); - this._contractSources = {}; - const contractIdToSourceFileId: ContractIdToSourceFileId = {}; - const contractDirs = Array.from(this._contractDirs.values()); - for (const contractDir of contractDirs) { - const sources = await Compiler._getContractSourcesAsync(contractDir.path, contractDir.path); - _.forIn(sources, (source, sourceFilePath) => { - const sourceFileId = constructUniqueSourceFileId(contractDir.namespace, sourceFilePath); - // Record the file's source and data - if (!_.isUndefined(this._contractSources[sourceFileId])) { - throw new Error(`Found duplicate source files with ID '${sourceFileId}'`); - } - this._contractSources[sourceFileId] = source; - // Create a mapping between the contract id and its source file id - const contractId = constructContractId(contractDir.namespace, sourceFilePath); - if (!_.isUndefined(contractIdToSourceFileId[contractId])) { - throw new Error(`Found duplicate contract with ID '${contractId}'`); - } - contractIdToSourceFileId[contractId] = sourceFileId; - }); + let contractNamesToCompile: string[] = []; + if (this._specifiedContracts.has(ALL_CONTRACTS_IDENTIFIER)) { + const allContracts = this._nameResolver.getAll(); + contractNamesToCompile = _.map(allContracts, contractSource => + path.basename(contractSource.path, constants.SOLIDITY_FILE_EXTENSION), + ); + } else { + contractNamesToCompile = Array.from(this._specifiedContracts.values()); + } + for (const contractNameToCompile of contractNamesToCompile) { + await this._compileContractAsync(contractNameToCompile); } - _.forIn(this._contractSources, this._setContractSpecificSourceData.bind(this)); - const specifiedContractIds = this._specifiedContracts.has(ALL_CONTRACTS_IDENTIFIER) - ? _.keys(contractIdToSourceFileId) - : Array.from(this._specifiedContracts.values()); - await Promise.all( - _.map(specifiedContractIds, async contractId => - this._compileContractAsync(contractIdToSourceFileId[contractId]), - ), - ); } /** * Compiles contract and saves artifact to artifactsDir. - * @param sourceFileId Unique ID of the source file. + * @param fileName Name of contract with '.sol' extension. */ - private async _compileContractAsync(sourceFileId: string): Promise<void> { - if (_.isUndefined(this._contractSources)) { - throw new Error('Contract sources not yet initialized'); - } - if (_.isUndefined(this._contractSourceDataByFileId[sourceFileId])) { - throw new Error(`Contract source for ${sourceFileId} not yet initialized`); - } - const contractSpecificSourceData = this._contractSourceDataByFileId[sourceFileId]; - const currentArtifactIfExists = await getContractArtifactIfExistsAsync(this._artifactsDir, sourceFileId); - const sourceHash = `0x${contractSpecificSourceData.sourceHash.toString('hex')}`; - const sourceTreeHash = `0x${contractSpecificSourceData.sourceTreeHash.toString('hex')}`; + private async _compileContractAsync(contractName: string): Promise<void> { + const contractSource = this._resolver.resolve(contractName); + const currentArtifactIfExists = await getContractArtifactIfExistsAsync(this._artifactsDir, contractName); + const sourceTreeHashHex = `0x${this._getSourceTreeHash(contractSource.path).toString('hex')}`; let shouldCompile = false; if (_.isUndefined(currentArtifactIfExists)) { @@ -169,16 +111,14 @@ export class Compiler { const currentArtifact = currentArtifactIfExists as ContractArtifact; shouldCompile = currentArtifact.networks[this._networkId].optimizer_enabled !== this._optimizerEnabled || - currentArtifact.networks[this._networkId].source_tree_hash !== sourceTreeHash; + currentArtifact.networks[this._networkId].source_tree_hash !== sourceTreeHashHex; } if (!shouldCompile) { return; } + const solcVersionRange = parseSolidityVersionRange(contractSource.source); const availableCompilerVersions = _.keys(binPaths); - const solcVersion = semver.maxSatisfying( - availableCompilerVersions, - contractSpecificSourceData.solcVersionRange, - ); + const solcVersion = semver.maxSatisfying(availableCompilerVersions, solcVersionRange); const fullSolcVersion = binPaths[solcVersion]; const compilerBinFilename = path.join(SOLC_BIN_DIR, fullSolcVersion); let solcjs: string; @@ -197,57 +137,77 @@ export class Compiler { } const solcInstance = solc.setupMethods(requireFromString(solcjs, compilerBinFilename)); - logUtils.log(`Compiling ${sourceFileId} with Solidity v${solcVersion}...`); - const source = this._contractSources[sourceFileId]; - const input = { - [sourceFileId]: source, - }; - const sourcesToCompile = { - sources: input, + logUtils.log(`Compiling ${contractName} with Solidity v${solcVersion}...`); + const source = contractSource.source; + const absoluteFilePath = contractSource.path; + const standardInput: solc.StandardInput = { + language: 'Solidity', + sources: { + [absoluteFilePath]: { + urls: [`file://${absoluteFilePath}`], + }, + }, + settings: { + optimizer: { + enabled: this._optimizerEnabled, + }, + outputSelection: { + '*': { + '*': [ + 'abi', + 'evm.bytecode.object', + 'evm.bytecode.sourceMap', + 'evm.deployedBytecode.object', + 'evm.deployedBytecode.sourceMap', + ], + }, + }, + }, }; - - const compiled = solcInstance.compile(sourcesToCompile, Number(this._optimizerEnabled), importPath => - findImportIfExist(this._contractSources, sourceFileId, importPath), + const compiled: solc.StandardOutput = JSON.parse( + solcInstance.compileStandardWrapper(JSON.stringify(standardInput), importPath => { + const sourceCodeIfExists = this._resolver.resolve(importPath); + return { contents: sourceCodeIfExists.source }; + }), ); if (!_.isUndefined(compiled.errors)) { - const SOLIDITY_WARNING_PREFIX = 'Warning'; - const isError = (errorOrWarning: string) => !errorOrWarning.includes(SOLIDITY_WARNING_PREFIX); - const isWarning = (errorOrWarning: string) => errorOrWarning.includes(SOLIDITY_WARNING_PREFIX); - const errors = _.filter(compiled.errors, isError); - const warnings = _.filter(compiled.errors, isWarning); + const SOLIDITY_WARNING = 'warning'; + const errors = _.filter(compiled.errors, entry => entry.severity !== SOLIDITY_WARNING); + const warnings = _.filter(compiled.errors, entry => entry.severity === SOLIDITY_WARNING); if (!_.isEmpty(errors)) { - errors.forEach(errMsg => { - const normalizedErrMsg = getNormalizedErrMsg(errMsg); - logUtils.log(normalizedErrMsg); + errors.forEach(error => { + const normalizedErrMsg = getNormalizedErrMsg(error.formattedMessage || error.message); + logUtils.log(chalk.red(normalizedErrMsg)); }); process.exit(1); } else { - warnings.forEach(errMsg => { - const normalizedErrMsg = getNormalizedErrMsg(errMsg); - logUtils.log(normalizedErrMsg); + warnings.forEach(warning => { + const normalizedWarningMsg = getNormalizedErrMsg(warning.formattedMessage || warning.message); + logUtils.log(chalk.yellow(normalizedWarningMsg)); }); } } - const contractName = path.basename(sourceFileId, constants.SOLIDITY_FILE_EXTENSION); - const contractIdentifier = `${sourceFileId}:${contractName}`; - if (_.isUndefined(compiled.contracts[contractIdentifier])) { + const compiledData = compiled.contracts[absoluteFilePath][contractName]; + if (_.isUndefined(compiledData)) { throw new Error( - `Contract ${contractName} not found in ${sourceFileId}. Please make sure your contract has the same name as it's file name`, + `Contract ${contractName} not found in ${absoluteFilePath}. Please make sure your contract has the same name as it's file name`, ); } - const abi: ContractAbi = JSON.parse(compiled.contracts[contractIdentifier].interface); - const bytecode = `0x${compiled.contracts[contractIdentifier].bytecode}`; - const runtimeBytecode = `0x${compiled.contracts[contractIdentifier].runtimeBytecode}`; - const sourceMap = compiled.contracts[contractIdentifier].srcmap; - const sourceMapRuntime = compiled.contracts[contractIdentifier].srcmapRuntime; - const sources = _.keys(compiled.sources); + const abi: ContractAbi = compiledData.abi; + const bytecode = `0x${compiledData.evm.bytecode.object}`; + const runtimeBytecode = `0x${compiledData.evm.deployedBytecode.object}`; + const sourceMap = compiledData.evm.bytecode.sourceMap; + const sourceMapRuntime = compiledData.evm.deployedBytecode.sourceMap; + const unresolvedSourcePaths = _.keys(compiled.sources); + const sources = _.map( + unresolvedSourcePaths, + unresolvedSourcePath => this._resolver.resolve(unresolvedSourcePath).path, + ); const updated_at = Date.now(); - const contractNetworkData: ContractNetworkData = { solc_version: solcVersion, - keccak256: sourceHash, - source_tree_hash: sourceTreeHash, + source_tree_hash: sourceTreeHashHex, optimizer_enabled: this._optimizerEnabled, abi, bytecode, @@ -280,44 +240,22 @@ export class Compiler { const artifactString = utils.stringifyWithFormatting(newArtifact); const currentArtifactPath = `${this._artifactsDir}/${contractName}.json`; await fsWrapper.writeFileAsync(currentArtifactPath, artifactString); - logUtils.log(`${sourceFileId} artifact saved!`); + logUtils.log(`${contractName} artifact saved!`); } /** - * Gets contract dependendencies and keccak256 hash from source. - * @param source Source code of contract. - * @param fileId FileId of the contract source file. - * @return Object with contract dependencies and keccak256 hash of source. - */ - private _setContractSpecificSourceData(source: string, fileId: string): void { - if (!_.isUndefined(this._contractSourceDataByFileId[fileId])) { - return; - } - const sourceHash = ethUtil.sha3(source); - const solcVersionRange = parseSolidityVersionRange(source); - const dependencies = parseDependencies(source, fileId); - const sourceTreeHash = this._getSourceTreeHash(fileId, sourceHash, dependencies); - this._contractSourceDataByFileId[fileId] = { - dependencies, - solcVersionRange, - sourceHash, - sourceTreeHash, - }; - } - - /** * Gets the source tree hash for a file and its dependencies. * @param fileName Name of contract file. */ - private _getSourceTreeHash(fileName: string, sourceHash: Buffer, dependencies: string[]): Buffer { + private _getSourceTreeHash(importPath: string): Buffer { + const contractSource = this._resolver.resolve(importPath); + const dependencies = parseDependencies(contractSource); + const sourceHash = ethUtil.sha3(contractSource.source); if (dependencies.length === 0) { return sourceHash; } else { - const dependencySourceTreeHashes = _.map(dependencies, dependency => { - const source = this._contractSources[dependency]; - this._setContractSpecificSourceData(source, dependency); - const sourceData = this._contractSourceDataByFileId[dependency]; - return this._getSourceTreeHash(dependency, sourceData.sourceHash, sourceData.dependencies); - }); + const dependencySourceTreeHashes = _.map(dependencies, (dependency: string) => + this._getSourceTreeHash(dependency), + ); const sourceTreeHashesBuffer = Buffer.concat([sourceHash, ...dependencySourceTreeHashes]); const sourceTreeHash = ethUtil.sha3(sourceTreeHashesBuffer); return sourceTreeHash; diff --git a/packages/deployer/src/utils/compiler.ts b/packages/deployer/src/utils/compiler.ts index 600495693..c571b2581 100644 --- a/packages/deployer/src/utils/compiler.ts +++ b/packages/deployer/src/utils/compiler.ts @@ -1,4 +1,4 @@ -import { AbiType, ContractAbi, MethodAbi } from '@0xproject/types'; +import { ContractSource, ContractSources } from '@0xproject/sol-resolver'; import { logUtils } from '@0xproject/utils'; import * as _ from 'lodash'; import * as path from 'path'; @@ -6,60 +6,19 @@ import * as solc from 'solc'; import { constants } from './constants'; import { fsWrapper } from './fs_wrapper'; -import { ContractArtifact, ContractSources, FunctionNameToSeenCount } from './types'; +import { ContractArtifact } from './types'; /** - * Constructs a system-wide unique identifier for a source file. - * @param directoryNamespace Namespace of the source file's root contract directory. - * @param sourceFilePath Path to a source file, relative to contractBaseDir. - * @return sourceFileId A system-wide unique identifier for the source file. - */ -export function constructUniqueSourceFileId(directoryNamespace: string, sourceFilePath: string): string { - const namespacePrefix = !_.isEmpty(directoryNamespace) ? `/${directoryNamespace}` : ''; - const sourceFilePathNoLeadingSlash = sourceFilePath.replace(/^\/+/g, ''); - const sourceFileId = `${namespacePrefix}/${sourceFilePathNoLeadingSlash}`; - return sourceFileId; -} -/** - * Constructs a system-wide unique identifier for a dependency file. - * @param dependencyFilePath Path from a sourceFile to a dependency. - * @param contractBaseDir Base contracts directory of search tree. - * @return sourceFileId A system-wide unique identifier for the source file. - */ -export function constructDependencyFileId(dependencyFilePath: string, sourceFilePath: string): string { - if (_.startsWith(dependencyFilePath, '/')) { - // Path of the form /namespace/path/to/dependency.sol - return dependencyFilePath; - } else { - // Dependency is relative to the source file: ./dependency.sol, ../../some/path/dependency.sol, etc. - // Join the two paths to construct a valid source file id: /namespace/path/to/dependency.sol - return path.join(path.dirname(sourceFilePath), dependencyFilePath); - } -} -/** - * Constructs a system-wide unique identifier for a contract. - * @param directoryNamespace Namespace of the source file's root contract directory. - * @param sourceFilePath Path to a source file, relative to contractBaseDir. - * @return sourceFileId A system-wide unique identifier for contract. - */ -export function constructContractId(directoryNamespace: string, sourceFilePath: string): string { - const namespacePrefix = !_.isEmpty(directoryNamespace) ? `${directoryNamespace}:` : ''; - const sourceFileName = path.basename(sourceFilePath, constants.SOLIDITY_FILE_EXTENSION); - const contractId = `${namespacePrefix}${sourceFileName}`; - return contractId; -} -/** * Gets contract data on network or returns if an artifact does not exist. * @param artifactsDir Path to the artifacts directory. - * @param fileName Name of contract file. + * @param contractName Name of contract. * @return Contract data on network or undefined. */ export async function getContractArtifactIfExistsAsync( artifactsDir: string, - fileName: string, + contractName: string, ): Promise<ContractArtifact | void> { let contractArtifact; - const contractName = path.basename(fileName, constants.SOLIDITY_FILE_EXTENSION); const currentArtifactPath = `${artifactsDir}/${contractName}.json`; try { const opts = { @@ -69,7 +28,7 @@ export async function getContractArtifactIfExistsAsync( contractArtifact = JSON.parse(contractArtifactString); return contractArtifact; } catch (err) { - logUtils.log(`Artifact for ${fileName} does not exist`); + logUtils.log(`Artifact for ${contractName} does not exist`); return undefined; } } @@ -123,11 +82,11 @@ export function getNormalizedErrMsg(errMsg: string): string { /** * Parses the contract source code and extracts the dendencies * @param source Contract source code - * @param sourceFilePath File path of the source code. * @return List of dependendencies */ -export function parseDependencies(source: string, sourceFileId: string): string[] { +export function parseDependencies(contractSource: ContractSource): string[] { // TODO: Use a proper parser + const source = contractSource.source; const IMPORT_REGEX = /(import\s)/; const DEPENDENCY_PATH_REGEX = /"([^"]+)"/; // Source: https://github.com/BlockChainCompany/soljitsu/blob/master/lib/shared.js const dependencies: string[] = []; @@ -136,35 +95,13 @@ export function parseDependencies(source: string, sourceFileId: string): string[ if (!_.isNull(line.match(IMPORT_REGEX))) { const dependencyMatch = line.match(DEPENDENCY_PATH_REGEX); if (!_.isNull(dependencyMatch)) { - const dependencyPath = dependencyMatch[1]; - const dependencyId = constructDependencyFileId(dependencyPath, sourceFileId); - dependencies.push(dependencyId); + let dependencyPath = dependencyMatch[1]; + if (dependencyPath.startsWith('.')) { + dependencyPath = path.join(path.dirname(contractSource.path), dependencyPath); + } + dependencies.push(dependencyPath); } } }); return dependencies; } - -/** - * Callback to resolve dependencies with `solc.compile`. - * Throws error if contractSources not yet initialized. - * @param contractSources Source codes of contracts. - * @param sourceFileId ID of the source file. - * @param importPath Path of dependency source file. - * @return Import contents object containing source code of dependency. - */ -export function findImportIfExist( - contractSources: ContractSources, - sourceFileId: string, - importPath: string, -): solc.ImportContents { - const dependencyFileId = constructDependencyFileId(importPath, sourceFileId); - const source = contractSources[dependencyFileId]; - if (_.isUndefined(source)) { - throw new Error(`Contract source not found for ${dependencyFileId}`); - } - const importContents: solc.ImportContents = { - contents: source, - }; - return importContents; -} diff --git a/packages/deployer/src/utils/types.ts b/packages/deployer/src/utils/types.ts index 1a866b873..a20d0f627 100644 --- a/packages/deployer/src/utils/types.ts +++ b/packages/deployer/src/utils/types.ts @@ -18,15 +18,9 @@ export interface ContractNetworks { [key: number]: ContractNetworkData; } -export interface ContractDirectory { - path: string; - namespace: string; -} - export interface ContractNetworkData { solc_version: string; optimizer_enabled: boolean; - keccak256: string; source_tree_hash: string; abi: ContractAbi; bytecode: string; @@ -45,7 +39,7 @@ export interface SolcErrors { export interface CliOptions extends yargs.Arguments { artifactsDir: string; - contractDirs: string; + contractsDir: string; jsonrpcUrl: string; networkId: number; shouldOptimize: boolean; @@ -56,7 +50,7 @@ export interface CliOptions extends yargs.Arguments { } export interface CompilerOptions { - contractDirs: Set<ContractDirectory>; + contractsDir: string; networkId: number; optimizerEnabled: boolean; artifactsDir: string; @@ -79,20 +73,11 @@ export interface UrlDeployerOptions extends BaseDeployerOptions { export type DeployerOptions = UrlDeployerOptions | ProviderDeployerOptions; -export interface ContractSources { - [key: string]: string; -} - -export interface ContractIdToSourceFileId { - [key: string]: string; -} - -export interface ContractSourceDataByFileId { - [key: string]: ContractSpecificSourceData; +export interface ContractSourceData { + [contractName: string]: ContractSpecificSourceData; } export interface ContractSpecificSourceData { - dependencies: string[]; solcVersionRange: string; sourceHash: Buffer; sourceTreeHash: Buffer; @@ -107,8 +92,4 @@ export interface Token { swarmHash: string; } -export interface FunctionNameToSeenCount { - [key: string]: number; -} - export type DoneCallback = (err?: Error) => void; |