Skip to content

Commit f3a005f

Browse files
jmcook1186holiman
andauthored
cmd/clef: add list-accounts and list-wallets to CLI (#26080)
This commit adds support for two new commands to clef, making it possible to list accounts / wallets from the command-line-interface. Co-authored-by: Martin Holst Swende <[email protected]>
1 parent 05037ea commit f3a005f

File tree

1 file changed

+97
-28
lines changed

1 file changed

+97
-28
lines changed

cmd/clef/main.go

Lines changed: 97 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -203,16 +203,41 @@ The delpw command removes a password for a given address (keyfile).
203203
},
204204
Description: `
205205
The 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: `
214213
The 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

218243
var 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+
354397
func 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-
437455
func 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("\nThe 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("\nThere 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

Comments
 (0)