UNPKG

@authereum/zos

Version:

Command-line interface for the ZeppelinOS smart contract platform

231 lines 11.7 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_uniqby_1 = __importDefault(require("lodash.uniqby")); const lodash_flatten_1 = __importDefault(require("lodash.flatten")); const lodash_isempty_1 = __importDefault(require("lodash.isempty")); const lodash_groupby_1 = __importDefault(require("lodash.groupby")); const lodash_difference_1 = __importDefault(require("lodash.difference")); const inquirer_1 = __importDefault(require("inquirer")); const zos_lib_1 = require("zos-lib"); const Session_1 = __importDefault(require("../models/network/Session")); const ConfigManager_1 = __importDefault(require("../models/config/ConfigManager")); const ProjectFile_1 = __importDefault(require("../models/files/ProjectFile")); const ContractManager_1 = __importDefault(require("../models/local/ContractManager")); const Dependency_1 = __importDefault(require("../models/dependency/Dependency")); const naming_1 = require("../utils/naming"); const NetworkFile_1 = __importDefault(require("../models/files/NetworkFile")); exports.DISABLE_INTERACTIVITY = !!process.env.ZOS_NON_INTERACTIVE || process.env.DEBIAN_FRONTEND === 'noninteractive'; /* * This function will parse and wrap both arguments and options into inquirer questions, where * the 'arguments' are the parameters sent right after the command name, e.g., * zos create Foo * (Foo is the argument) and the options are the parameters sent right after a flag * e.g., * zos push --network local (local is the option). In addition to this, `props` is an object with some * inquirer questions attributes (such as question type, message and name) and `defaults` is an object with * default values for each args/props attributes. * */ function promptIfNeeded({ args = {}, opts = {}, defaults, props }, interactive) { return __awaiter(this, void 0, void 0, function* () { const argsAndOpts = Object.assign({}, args, opts); if (exports.DISABLE_INTERACTIVITY) interactive = false; const argsAndOptsQuestions = Object.keys(argsAndOpts) .filter(name => argsAndOpts[name] === undefined || (typeof argsAndOpts[name] !== 'boolean' && lodash_isempty_1.default(argsAndOpts[name]))) .filter(name => props[name] && !hasEmptyChoices(props[name])) .map(name => promptFor(name, defaults, props)); return yield answersFor(argsAndOpts, argsAndOptsQuestions, props, interactive); }); } exports.promptIfNeeded = promptIfNeeded; function networksList(name, type, message) { message = message || 'Pick a network'; const networks = ConfigManager_1.default.getNetworkNamesFromConfig(); return inquirerQuestion(name, message, type, networks); } exports.networksList = networksList; // Returns a list of all proxies, grouped by package function proxiesList(pickProxyBy, network, filter, projectFile) { projectFile = projectFile || new ProjectFile_1.default(); const networkFile = new NetworkFile_1.default(projectFile, network); const proxies = networkFile.getProxies(filter || {}); const groupedByPackage = lodash_groupby_1.default(proxies, 'package'); const list = Object.keys(groupedByPackage).map(packageName => { const separator = packageName === projectFile.name ? 'Your contracts' : packageName; const packageList = groupedByPackage[packageName].map(({ contract, address }) => { const name = pickProxyBy === 'byAddress' ? `${contract} at ${address}` : contract; const contractFullName = packageName === projectFile.name ? `${contract}` : `${packageName}/${contract}`; const proxyReference = pickProxyBy === 'byAddress' ? address : contractFullName; return { name, value: { address, contractFullName, proxyReference, }, }; }); return [ new inquirer_1.default.Separator(` = ${separator} =`), ...lodash_uniqby_1.default(packageList, 'name'), ]; }); return lodash_flatten_1.default(list); } exports.proxiesList = proxiesList; // Generate a list of contracts names function contractsList(name, message, type, source) { const localProjectFile = new ProjectFile_1.default(); const contractManager = new ContractManager_1.default(localProjectFile); const contractsFromBuild = contractManager.getContractNames(); const contractsFromLocal = Object.keys(localProjectFile.contracts) .map(alias => ({ name: localProjectFile.contracts[alias], alias })) .map(({ name: contractName, alias }) => { const label = contractName === alias ? alias : `${alias}[${contractName}]`; return { name: label, value: alias }; }); // get contracts from `build/contracts` if (!source || source === 'built') { return inquirerQuestion(name, message, type, contractsFromBuild); // get contracts from project.json file } else if (source === 'notAdded') { const contracts = lodash_difference_1.default(contractsFromBuild, contractsFromLocal.map(({ value }) => value)); return inquirerQuestion(name, message, type, contracts); } else if (source === 'added') { return inquirerQuestion(name, message, type, contractsFromLocal); // generate a list of built contracts and package contracts } else if (source === 'all') { const packageContracts = Object.keys(localProjectFile.dependencies).map(dependencyName => { const contractNames = new Dependency_1.default(dependencyName).projectFile.contractAliases.map(contractName => `${dependencyName}/${contractName}`); if (contractNames.length > 0) { contractNames.unshift(new inquirer_1.default.Separator(` = ${dependencyName} =`)); } return contractNames; }); if (contractsFromBuild.length > 0) contractsFromBuild.unshift(new inquirer_1.default.Separator(` = Your contracts =`)); return inquirerQuestion(name, message, type, [ ...contractsFromBuild, ...lodash_flatten_1.default(packageContracts), ]); } else return []; } exports.contractsList = contractsList; // Generate a list of methods names for a particular contract function methodsList(contractFullName, constant, projectFile) { return contractMethods(contractFullName, constant, projectFile) .map(({ name, hasInitializer, inputs, selector }) => { const initializable = hasInitializer ? '* ' : ''; const args = inputs.map(({ name: inputName, type }) => `${inputName}: ${type}`); const label = `${initializable}${name}(${args.join(', ')})`; return { name: label, value: { name, selector } }; }) .sort((a, b) => { if (a.name.startsWith('*') && !b.name.startsWith('*')) return -1; else if ((a.name.startsWith('*') && b.name.startsWith('*')) || (!a.name.startsWith('*') && !b.name.startsWith('*'))) return 0; else if (!a.name.startsWith('*') && b.name.startsWith('*')) return 1; }); } exports.methodsList = methodsList; // Returns an inquirer question with a list of arguments for a particular method function argsList(contractFullName, methodIdentifier, constant, projectFile) { const method = contractMethods(contractFullName, constant, projectFile).find(({ name, selector }) => selector === methodIdentifier || name === methodIdentifier); return method ? method.inputs : []; } exports.argsList = argsList; function contractMethods(contractFullName, constant = zos_lib_1.ContractMethodMutability.NotConstant, projectFile) { const { contract: contractAlias, package: packageName, } = naming_1.fromContractFullName(contractFullName); const contractManager = new ContractManager_1.default(projectFile); if (!contractManager.hasContract(packageName, contractAlias)) return []; const contract = contractManager.getContractClass(packageName, contractAlias); return zos_lib_1.contractMethodsFromAbi(contract, constant); } function proxyInfo(contractInfo, network) { const { contractAlias, proxyAddress, packageName } = contractInfo; const projectFile = new ProjectFile_1.default(); const networkFile = new NetworkFile_1.default(projectFile, network); const proxyParams = { contract: contractAlias, address: proxyAddress, package: packageName, }; if (!proxyAddress && !contractAlias) { return { proxyReference: undefined, contractFullName: undefined }; } else if (!networkFile.hasProxies(proxyParams)) { const contractFullName = naming_1.toContractFullName(packageName, contractAlias); return { proxyReference: proxyAddress || contractFullName, contractFullName, }; } else { const proxies = networkFile.getProxies(proxyParams); const proxy = proxies[0] || {}; const contractFullName = naming_1.toContractFullName(proxy.package, proxy.contract); return { contractFullName, address: proxy.address, proxyReference: proxyAddress || contractFullName, }; } } exports.proxyInfo = proxyInfo; function promptForNetwork(options, getCommandProps) { return __awaiter(this, void 0, void 0, function* () { const { network: networkInOpts, interactive } = options; const { network: networkInSession, expired } = Session_1.default.getNetwork(); const defaults = { network: networkInSession }; const opts = { network: networkInOpts || (!expired ? networkInSession : undefined), }; const props = getCommandProps(); return promptIfNeeded({ opts, defaults, props }, interactive); }); } exports.promptForNetwork = promptForNetwork; function answersFor(inputs, questions, props, interactive) { return __awaiter(this, void 0, void 0, function* () { const merged = interactive ? Object.assign({}, inputs, (yield inquirer_1.default.prompt(questions))) : inputs; Object.keys(merged).forEach(propName => { if (props[propName] && props[propName].normalize) merged[propName] = props[propName].normalize(merged[propName]); }); return merged; }); } function inquirerQuestion(name, message, type, choices) { return { [name]: { type, message, choices } }; } function promptFor(name, defaults, props) { const defaultValue = defaults ? defaults[name] : undefined; return Object.assign({ isInquirerQuestion: true, name }, props[name], { default: defaultValue || props[name].default }); } function hasEmptyChoices({ choices }) { return choices && lodash_isempty_1.default(choices) && typeof choices !== 'function'; } //# sourceMappingURL=prompt.js.map