PK!6O'create_tomochain_masternode/__init__.py__version__ = '1.1.0' PK!#create_tomochain_masternode/envs.pymainnet = { 'metrics_endpoint': 'https://metrics.tomochain.com', 'network_id': '88', 'ws_secret': 'getty-site-pablo-auger-room-sos-blair-shin-whiz-delhi', 'bootnodes': ( 'enode://97f0ca95a653e3c44d5df2674e19e9324ea4bf4d47a46b1d8560f3ed' '4ea328f725acec3fcfcb37eb11706cf07da669e9688b091f1543f89b2425700a' '68bc8876@104.248.98.78:30301,enode://b72927f349f3a27b789d0ca615f' 'fe3526f361665b496c80e7cc19dace78bd94785fdadc270054ab727dbb172d9e' '3113694600dd31b2558dd77ad85a869032dea@188.166.207.189:30301,enod' 'e://c8f2f0643527d4efffb8cb10ef9b6da4310c5ac9f2e988a7f85363e81d42' 'f1793f64a9aa127dbaff56b1e8011f90fe9ff57fa02a36f73220da5ff81d8b8d' 'f351@104.248.98.60:30301' ) } testnet = { 'metrics_endpoint': 'https://metrics.testnet.tomochain.com', 'network_id': '89', 'ws_secret': 'anna-coal-flee-carrie-zip-hhhh-tarry-laue-felon-rhine', 'bootnodes': ( 'enode://4d3c2cc0ce7135c1778c6f1cfda623ab44b4b6db55289543d48ecfde' '7d7111fd420c42174a9f2fea511a04cf6eac4ec69b4456bfaaae0e5bd236107d' '3172b013@52.221.28.223:30301,enode://298780104303fcdb37a84c5702e' 'bd9ec660971629f68a933fd91f7350c54eea0e294b0857f1fd2e8dba2869fcc3' '6b83e6de553c386cf4ff26f19672955d9f312@13.251.101.216:30301,enode' '://46dba3a8721c589bede3c134d755eb1a38ae7c5a4c69249b8317c55adc8d4' '6a369f98b06514ecec4b4ff150712085176818d18f59a9e6311a52dbe68cff5b' '2ae@13.250.94.232:30301' ) } PK!#create_tomochain_masternode/main.pyfrom typing import Dict import os import shutil import sys from jinja2 import Template import click from create_tomochain_masternode import __version__, envs, templates @click.command(help='Set up a TomoChain masternode by running one command.') @click.argument('name', type=click.Path( file_okay=False, resolve_path=True )) @click.option('--testnet', is_flag=True, help='Testnet instead of mainnet.') @click.version_option(version=__version__) def entrypoint(name: click.Path, testnet: bool) -> None: """Command line interface entrypoint""" env = envs.testnet if testnet else envs.mainnet masternode_path = name masternode_name = os.path.basename(os.path.normpath(name)) if not is_folder_empty(masternode_path): error('Folder is not empty.') sys.exit(1) display( 'Creating a new masternode in ' f'{click.style(masternode_path, fg="green")}.', spacing=1 ) preflight() answers = ask() compose_template = Template(templates.compose) compose_content = compose_template.render(**answers, **env) env_template = Template(templates.env) env_content = env_template.render(name=masternode_name, **answers, **env) try: if not os.path.exists(masternode_path): os.makedirs(masternode_path) with open(f'{masternode_path}/docker-compose.yml', 'w') as file: print(compose_content, file=file) with open(f'{masternode_path}/.env', 'w') as file: print(env_content, file=file) except Exception: error('Could not create files.') success(masternode_name, masternode_path) def is_folder_empty(path: str) -> bool: """Check if folder is empty or not""" try: return False if os.listdir(path) else True except FileNotFoundError: return True def display( message: str, spacing_top: int = 0, spacing_bottom: int = 0, spacing: int = 0, padding: int = 0, ) -> None: """Printing helper function""" newlines_top = '\n' * spacing_top if not spacing else '\n' * spacing newlines_bottom = '\n' * spacing_bottom if not spacing else '\n' * spacing leftpad = ' ' * padding click.echo(f'{newlines_top}{leftpad}{message}{newlines_bottom}') def error(message: str) -> None: """Error helper function""" display( f'{click.style("! ", fg="red")}{message}', spacing=1 ) def preflight() -> None: """Display errors if preflight checks are missing""" if not shutil.which('docker'): error('Docker not found on your system.') if not shutil.which('docker-compose'): error('Docker-compose not found on your system.') def ask() -> Dict[str, str]: """Prompt users for parameters""" answers = {} bullet = f'{click.style("?", fg="cyan")}' answers['private_key'] = click.prompt( f'{bullet} Coinbase private key', hide_input=True, ) answers['storage'] = click.prompt( f'{bullet} Storage', type=click.Choice(['docker volume', 'host directory']), default='host directory', ) answers['data'] = click.prompt( f'{bullet} Chaindata {answers["storage"]}', type=click.Path( exists=True, file_okay=False, resolve_path=True, ) if answers["storage"] == 'host directory' else click.STRING ) answers['expose_rpc'] = click.confirm( f'{bullet} Expose RPC', ) answers['expose_ws'] = click.confirm( f'{bullet} Expose WebSocket', ) answers['logging_level'] = logging_name_to_int(click.prompt( f'{bullet} Logging level', type=click.Choice(['error', 'info', 'debug']), default='info', )) print(answers['logging_level']) return answers def success(name: str, masternode_path: str) -> None: """Display instruction text when finished with success""" display( f'Success! Created {name} at {masternode_path}\n' 'Inside that directory you can run several commands:', spacing_top=1 ) display( f'{click.style("docker-compose up|down", fg="cyan")}', spacing_top=1, padding=2 ) display( f'Create|remove your masternode', padding=2 ) display( f'{click.style("docker-compose ps", fg="cyan")}', spacing_top=1, padding=2 ) display( f'Check if your masternode is running', padding=2 ) display( f'{click.style("docker-compose stop|start [SERVICE...]", fg="cyan")}', spacing_top=1, padding=2 ) display( f'Stop|start your masternode', padding=2 ) display( f'{click.style("docker-compose logs [SERVICES...]", fg="cyan")}', spacing_top=1, padding=2 ) display( f'View your masternode logs', padding=2 ) display( f'{click.style("docker-compose --help", fg="cyan")}', spacing_top=1, padding=2 ) display( f'View all the possible docker-compose commands', padding=2 ) display( f'We suggest that you begin by typing:', spacing_top=1, ) display( f'{click.style("cd", fg="cyan")} {name}', spacing_top=1, padding=2 ) display( f'{click.style("docker-compose up -d", fg="cyan")}', padding=2 ) display( f'May the rewards be with you!', spacing=1 ) def logging_name_to_int(name: str) -> int: """Transform logging name to numerical level for tomo client""" print(name) if name == 'error': return 2 elif name == 'info': return 3 elif name == 'debug': return 4 else: return 5 if __name__ == '__main__': # frozen app fix if getattr(sys, 'frozen', False): entrypoint(sys.argv[1:]) PK!'PP1create_tomochain_masternode/templates/__init__.pyfrom .compose import compose from .env import env __all__ = ['compose', 'env'] PK!J?0create_tomochain_masternode/templates/compose.pycompose = """version: "3.4" services: tomochain: image: tomochain/node:stable environment: IDENTITY: $IDENTITY PRIVATE_KEY: $PRIVATE_KEY BOOTNODES: {{ bootnodes }} NETWORK_ID: {{ network_id }} VERBOSITY: {{ logging_level }} NETSTATS_HOST: stats.tomochain.com NETSTATS_PORT: 443 WS_SECRET: {{ ws_secret }} volumes: - $DATA:/tomochain/data ports: - 30303:30303/tcp - 30303:30303/udp {%- if expose_rpc %} - 8545:8545 {%- endif %} {%- if expose_ws %} - 8546:8546 {%- endif %} restart: always {% if storage == "docker volume" -%} volumes: {{ data }}: {%- endif %} """ PK!IvPP,create_tomochain_masternode/templates/env.pyenv = """IDENTITY={{ name }} PRIVATE_KEY={{ private_key }} DATA={{ data }} """ PK!H6F[<create_tomochain_masternode-1.1.0.dist-info/entry_points.txtEA @YLHH]K/8Jn'cRȨ܀{q+W5Y;/wߤgkXPK!HڽTU1create_tomochain_masternode-1.1.0.dist-info/WHEEL A н#Z;/"d&F[xzw@Zpy3Fv]\fi4WZ^EgM_-]#0(q7PK!HK84create_tomochain_masternode-1.1.0.dist-info/METADATASao0_qR 4:Em 4Vu}&a ].@&$ɽw+ wt^Õ'c Cd)6)]a"ϥ+c`‚gb*X0+Z+C, ȭ\ev=U USy0Ht.,_K} 55LC[[EXZ#Қ Iľ1*ǏWz>* L[EuVe{5WH2!ufi=xzjt2Q1TR7yA nQۑ3 'm( ;5):/f?qs0|Dkh݈N4F^ɫ B9$L-Kg&h{ MFzV20Fk ƕ:P ŬCڧ"G8eŜ.-0ЦS8REOER@?$EN2d6CIIH%3DQŽ?oo/>h9eF]\@7[ufQ J)FηwmTj E:E(.[[s\h݇cyGq&Չ;PK!H$d2create_tomochain_masternode-1.1.0.dist-info/RECORD˒0}? 8\5\UhP1@nQQ|qSV͔ӽL$dEHK.k!eEߑe,&Ǒ()^ׂRouyCZ'iaC*T^t}(53Nj'~ +m mb3l@ۊQynvJ0h.NU.jwQ|jr N iO#jjI0*ai"KM-Mbߟܑӿ  -d{wIPc?U` joIvZnI#s1s<&\<^5`Y۫-*O6"{<?DS$wcv$ct®Ainz@~5/ Q gΉM Gdpv9:%7#2 G4@ ۶z4'ZsM ieLxc=[~]h%_~8Q6Ի3m{ PK!6O'create_tomochain_masternode/__init__.pyPK!#[create_tomochain_masternode/envs.pyPK!#create_tomochain_masternode/main.pyPK!'PP1create_tomochain_masternode/templates/__init__.pyPK!J?0icreate_tomochain_masternode/templates/compose.pyPK!IvPP,l!create_tomochain_masternode/templates/env.pyPK!H6F[<"create_tomochain_masternode-1.1.0.dist-info/entry_points.txtPK!HڽTU1"create_tomochain_masternode-1.1.0.dist-info/WHEELPK!HK84I#create_tomochain_masternode-1.1.0.dist-info/METADATAPK!H$d2%create_tomochain_masternode-1.1.0.dist-info/RECORDPK (