UNPKG

@authereum/zos

Version:

Command-line interface for the ZeppelinOS smart contract platform

155 lines 8.53 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 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) : new P(function (resolve) { resolve(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 lodash_map_1 = __importDefault(require("lodash.map")); const lodash_uniq_1 = __importDefault(require("lodash.uniq")); const lodash_flatten_1 = __importDefault(require("lodash.flatten")); const lodash_frompairs_1 = __importDefault(require("lodash.frompairs")); const semver_1 = __importDefault(require("semver")); const npm_programmatic_1 = __importDefault(require("npm-programmatic")); const child_process_1 = require("child_process"); const util_1 = require("util"); const zos_lib_1 = require("zos-lib"); const ProjectFile_1 = __importDefault(require("../files/ProjectFile")); const NetworkFile_1 = __importDefault(require("../files/NetworkFile")); const constants_1 = require("../files/constants"); class Dependency { static fromNameWithVersion(nameAndVersion) { const [name, version] = nameAndVersion.split('@'); return new this(name, version); } static satisfiesVersion(version, requirement) { return (!requirement || version === requirement || semver_1.default.satisfies(semver_1.default.coerce(version), requirement)); } static fetchVersionFromNpm(name) { return __awaiter(this, void 0, void 0, function* () { const execAsync = util_1.promisify(child_process_1.exec); try { const { stdout } = yield execAsync(`npm view ${name} | grep latest`); const versionMatch = stdout.match(/([0-9]+\.){2}[0-9]+/); return Array.isArray(versionMatch) && versionMatch.length > 0 ? `${name}@${versionMatch[0]}` : name; } catch (error) { return name; } }); } static hasDependenciesForDeploy(network) { const dependencies = ProjectFile_1.default.getLinkedDependencies() || []; const networkDependencies = new NetworkFile_1.default(null, network).dependencies; const hasDependenciesForDeploy = dependencies.find((depNameAndVersion) => { const [name, version] = depNameAndVersion.split('@'); const networkFilePath = Dependency.getExistingNetworkFilePath(name, network); const projectDependency = networkDependencies[name]; const satisfiesVersion = projectDependency && this.satisfiesVersion(projectDependency.version, version); return !zos_lib_1.FileSystem.exists(networkFilePath) && !satisfiesVersion; }); return !!hasDependenciesForDeploy; } static install(nameAndVersion) { return __awaiter(this, void 0, void 0, function* () { zos_lib_1.Loggy.spin(__filename, 'install', `install-dependency-${nameAndVersion}`, `Installing ${nameAndVersion} via npm`); yield npm_programmatic_1.default.install([nameAndVersion], { save: true, cwd: process.cwd() }); zos_lib_1.Loggy.succeed(`install-dependency-${nameAndVersion}`, `Dependency ${nameAndVersion} installed`); return this.fromNameWithVersion(nameAndVersion); }); } constructor(name, requirement) { this.name = name; this._networkFiles = {}; const projectVersion = this.projectFile.version; this.validateSatisfiesVersion(projectVersion, requirement); this.version = projectVersion; this.nameAndVersion = `${name}@${projectVersion}`; this.requirement = requirement || tryWithCaret(projectVersion); } deploy(txParams) { return __awaiter(this, void 0, void 0, function* () { const version = semver_1.default.coerce(this.version).toString(); const project = yield zos_lib_1.PackageProject.fetchOrDeploy(version, txParams, {}); // REFACTOR: Logic for filling in solidity libraries is partially duplicated from network base controller, // this should all be handled at the Project level. Consider adding a setImplementations (plural) method // to Projects, which handle library deployment and linking for a set of contracts altogether. const contracts = lodash_map_1.default(this.projectFile.contracts, (contractName, contractAlias) => [ zos_lib_1.Contracts.getFromNodeModules(this.name, contractName), contractAlias, ]); const pipeline = [ someContracts => lodash_map_1.default(someContracts, ([contract]) => zos_lib_1.getSolidityLibNames(contract.schema.bytecode)), someContracts => lodash_flatten_1.default(someContracts), someContracts => lodash_uniq_1.default(someContracts), ]; const libraryNames = pipeline.reduce((xs, f) => f(xs), contracts); const libraries = lodash_frompairs_1.default(yield Promise.all(lodash_map_1.default(libraryNames, (libraryName) => __awaiter(this, void 0, void 0, function* () { const implementation = yield project.setImplementation(zos_lib_1.Contracts.getFromNodeModules(this.name, libraryName), libraryName); return [libraryName, implementation.address]; })))); yield Promise.all(lodash_map_1.default(contracts, ([contract, contractAlias]) => __awaiter(this, void 0, void 0, function* () { contract.link(libraries); yield project.setImplementation(contract, contractAlias); }))); return project; }); } get projectFile() { if (!this._projectFile) { const filePath = ProjectFile_1.default.getExistingFilePath(`node_modules/${this.name}`); if (!filePath) { throw new Error(`Could not find a project.json file for '${this.name}'. Make sure it is provided by the npm package.`); } this._projectFile = new ProjectFile_1.default(filePath); } return this._projectFile; } getNetworkFile(network) { if (!this._networkFiles[network]) { const filePath = Dependency.getExistingNetworkFilePath(this.name, network); if (!zos_lib_1.FileSystem.exists(filePath)) { throw Error(`Could not find a project file for network '${network}' for '${this.name}'`); } this._networkFiles[network] = new NetworkFile_1.default(this.projectFile, network, filePath); this.validateSatisfiesVersion(this._networkFiles[network].version, this.requirement); } return this._networkFiles[network]; } isDeployedOnNetwork(network) { const filePath = Dependency.getExistingNetworkFilePath(this.name, network); if (!zos_lib_1.FileSystem.exists(filePath)) return false; return !!this.getNetworkFile(network).packageAddress; } static getExistingNetworkFilePath(name, network) { // TODO-v3: Remove legacy project file support let legacyFilePath = `node_modules/${name}/zos.${network}.json`; legacyFilePath = zos_lib_1.FileSystem.exists(legacyFilePath) ? legacyFilePath : null; let filePath = `node_modules/${this.name}/${constants_1.OPEN_ZEPPELIN_FOLDER}/${network}.json`; filePath = zos_lib_1.FileSystem.exists(filePath) ? filePath : null; return filePath || legacyFilePath; } validateSatisfiesVersion(version, requirement) { if (!Dependency.satisfiesVersion(version, requirement)) { throw Error(`Required dependency version ${requirement} does not match version ${version}`); } } } exports.default = Dependency; function tryWithCaret(version) { const cleaned = semver_1.default.clean(version); return cleaned ? `^${cleaned}` : version; } //# sourceMappingURL=Dependency.js.map