22import os
33import subprocess
44import time
5- import inquirer
5+ import questionary
66import requests
77
88
99def get_archive_ttl_message (answers : dict ):
10- global default_archive_ttl
1110 archive_blocks = answers .get ('archive-blocks' )
1211 if not archive_blocks and answers ['archive-blocks' ] != 0 :
1312 return 'Send the number of seconds to keep the block data in the node database. Default is 2592000 (30 days)'
@@ -24,7 +23,7 @@ def get_archive_ttl_message(answers: dict):
2423 utime = int (datetime .datetime .strptime (block_from , '%Y-%m-%d' ).timestamp ())
2524 default_archive_ttl = int (time .time () - (utime - datetime .timedelta (days = 30 ).total_seconds ()))
2625 answers ['archive-ttl-default' ] = default_archive_ttl
27- return f'Send the number of seconds to keep the block data in the node database. Default is { default_archive_ttl } to keep archive blocks from { datetime .datetime .fromtimestamp (utime - datetime .timedelta (days = 30 ).total_seconds ())} \n Or send -1 to keep downloaded blocks always (recommended).'
26+ return f'Send the number of seconds to keep the block data in the node database.\n Skip to use default: { default_archive_ttl } to keep blocks from provided date for 30 days ( { datetime .datetime .fromtimestamp (utime - datetime .timedelta (days = 30 ).total_seconds ())} ) \n Or send -1 to keep downloaded blocks always (recommended).'
2827
2928
3029def is_valid_date_format (date_str ):
@@ -35,77 +34,114 @@ def is_valid_date_format(date_str):
3534 return False
3635
3736
38- def validate_archive_blocks (_ , value ):
37+ def validate_archive_blocks (value ):
3938 if not value :
4039 return True
4140 parts = value .split ()
4241 if len (parts ) > 2 :
43- return False
42+ return "Too many parameters provided"
4443
4544 for part in parts :
4645 if part .isdigit () and int (part ) < 0 :
47- return False
48- elif not is_valid_date_format (part ):
49- return False
46+ return "Block number cannot be negative"
47+ elif not part .isdigit () and not is_valid_date_format (part ):
48+ return "Incorrect date format, use YYYY-MM-DD"
49+ return True
50+
51+
52+ def validate_http_url (value ):
53+ if not value .startswith ("http" ):
54+ return "URL must start with http"
55+ return True
56+
57+
58+ def validate_digits (value ):
59+ try :
60+ int (value )
61+ return True
62+ except ValueError :
63+ return "Input must be a number"
64+
65+
66+ def validate_shard_format (value ):
67+ if not value :
68+ return True
69+ for shard in value .split ():
70+ if ":" not in shard :
71+ return "Each shard must be in format <workchain>:<shard>"
5072 return True
5173
5274
5375def run_cli ():
54- questions = [
55- inquirer . List (
56- "mode" ,
57- message = "Select installation mode (More on https://docs.ton.org/participate/nodes/node-types)" ,
58- choices = [ "validator" , "liteserver" ],
59- ),
60- inquirer . List (
61- "network" ,
62- message = "Select network" ,
63- choices = [ "Mainnet" , "Testnet" , "Other" ],
64- ),
65- inquirer . Text (
66- "config" ,
67- message = "Provide network config uri" ,
68- ignore = lambda x : x [ "network" ] != "Other" , # do not ask this question if network is not 'Other'
69- validate = lambda _ , x : x . startswith ( "http" ),
70- ),
71- inquirer . List (
72- "validator-mode" ,
73- message = "Select mode for validator usage. You can skip and set up this later" ,
74- ignore = lambda x : x [ " mode" ] != " validator" , # do not ask this question if mode is not validator
76+ mode = questionary . select (
77+ "Select installation mode (More on https://docs.ton.org/participate/nodes/node-types)" ,
78+ choices = [ "validator" , "liteserver" ] ,
79+ ). unsafe_ask ()
80+
81+ network = questionary . select (
82+ "Select network" ,
83+ choices = [ "Mainnet" , "Testnet" , "Other" ] ,
84+ ). unsafe_ask ()
85+
86+ config = None
87+ if network == "Other" :
88+ config = questionary . text (
89+ "Provide network config uri" ,
90+ validate = validate_http_url
91+ ). unsafe_ask ()
92+
93+ validator_mode = None
94+ if mode == "validator" :
95+ validator_mode = questionary . select (
96+ "Select mode for validator usage. You can set up this later" ,
7597 choices = ["Validator wallet" , "Nominator pool" , "Single pool" , "Liquid Staking" , "Skip" ],
76- ),
77- inquirer .Text (
78- "archive-blocks" ,
79- message = "Do you want to download archive blocks via TON Storage? Press Enter to skip.\n "
80- "If yes, provide block seqno or date to start from and (optionally) block seqno or date to end with (send 0 to download all blocks and setup full archive node).\n "
81- "Examples: `30850000`, `10000000 10200000`, `2025-01-01`, `2025-01-01 2025-01-30`" ,
82- ignore = lambda x : x ["mode" ] == "validator" ,
83- validate = validate_archive_blocks ,
84- ),
85- inquirer .Text (
86- "archive-ttl" ,
87- message = get_archive_ttl_message ,
88- ignore = lambda x : x ["mode" ] != "liteserver" , # do not ask this question if mode is not liteserver
89- validate = lambda _ , x : not x or x .isdigit (), # must be empty string or a number
90- # default=get_default_archive_ttl
91- ),
92- inquirer .Confirm (
93- "dump" ,
94- message = "Do you want to download blockchain's dump? "
95- "This reduces synchronization time but requires to download a large file" ,
96- ignore = lambda x : x ["archive-blocks" ],
97- ),
98- inquirer .Text (
99- "add-shard" ,
100- message = "Set shards node will sync. Skip to sync all shards. "
101- "Format: <workchain>:<shard>. Divide multiple shards with space. "
102- "Example: `0:2000000000000000 0:6000000000000000`" ,
103- validate = lambda _ , x : not x or all ([":" in i for i in x .split ()])
104- )
105- ]
106-
107- answers = inquirer .prompt (questions )
108-
98+ ).unsafe_ask ()
99+
100+ archive_blocks = None
101+ if mode != "validator" :
102+ archive_blocks = questionary .text (
103+ "Do you want to download archive blocks via TON Storage? Press Enter to skip.\n "
104+ "If yes, provide block seqno or date to start from and (optionally) block seqno or date to end with (send 0 to download all blocks and setup full archive node).\n "
105+ "Examples: `30850000`, `10000000 10200000`, `2025-01-01`, `2025-01-01 2025-01-30`" ,
106+ validate = validate_archive_blocks
107+ ).unsafe_ask ()
108+
109+ archive_ttl = None
110+ if mode == "liteserver" :
111+ temp_answers = {
112+ 'archive-blocks' : archive_blocks ,
113+ 'network' : network
114+ }
115+ archive_ttl = questionary .text (
116+ get_archive_ttl_message (temp_answers ),
117+ validate = validate_digits
118+ ).unsafe_ask ()
119+
120+ dump = None
121+ if not archive_blocks :
122+ dump = questionary .confirm (
123+ "Do you want to download blockchain's dump? "
124+ "This reduces synchronization time but requires to download a large file"
125+ ).unsafe_ask ()
126+
127+ add_shard = questionary .text (
128+ "Set shards node will sync. Skip to sync all shards. "
129+ "Format: <workchain>:<shard>. Divide multiple shards with space. "
130+ "Example: `0:2000000000000000 0:6000000000000000`" ,
131+ validate = validate_shard_format
132+ ).unsafe_ask ()
133+
134+ answers = {
135+ "mode" : mode ,
136+ "network" : network ,
137+ "config" : config ,
138+ "validator-mode" : validator_mode ,
139+ "archive-blocks" : archive_blocks ,
140+ "archive-ttl" : archive_ttl ,
141+ "dump" : dump ,
142+ "add-shard" : add_shard
143+ }
144+ print (answers )
109145 return answers
110146
111147
@@ -149,7 +185,11 @@ def parse_args(answers: dict):
149185
150186
151187def main ():
152- answers = run_cli ()
188+ try :
189+ answers = run_cli ()
190+ except KeyboardInterrupt :
191+ print ("\n Installation cancelled by user" )
192+ return
153193 command = parse_args (answers )
154194 # subprocess.run('bash scripts/install.sh ' + command, shell=True)
155195 print ('bash install.sh ' + command )
0 commit comments