UNPKG

@hashgraph/hedera-local

Version:

Developer tooling for running Local Hedera Network (Consensus + Mirror Nodes).

561 lines (526 loc) 19 kB
// SPDX-License-Identifier: Apache-2.0 import yargs, { ArgumentsCamelCase, Argv } from 'yargs'; import { IService } from './IService'; import { CLIOptions } from '../types/CLIOptions'; import { VerboseLevel } from '../types/VerboseLevel'; import { LoggerService } from './LoggerService'; import { ServiceLocator } from './ServiceLocator'; import { FileSystemUtils } from '../utils/FileSystemUtils'; /** * Class representing the CLI service. * @implements {IService} */ export class CLIService implements IService{ /** * The logger service. * @private */ private logger: LoggerService; /** * The name of the service. * @private */ private serviceName: string; /** * The current command line arguments. * @private */ private currentArgv: ArgumentsCamelCase<{}> | undefined; /** * Get the verbose level. * @returns {string} The verbose level. */ public get verboseLevel() : string { return this.currentArgv?.verboseLevel as string; } /** * Create a CLI service. * @param {yargs.ArgumentsCamelCase<{}>} argv - The command line arguments. */ constructor(argv: yargs.ArgumentsCamelCase<{}>) { this.serviceName = CLIService.name; this.setCurrentArgv(argv); this.logger = ServiceLocator.Current.get<LoggerService>(LoggerService.name); this.logger.trace('CLI Service Initialized!', this.serviceName); } /** * Loads the startup options for the CLI service. * @param {yargs.Argv<{}>} yargs - The yargs instance. */ public static loadStartupOptions(yargs: Argv<{}>): void { CLIService.loadCommonOptions(yargs) CLIService.loadAccountOptions(yargs, true); CLIService.hostOption(yargs); CLIService.rateLimitOption(yargs); CLIService.devModeOption(yargs); CLIService.fullModeOption(yargs); CLIService.enableBlockNode(yargs); CLIService.multiNodeOption(yargs); CLIService.userComposeOption(yargs); CLIService.userComposeDirOption(yargs); CLIService.blocklistingOption(yargs); CLIService.selectNetworkTag(yargs); CLIService.selectMirrorTag(yargs); CLIService.selectRelayTag(yargs); CLIService.selectBlockNodeTag(yargs); CLIService.createInitialResources(yargs); } /** * Loads the account options for the CLI. * @param {yargs.Argv<{}>} yargs - The yargs instance. * @param {boolean} skipCommon - Whether to skip loading common options. */ public static loadAccountOptions(yargs: Argv<{}>, skipCommon = false): void { if(!skipCommon) CLIService.loadCommonOptions(yargs) CLIService.accountOption(yargs); CLIService.asyncOption(yargs); CLIService.balanceOption(yargs); CLIService.hostOption(yargs); } /** * Loads the stop options for the CLI. * @param {yargs.Argv<{}>} yargs - The yargs instance. */ public static loadStopOptions(yargs: Argv<{}>): void { CLIService.loadCommonOptions(yargs); } /** * Loads the generate accounts options for the CLI. * @param {yargs.Argv<{}>} yargs - The yargs instance. */ private static loadCommonOptions(yargs: Argv<{}>): void { CLIService.verboseLevelOption(yargs); CLIService.workDirOption(yargs); } /** * Get the current command line arguments. * @returns {CLIOptions} The current command line arguments. * @public */ public getCurrentArgv() { const argv = this.currentArgv as ArgumentsCamelCase<{}>; const accounts = argv.accounts as number; const async = argv.async as boolean; const balance = argv.balance as number; const host = argv.host as string; const limits = argv.limits as boolean; const devMode = argv.dev as boolean; const fullMode = argv.full as boolean; const blockNode = argv.enableBlockNode as boolean; const multiNode = argv.multinode as boolean; const userCompose = argv.usercompose as boolean; const userComposeDir = argv.composedir as string; const blocklisting = argv.blocklist as boolean; const startup = argv.startup as boolean; const verbose = CLIService.resolveVerboseLevel(argv.verbose as string); const networkTag = argv.networkTag as string; const mirrorTag = argv.mirrorTag as string; const relayTag = argv.relayTag as string; const blockNodeTag = argv.blockNodeTag as string; const workDir = FileSystemUtils.parseWorkDir(argv.workdir as string); const createInitialResources = argv.createInitialResources as boolean; const persistTransactionBytes = argv.persistTransactionBytes as boolean; const currentArgv: CLIOptions = { accounts, async, balance, host, limits, devMode, fullMode, blockNode, multiNode, userCompose, userComposeDir, blocklisting, startup, verbose, networkTag, mirrorTag, relayTag, blockNodeTag, workDir, createInitialResources, persistTransactionBytes, }; return currentArgv; } /** * Set the current command line arguments. * @param {yargs.ArgumentsCamelCase<{}>} argv - The current command line arguments. * @public */ public setCurrentArgv(argv: ArgumentsCamelCase<{}>): void { const state = argv._[0] as string this.currentArgv = { ...argv, startup: CLIService.isStartup(state) }; } /** * Checks if the given state represents a startup operation. * @param {string} state - The state to check. * @returns {boolean} True if the state represents a startup operation, false otherwise. * @private */ private static isStartup(state: string): boolean { switch (state) { case 'start': return true; case 'restart': return true; case 'stop': return false; case 'generate-accounts': return false; default: return true; }; } /** * Adds the 'accounts' option to the command line arguments. * This option specifies the number of generated accounts of each type. * It defaults to 10. * * @param {yargs.Argv<{}>} yargs - The yargs instance to which the option is added. * @private * @static */ private static accountOption(yargs: Argv<{}>): void { yargs.positional('accounts', { describe: 'Generated accounts of each type.', default: 10 }); } /** * Adds the 'host' option to the command line arguments. * This option is a string that specifies the host to run the local node with. * It is not required and defaults to '127.0.0.1'. * The option can also be set using the alias 'h'. * * @param {yargs.Argv<{}>} yargs - The yargs instance to which the option is added. * @private * @static */ private static hostOption(yargs: Argv<{}>): void { yargs.option('host', { alias: 'h', type: 'string', describe: 'Run the local node with host', demandOption: false, default: '127.0.0.1' }); } /** * Adds the 'limits' option to the command line arguments. * This option is a boolean that enables or disables the rate limits in the JSON-RPC relay. * It is not required and defaults to false. * The option can also be set using the alias 'l'. * * @param {yargs.Argv<{}>} yargs - The yargs instance to which the option is added. * @private * @static */ private static rateLimitOption(yargs: Argv<{}>): void { yargs.option('limits', { alias: 'l', type: 'boolean', describe: 'Enable or disable the rate limits in the JSON-RPC relay', demandOption: false, default: false }); } /** * Adds the 'dev' option to the command line arguments. * This option is a boolean that enables or disables developer mode. * It is not required and defaults to false. * * @param {yargs.Argv<{}>} yargs - The yargs instance to which the option is added. * @private * @static */ private static devModeOption(yargs: Argv<{}>): void { yargs.option('dev', { type: 'boolean', describe: 'Enable or disable developer mode', demandOption: false, default: false }); } /** * Adds the 'block-node' option to the command line arguments. * This option is a boolean that enables or disables block-node. * It is not required and defaults to false. * * @param {yargs.Argv<{}>} yargs - The yargs instance to which the option is added. * @private * @static */ private static enableBlockNode(yargs: Argv<{}>): void { yargs.option('enable-block-node', { type: 'boolean', describe: 'Enable or disable block-node', demandOption: false, default: false }); } /** * Adds the 'full' option to the command line arguments. * This option is a boolean that enables or disables full mode for a production local-node. * It is not required and defaults to false. * * @param {yargs.Argv<{}>} yargs - The yargs instance to which the option is added. * @private * @static */ private static fullModeOption(yargs: Argv<{}>): void { yargs.option('full', { type: 'boolean', describe: 'Enable or disable full mode. Production local-node.', demandOption: false, default: false }); } /** * Adds the 'multinode' option to the command line arguments. * This option is a boolean that enables or disables multi-node mode. * It is not required and defaults to false. * * @param {yargs.Argv<{}>} yargs - The yargs instance to which the option is added. * @private * @static */ private static multiNodeOption(yargs: Argv<{}>): void { yargs.option('multinode', { type: 'boolean', describe: 'Enable or disable multi-node mode.', demandOption: false, default: false }); } /** * Adds the 'balance' option to the command line arguments. * This option is a number that sets the starting balance of the created accounts in HBAR. * It is not required and defaults to 10000. * * @param {yargs.Argv<{}>} yargs - The yargs instance to which the option is added. * @private * @static */ private static balanceOption(yargs: Argv<{}>): void { yargs.option('balance', { type: 'number', describe: 'Set starting balance of the created accounts in HBAR', demandOption: false, default: 10000 }); } /** * Adds the 'async' option to the command line arguments. * This option is a boolean that enables or disables asynchronous creation of accounts. * It is not required and defaults to false. * The option can also be set using the alias 'a'. * * @param {yargs.Argv<{}>} yargs - The yargs instance to which the option is added. * @private * @static */ private static asyncOption(yargs: Argv<{}>): void { yargs.option('async', { alias: 'a', type: 'boolean', describe: 'Enable or disable asynchronous creation of accounts', demandOption: false, default: false }); } /** * Adds the 'usercompose' option to the command line arguments. * This option is a boolean that enables or disables user Compose configuration files. * It is not required and defaults to true. * * @param {yargs.Argv<{}>} yargs - The yargs instance to which the option is added. * @private * @static */ private static userComposeOption(yargs: Argv<{}>): void { yargs.option('usercompose', { type: 'boolean', describe: 'Enable or disable user Compose configuration files', demandOption: false, default: true }); } /** * Adds the 'composedir' option to the command line arguments. * This option is a string that specifies the path to a directory with user Compose configuration files. * It is not required and defaults to './overrides/'. * * @param {yargs.Argv<{}>} yargs - The yargs instance to which the option is added. * @private * @static */ private static userComposeDirOption(yargs: Argv<{}>): void { yargs.option('composedir', { type: 'string', describe: 'Path to a directory with user Compose configuration files', demandOption: false, default: './overrides/' }); } private static workDirOption(yargs: Argv<{}>): void { yargs.option('workdir', { type: 'string', describe: 'Path to the working directory for local node', demandOption: false, default: FileSystemUtils.getPlatformSpecificAppDataPath('hedera-local') }); } /** * Adds the 'blocklist' option to the command line arguments. * This option is a boolean that enables or disables blocklisting of accounts. * It is not required and defaults to false. * The option can also be set using the alias 'b'. * * @param {yargs.Argv<{}>} yargs - The yargs instance to which the option is added. * @private * @static */ private static blocklistingOption(yargs: Argv<{}>): void { yargs.option('blocklist', { alias: 'b', type: 'boolean', describe: 'Enable or disable blocklisting accounts', demandOption: false, default: false }); } /** * Adds the 'verbose' option to the command line arguments. * This option is a string that sets the verbose level. * It is not required and defaults to 'info'. * The valid choices for this option are 'info' and 'trace'. * * @param {yargs.Argv<{}>} yargs - The yargs instance to which the option is added. * @public * @static */ public static verboseLevelOption(yargs: Argv<{}>): void { yargs.option('verbose', { type: 'string', describe: 'Set the verbose level', demandOption: false, choices: ['silent', 'error', 'warning', 'info', 'debug', 'trace'], default: 'info', }) } /** * Adds the 'network-tag' option to the command line arguments. * This option is a string that enables usage of custom network tag. * It is not required and defaults to predefined configuration. * * @param {yargs.Argv<{}>} yargs - The yargs instance to which the option is added. * @private * @static */ private static selectNetworkTag(yargs: Argv<{}>): void { yargs.option('network-tag', { type: 'string', describe: 'Select custom network node tag', demandOption: false, default: '' }); } /** * Adds the 'mirror-tag' option to the command line arguments. * This option is a string that enables usage of custom mirror-node tag. * It is not required and defaults to predefined configuration. * * @param {yargs.Argv<{}>} yargs - The yargs instance to which the option is added. * @private * @static */ private static selectMirrorTag(yargs: Argv<{}>): void { yargs.option('mirror-tag', { type: 'string', describe: 'Select custom mirror-node tag', demandOption: false, default: '' }); } /** * Adds the 'block-node-tag' option to the command line arguments. * This option is a string that enables usage of custom block-node tag. * It is not required and defaults to predefined configuration. * * @param {yargs.Argv<{}>} yargs - The yargs instance to which the option is added. * @private * @static */ private static selectBlockNodeTag(yargs: Argv<{}>): void { yargs.option('block-node-tag', { type: 'string', describe: 'Select custom block-node tag', demandOption: false, default: '' }); } /** * Adds the 'mirror-tag' option to the command line arguments. * This option is a string that enables usage of custom mirror-node tag. * It is not required and defaults to predefined configuration. * * @param {yargs.Argv<{}>} yargs - The yargs instance to which the option is added. * @private * @static */ private static selectRelayTag(yargs: Argv<{}>): void { yargs.option('relay-tag', { type: 'string', describe: 'Select custom hedera-json-rpc relay tag', demandOption: false, default: '' }); } /** * Adds the 'create-initial-resources' option to the command line arguments. * This option is a boolean that enables or disables creation of initial resources. * It is not required and defaults to false. * * @param {yargs.Argv<{}>} yargs - The yargs instance to which the option is added. * @private * @static */ private static createInitialResources(yargs: Argv<{}>): void { yargs.option('create-initial-resources', { type: 'boolean', describe: 'Enable or disable creation of initial resources', demandOption: false, default: false }); } /** * Resolve the verbose level from a string. * @param {string} level - The verbose level as a string. * @returns {VerboseLevel} The verbose level. * @public */ public static resolveVerboseLevel(level: string): VerboseLevel { switch (level) { case 'silent': return VerboseLevel.SILENT; case 'error': return VerboseLevel.ERROR; case 'warning': return VerboseLevel.WARNING; case 'info': return VerboseLevel.INFO; case 'debug': return VerboseLevel.DEBUG; case 'trace': return VerboseLevel.TRACE; default: return VerboseLevel.INFO; } } }