code.vegaprotocol.io/vega@v0.79.0/wallet/api/admin_create_wallet_test.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 api_test 17 18 import ( 19 "context" 20 "fmt" 21 "testing" 22 23 "code.vegaprotocol.io/vega/libs/jsonrpc" 24 vgrand "code.vegaprotocol.io/vega/libs/rand" 25 "code.vegaprotocol.io/vega/wallet/api" 26 "code.vegaprotocol.io/vega/wallet/api/mocks" 27 "code.vegaprotocol.io/vega/wallet/wallet" 28 29 "github.com/golang/mock/gomock" 30 "github.com/stretchr/testify/assert" 31 "github.com/stretchr/testify/require" 32 ) 33 34 func TestAdminCreateWallet(t *testing.T) { 35 t.Run("Documentation matches the code", testAdminCreateWalletSchemaCorrect) 36 t.Run("Creating a wallet with invalid params fails", testCreatingWalletWithInvalidParamsFails) 37 t.Run("Creating a wallet with valid params succeeds", testCreatingWalletWithValidParamsSucceeds) 38 t.Run("Creating a wallet that already exists fails", testCreatingWalletThatAlreadyExistsFails) 39 t.Run("Getting internal error during verification does not create the wallet", testGettingInternalErrorDuringVerificationDoesNotCreateWallet) 40 t.Run("Getting internal error during saving does not create the wallet", testGettingInternalErrorDuringSavingDoesNotCreateWallet) 41 } 42 43 func testAdminCreateWalletSchemaCorrect(t *testing.T) { 44 assertEqualSchema(t, "admin.create_wallet", api.AdminCreateWalletParams{}, api.AdminCreateWalletResult{}) 45 } 46 47 func testCreatingWalletWithInvalidParamsFails(t *testing.T) { 48 tcs := []struct { 49 name string 50 params interface{} 51 expectedError error 52 }{ 53 { 54 name: "with nil params", 55 params: nil, 56 expectedError: api.ErrParamsRequired, 57 }, { 58 name: "with wrong type of params", 59 params: "test", 60 expectedError: api.ErrParamsDoNotMatch, 61 }, { 62 name: "with empty name", 63 params: api.AdminCreateWalletParams{ 64 Wallet: "", 65 Passphrase: vgrand.RandomStr(5), 66 }, 67 expectedError: api.ErrWalletIsRequired, 68 }, { 69 name: "with empty passphrase", 70 params: api.AdminCreateWalletParams{ 71 Wallet: vgrand.RandomStr(5), 72 Passphrase: "", 73 }, 74 expectedError: api.ErrPassphraseIsRequired, 75 }, 76 } 77 78 for _, tc := range tcs { 79 t.Run(tc.name, func(tt *testing.T) { 80 // given 81 ctx := context.Background() 82 83 // setup 84 handler := newCreateWalletHandler(tt) 85 86 // when 87 result, errorDetails := handler.handle(t, ctx, tc.params) 88 89 // then 90 require.Empty(tt, result) 91 assertInvalidParams(tt, errorDetails, tc.expectedError) 92 }) 93 } 94 } 95 96 func testCreatingWalletWithValidParamsSucceeds(t *testing.T) { 97 // given 98 ctx := context.Background() 99 passphrase := vgrand.RandomStr(5) 100 name := vgrand.RandomStr(5) 101 var createdWallet wallet.Wallet 102 103 // setup 104 handler := newCreateWalletHandler(t) 105 // -- expected calls 106 handler.walletStore.EXPECT().WalletExists(ctx, name).Times(1).Return(false, nil) 107 handler.walletStore.EXPECT().CreateWallet(ctx, gomock.Any(), passphrase).Times(1).DoAndReturn(func(_ context.Context, w wallet.Wallet, passphrase string) error { 108 createdWallet = w 109 return nil 110 }) 111 112 // when 113 result, errorDetails := handler.handle(t, ctx, api.AdminCreateWalletParams{ 114 Wallet: name, 115 Passphrase: passphrase, 116 }) 117 118 // then 119 require.Nil(t, errorDetails) 120 // Verify generated wallet. 121 assert.Equal(t, name, createdWallet.Name()) 122 // Verify the first generated key. 123 assert.Len(t, createdWallet.ListKeyPairs(), 1) 124 keyPair := createdWallet.ListKeyPairs()[0] 125 assert.Equal(t, []wallet.Metadata{{Key: "name", Value: "Key 1"}}, keyPair.Metadata()) 126 // Verify the result. 127 assert.Equal(t, name, result.Wallet.Name) 128 assert.NotEmpty(t, result.Wallet.RecoveryPhrase) 129 assert.Equal(t, uint32(2), result.Wallet.KeyDerivationVersion) 130 assert.Equal(t, keyPair.PublicKey(), result.Key.PublicKey) 131 assert.Equal(t, keyPair.AlgorithmName(), result.Key.Algorithm.Name) 132 assert.Equal(t, keyPair.AlgorithmVersion(), result.Key.Algorithm.Version) 133 assert.Equal(t, keyPair.Metadata(), result.Key.Metadata) 134 } 135 136 func testCreatingWalletThatAlreadyExistsFails(t *testing.T) { 137 // given 138 ctx := context.Background() 139 passphrase := vgrand.RandomStr(5) 140 name := vgrand.RandomStr(5) 141 142 // setup 143 handler := newCreateWalletHandler(t) 144 // -- expected calls 145 handler.walletStore.EXPECT().WalletExists(ctx, name).Times(1).Return(true, nil) 146 147 // when 148 result, errorDetails := handler.handle(t, ctx, api.AdminCreateWalletParams{ 149 Wallet: name, 150 Passphrase: passphrase, 151 }) 152 153 // then 154 require.NotNil(t, errorDetails) 155 assert.Empty(t, result) 156 assertInvalidParams(t, errorDetails, api.ErrWalletAlreadyExists) 157 } 158 159 func testGettingInternalErrorDuringVerificationDoesNotCreateWallet(t *testing.T) { 160 // given 161 ctx := context.Background() 162 passphrase := vgrand.RandomStr(5) 163 name := vgrand.RandomStr(5) 164 165 // setup 166 handler := newCreateWalletHandler(t) 167 // -- expected calls 168 handler.walletStore.EXPECT().WalletExists(ctx, name).Times(1).Return(false, assert.AnError) 169 170 // when 171 result, errorDetails := handler.handle(t, ctx, api.AdminCreateWalletParams{ 172 Wallet: name, 173 Passphrase: passphrase, 174 }) 175 176 // then 177 require.NotNil(t, errorDetails) 178 assert.Empty(t, result) 179 assertInternalError(t, errorDetails, fmt.Errorf("could not verify the wallet exists: %w", assert.AnError)) 180 } 181 182 func testGettingInternalErrorDuringSavingDoesNotCreateWallet(t *testing.T) { 183 // given 184 ctx := context.Background() 185 passphrase := vgrand.RandomStr(5) 186 name := vgrand.RandomStr(5) 187 188 // setup 189 handler := newCreateWalletHandler(t) 190 // -- expected calls 191 handler.walletStore.EXPECT().WalletExists(ctx, name).Times(1).Return(false, nil) 192 handler.walletStore.EXPECT().CreateWallet(ctx, gomock.Any(), passphrase).Times(1).Return(assert.AnError) 193 194 // when 195 result, errorDetails := handler.handle(t, ctx, api.AdminCreateWalletParams{ 196 Wallet: name, 197 Passphrase: passphrase, 198 }) 199 200 // then 201 require.NotNil(t, errorDetails) 202 assert.Empty(t, result) 203 assertInternalError(t, errorDetails, fmt.Errorf("could not save the wallet: %w", assert.AnError)) 204 } 205 206 type createWalletHandler struct { 207 *api.AdminCreateWallet 208 ctrl *gomock.Controller 209 walletStore *mocks.MockWalletStore 210 } 211 212 func (h *createWalletHandler) handle(t *testing.T, ctx context.Context, params jsonrpc.Params) (api.AdminCreateWalletResult, *jsonrpc.ErrorDetails) { 213 t.Helper() 214 215 rawResult, err := h.Handle(ctx, params) 216 if rawResult != nil { 217 result, ok := rawResult.(api.AdminCreateWalletResult) 218 if !ok { 219 t.Fatal("AdminCreateWallet handler result is not a AdminCreateWalletResult") 220 } 221 return result, err 222 } 223 return api.AdminCreateWalletResult{}, err 224 } 225 226 func newCreateWalletHandler(t *testing.T) *createWalletHandler { 227 t.Helper() 228 229 ctrl := gomock.NewController(t) 230 walletStore := mocks.NewMockWalletStore(ctrl) 231 232 return &createWalletHandler{ 233 AdminCreateWallet: api.NewAdminCreateWallet(walletStore), 234 ctrl: ctrl, 235 walletStore: walletStore, 236 } 237 }