code.vegaprotocol.io/vega@v0.79.0/cmd/vegawallet/commands/wallet_create.go (about) 1 // Copyright (C) 2023 Gobalsky Labs Limited 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package cmd 17 18 import ( 19 "context" 20 "errors" 21 "fmt" 22 "io" 23 "os" 24 25 "code.vegaprotocol.io/vega/cmd/vegawallet/commands/cli" 26 "code.vegaprotocol.io/vega/cmd/vegawallet/commands/flags" 27 "code.vegaprotocol.io/vega/cmd/vegawallet/commands/printer" 28 "code.vegaprotocol.io/vega/wallet/api" 29 "code.vegaprotocol.io/vega/wallet/wallet" 30 "code.vegaprotocol.io/vega/wallet/wallets" 31 32 "github.com/spf13/cobra" 33 ) 34 35 var ( 36 createWalletLong = cli.LongDesc(` 37 Create a wallet and generate the first Ed25519 key pair. 38 39 You will be asked to create a passphrase. The passphrase is used to protect 40 the file in which the keys are stored. This doesn't affect the key generation 41 process in any way. 42 `) 43 44 createWalletExample = cli.Examples(` 45 # Creating a wallet 46 {{.Software}} create --wallet WALLET 47 `) 48 ) 49 50 type createdWallet struct { 51 Name string `json:"name"` 52 KeyDerivationVersion uint32 `json:"keyDerivationVersion"` 53 RecoveryPhrase string `json:"recoveryPhrase"` 54 FilePath string `json:"filePath"` 55 } 56 57 type firstPublicKey struct { 58 PublicKey string `json:"publicKey"` 59 Algorithm wallet.Algorithm `json:"algorithm"` 60 Meta []wallet.Metadata `json:"metadata"` 61 } 62 63 type createWalletResult struct { 64 Wallet createdWallet `json:"wallet"` 65 Key firstPublicKey `json:"key"` 66 } 67 68 type CreateWalletHandler func(api.AdminCreateWalletParams) (createWalletResult, error) 69 70 func NewCmdCreateWallet(w io.Writer, rf *RootFlags) *cobra.Command { 71 h := func(params api.AdminCreateWalletParams) (createWalletResult, error) { 72 walletStore, err := wallets.InitialiseStore(rf.Home, false) 73 if err != nil { 74 return createWalletResult{}, fmt.Errorf("couldn't initialise wallets store: %w", err) 75 } 76 defer walletStore.Close() 77 78 createWallet := api.NewAdminCreateWallet(walletStore) 79 80 rawResult, errDetails := createWallet.Handle(context.Background(), params) 81 if errDetails != nil { 82 return createWalletResult{}, errors.New(errDetails.Data) 83 } 84 85 result := rawResult.(api.AdminCreateWalletResult) 86 87 return createWalletResult{ 88 Wallet: createdWallet{ 89 Name: result.Wallet.Name, 90 KeyDerivationVersion: result.Wallet.KeyDerivationVersion, 91 RecoveryPhrase: result.Wallet.RecoveryPhrase, 92 FilePath: walletStore.GetWalletPath(result.Wallet.Name), 93 }, 94 Key: firstPublicKey{ 95 PublicKey: result.Key.PublicKey, 96 Algorithm: result.Key.Algorithm, 97 Meta: result.Key.Metadata, 98 }, 99 }, nil 100 } 101 102 return BuildCmdCreateWallet(w, h, rf) 103 } 104 105 func BuildCmdCreateWallet(w io.Writer, handler CreateWalletHandler, rf *RootFlags) *cobra.Command { 106 f := &CreateWalletFlags{} 107 108 cmd := &cobra.Command{ 109 Use: "create", 110 Short: "Create a wallet", 111 Long: createWalletLong, 112 Example: createWalletExample, 113 RunE: func(_ *cobra.Command, _ []string) error { 114 req, err := f.Validate() 115 if err != nil { 116 return err 117 } 118 119 resp, err := handler(req) 120 if err != nil { 121 return err 122 } 123 124 switch rf.Output { 125 case flags.InteractiveOutput: 126 PrintCreateWalletResponse(w, resp) 127 case flags.JSONOutput: 128 return printer.FprintJSON(w, resp) 129 } 130 131 return nil 132 }, 133 } 134 135 cmd.Flags().StringVarP(&f.Wallet, 136 "wallet", "w", 137 "", 138 "The wallet where the key is generated in", 139 ) 140 cmd.Flags().StringVarP(&f.PassphraseFile, 141 "passphrase-file", "p", 142 "", 143 "Path to the file containing the wallet's passphrase", 144 ) 145 146 return cmd 147 } 148 149 type CreateWalletFlags struct { 150 Wallet string 151 PassphraseFile string 152 } 153 154 func (f *CreateWalletFlags) Validate() (api.AdminCreateWalletParams, error) { 155 req := api.AdminCreateWalletParams{} 156 157 if len(f.Wallet) == 0 { 158 return api.AdminCreateWalletParams{}, flags.MustBeSpecifiedError("wallet") 159 } 160 req.Wallet = f.Wallet 161 162 passphrase, err := flags.GetConfirmedPassphrase(f.PassphraseFile) 163 if err != nil { 164 return api.AdminCreateWalletParams{}, err 165 } 166 req.Passphrase = passphrase 167 168 return req, nil 169 } 170 171 func PrintCreateWalletResponse(w io.Writer, resp createWalletResult) { 172 p := printer.NewInteractivePrinter(w) 173 174 str := p.String() 175 defer p.Print(str) 176 177 str.CheckMark().Text("Wallet ").Bold(resp.Wallet.Name).Text(" has been created at: ").SuccessText(resp.Wallet.FilePath).NextLine() 178 str.CheckMark().Text("First key pair has been generated for the wallet ").Bold(resp.Wallet.Name).Text(" at: ").SuccessText(resp.Wallet.FilePath).NextLine() 179 str.CheckMark().SuccessText("Creating wallet succeeded").NextSection() 180 181 str.Text("Wallet recovery phrase:").NextLine() 182 str.WarningText(resp.Wallet.RecoveryPhrase).NextLine() 183 str.Text("Wallet version:").NextLine() 184 str.WarningText(fmt.Sprintf("%d", resp.Wallet.KeyDerivationVersion)).NextLine() 185 str.Text("First public key:").NextLine() 186 str.WarningText(resp.Key.PublicKey).NextLine() 187 str.NextSection() 188 189 str.RedArrow().DangerText("Important").NextLine() 190 str.Text("Write down the ").Bold("recovery phrase").Text(" and the ").Bold("wallet's version").Text(", and store it somewhere safe and secure, now.").NextLine() 191 str.DangerText("The recovery phrase will not be displayed ever again, nor will you be able to retrieve it!").NextSection() 192 193 str.BlueArrow().InfoText("Run the service").NextLine() 194 str.Text("Now, you can run the service. See the following command:").NextSection() 195 str.Code(fmt.Sprintf("%s service run --help", os.Args[0])).NextLine() 196 }