@@ -68,18 +68,19 @@ def groups_layout( names, group_threshold, groups, passphrase=None ):
6868 [
6969 sg .Text ( "Seed File Name(s): " , size = prefix , ** T_kwds ),
7070 sg .Input ( f"{ ', ' .join ( names )} " , key = '-NAMES-' , ** I_kwds ),
71- sg .Text ( "(comma-separted )" , ** T_kwds ),
71+ sg .Text ( "(optional; comma-separated )" , ** T_kwds ),
7272 ]
7373 ] + [
7474 [
7575 sg .Text ( "Requires recovery of at least: " , size = prefix , ** T_kwds ),
7676 sg .Input ( f"{ group_threshold } " , key = '-THRESHOLD-' , ** I_kwds ),
77- sg .Text ( f"of { len (groups )} SLIP-39 Recovery Groups" , key = '-RECOVERY-' , ** T_kwds ),
77+ sg .Text ( f"( of { len (groups )} SLIP-39 Recovery Groups) " , key = '-RECOVERY-' , ** T_kwds ),
7878 ],
7979 ] + [
8080 [
8181 sg .Text ( "Passphrase to encrypt Seed: " , size = prefix , ** T_kwds ),
8282 sg .Input ( f"{ passphrase or '' } " , key = '-PASSPHRASE-' , ** I_kwds ),
83+ sg .Text ( "(optional; must be remembered separately!!)" , ** T_kwds ),
8384 ],
8485 ] + [
8586 [
@@ -144,29 +145,21 @@ def app(
144145 window = None
145146 status = None
146147 event = False
147- while event not in (sg .WIN_CLOSED , 'Exit' ,):
148+ events_termination = (sg .WIN_CLOSED , 'Exit' ,)
149+ while event not in events_termination :
148150 # Create window (for initial window.read()), or update status
149151 if window :
150152 window ['-STATUS-' ].update ( status or 'OK' )
151- window ['-RECOVERY-' ].update ( f"of { len (groups )} SLIP-39 Recovery Groups" , ** T_kwds ),
153+ window ['-RECOVERY-' ].update ( f"( of { len (groups )} SLIP-39 Recovery Groups) " , ** T_kwds ),
152154 else :
153- window = sg .Window ( f"{ ', ' .join ( names )} Mnemonic Cards" , layout )
155+ window = sg .Window ( f"{ ', ' .join ( names or [ 'SLIP39' ] )} Mnemonic Cards" , layout )
154156
155157 status = None
156158 event , values = window .read ()
157159 logging .info ( f"{ event } , { values } " )
158- if not values :
160+ if not values or event in events_termination :
159161 continue
160162
161- if '-TARGET-' in values :
162- # A target directory has been selected;
163- try :
164- os .chdir ( values ['-TARGET-' ] )
165- except Exception as exc :
166- status = f"Error changing to target directory { values ['-TARGET-' ]} : { exc } "
167- logging .exception ( f"{ status } " )
168- continue
169-
170163 if event == '+' :
171164 g = len (groups )
172165 name = f"Group { g + 1 } "
@@ -177,15 +170,17 @@ def app(
177170 window .extend_layout ( window ['-GROUP-NEEDS-' ], [[ sg .Input ( f"{ needs [0 ]} " , key = f"-G-NEED-{ g } " , ** I_kwds ) ]] ) # noqa: 241
178171 window .extend_layout ( window ['-GROUP-SIZES-' ], [[ sg .Input ( f"{ needs [1 ]} " , key = f"-G-SIZE-{ g } " , ** I_kwds ) ]] ) # noqa: 241
179172
173+ # A target directory must be selected; use it. This is where any output will be written.
174+ # It should usually be a removable volume, but we do not check for this.
180175 try :
181- g_thr_val = values ['-THRESHOLD-' ]
182- g_thr = int ( g_thr_val )
176+ os .chdir ( values ['-TARGET-' ] )
183177 except Exception as exc :
184- status = f"Error defining group threshold { g_thr_val } : { exc } "
178+ status = f"Error changing to target directory { values [ '-TARGET-' ]!r } : { exc } "
185179 logging .exception ( f"{ status } " )
186180 continue
187181
188- # Collect up the specified Group names; ignores groups with an empty name
182+ # Collect up the specified Group names; ignores groups with an empty name (effectively
183+ # eliminating that group)
189184 g_rec = {}
190185 status = None
191186 for g in range ( 16 ):
@@ -203,20 +198,34 @@ def app(
203198 logging .exception ( f"{ status } " )
204199 continue
205200
201+ # Confirm the selected Group Threshold requirement
202+ try :
203+ g_thr_val = values ['-THRESHOLD-' ]
204+ g_thr = int ( g_thr_val )
205+ assert 0 < g_thr <= len ( g_rec ), \
206+ f"must be an integer between 1 and the number of groups ({ len (g_rec )} )"
207+ except Exception as exc :
208+ status = f"Error defining group threshold { g_thr_val !r} : { exc } "
209+ logging .exception ( f"{ status } " )
210+ continue
211+
206212 summary = f"Require { g_thr } /{ len (g_rec )} Groups, from: { f', ' .join ( f'{ n } ({ need } /{ size } )' for n ,(need ,size ) in g_rec .items ())} "
207213 passphrase = values ['-PASSPHRASE-' ].strip ()
208214 if passphrase :
209215 summary += f", decrypted w/ passphrase { passphrase !r} "
210216 window ['-SUMMARY-' ].update ( summary )
211217
218+ # Deduce the desired Seed names, defaulting to "SLIP39"
212219 names = [
213220 name .strip ()
214- for name in values ['-NAMES-' ].split ( ',' )
221+ for name in ( values ['-NAMES-' ]. strip () or "SLIP39" ) .split ( ',' )
215222 if name and name .strip ()
216223 ]
224+
225+ # Compute the SLIP39 Seed details
217226 details = {}
218227 try :
219- for name in names or [ "SLIP39" ] :
228+ for name in names :
220229 details [name ] = create (
221230 name = name ,
222231 group_threshold = group_threshold ,
@@ -229,12 +238,20 @@ def app(
229238 logging .exception ( f"{ status } " )
230239 continue
231240
232- # If we get here, no failure status has been detected; we could save (details is now { "<filename>": <details> })
241+ # If we get here, no failure status has been detected, and SLIP39 mnemonic and account
242+ # details { "name": <details> } have been created; we can now save the PDFs; converted
243+ # details is now { "<filename>": <details> })
233244 if event == 'Save' :
234- details = write_pdfs (
235- names = details ,
236- )
245+ try :
246+ details = write_pdfs (
247+ names = details ,
248+ )
249+ except Exception as exc :
250+ status = f"Error saving PDF(s): { exc } "
251+ logging .exception ( f"{ status } " )
252+ continue
237253
254+ # Finally, if all has gone well -- display the resultant <name>/<filename>, and some derived account details
238255 name_len = max ( len ( name ) for name in details )
239256 status = '\n ' .join (
240257 f"{ name :>{name_len }} == " + ', ' .join ( f'{ a .crypto } @ { a .path } : { a .address } ' for a in details [name ].accounts [0 ] )
0 commit comments