@@ -203,16 +203,41 @@ The delpw command removes a password for a given address (keyfile).
203203 },
204204 Description : `
205205The newaccount command creates a new keystore-backed account. It is a convenience-method
206- which can be used in lieu of an external UI.` ,
207- }
208-
206+ which can be used in lieu of an external UI.
207+ ` }
209208 gendocCommand = & cli.Command {
210209 Action : GenDoc ,
211210 Name : "gendoc" ,
212211 Usage : "Generate documentation about json-rpc format" ,
213212 Description : `
214213The gendoc generates example structures of the json-rpc communication types.
215214` }
215+ listAccountsCommand = & cli.Command {
216+ Action : listAccounts ,
217+ Name : "list-accounts" ,
218+ Usage : "List accounts in the keystore" ,
219+ Flags : []cli.Flag {
220+ logLevelFlag ,
221+ keystoreFlag ,
222+ utils .LightKDFFlag ,
223+ acceptFlag ,
224+ },
225+ Description : `
226+ Lists the accounts in the keystore.
227+ ` }
228+ listWalletsCommand = & cli.Command {
229+ Action : listWallets ,
230+ Name : "list-wallets" ,
231+ Usage : "List wallets known to Clef" ,
232+ Flags : []cli.Flag {
233+ logLevelFlag ,
234+ keystoreFlag ,
235+ utils .LightKDFFlag ,
236+ acceptFlag ,
237+ },
238+ Description : `
239+ Lists the wallets known to Clef.
240+ ` }
216241)
217242
218243var app = flags .NewApp ("Manage Ethereum account operations" )
@@ -249,6 +274,8 @@ func init() {
249274 delCredentialCommand ,
250275 newAccountCommand ,
251276 gendocCommand ,
277+ listAccountsCommand ,
278+ listWalletsCommand ,
252279 }
253280}
254281
@@ -351,6 +378,22 @@ func attestFile(ctx *cli.Context) error {
351378 return nil
352379}
353380
381+ func initInternalApi (c * cli.Context ) (* core.UIServerAPI , error ) {
382+ if err := initialize (c ); err != nil {
383+ return nil , err
384+ }
385+ var (
386+ ui = core .NewCommandlineUI ()
387+ pwStorage storage.Storage = & storage.NoStorage {}
388+ ksLoc = c .String (keystoreFlag .Name )
389+ lightKdf = c .Bool (utils .LightKDFFlag .Name )
390+ )
391+ am := core .StartClefAccountManager (ksLoc , true , lightKdf , "" )
392+ api := core .NewSignerAPI (am , 0 , true , ui , nil , false , pwStorage )
393+ internalApi := core .NewUIServerAPI (api )
394+ return internalApi , nil
395+ }
396+
354397func setCredential (ctx * cli.Context ) error {
355398 if ctx .NArg () < 1 {
356399 utils .Fatalf ("This command requires an address to be passed as an argument" )
@@ -409,31 +452,6 @@ func removeCredential(ctx *cli.Context) error {
409452 return nil
410453}
411454
412- func newAccount (c * cli.Context ) error {
413- if err := initialize (c ); err != nil {
414- return err
415- }
416- // The newaccount is meant for users using the CLI, since 'real' external
417- // UIs can use the UI-api instead. So we'll just use the native CLI UI here.
418- var (
419- ui = core .NewCommandlineUI ()
420- pwStorage storage.Storage = & storage.NoStorage {}
421- ksLoc = c .String (keystoreFlag .Name )
422- lightKdf = c .Bool (utils .LightKDFFlag .Name )
423- )
424- log .Info ("Starting clef" , "keystore" , ksLoc , "light-kdf" , lightKdf )
425- am := core .StartClefAccountManager (ksLoc , true , lightKdf , "" )
426- // This gives is us access to the external API
427- apiImpl := core .NewSignerAPI (am , 0 , true , ui , nil , false , pwStorage )
428- // This gives us access to the internal API
429- internalApi := core .NewUIServerAPI (apiImpl )
430- addr , err := internalApi .New (context .Background ())
431- if err == nil {
432- fmt .Printf ("Generated account %v\n " , addr .String ())
433- }
434- return err
435- }
436-
437455func initialize (c * cli.Context ) error {
438456 // Set up the logger to print everything
439457 logOutput := os .Stdout
@@ -459,6 +477,57 @@ func initialize(c *cli.Context) error {
459477 return nil
460478}
461479
480+ func newAccount (c * cli.Context ) error {
481+ internalApi , err := initInternalApi (c )
482+ if err != nil {
483+ return err
484+ }
485+ addr , err := internalApi .New (context .Background ())
486+ if err == nil {
487+ fmt .Printf ("Generated account %v\n " , addr .String ())
488+ }
489+ return err
490+ }
491+
492+ func listAccounts (c * cli.Context ) error {
493+ internalApi , err := initInternalApi (c )
494+ if err != nil {
495+ return err
496+ }
497+ accs , err := internalApi .ListAccounts (context .Background ())
498+ if err != nil {
499+ return err
500+ }
501+ if len (accs ) == 0 {
502+ fmt .Println ("\n The keystore is empty." )
503+ }
504+ fmt .Println ()
505+ for _ , account := range accs {
506+ fmt .Printf ("%v (%v)\n " , account .Address , account .URL )
507+ }
508+ return err
509+ }
510+
511+ func listWallets (c * cli.Context ) error {
512+ internalApi , err := initInternalApi (c )
513+ if err != nil {
514+ return err
515+ }
516+ wallets := internalApi .ListWallets ()
517+ if len (wallets ) == 0 {
518+ fmt .Println ("\n There are no wallets." )
519+ }
520+ fmt .Println ()
521+ for i , wallet := range wallets {
522+ fmt .Printf ("- Wallet %d at %v (%v %v)\n " , i , wallet .URL , wallet .Status , wallet .Failure )
523+ for j , acc := range wallet .Accounts {
524+ fmt .Printf (" -Account %d: %v (%v)\n " , j , acc .Address , acc .URL )
525+ }
526+ fmt .Println ()
527+ }
528+ return nil
529+ }
530+
462531// ipcEndpoint resolves an IPC endpoint based on a configured value, taking into
463532// account the set data folders as well as the designated platform we're currently
464533// running on.
0 commit comments