code.vegaprotocol.io/vega@v0.79.0/core/faucet/wallet.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 faucet 17 18 import ( 19 "context" 20 "errors" 21 "fmt" 22 "time" 23 24 "code.vegaprotocol.io/vega/paths" 25 "code.vegaprotocol.io/vega/wallet/wallet" 26 storev1 "code.vegaprotocol.io/vega/wallet/wallet/store/v1" 27 ) 28 29 // ErrFaucetHasNoKeyInItsWallet is returned when trying to get the wallet 30 // key of the faucet whereas no key has been generated or added to the 31 // faucet's wallet. 32 var ErrFaucetHasNoKeyInItsWallet = errors.New("faucet has no key in its wallet") 33 34 type faucetWallet struct { 35 // publicKey is the one used to retrieve the private key to sign messages. 36 publicKey string 37 wallet wallet.Wallet 38 } 39 40 func (w *faucetWallet) Sign(message []byte) ([]byte, string, error) { 41 sig, err := w.wallet.SignAny(w.publicKey, message) 42 if err != nil { 43 return nil, "", fmt.Errorf("could not sign the message: %w", err) 44 } 45 46 return sig, w.publicKey, nil 47 } 48 49 type WalletGenerationResult struct { 50 Mnemonic string 51 FilePath string 52 Name string 53 PublicKey string 54 } 55 56 func GenerateWallet(vegaPaths paths.Paths, passphrase string) (*WalletGenerationResult, error) { 57 ctx := context.Background() 58 59 walletsHome, err := vegaPaths.CreateDataDirFor(paths.FaucetWalletsDataHome) 60 if err != nil { 61 return nil, fmt.Errorf("could not get directory for %s: %w", paths.FaucetWalletsDataHome, err) 62 } 63 64 store, err := storev1.InitialiseStore(walletsHome, false) 65 if err != nil { 66 return nil, fmt.Errorf("could not initialise faucet wallet store at %s: %w", walletsHome, err) 67 } 68 defer store.Close() 69 70 walletName := fmt.Sprintf("vega.%v", time.Now().UnixNano()) 71 72 if exists, err := store.WalletExists(ctx, walletName); err != nil { 73 return nil, fmt.Errorf("couldn't verify the wallet existence: %w", err) 74 } else if exists { 75 return nil, wallet.ErrWalletAlreadyExists 76 } 77 78 w, recoveryPhrase, err := wallet.NewHDWallet(walletName) 79 if err != nil { 80 return nil, fmt.Errorf("could not generate faucet wallet: %w", err) 81 } 82 83 keyPair, err := w.GenerateKeyPair([]wallet.Metadata{}) 84 if err != nil { 85 return nil, fmt.Errorf("could not generate key pair for faucet wallet %s: %w", walletName, err) 86 } 87 88 if err := store.CreateWallet(ctx, w, passphrase); err != nil { 89 return nil, fmt.Errorf("could not save the generated faucet wallet: %w", err) 90 } 91 92 return &WalletGenerationResult{ 93 Mnemonic: recoveryPhrase, 94 FilePath: store.GetWalletPath(walletName), 95 Name: walletName, 96 PublicKey: keyPair.PublicKey(), 97 }, nil 98 } 99 100 func loadWallet(vegaPaths paths.Paths, walletName, passphrase string) (*faucetWallet, error) { 101 ctx := context.Background() 102 103 walletsHome, err := vegaPaths.CreateDataDirFor(paths.FaucetWalletsDataHome) 104 if err != nil { 105 return nil, fmt.Errorf("could not get directory for %q: %w", paths.FaucetWalletsDataHome, err) 106 } 107 108 store, err := storev1.InitialiseStore(walletsHome, false) 109 if err != nil { 110 return nil, fmt.Errorf("could not initialise faucet wallet store at %q: %w", walletsHome, err) 111 } 112 defer store.Close() 113 114 if exists, err := store.WalletExists(ctx, walletName); err != nil { 115 return nil, fmt.Errorf("could not verify the faucet wallet existence: %w", err) 116 } else if !exists { 117 return nil, fmt.Errorf("the faucet wallet %q does not exist", walletName) 118 } 119 120 if err := store.UnlockWallet(ctx, walletName, passphrase); err != nil { 121 if errors.Is(err, wallet.ErrWrongPassphrase) { 122 return nil, err 123 } 124 return nil, fmt.Errorf("could not unlock the faucet wallet %q: %w", walletName, err) 125 } 126 127 w, err := store.GetWallet(ctx, walletName) 128 if err != nil { 129 return nil, fmt.Errorf("could not get the faucet wallet %q: %w", walletName, err) 130 } 131 132 keyPairs := w.ListKeyPairs() 133 134 if len(keyPairs) == 0 { 135 return nil, ErrFaucetHasNoKeyInItsWallet 136 } 137 138 return &faucetWallet{ 139 wallet: w, 140 publicKey: keyPairs[0].PublicKey(), 141 }, nil 142 }