UNPKG

@sentio/truffle-fetch-and-compile

Version:
201 lines 9.44 kB
"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 }); exports.getSortedFetcherConstructors = exports.fetchAndCompileForRecognizer = void 0; const debug_1 = __importDefault(require("debug")); const debug = (0, debug_1.default)("fetch-and-compile:fetch"); const semver_1 = __importDefault(require("semver")); const source_fetcher_1 = __importDefault(require("@truffle/source-fetcher")); const source_fetcher_2 = require("@truffle/source-fetcher"); const config_1 = __importDefault(require("@truffle/config")); const { Compile } = require("@truffle/compile-solidity"); //sorry for untyped import! const utils_1 = require("./utils"); function fetchAndCompileForRecognizer(recognizer, options, optimizerOverride) { return __awaiter(this, void 0, void 0, function* () { const normalizedOptions = (0, utils_1.normalizeFetchAndCompileOptions)(options); const fetcherConstructors = getSortedFetcherConstructors((0, utils_1.normalizeFetcherNames)(normalizedOptions)); const fetchers = yield getFetchers(fetcherConstructors, normalizedOptions, recognizer); //now: the main loop! let address; while ((address = recognizer.getAnUnrecognizedAddress()) !== undefined) { yield tryFetchAndCompileAddress(address, fetchers, recognizer, normalizedOptions, optimizerOverride); } }); } exports.fetchAndCompileForRecognizer = fetchAndCompileForRecognizer; //sort/filter fetchers by user's order, if given; otherwise use default order function getSortedFetcherConstructors(userFetcherNames) { let sortedFetchers = []; if (userFetcherNames) { for (let name of userFetcherNames) { let Fetcher = source_fetcher_1.default.find(Fetcher => Fetcher.fetcherName === name); if (Fetcher) { sortedFetchers.push(Fetcher); } else { throw new Error(`Unknown external source service ${name}.`); } } } else { sortedFetchers = source_fetcher_1.default; } return sortedFetchers; } exports.getSortedFetcherConstructors = getSortedFetcherConstructors; function getFetchers(fetcherConstructors, options, recognizer) { return __awaiter(this, void 0, void 0, function* () { const networkId = options.network.networkId; //make fetcher instances. we'll filter out ones that don't support this //network (and note ones that yielded errors) return (yield Promise.all(fetcherConstructors.map((Fetcher) => __awaiter(this, void 0, void 0, function* () { try { return yield Fetcher.forNetworkId(networkId, ((options.fetch || {}).fetcherOptions || {})[Fetcher.fetcherName]); } catch (error) { if (!(error instanceof source_fetcher_2.InvalidNetworkError)) { //if it's *not* just an invalid network, log the error. recognizer.markBadFetcher(Fetcher.fetcherName); } //either way, filter this fetcher out return null; } })))).filter((fetcher) => fetcher !== null); }); } function tryFetchAndCompileAddress(address, fetchers, recognizer, fetchAndCompileOptions, optimizerOverride) { var _a, _b, _c; return __awaiter(this, void 0, void 0, function* () { let found = false; let failureReason; //undefined if no failure let failureError; //(this includes if no source is found) for (const fetcher of fetchers) { //now comes all the hard parts! //get our sources let result; try { debug("getting sources for %s via %s", address, fetcher.fetcherName); result = yield fetcher.fetchSourcesForAddress(address); } catch (error) { debug("error in getting sources! %o", error); failureReason = "fetch"; failureError = error; continue; } if (result === null) { debug("no sources found"); //null means they don't have that address continue; } //if we do have it, extract sources & options debug("got sources!"); const { sources, options } = result; //not same options as above, sorry for name confusion if (options.language === "Vyper") { //if it's not Solidity, bail out now debug("found Vyper, bailing out!"); recognizer.markUnrecognizable(address, "language"); //break out of the fetcher loop, since *no* fetcher will work here break; } //set up the config let externalConfig = config_1.default.default().with({ compilers: { solc: options } }); //if using docker, transform it (this does nothing if not using docker) externalConfig = transformIfUsingDocker(externalConfig, fetchAndCompileOptions); // TODO handle nightly version, see docker if ((_a = fetchAndCompileOptions.compile) === null || _a === void 0 ? void 0 : _a.nativeCompilerMap) { externalConfig.compilers.solc.nativeCompilerMap = (_b = fetchAndCompileOptions.compile) === null || _b === void 0 ? void 0 : _b.nativeCompilerMap; } if (optimizerOverride) { externalConfig.compilers.solc.settings.optimizer = optimizerOverride; // it is deliberately dropped in source fetcher // not sure why if ((_c = options.specializations) === null || _c === void 0 ? void 0 : _c.libraries) { externalConfig.compilers.solc.settings.libraries = options.specializations.libraries; } } //compile the sources let compileResult; try { compileResult = yield Compile.sources({ options: externalConfig.with({ quiet: true }), sources }); } catch (error) { debug("compile error: %O", error); failureReason = "compile"; failureError = error; continue; //try again with a different fetcher, I guess? } //add it! yield recognizer.addCompiledInfo({ compileResult, sourceInfo: result, fetchedVia: fetcher.fetcherName }, address); failureReason = undefined; //mark as *not* failed in case a previous fetcher failed failureError = undefined; //check: did this actually help? debug("checking result"); if (!recognizer.isAddressUnrecognized(address)) { debug("address %s successfully recognized via %s", address, fetcher.fetcherName); found = true; //break out of the fetcher loop -- we got what we want break; } debug("address %s still unrecognized", address); } if (found === false) { //if we couldn't find it, add it to the list of addresses to skip recognizer.markUnrecognizable(address, failureReason, failureError); } }); } function transformIfUsingDocker(externalConfig, fetchAndCompileOptions) { const useDocker = Boolean((fetchAndCompileOptions.compile || {}).docker); if (!useDocker) { //if they're not using docker, no need to transform anything :) return externalConfig; } const givenVersion = externalConfig.compilers.solc.version; //if they are, we have to ask: are they using a nightly? if (semver_1.default.prerelease(givenVersion)) { //we're not going to attempt to make Docker work with nightlies. //just keep Docker turned off. return externalConfig; } //otherwise, turn on Docker, and reduce the version to its simple form. const simpleVersion = semver_1.default.valid(givenVersion); if (simpleVersion === null) { //this should never happen throw new Error("Fetched source has unparseable compiler version"); } return externalConfig.merge({ compilers: { solc: { version: simpleVersion, docker: true } } }); } //# sourceMappingURL=fetch.js.map