@@ -3,13 +3,27 @@ package cmd
3
3
import (
4
4
"encoding/json"
5
5
"fmt"
6
+ "strconv"
6
7
"strings"
7
8
9
+ "github.com/charmbracelet/huh"
8
10
"github.com/spf13/cobra"
9
11
10
12
"github.com/bandprotocol/falcon/relayer"
11
13
)
12
14
15
+ const (
16
+ privateKeyLabel = "Private key (provide an existing private key)"
17
+ mnemonicLabel = "Mnemonic (recover from an existing mnemonic phrase)"
18
+ defaultLabel = "Generate new address (no private key or mnemonic needed)"
19
+ )
20
+
21
+ const (
22
+ privateKeyResult = iota
23
+ mnemonicResult
24
+ defaultResult
25
+ )
26
+
13
27
// keysCmd represents the keys command
14
28
func keysCmd (app * relayer.App ) * cobra.Command {
15
29
cmd := & cobra.Command {
@@ -42,41 +56,133 @@ $ %s k a eth test-key`, appName, appName)),
42
56
RunE : func (cmd * cobra.Command , args []string ) error {
43
57
chainName := args [0 ]
44
58
keyName := args [1 ]
45
-
46
- mnemonic , err := cmd .Flags ().GetString (flagMnemonic )
47
- if err != nil {
59
+ mnemonic := ""
60
+ privateKey := ""
61
+
62
+ var (
63
+ coinType , account , index uint64
64
+ coinTypeStr , accountStr , indexStr string
65
+ )
66
+
67
+ // Use huh to create a form for user input
68
+ selection := 0
69
+ selectionPrompt := huh .NewGroup (huh .NewSelect [int ]().
70
+ Title ("Choose how to add a key" ).
71
+ Options (
72
+ huh .NewOption (privateKeyLabel , privateKeyResult ),
73
+ huh .NewOption (mnemonicLabel , mnemonicResult ),
74
+ huh .NewOption (defaultLabel , defaultResult ),
75
+ ).
76
+ Value (& selection ))
77
+
78
+ form := huh .NewForm (selectionPrompt )
79
+ if err := form .WithTheme (huh .ThemeBase ()).Run (); err != nil {
48
80
return err
49
81
}
50
82
51
- privateKey , err := cmd .Flags ().GetString (flagPrivateKey )
52
- if err != nil {
53
- return err
54
- }
55
-
56
- if mnemonic != "" && privateKey != "" {
57
- return fmt .Errorf ("only one of mnemonic or private key should be provided, not both" )
83
+ // Coin type input
84
+ coinTypeInput := huh .NewInput ().
85
+ Title ("Enter a coin type" ).
86
+ Description ("Coin type number for HD derivation (default: 60; leave empty to use default)" ).
87
+ Value (& coinTypeStr ).Validate (
88
+ func (s string ) error {
89
+ if s == "" {
90
+ coinType = defaultCoinType
91
+ return nil
92
+ }
93
+ var err error
94
+ coinType , err = strconv .ParseUint (s , 10 , 32 )
95
+ if err != nil {
96
+ return fmt .Errorf ("invalid coin type input (should be uint32)" )
97
+ }
98
+
99
+ return nil
100
+ },
101
+ )
102
+
103
+ // Account type input
104
+ accountInput := huh .NewInput ().
105
+ Title ("Enter an account" ).
106
+ Description ("Account number in the HD derivation path (default: 0; leave empty to use default)" ).
107
+ Value (& accountStr ).Validate (
108
+ func (s string ) error {
109
+ if s == "" {
110
+ account = 0
111
+ return nil
112
+ }
113
+ var err error
114
+ account , err = strconv .ParseUint (s , 10 , 32 )
115
+ if err != nil {
116
+ return fmt .Errorf ("invalid account input (should be uint32)" )
117
+ }
118
+
119
+ return nil
120
+ },
121
+ )
122
+
123
+ // Index type input
124
+ indexInput := huh .NewInput ().
125
+ Title ("Enter an index" ).
126
+ Description ("Index number for the specific address within an account in the HD derivation path (default: 0; leave empty to use default)" ).
127
+ Value (& indexStr ).Validate (
128
+ func (s string ) error {
129
+ if s == "" {
130
+ index = 0
131
+ return nil
132
+ }
133
+ var err error
134
+ index , err = strconv .ParseUint (s , 10 , 32 )
135
+ if err != nil {
136
+ return fmt .Errorf ("invalid index input (should be uint32)" )
137
+ }
138
+
139
+ return nil
140
+ },
141
+ )
142
+
143
+ // Handle the selected option
144
+ switch selection {
145
+ case privateKeyResult :
146
+ privateKeyPrompt := huh .NewGroup (huh .NewInput ().
147
+ Title ("Enter your private key" ).
148
+ Value (& privateKey ))
149
+
150
+ form := huh .NewForm (privateKeyPrompt )
151
+ if err := form .WithTheme (huh .ThemeBase ()).Run (); err != nil {
152
+ return err
153
+ }
154
+
155
+ case mnemonicResult :
156
+ mnemonicPrompt := huh .NewGroup (huh .NewInput ().
157
+ Title ("Enter your mnemonic" ).
158
+ Value (& mnemonic ),
159
+ coinTypeInput ,
160
+ accountInput ,
161
+ indexInput ,
162
+ )
163
+
164
+ form := huh .NewForm (mnemonicPrompt )
165
+ if err := form .WithTheme (huh .ThemeBase ()).Run (); err != nil {
166
+ return err
167
+ }
168
+ case defaultResult :
169
+ defaultPrompt := huh .NewGroup (coinTypeInput , accountInput , indexInput )
170
+ form := huh .NewForm (defaultPrompt )
171
+ if err := form .WithTheme (huh .ThemeBase ()).Run (); err != nil {
172
+ return err
173
+ }
58
174
}
59
175
60
- coinType , err := cmd .Flags ().GetInt32 (flagCoinType )
61
- if err != nil {
62
- return err
63
- }
64
-
65
- if coinType < 0 {
66
- coinType = defaultCoinType
67
- }
68
-
69
- account , err := cmd .Flags ().GetUint (flagAccount )
70
- if err != nil {
71
- return err
72
- }
73
-
74
- index , err := cmd .Flags ().GetUint (flagAccountIndex )
75
- if err != nil {
76
- return err
77
- }
78
-
79
- keyOutput , err := app .AddKey (chainName , keyName , mnemonic , privateKey , uint32 (coinType ), account , index )
176
+ // Add the key to the app
177
+ keyOutput , err := app .AddKey (
178
+ chainName ,
179
+ keyName ,
180
+ mnemonic ,
181
+ privateKey ,
182
+ uint32 (coinType ),
183
+ uint (account ),
184
+ uint (index ),
185
+ )
80
186
if err != nil {
81
187
return err
82
188
}
@@ -90,12 +196,7 @@ $ %s k a eth test-key`, appName, appName)),
90
196
return nil
91
197
},
92
198
}
93
- cmd .Flags ().StringP (flagMnemonic , "m" , "" , "add new key from specified mnemonic" )
94
- cmd .Flags ().StringP (flagPrivateKey , "p" , "" , "add new key from specified private key" )
95
- cmd .Flags ().Int32 (flagCoinType , - 1 , "coin type number for HD derivation" )
96
- cmd .Flags ().Uint (flagAccount , 0 , "account number within the HD derivation path" )
97
- cmd .Flags ().
98
- Uint (flagAccountIndex , 0 , "Index number for the specific address within an account in the HD derivation path" )
199
+
99
200
return cmd
100
201
}
101
202
0 commit comments