@authereum/zos
Version:
Command-line interface for the ZeppelinOS smart contract platform
231 lines • 11.7 kB
JavaScript
;
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