UNPKG

truffle

Version:

Truffle - Simple development framework for Ethereum

1,383 lines (1,215 loc) 43.9 kB
#!/usr/bin/env node exports.id = 7017; exports.ids = [7017]; exports.modules = { /***/ 74269: /***/ ((module, __unused_webpack_exports, __webpack_require__) => { const debug = __webpack_require__(15158)("compile-vyper"); const path = __webpack_require__(71017); const exec = (__webpack_require__(32081).exec); const fs = __webpack_require__(57147); const colors = __webpack_require__(83196); const minimatch = __webpack_require__(91171); const semver = __webpack_require__(81249); const findContracts = __webpack_require__(23542); const Config = __webpack_require__(20553); const { Profiler } = __webpack_require__(76273); const { requiredSources } = __webpack_require__(53377); const { Compilations } = __webpack_require__(29833); const { compileJson } = __webpack_require__(13919); const VYPER_PATTERN_STRICT = "**/*.{vy,v.py,vyper.py}"; //no JSON // Check that vyper is available, return its version function checkVyper() { return new Promise((resolve, reject) => { exec("vyper-json --version", function (err, stdout, _stderr) { if (err) { //vyper-json not available, check vyper exec("vyper --version", function (err, stdout, stderr) { if (err) { //error: neither vyper nor vyper-json available return reject(`${colors.red("Error executing vyper:")}\n${stderr}`); } const version = normalizeVersion(stdout.trim()); if ( semver.satisfies(version, ">=0.2.5", { loose: true, includePrerelase: true }) ) { //if version is >=0.2.5, we can still use JSON via //vyper --standard-json resolve({ version, json: true, jsonCommand: "vyper --standard-json" }); } else { //otherwise, we're stuck using vyper w/o JSON resolve({ version, json: false }); } }); } else { //no error: vyper-json is available const version = normalizeVersion(stdout.trim()); resolve({ version, json: true, jsonCommand: "vyper-json" }); } }); }); } //HACK: alters prerelease versions so semver can understand them function normalizeVersion(version) { return version.replace(/^(\d+\.\d+\.\d+)b(\d+)/, "$1-beta.$2"); } // Execute vyper for single source file function execVyper(options, sourcePath, version, callback) { const formats = ["abi", "bytecode", "bytecode_runtime"]; debug("version: %s", version); if ( semver.satisfies(version, ">=0.1.0-beta.7", { loose: true, includePrerelase: true }) ) { //Vyper chokes on unknown formats, so only include this for //ones that support it (they were introduced in 0.1.0b7) formats.push("source_map"); } let evmVersionOption = ""; if ( options.compilers.vyper.settings && options.compilers.vyper.settings.evmVersion ) { const evmVersion = options.compilers.vyper.settings.evmVersion; if (evmVersion.includes("'")) { throw new Error("Invalid EVM version"); } evmVersionOption = `--evm-version '${evmVersion}'`; } if (options.contracts_directory.includes("'")) { throw new Error("Contracts directory contains apostrophe"); } const command = `vyper -f ${formats.join( "," )} ${evmVersionOption} ${sourcePath} -p '${options.contracts_directory}'`; exec(command, { maxBuffer: 600 * 1024 }, function (err, stdout, stderr) { if (err) return callback( `${stderr}\n${colors.red( `Compilation of ${sourcePath} failed. See above.` )}` ); var outputs = stdout.split(/\r?\n/); debug("formats: %O", formats); debug("outputs: %O", outputs); const compiledContract = outputs.reduce((contract, output, index) => { return Object.assign(contract, { [formats[index]]: output }); }, {}); callback(null, compiledContract); }); } /** * * read source contents from sourcePath */ function readSource(sourcePath) { const sourceBuffer = fs.readFileSync(sourcePath); return sourceBuffer.toString(); } /** * aggregate source information based on compiled output; * this can include sources that are not contracts */ //note: this takes paths, rather than full source objects like compileJson! async function compileNoJson({ paths: sources, options, version }) { const compiler = { name: "vyper", version }; const promises = []; const properSources = sources.filter(source => !source.endsWith(".json")); //filter out JSON interfaces const targets = options.compilationTargets ? properSources.filter(sourcePath => options.compilationTargets.includes(sourcePath) ) : properSources; targets.forEach(sourcePath => { promises.push( new Promise((resolve, reject) => { execVyper( options, sourcePath, version, function (error, compiledContract) { if (error) return reject(error); debug("compiledContract: %O", compiledContract); // remove first extension from filename const extension = path.extname(sourcePath); const basename = path.basename(sourcePath, extension); // if extension is .py, remove second extension from filename const contractName = extension !== ".py" ? basename : path.basename(basename, path.extname(basename)); const sourceContents = readSource(sourcePath); const deployedSourceMap = compiledContract.source_map //there is no constructor source map ? JSON.parse(compiledContract.source_map) : undefined; const contractDefinition = { contractName: contractName, sourcePath: sourcePath, source: sourceContents, abi: JSON.parse(compiledContract.abi), bytecode: { bytes: compiledContract.bytecode.slice(2), //remove "0x" prefix linkReferences: [] //no libraries in Vyper }, deployedBytecode: { bytes: compiledContract.bytecode_runtime.slice(2), //remove "0x" prefix linkReferences: [] //no libraries in Vyper }, deployedSourceMap, compiler }; const compilation = { sources: [ { sourcePath, contents: sourceContents, language: "Vyper" } ], contracts: [contractDefinition], compiler, sourceIndexes: [sourcePath] }; resolve(compilation); } ); }) ); }); const compilations = await Promise.all(promises); return Compilations.promoteCompileResult({ compilations }); } const Compile = { // Check that vyper is available then forward to internal compile function async sources({ sources = {}, options }) { options = Config.default().merge(options); const paths = Object.keys(sources); const vyperFiles = paths.filter(path => minimatch(path, VYPER_PATTERN_STRICT, { dot: true }) ); // no vyper files found, no need to check vyper // (note that JSON-only will not activate vyper) if (vyperFiles.length === 0) { return Compilations.emptyWorkflowCompileResult(); } Compile.display(vyperFiles, options); const { version, json: useJson, jsonCommand } = await checkVyper(); if (!useJson) { //it might be possible to handle this case by writing the sources //to a temporary directory (and possibly using some sort of remapping-- //a manual one I mean, Vyper doesn't have remappings), //but for now I'll just have it throw for simplicity throw new Error("Compiling literal Vyper sources requires vyper-json"); } return compileJson({ sources, options, version, command: jsonCommand }); }, async sourcesWithDependencies({ paths = [], options }) { options = Config.default().merge(options); debug("paths: %O", paths); const vyperFilesStrict = paths.filter(path => minimatch(path, VYPER_PATTERN_STRICT, { dot: true }) ); debug("vyperFilesStrict: %O", vyperFilesStrict); // no vyper targets found, no need to check Vyper if (vyperFilesStrict.length === 0) { return Compilations.emptyWorkflowCompileResult(); } const { allSources, compilationTargets } = await requiredSources( options.with({ paths: vyperFilesStrict, base_path: options.contracts_directory, compiler: { name: "vyper" //HACK: we leave version empty because we haven't determined //it at this point and we don't want to pay the cost of doing //so, and nothing in the resolver sources currently uses //precise vyper version } }) ); debug("allSources: %O", allSources); debug("compilationTargets: %O", compilationTargets); const vyperTargets = compilationTargets.filter(path => minimatch(path, VYPER_PATTERN_STRICT, { dot: true }) ); // no vyper targets found, no need to activate Vyper if (vyperTargets.length === 0) { return Compilations.emptyWorkflowCompileResult(); } //having gotten the sources from the resolver, we invoke compileJson //ourselves, rather than going through Compile.sources() Compile.display(compilationTargets, options); const { version, json: useJson, jsonCommand } = await checkVyper(); if (useJson) { return compileJson({ sources: allSources, options: options.with({ compilationTargets }), version, command: jsonCommand }); } else { return await compileNoJson({ paths: Object.keys(allSources), options: options.with({ compilationTargets }), version }); } }, // contracts_directory: String. Directory where contract files can be found. // quiet: Boolean. Suppress output. Defaults to false. // strict: Boolean. Return compiler warnings as errors. Defaults to false. async all(options) { options = Config.default().merge(options); const files = await findContracts(options.contracts_directory); const vyperFilesStrict = files.filter(path => minimatch(path, VYPER_PATTERN_STRICT, { dot: true }) ); // no vyper targets found, no need to check Vyper if (vyperFilesStrict.length === 0) { return Compilations.emptyWorkflowCompileResult(); } return await Compile.sourcesWithDependencies({ paths: files, options }); }, // contracts_directory: String. Directory where contract files can be found. // all: Boolean. Compile all sources found. Defaults to true. If false, will compare sources against built files // in the build directory to see what needs to be compiled. // quiet: Boolean. Suppress output. Defaults to false. // strict: Boolean. Return compiler warnings as errors. Defaults to false. async necessary(options) { options = Config.default().merge(options); const profiler = await new Profiler({}); const updated = await profiler.updated(options); if (updated.length === 0) { return Compilations.emptyWorkflowCompileResult(); } return await Compile.sourcesWithDependencies({ paths: updated, options }); }, async display(paths, options) { if (options.quiet !== true) { if (!Array.isArray(paths)) { paths = Object.keys(paths); } const sourceFileNames = paths.sort().map(contract => { if (path.isAbsolute(contract)) { return `.${path.sep}${path.relative( options.working_directory, contract )}`; } return contract; }); options.events.emit("compile:sourcesToCompile", { sourceFileNames }); } } }; module.exports = { Compile }; /***/ }), /***/ 87359: /***/ ((module, __unused_webpack_exports, __webpack_require__) => { const debug = __webpack_require__(15158)("compile-vyper:parser"); const OS = __webpack_require__(22037); function parseImports(body) { // WARNING: We're going to do this crudely with regexes!! // // Vyper has a rigid enough syntax that I think this is workable. // // We can't use the Solidity approach here of analyzing error messages // because the Vyper compiler will only provide an error for the *first* // failing import, not all of them. // (before we do all that, though, we'll try parsing as JSON // and return no imports if it parses, in case this gets passed // a JSON file!) try { JSON.parse(body); debug("was JSON, no imports"); return []; //if we reach this point it was a JSON file } catch (_) { //it was Vyper, proceed onward } const stripWhitespace = str => str.replace(/\s/g, ""); //remove even internal whitespace //HACK: this isn't actually a correct way of handling line //extensions and comments... but it should be good enough //for our purposes! I can't think of any cases that this //gets wrong *in a way that we care about* return ( body .replace(/(#.*)\\\r?\n/g, "$1") //remove backslashes from end of comments // (this is the most-incorrect step; it will detect a "comment" even if // the # is used in a string literal. but this shouldn't screw up imports, // so...) .replace(/\\\r?\n/g, " ") //process line extensions; //for convenience we use \r?\n instead of OS.EOL //(we don't care that this screws up string literals) .split(OS.EOL) //split body into lines .map(line => { //extract imports! const importRegex = /^import\b(.*?)\bas\b/; const fromImportRegex = /^from\b(.*?)\bimport\b(.*?)($|\bas\b)/; let matches; if ((matches = line.match(importRegex))) { const [_, path] = matches; return stripWhitespace(path); } else if ((matches = line.match(fromImportRegex))) { const [_, basePath, endPath] = matches; debug("basePath: %s; endPath: %s", basePath, endPath); const strippedBasePath = stripWhitespace(basePath); if (strippedBasePath === "vyper.interfaces") { //built-in import; we should not attempt to resolve it return null; } const strippedEndPath = stripWhitespace(endPath); return strippedBasePath.endsWith(".") ? `${strippedBasePath}${strippedEndPath}` //don't add extra "." for "from . import", etc : `${strippedBasePath}.${strippedEndPath}`; //on the endPath because } else { return null; } }) .filter(moduleName => moduleName !== null) ); } module.exports = { parseImports }; /***/ }), /***/ 53377: /***/ ((module, __unused_webpack_exports, __webpack_require__) => { const debug = __webpack_require__(15158)("compile-vyper:profiler"); const { Profiler } = __webpack_require__(76273); const { Resolver } = __webpack_require__(48511); const { parseImports } = __webpack_require__(87359); // Returns the minimal set of sources to pass to vyper-json as compilations targets, // as well as the complete set of sources so vyper-json can resolve the comp targets' imports. async function requiredSources(options) { const resolver = new Resolver(options); debug("resolver.sources.length: %d", resolver.sources.length); // generate profiler const profiler = new Profiler({ parseImports, shouldIncludePath }); // invoke profiler debug("invoking profiler"); return await profiler.requiredSources(options.with({ resolver })); } function shouldIncludePath(path) { return path.match(/\.(vy|json|v\.py|vyper\.py)$/) !== null; } module.exports = { requiredSources }; /***/ }), /***/ 13919: /***/ ((module, __unused_webpack_exports, __webpack_require__) => { const debug = __webpack_require__(15158)("compile-vyper:vyper-json"); const execSync = (__webpack_require__(32081).execSync); const path = __webpack_require__(71017); const semver = __webpack_require__(81249); const Common = __webpack_require__(29833); const partition = __webpack_require__(43174); //NOTE: this file has a fair bit of copypaste-with-modifications //from compile-solidity/run.js, so be warned... //(some has since been factored into compile-common, but not all) function compileJson({ sources: rawSources, options, version, command }) { const compiler = { name: "vyper", version }; //in order to better support absolute Vyper imports, we pretend that //the contracts directory is the root directory. note this means that //if an imported source from somewhere other than FS uses an absolute //import to refer to its own project root, it won't work. But, oh well. const { sources, targets, originalSourcePaths } = Common.Sources.collectSources( rawSources, options.compilationTargets, options.contracts_directory ); //Vyper complains if we give it a source that is not also a target, //*unless* we give it as an interface. So we have to split that out. //(JSON files also must always be interfaces) const [properSourcePaths, interfacePaths] = partition( Object.keys(sources), targets.length > 0 ? sourcePath => !sourcePath.endsWith(".json") && targets.includes(sourcePath) : sourcePath => !sourcePath.endsWith(".json") ); const properSources = Object.assign( {}, ...properSourcePaths.map(sourcePath => ({ [sourcePath]: sources[sourcePath] })) ); const interfaces = Object.assign( {}, ...interfacePaths.map(sourcePath => ({ [sourcePath]: sources[sourcePath] })) ); // construct compiler input const compilerInput = prepareCompilerInput({ sources: properSources, interfaces, settings: options.compilers.vyper.settings || {}, version }); // perform compilation const rawCompilerOutput = invokeCompiler({ compilerInput, command }); debug("rawCompilerOutput: %O", rawCompilerOutput); // handle warnings as errors if options.strict // log if not options.quiet const { warnings, errors } = detectErrors({ compilerOutput: rawCompilerOutput, options }); if (warnings.length > 0) { options.events.emit("compile:warnings", { warnings }); } if (errors.length > 0) { if (!options.quiet) { options.logger.log(""); } throw new Common.Errors.CompileError(errors); } const compilerOutput = correctPaths(rawCompilerOutput); const outputSources = processAllSources({ sources, compilerOutput, originalSourcePaths }); const sourceIndexes = outputSources.map(source => source.sourcePath); const compilation = { sourceIndexes, contracts: processContracts({ sources, compilerOutput, version, originalSourcePaths }), sources: outputSources, compiler }; return Common.Compilations.promoteCompileResult({ compilations: [compilation] }); } function invokeCompiler({ compilerInput, command }) { const inputString = JSON.stringify(compilerInput); const outputString = execVyperJson(inputString, command); return JSON.parse(outputString); } function execVyperJson(inputString, command) { return execSync(command, { input: inputString, maxBuffer: 1024 * 1024 * 10 //I guess?? copied from compile-solidity }); } function prepareCompilerInput({ sources, settings, interfaces, version }) { const outputSelection = prepareOutputSelection({ version }); return { language: "Vyper", sources: prepareSources({ sources }), interfaces: prepareInterfaces({ interfaces }), settings: { ...settings, outputSelection }, //older versions of vyper require outputSelection *outside* of settings. //we'll put it in both places for compatibility. outputSelection }; } function prepareSources({ sources }) { return Object.entries(sources) .map(([sourcePath, content]) => ({ [sourcePath]: { content } })) .reduce((a, b) => Object.assign({}, a, b), {}); } function prepareInterfaces({ interfaces }) { return Object.entries(interfaces) .map(([sourcePath, content]) => sourcePath.endsWith(".json") //for JSON we need the ABI *object*, not JSON! ? { [sourcePath]: { abi: JSON.parse(content) } } : { [sourcePath]: { content } } ) .reduce((a, b) => Object.assign({}, a, b), {}); } function prepareOutputSelection({ version }) { //Vyper uses a simpler output selection format //than solc does; it also supports solc's format, //but I've gone with the simpler version here let defaultSelectors = [ "abi", "ast", "evm.bytecode.object", //we have to omit sourceMap here, as annoyingly, //Vyper errors if you give it a not-yet-supported output selection... "evm.deployedBytecode.object", "evm.deployedBytecode.sourceMap" ]; if ( semver.satisfies(version, ">=0.1.0-beta.17", { loose: true, includePrerelase: true }) ) { //again, due to Vyper erroring if you ask for output it doesn't know about, //we have to only add these to the output if we're on a sufficiently recent //version const additionalSelectors = ["userdoc", "devdoc"]; defaultSelectors = defaultSelectors.concat(additionalSelectors); } //because we've already filtered down the sources to match the targets, //we can just say that the targets are everything return { "*": defaultSelectors }; } //this also is copy-pasted, but minus some complications function detectErrors({ compilerOutput: { errors: outputErrors }, options }) { outputErrors = outputErrors || []; const rawErrors = options.strict ? outputErrors : outputErrors.filter(({ severity }) => severity !== "warning"); const rawWarnings = options.strict ? [] // none of those in strict mode : outputErrors.filter(({ severity }) => severity === "warning"); // extract messages // NOTE: sufficiently old Vyper versions don't have formattedMessage, so we use message // instead in those cases let errors = rawErrors .map(({ formattedMessage, message }) => formattedMessage || message) .join(); const warnings = rawWarnings.map( ({ formattedMessage, message }) => formattedMessage || message ); return { warnings, errors }; } //warning: copypaste function processAllSources({ sources, compilerOutput, originalSourcePaths }) { if (!compilerOutput.sources) return []; let outputSources = []; for (const [sourcePath, { id, ast }] of Object.entries( compilerOutput.sources )) { outputSources[id] = { sourcePath: originalSourcePaths[sourcePath], contents: sources[sourcePath], ast, language: "Vyper" }; } return outputSources; } function processContracts({ compilerOutput, sources, version, originalSourcePaths }) { if (!compilerOutput.contracts) return []; return ( Object.entries(compilerOutput.contracts) // map to [[{ source, contractName, contract }]] .map(([sourcePath, sourceContracts]) => Object.entries(sourceContracts).map(([contractName, contract]) => ({ // if extension is .py, remove second extension from contract name (HACK) contractName: path.extname(sourcePath) !== ".py" ? contractName : path.basename(contractName, path.extname(contractName)), contract, source: { ast: compilerOutput.sources[sourcePath].ast, contents: sources[sourcePath], sourcePath } })) ) // and flatten .reduce((a, b) => [...a, ...b], []) // All source will have a key, but only the compiled source will have // the evm output. .filter(({ contract: { evm } }) => Object.keys(evm).length > 0) // convert to output format .map( ({ contractName, contract: { evm: { bytecode: { object: bytecode }, deployedBytecode: { sourceMap: deployedSourceMap, object: deployedBytecode } }, abi, devdoc, userdoc }, source: { ast, sourcePath: transformedSourcePath, contents: source } }) => ({ contractName, abi, devdoc, userdoc, sourcePath: originalSourcePaths[transformedSourcePath], source, deployedSourceMap, ast, bytecode: { bytes: bytecode.slice(2), //Vyper uses a "0x" prefix linkReferences: [] //no libraries in Vyper }, deployedBytecode: { bytes: deployedBytecode.slice(2), //Vyper uses a "0x" prefix linkReferences: [] //no libraries in Vyper }, compiler: { name: "vyper", version } }) ) ); } function correctPaths(compilerOutput) { return { compiler: compilerOutput.compiler, errors: compilerOutput.errors, sources: fixKeys(compilerOutput.sources), contracts: fixKeys(compilerOutput.contracts) }; } function fixKeys(pathKeyedObject) { return Object.assign( {}, ...Object.entries(pathKeyedObject).map(([key, value]) => ({ [fixPath(key)]: value })) ); } function fixPath(path) { if (path[0] === "/") { return path; } else { return "/" + path; } } module.exports = { compileJson, execVyperJson }; /***/ }), /***/ 96412: /***/ ((module, __unused_webpack_exports, __webpack_require__) => { "use strict"; const debug = __webpack_require__(15158)("external-compile"); const { exec, execSync } = __webpack_require__(32081); const resolve = (__webpack_require__(71017).resolve); const { promisify } = __webpack_require__(73837); const glob = promisify(__webpack_require__(12884)); const fs = __webpack_require__(57147); const expect = __webpack_require__(14096); const Schema = __webpack_require__(67078); const web3Utils = __webpack_require__(18269); const { Shims, Compilations } = __webpack_require__(29833); const Config = __webpack_require__(20553); const DEFAULT_ABI = [ { payable: true, stateMutability: "payable", type: "fallback" } ]; /** * buffer a line of data, yielding each full line * * returned generator alternates between two states: * 1. reset * 2. read/write * * usage: * * let gen = bufferLines(); * * // first reset * gen.next(); // reset * * // pass string data with zero or more new lines * // or pass `null` to signal EOF * let { value, done } = gen.next(data); * * // if done, value possibly contains string value with unterminated output * // otherwise, value contains any/all complete lines */ function* bufferLines() { let buffer = []; while (true) { // read input string or null as eof const input = yield; // eof returns buffer if (input == null) { const unterminated = buffer.join(""); return unterminated ? [`${unterminated}%`] : []; } // split lines // last element is always partial line const data = input.split("\n"); // add first element to buffer let [first] = data.slice(0); buffer.push(first); if (data.length > 1) { // split off partial line to save as new buffer const [last] = data.slice(-1); const [...middle] = data.slice(1, -1); // use buffer as first element (now complete line) // and yield all complete lines const lines = [buffer.join(""), ...middle]; yield lines; // reset buffer buffer = [last]; } else { // nothing to see yet yield []; } } } /** * run a command, forwarding data to arbitrary logger. * invokes callback when process exits, error on nonzero exit code. */ const runCommand = promisify(function (command, options, callback) { const { cwd, logger, input } = options; const child = exec(command, { cwd, input }); // wrap buffer generator for easy use const buffer = func => { const gen = bufferLines(); return data => { gen.next(); let { value: lines } = gen.next(data); for (let line of lines) { func(line); } }; }; const log = buffer(logger.log); const warn = buffer(logger.warn || logger.log); child.stdout.on("data", data => log(data.toString())); child.stderr.on("data", data => warn(data.toString())); child.on("close", function (code) { // close streams to flush unterminated lines log(null); warn(null); // If the command didn't exit properly, show the output and throw. if (code !== 0) { var err = new Error("Unknown exit code: " + code); return callback(err); } callback(); }); }); /** * identify and process contents as one of: * 1. JSON literal * 2. Hex string * 3. Raw binary data */ function decodeContents(contents) { // JSON try { return JSON.parse(contents); } catch (e) { /* no-op */ } // hex string if (contents.toString().startsWith("0x")) { return contents.toString(); } // raw binary return web3Utils.bytesToHex(contents); } async function processTargets(targets, cwd, logger) { const contracts = []; for (let target of targets) { let targetContracts = await processTarget(target, cwd, logger); for (let contract of Object.values(targetContracts)) { contracts.push(Schema.validate(contract)); } } return contracts; } async function processTarget(target, cwd, logger) { const usesPath = target.path != undefined; const usesCommand = target.command != undefined; const usesStdin = target.stdin || target.stdin == undefined; // default true const usesProperties = target.properties || target.fileProperties; if (usesProperties && usesPath) { throw new Error( "External compilation target cannot define both properties and path" ); } if (usesProperties && usesCommand) { throw new Error( "External compilation target cannot define both properties and command" ); } if (usesCommand && !usesPath) { // just run command const output = execSync(target.command, { cwd }); const contract = JSON.parse(output); return { [contract.contractName]: contract }; } if (usesPath && !glob.hasMagic(target.path)) { // individual file const filename = resolve(cwd, target.path); let input, command, execOptions; if (usesStdin) { input = fs.readFileSync(filename).toString(); command = target.command; execOptions = { cwd, input }; } else { command = `${target.command} ${filename}`; execOptions = { cwd }; } const output = usesCommand ? execSync(command, execOptions) : input; const contract = JSON.parse(output); return { [contract.contractName]: contract }; } if (usesPath && glob.hasMagic(target.path)) { // glob expression, recurse after expansion let paths = await glob(target.path, { cwd, follow: true }); // copy target properties, overriding path with expanded form let targets = paths.map(path => Object.assign({}, target, { path })); return await processTargets(targets, cwd, logger); } if (usesProperties) { // contract properties listed individually const contract = Object.assign({}, target.properties || {}); for (let [key, path] of Object.entries(target.fileProperties || {})) { const contents = fs.readFileSync(resolve(cwd, path)); const value = decodeContents(contents); contract[key] = value; } if (!contract.contractName) { throw new Error("External compilation target must specify contractName"); } if (!contract.abi) { contract.abi = DEFAULT_ABI; } if (!contract.bytecode && logger) { logger.log( "Warning: contract " + contract.contractName + " does not specify bytecode. You won't be able to deploy it." ); } return { [contract.contractName]: contract }; } } const Compile = { async all(options) { return await Compile.sources({ // currently you cannot specify sources here sources: undefined, options }); }, async necessary(options) { return await Compile.sources({ // currently you cannot specify sources here sources: undefined, options }); }, // compile-common defines object argument to include `sources`, but this is // unused as the user is responsible for dealing with compiling their sources async sources({ options }) { options = Config.default().merge(options); if (options.logger == null) { options.logger = console; } expect.options(options, ["compilers"]); expect.options(options.compilers, ["external"]); expect.options(options.compilers.external, ["command", "targets"]); const { command, targets } = options.compilers.external; const cwd = options.compilers.external.workingDirectory || options.compilers.external.working_directory || // just in case options.working_directory; const logger = options.logger; debug("running compile command: %s", command); await runCommand(command, { cwd, logger }); const contracts = await processTargets(targets, cwd, logger); const compilations = [ { contracts: contracts.map(Shims.LegacyToNew.forContract), // sourceIndexes is empty because we have no way of // knowing for certain the source paths for the contracts sourceIndexes: [], // since we don't know the sourcePaths, we can't really provide // the source info reliably sources: [], compiler: { name: "external", version: undefined } } ]; return Compilations.promoteCompileResult({ compilations }); }, async sourcesWithDependencies({ options }) { return await Compile.sources({ options }); } }; module.exports = { Compile, DEFAULT_ABI, processTarget }; /***/ }), /***/ 37017: /***/ (function(__unused_webpack_module, exports, __webpack_require__) { "use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); const debug_1 = __importDefault(__webpack_require__(15158)); const debug = (0, debug_1.default)("workflow-compile"); const fs_extra_1 = __importDefault(__webpack_require__(55674)); const utils_1 = __webpack_require__(80404); const compile_common_1 = __webpack_require__(29833); const db_loader_1 = __webpack_require__(70972); const SUPPORTED_COMPILERS = { solc: (__webpack_require__(4273).Compile), vyper: (__webpack_require__(74269).Compile), external: (__webpack_require__(96412).Compile) }; function compile(config) { return __awaiter(this, void 0, void 0, function* () { // determine compiler(s) to use const compilers = config.compiler ? config.compiler === "none" ? [] : [config.compiler] : Object.keys(config.compilers); // invoke compilers const rawCompilations = yield Promise.all(compilers.map((name) => __awaiter(this, void 0, void 0, function* () { const Compile = SUPPORTED_COMPILERS[name]; if (!Compile) throw new Error("Unsupported compiler: " + name); if (config.all === true || config.compileAll === true) { return yield Compile.all(config); } else if (Array.isArray(config.paths) && config.paths.length > 0) { // compile only user specified sources return yield Compile.sourcesWithDependencies({ options: config, paths: config.paths }); } else { return yield Compile.necessary(config); } }))); // collect results - rawCompilations is CompilerResult[] // flatten the array and remove compilations without results const compilations = rawCompilations.reduce((a, compilerResult) => { compilerResult.compilations.forEach((compilation) => { if (compilation.contracts.length > 0) { a = a.concat(compilation); } }); return a; }, []); // collect together contracts as well as compilations const contracts = rawCompilations.flatMap(compilerResult => compilerResult.contracts); // return WorkflowCompileResult return { contracts, compilations }; }); } exports["default"] = { compile(options) { return __awaiter(this, void 0, void 0, function* () { const config = (0, utils_1.prepareConfig)(options); if (config.events) config.events.emit("compile:start"); const { contracts, compilations } = yield compile(config); const compilers = compilations .reduce((a, compilation) => { return a.concat(compilation.compiler); }, []) .filter(compiler => compiler); if (contracts.length === 0 && config.events) { if (config.compileNone || config["compile-none"]) { config.events.emit("compile:skipped"); } else { config.events.emit("compile:nothingToCompile"); } } const result = { contracts, compilations }; if (config.events) { yield config.events.emit("compile:succeed", { contractsBuildDirectory: config.contracts_build_directory, compilers, result }); } return result; }); }, compileAndSave(options) { return __awaiter(this, void 0, void 0, function* () { const { contracts, compilations } = yield this.compile(options); return yield this.save(options, { contracts, compilations }); }); }, save(options, { contracts, compilations }) { return __awaiter(this, void 0, void 0, function* () { const config = (0, utils_1.prepareConfig)(options); yield fs_extra_1.default.ensureDir(config.contracts_build_directory); if (options.db && options.db.enabled === true && contracts.length > 0) { // currently if Truffle Db fails to load, getTruffleDb returns `null` const Db = (0, db_loader_1.getTruffleDb)(); if (Db) { debug("saving to @truffle/db"); const db = Db.connect(config.db); const project = yield Db.Project.initialize({ db, project: { directory: config.working_directory } }); ({ contracts, compilations } = yield project.loadCompile({ result: { contracts, compilations } })); } } const artifacts = contracts.map(compile_common_1.Shims.NewToLegacy.forContract); yield config.artifactor.saveAll(artifacts); return { contracts, compilations }; }); }, assignNames(options, { contracts }) { return __awaiter(this, void 0, void 0, function* () { // currently if Truffle Db fails to load, getTruffleDb returns `null` const Db = (0, db_loader_1.getTruffleDb)(); const config = (0, utils_1.prepareConfig)(options); if (!Db || !config.db || !config.db.enabled || contracts.length === 0) { return; } const db = Db.connect(config.db); const project = yield Db.Project.initialize({ db, project: { directory: config.working_directory } }); yield project.assignNames({ assignments: { contracts: contracts.map(({ db: { contract } }) => contract) } }); }); } }; //# sourceMappingURL=index.js.map /***/ }), /***/ 80404: /***/ (function(__unused_webpack_module, exports, __webpack_require__) { "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.multiPromisify = exports.prepareConfig = void 0; const config_1 = __importDefault(__webpack_require__(20553)); const expect = __importStar(__webpack_require__(14096)); const resolver_1 = __webpack_require__(48511); const artifactor_1 = __importDefault(__webpack_require__(29463)); function prepareConfig(options) { expect.options(options, ["contracts_build_directory"]); expect.one(options, ["contracts_directory", "files"]); // Use a config object to ensure we get the default sources. const config = config_1.default.default().merge(options); config.compilersInfo = {}; if (!config.resolver) config.resolver = new resolver_1.Resolver(config); if (!config.artifactor) { config.artifactor = new artifactor_1.default(config.contracts_build_directory); } return config; } exports.prepareConfig = prepareConfig; function multiPromisify(func) { return (...args) => new Promise((accept, reject) => { const callback = (err, ...results) => { if (err) reject(err); accept(results); }; func(...args, callback); }); } exports.multiPromisify = multiPromisify; //# sourceMappingURL=utils.js.map /***/ }) }; ; //# sourceMappingURL=7017.bundled.js.map