code.vegaprotocol.io/vega@v0.79.0/wallet/api/client_connect_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 vgrand "code.vegaprotocol.io/vega/libs/rand" 24 "code.vegaprotocol.io/vega/wallet/api" 25 "code.vegaprotocol.io/vega/wallet/api/mocks" 26 "code.vegaprotocol.io/vega/wallet/preferences" 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 TestConnectWallet(t *testing.T) { 35 t.Run("Connecting to one of the existing wallet with valid params succeeds", testConnectingToOneOfMultipleWalletsWithValidParamsSucceeds) 36 t.Run("Connecting to the only wallet with valid params succeeds", testConnectingToTheOnlyWalletWithValidParamsSucceeds) 37 t.Run("Connecting to one of the existing wallet when already unlocked skips the passphrase", testConnectingToOneOfMultipleWalletsWhenAlreadyUnlockedSkipsPassphrase) 38 t.Run("Connecting to the only wallet when already unlocked skips the passphrase", testConnectingToTheOnlyWalletWhenAlreadyUnlockedSkipsPassphrase) 39 t.Run("Connecting to a connected wallet disconnects the previous one and generates a new token", testConnectingToConnectedWalletDisconnectsPreviousOneAndGeneratesNewToken) 40 t.Run("Connecting to a wallet without wallets fails", testConnectingWalletWithoutWalletsFails) 41 t.Run("Getting internal error during the wallet listing does not connect to a wallet", testGettingInternalErrorDuringWalletListingDoesNotConnectToWallet) 42 t.Run("Refusing a wallet connection does not connect to a wallet", testRefusingWalletConnectionDoesNotConnectToWallet) 43 t.Run("Canceling the review does not connect to a wallet", testCancelingTheReviewDoesNotConnectToWallet) 44 t.Run("Interrupting the request during the review does not connect to a wallet", testInterruptingTheRequestDuringReviewDoesNotConnectToWallet) 45 t.Run("Getting internal error during the review does not connect to a wallet", testGettingInternalErrorDuringReviewDoesNotConnectToWallet) 46 t.Run("Cancelling the wallet selection does not connect to a wallet", testCancellingTheWalletSelectionDoesNotConnectToWallet) 47 t.Run("Interrupting the request during the wallet selection does not connect to a wallet", testInterruptingTheRequestDuringWalletSelectionDoesNotConnectToWallet) 48 t.Run("Getting internal error during the wallet selection does not connect to a wallet", testGettingInternalErrorDuringWalletSelectionDoesNotConnectToWallet) 49 t.Run("Selecting a non-existing wallet does not connect to a wallet", testSelectingNonExistingWalletDoesNotConnectToWallet) 50 t.Run("Getting internal error during the wallet lock state verification does not connect to a wallet", testGettingInternalErrorDuringWalletLockStateVerificationDoesNotConnectToWallet) 51 t.Run("Getting internal error during the passphrase request does not connect to a wallet", testGettingInternalErrorDuringPassphraseRequestDoesNotConnectToWallet) 52 t.Run("Cancelling the passphrase request does not connect to a wallet", testCancellingThePassphraseRequestDoesNotConnectToWallet) 53 t.Run("Interrupting the request during the passphrase request does not connect to a wallet", testInterruptingTheRequestDuringPassphraseRequestDoesNotConnectToWallet) 54 t.Run("Getting internal error during the wallet unlocking does not connect to a wallet", testGettingInternalErrorDuringWalletUnlockingDoesNotConnectToWallet) 55 t.Run("Getting internal error during the wallet verification does not connect to a wallet", testGettingInternalErrorDuringWalletVerificationDoesNotConnectToWallet) 56 t.Run("Using the wrong passphrase does not connect to a wallet", testUsingWrongPassphraseDoesNotConnectToWallet) 57 t.Run("Getting internal error during the wallet retrieval does not connect to a wallet", testGettingInternalErrorDuringWalletRetrievalDoesNotConnectToWallet) 58 } 59 60 func testConnectingToOneOfMultipleWalletsWithValidParamsSucceeds(t *testing.T) { 61 // given 62 ctx, traceID := clientContextForTest() 63 hostname := vgrand.RandomStr(5) + ".xyz" 64 expectedPermissions := wallet.Permissions{ 65 PublicKeys: wallet.PublicKeysPermission{ 66 Access: wallet.ReadAccess, 67 AllowedKeys: []string{}, 68 }, 69 } 70 expectedSelectedWallet := walletWithPerms(t, hostname, expectedPermissions) 71 nonSelectedWallet := walletWithPerms(t, hostname, wallet.Permissions{}) 72 73 passphrase := vgrand.RandomStr(5) 74 availableWallets := []string{ 75 expectedSelectedWallet.Name(), 76 nonSelectedWallet.Name(), 77 } 78 79 // setup 80 // -- expected calls 81 handler := newConnectWalletHandler(t) 82 handler.walletStore.EXPECT().WalletExists(ctx, expectedSelectedWallet.Name()).Times(1).Return(true, nil) 83 handler.walletStore.EXPECT().IsWalletAlreadyUnlocked(ctx, expectedSelectedWallet.Name()).Times(1).Return(false, nil) 84 handler.walletStore.EXPECT().ListWallets(ctx).Times(1).Return(availableWallets, nil) 85 handler.walletStore.EXPECT().GetWallet(ctx, expectedSelectedWallet.Name()).Times(1).Return(expectedSelectedWallet, nil) 86 handler.walletStore.EXPECT().UnlockWallet(ctx, expectedSelectedWallet.Name(), passphrase).Times(1).Return(nil) 87 handler.interactor.EXPECT().NotifyInteractionSessionBegan(ctx, traceID, api.WalletConnectionWorkflow, uint8(4)).Times(1).Return(nil) 88 handler.interactor.EXPECT().NotifyInteractionSessionEnded(ctx, traceID).Times(1) 89 handler.interactor.EXPECT().RequestWalletConnectionReview(ctx, traceID, uint8(1), hostname).Times(1).Return(string(preferences.ApprovedOnlyThisTime), nil) 90 handler.interactor.EXPECT().RequestWalletSelection(ctx, traceID, uint8(2), hostname, availableWallets).Times(1).Return(expectedSelectedWallet.Name(), nil) 91 handler.interactor.EXPECT().RequestPassphrase(ctx, traceID, uint8(3), expectedSelectedWallet.Name(), api.PassphraseRequestReasonUnlockWallet).Times(1).Return(passphrase, nil) 92 handler.interactor.EXPECT().NotifySuccessfulRequest(ctx, traceID, uint8(4), api.WalletConnectionSuccessfullyEstablished).Times(1) 93 94 // when 95 token, errorDetails := handler.Handle(ctx, hostname) 96 97 // then 98 require.Nil(t, errorDetails) 99 assert.NotEmpty(t, token) 100 } 101 102 func testConnectingToTheOnlyWalletWithValidParamsSucceeds(t *testing.T) { 103 // given 104 ctx, traceID := clientContextForTest() 105 hostname := vgrand.RandomStr(5) + ".xyz" 106 expectedPermissions := wallet.Permissions{ 107 PublicKeys: wallet.PublicKeysPermission{ 108 Access: wallet.ReadAccess, 109 AllowedKeys: []string{}, 110 }, 111 } 112 onlyWallet := walletWithPerms(t, hostname, expectedPermissions) 113 114 passphrase := vgrand.RandomStr(5) 115 availableWallets := []string{onlyWallet.Name()} 116 117 // setup 118 // -- expected calls 119 handler := newConnectWalletHandler(t) 120 handler.walletStore.EXPECT().IsWalletAlreadyUnlocked(ctx, onlyWallet.Name()).Times(1).Return(false, nil) 121 handler.walletStore.EXPECT().ListWallets(ctx).Times(1).Return(availableWallets, nil) 122 handler.walletStore.EXPECT().GetWallet(ctx, onlyWallet.Name()).Times(1).Return(onlyWallet, nil) 123 handler.walletStore.EXPECT().UnlockWallet(ctx, onlyWallet.Name(), passphrase).Times(1).Return(nil) 124 handler.interactor.EXPECT().NotifyInteractionSessionBegan(ctx, traceID, api.WalletConnectionWorkflow, uint8(4)).Times(1).Return(nil) 125 handler.interactor.EXPECT().NotifyInteractionSessionEnded(ctx, traceID).Times(1) 126 handler.interactor.EXPECT().RequestWalletConnectionReview(ctx, traceID, uint8(1), hostname).Times(1).Return(string(preferences.ApprovedOnlyThisTime), nil) 127 handler.interactor.EXPECT().RequestPassphrase(ctx, traceID, uint8(3), onlyWallet.Name(), api.PassphraseRequestReasonUnlockWallet).Times(1).Return(passphrase, nil) 128 handler.interactor.EXPECT().NotifySuccessfulRequest(ctx, traceID, uint8(4), api.WalletConnectionSuccessfullyEstablished).Times(1) 129 130 // when 131 token, errorDetails := handler.Handle(ctx, hostname) 132 133 // then 134 require.Nil(t, errorDetails) 135 assert.NotEmpty(t, token) 136 } 137 138 func testConnectingToOneOfMultipleWalletsWhenAlreadyUnlockedSkipsPassphrase(t *testing.T) { 139 // given 140 ctx, traceID := clientContextForTest() 141 hostname := vgrand.RandomStr(5) + ".xyz" 142 expectedPermissions := wallet.Permissions{ 143 PublicKeys: wallet.PublicKeysPermission{ 144 Access: wallet.ReadAccess, 145 AllowedKeys: []string{}, 146 }, 147 } 148 expectedSelectedWallet := walletWithPerms(t, hostname, expectedPermissions) 149 nonSelectedWallet := walletWithPerms(t, hostname, wallet.Permissions{}) 150 151 availableWallets := []string{ 152 expectedSelectedWallet.Name(), 153 nonSelectedWallet.Name(), 154 } 155 156 // setup 157 // -- expected calls 158 handler := newConnectWalletHandler(t) 159 handler.walletStore.EXPECT().WalletExists(ctx, expectedSelectedWallet.Name()).Times(1).Return(true, nil) 160 handler.walletStore.EXPECT().IsWalletAlreadyUnlocked(ctx, expectedSelectedWallet.Name()).Times(1).Return(true, nil) 161 handler.walletStore.EXPECT().ListWallets(ctx).Times(1).Return(availableWallets, nil) 162 handler.walletStore.EXPECT().GetWallet(ctx, expectedSelectedWallet.Name()).Times(1).Return(expectedSelectedWallet, nil) 163 handler.interactor.EXPECT().NotifyInteractionSessionBegan(ctx, traceID, api.WalletConnectionWorkflow, uint8(4)).Times(1).Return(nil) 164 handler.interactor.EXPECT().NotifyInteractionSessionEnded(ctx, traceID).Times(1) 165 handler.interactor.EXPECT().RequestWalletConnectionReview(ctx, traceID, uint8(1), hostname).Times(1).Return(string(preferences.ApprovedOnlyThisTime), nil) 166 handler.interactor.EXPECT().RequestWalletSelection(ctx, traceID, uint8(2), hostname, availableWallets).Times(1).Return(expectedSelectedWallet.Name(), nil) 167 handler.interactor.EXPECT().NotifySuccessfulRequest(ctx, traceID, uint8(4), api.WalletConnectionSuccessfullyEstablished).Times(1) 168 169 // when 170 token, errorDetails := handler.Handle(ctx, hostname) 171 172 // then 173 require.Nil(t, errorDetails) 174 assert.NotEmpty(t, token) 175 } 176 177 func testConnectingToTheOnlyWalletWhenAlreadyUnlockedSkipsPassphrase(t *testing.T) { 178 // given 179 ctx, traceID := clientContextForTest() 180 hostname := vgrand.RandomStr(5) + ".xyz" 181 expectedPermissions := wallet.Permissions{ 182 PublicKeys: wallet.PublicKeysPermission{ 183 Access: wallet.ReadAccess, 184 AllowedKeys: []string{}, 185 }, 186 } 187 onlyWallet := walletWithPerms(t, hostname, expectedPermissions) 188 189 availableWallets := []string{onlyWallet.Name()} 190 191 // setup 192 // -- expected calls 193 handler := newConnectWalletHandler(t) 194 handler.walletStore.EXPECT().IsWalletAlreadyUnlocked(ctx, onlyWallet.Name()).Times(1).Return(true, nil) 195 handler.walletStore.EXPECT().ListWallets(ctx).Times(1).Return(availableWallets, nil) 196 handler.walletStore.EXPECT().GetWallet(ctx, onlyWallet.Name()).Times(1).Return(onlyWallet, nil) 197 handler.interactor.EXPECT().NotifyInteractionSessionBegan(ctx, traceID, api.WalletConnectionWorkflow, uint8(4)).Times(1).Return(nil) 198 handler.interactor.EXPECT().NotifyInteractionSessionEnded(ctx, traceID).Times(1) 199 handler.interactor.EXPECT().RequestWalletConnectionReview(ctx, traceID, uint8(1), hostname).Times(1).Return(string(preferences.ApprovedOnlyThisTime), nil) 200 handler.interactor.EXPECT().NotifySuccessfulRequest(ctx, traceID, uint8(4), api.WalletConnectionSuccessfullyEstablished).Times(1) 201 202 // when 203 token, errorDetails := handler.Handle(ctx, hostname) 204 205 // then 206 require.Nil(t, errorDetails) 207 assert.NotEmpty(t, token) 208 } 209 210 func testConnectingToConnectedWalletDisconnectsPreviousOneAndGeneratesNewToken(t *testing.T) { 211 // given 212 ctx, traceID := clientContextForTest() 213 hostname := vgrand.RandomStr(5) + ".xyz" 214 expectedPermissions := wallet.Permissions{ 215 PublicKeys: wallet.PublicKeysPermission{ 216 Access: wallet.ReadAccess, 217 AllowedKeys: []string{}, 218 }, 219 } 220 expectedSelectedWallet := walletWithPerms(t, hostname, expectedPermissions) 221 nonSelectedWallet := walletWithPerms(t, hostname, wallet.Permissions{}) 222 223 passphrase := vgrand.RandomStr(5) 224 availableWallets := []string{ 225 expectedSelectedWallet.Name(), 226 nonSelectedWallet.Name(), 227 } 228 229 // setup 230 handler := newConnectWalletHandler(t) 231 // -- expected calls 232 handler.walletStore.EXPECT().WalletExists(ctx, expectedSelectedWallet.Name()).Times(1).Return(true, nil) 233 handler.walletStore.EXPECT().IsWalletAlreadyUnlocked(ctx, expectedSelectedWallet.Name()).Times(1).Return(false, nil) 234 handler.walletStore.EXPECT().ListWallets(ctx).Times(1).Return(availableWallets, nil) 235 handler.walletStore.EXPECT().UnlockWallet(ctx, expectedSelectedWallet.Name(), passphrase).Times(1).Return(nil) 236 handler.walletStore.EXPECT().GetWallet(ctx, expectedSelectedWallet.Name()).Times(1).Return(expectedSelectedWallet, nil) 237 handler.interactor.EXPECT().NotifyInteractionSessionBegan(ctx, traceID, api.WalletConnectionWorkflow, uint8(4)).Times(1).Return(nil) 238 handler.interactor.EXPECT().NotifyInteractionSessionEnded(ctx, traceID).Times(1) 239 handler.interactor.EXPECT().RequestWalletConnectionReview(ctx, traceID, uint8(1), hostname).Times(1).Return(string(preferences.ApprovedOnlyThisTime), nil) 240 handler.interactor.EXPECT().RequestWalletSelection(ctx, traceID, uint8(2), hostname, availableWallets).Times(1).Return(expectedSelectedWallet.Name(), nil) 241 handler.interactor.EXPECT().RequestPassphrase(ctx, traceID, uint8(3), expectedSelectedWallet.Name(), api.PassphraseRequestReasonUnlockWallet).Times(1).Return(passphrase, nil) 242 handler.interactor.EXPECT().NotifySuccessfulRequest(ctx, traceID, uint8(4), api.WalletConnectionSuccessfullyEstablished).Times(1) 243 244 // when 245 wallet1, errorDetails := handler.Handle(ctx, hostname) 246 247 // then 248 assert.Nil(t, errorDetails) 249 assert.NotEmpty(t, wallet1) 250 251 // setup 252 // -- expected calls 253 handler.walletStore.EXPECT().IsWalletAlreadyUnlocked(ctx, expectedSelectedWallet.Name()).Times(1).Return(true, nil) 254 handler.walletStore.EXPECT().WalletExists(ctx, expectedSelectedWallet.Name()).Times(1).Return(true, nil) 255 handler.walletStore.EXPECT().ListWallets(ctx).Times(1).Return(availableWallets, nil) 256 handler.walletStore.EXPECT().GetWallet(ctx, expectedSelectedWallet.Name()).Times(1).Return(expectedSelectedWallet, nil) 257 handler.interactor.EXPECT().NotifyInteractionSessionBegan(ctx, traceID, api.WalletConnectionWorkflow, uint8(4)).Times(1).Return(nil) 258 handler.interactor.EXPECT().NotifyInteractionSessionEnded(ctx, traceID).Times(1) 259 handler.interactor.EXPECT().RequestWalletConnectionReview(ctx, traceID, uint8(1), hostname).Times(1).Return(string(preferences.ApprovedOnlyThisTime), nil) 260 handler.interactor.EXPECT().RequestWalletSelection(ctx, traceID, uint8(2), hostname, availableWallets).Times(1).Return(expectedSelectedWallet.Name(), nil) 261 handler.interactor.EXPECT().NotifySuccessfulRequest(ctx, traceID, uint8(4), api.WalletConnectionSuccessfullyEstablished).Times(1) 262 263 // when 264 wallet2, errorDetails := handler.Handle(ctx, hostname) 265 266 // then 267 assert.Nil(t, errorDetails) 268 assert.Equal(t, wallet2, wallet1) 269 } 270 271 func testConnectingWalletWithoutWalletsFails(t *testing.T) { 272 // given 273 ctx, traceID := clientContextForTest() 274 hostname := vgrand.RandomStr(5) + ".xyz" 275 276 // setup 277 handler := newConnectWalletHandler(t) 278 // -- expected calls 279 handler.interactor.EXPECT().NotifyInteractionSessionBegan(ctx, traceID, api.WalletConnectionWorkflow, uint8(4)).Times(1).Return(nil) 280 handler.interactor.EXPECT().NotifyInteractionSessionEnded(ctx, traceID).Times(1) 281 handler.interactor.EXPECT().NotifyError(ctx, traceID, api.ApplicationErrorType, api.ErrNoWalletToConnectTo).Times(1) 282 handler.walletStore.EXPECT().ListWallets(ctx).Times(1).Return([]string{}, nil) 283 284 // when 285 result, errorDetails := handler.Handle(ctx, hostname) 286 287 // then 288 assertApplicationCancellationError(t, errorDetails) 289 assert.Empty(t, result) 290 } 291 292 func testGettingInternalErrorDuringWalletListingDoesNotConnectToWallet(t *testing.T) { 293 // given 294 ctx, traceID := clientContextForTest() 295 hostname := vgrand.RandomStr(5) + ".xyz" 296 297 // setup 298 handler := newConnectWalletHandler(t) 299 // -- expected calls 300 handler.interactor.EXPECT().NotifyInteractionSessionBegan(ctx, traceID, api.WalletConnectionWorkflow, uint8(4)).Times(1).Return(nil) 301 handler.interactor.EXPECT().NotifyInteractionSessionEnded(ctx, traceID).Times(1) 302 handler.walletStore.EXPECT().ListWallets(ctx).Times(1).Return(nil, assert.AnError) 303 handler.interactor.EXPECT().NotifyError(ctx, traceID, api.InternalErrorType, fmt.Errorf("could not list the available wallets: %w", assert.AnError)).Times(1) 304 305 // when 306 result, errorDetails := handler.Handle(ctx, hostname) 307 308 // then 309 assertInternalError(t, errorDetails, api.ErrCouldNotConnectToWallet) 310 assert.Empty(t, result) 311 } 312 313 func testRefusingWalletConnectionDoesNotConnectToWallet(t *testing.T) { 314 // given 315 ctx, traceID := clientContextForTest() 316 hostname := vgrand.RandomStr(5) + ".xyz" 317 wallet1 := walletWithPerms(t, hostname, wallet.Permissions{}) 318 319 // setup 320 handler := newConnectWalletHandler(t) 321 // -- expected calls 322 handler.interactor.EXPECT().NotifyInteractionSessionBegan(ctx, traceID, api.WalletConnectionWorkflow, uint8(4)).Times(1).Return(nil) 323 handler.interactor.EXPECT().NotifyInteractionSessionEnded(ctx, traceID).Times(1) 324 handler.interactor.EXPECT().RequestWalletConnectionReview(ctx, traceID, uint8(1), hostname).Times(1).Return(string(preferences.RejectedOnlyThisTime), nil) 325 handler.walletStore.EXPECT().ListWallets(ctx).Times(1).Return([]string{wallet1.Name()}, nil) 326 327 // when 328 result, errorDetails := handler.Handle(ctx, hostname) 329 330 // then 331 assertUserRejectionError(t, errorDetails, api.ErrUserRejectedWalletConnection) 332 assert.Empty(t, result) 333 } 334 335 func testCancelingTheReviewDoesNotConnectToWallet(t *testing.T) { 336 // given 337 ctx, traceID := clientContextForTest() 338 hostname := vgrand.RandomStr(5) + ".xyz" 339 wallet1 := walletWithPerms(t, hostname, wallet.Permissions{}) 340 341 // setup 342 handler := newConnectWalletHandler(t) 343 // -- expected calls 344 handler.interactor.EXPECT().NotifyInteractionSessionBegan(ctx, traceID, api.WalletConnectionWorkflow, uint8(4)).Times(1).Return(nil) 345 handler.interactor.EXPECT().NotifyInteractionSessionEnded(ctx, traceID).Times(1) 346 handler.interactor.EXPECT().RequestWalletConnectionReview(ctx, traceID, uint8(1), hostname).Times(1).Return("", api.ErrUserCloseTheConnection) 347 handler.interactor.EXPECT().NotifyError(ctx, traceID, api.ApplicationErrorType, api.ErrConnectionClosed).Times(1) 348 handler.walletStore.EXPECT().ListWallets(ctx).Times(1).Return([]string{wallet1.Name()}, nil) 349 350 // when 351 result, errorDetails := handler.Handle(ctx, hostname) 352 353 // then 354 assertConnectionClosedError(t, errorDetails) 355 assert.Empty(t, result) 356 } 357 358 func testInterruptingTheRequestDuringReviewDoesNotConnectToWallet(t *testing.T) { 359 // given 360 ctx, traceID := clientContextForTest() 361 hostname := vgrand.RandomStr(5) + ".xyz" 362 wallet1 := walletWithPerms(t, hostname, wallet.Permissions{}) 363 364 // setup 365 handler := newConnectWalletHandler(t) 366 // -- expected calls 367 handler.interactor.EXPECT().NotifyInteractionSessionBegan(ctx, traceID, api.WalletConnectionWorkflow, uint8(4)).Times(1).Return(nil) 368 handler.interactor.EXPECT().NotifyInteractionSessionEnded(ctx, traceID).Times(1) 369 handler.interactor.EXPECT().RequestWalletConnectionReview(ctx, traceID, uint8(1), hostname).Times(1).Return("", api.ErrRequestInterrupted) 370 handler.interactor.EXPECT().NotifyError(ctx, traceID, api.ServerErrorType, api.ErrRequestInterrupted).Times(1) 371 handler.walletStore.EXPECT().ListWallets(ctx).Times(1).Return([]string{wallet1.Name()}, nil) 372 373 // when 374 result, errorDetails := handler.Handle(ctx, hostname) 375 376 // then 377 assertRequestInterruptionError(t, errorDetails) 378 assert.Empty(t, result) 379 } 380 381 func testGettingInternalErrorDuringReviewDoesNotConnectToWallet(t *testing.T) { 382 // given 383 ctx, traceID := clientContextForTest() 384 hostname := vgrand.RandomStr(5) + ".xyz" 385 wallet1 := walletWithPerms(t, hostname, wallet.Permissions{}) 386 387 // setup 388 handler := newConnectWalletHandler(t) 389 // -- expected calls 390 handler.interactor.EXPECT().NotifyInteractionSessionBegan(ctx, traceID, api.WalletConnectionWorkflow, uint8(4)).Times(1).Return(nil) 391 handler.interactor.EXPECT().NotifyInteractionSessionEnded(ctx, traceID).Times(1) 392 handler.interactor.EXPECT().RequestWalletConnectionReview(ctx, traceID, uint8(1), hostname).Times(1).Return("", assert.AnError) 393 handler.interactor.EXPECT().NotifyError(ctx, traceID, api.InternalErrorType, fmt.Errorf("reviewing the wallet connection failed: %w", assert.AnError)).Times(1) 394 handler.walletStore.EXPECT().ListWallets(ctx).Times(1).Return([]string{wallet1.Name()}, nil) 395 396 // when 397 result, errorDetails := handler.Handle(ctx, hostname) 398 399 // then 400 assertInternalError(t, errorDetails, api.ErrCouldNotConnectToWallet) 401 assert.Empty(t, result) 402 } 403 404 func testCancellingTheWalletSelectionDoesNotConnectToWallet(t *testing.T) { 405 // given 406 ctx, traceID := clientContextForTest() 407 hostname := vgrand.RandomStr(5) + ".xyz" 408 wallet1 := walletWithPerms(t, hostname, wallet.Permissions{}) 409 wallet2 := walletWithPerms(t, hostname, wallet.Permissions{}) 410 411 // setup 412 handler := newConnectWalletHandler(t) 413 // -- expected calls 414 handler.interactor.EXPECT().NotifyInteractionSessionBegan(ctx, traceID, api.WalletConnectionWorkflow, uint8(4)).Times(1).Return(nil) 415 handler.interactor.EXPECT().NotifyInteractionSessionEnded(ctx, traceID).Times(1) 416 handler.interactor.EXPECT().RequestWalletConnectionReview(ctx, traceID, uint8(1), hostname).Times(1).Return(string(preferences.ApprovedOnlyThisTime), nil) 417 handler.walletStore.EXPECT().ListWallets(ctx).Times(1).Return([]string{wallet1.Name(), wallet2.Name()}, nil) 418 handler.interactor.EXPECT().RequestWalletSelection(ctx, traceID, uint8(2), hostname, []string{wallet1.Name(), wallet2.Name()}).Times(1).Return("", api.ErrUserCloseTheConnection) 419 handler.interactor.EXPECT().NotifyError(ctx, traceID, api.ApplicationErrorType, api.ErrConnectionClosed).Times(1) 420 421 // when 422 result, errorDetails := handler.Handle(ctx, hostname) 423 424 // then 425 assertConnectionClosedError(t, errorDetails) 426 assert.Empty(t, result) 427 } 428 429 func testInterruptingTheRequestDuringWalletSelectionDoesNotConnectToWallet(t *testing.T) { 430 // given 431 ctx, traceID := clientContextForTest() 432 hostname := vgrand.RandomStr(5) + ".xyz" 433 wallet1 := walletWithPerms(t, hostname, wallet.Permissions{}) 434 wallet2 := walletWithPerms(t, hostname, wallet.Permissions{}) 435 436 // setup 437 handler := newConnectWalletHandler(t) 438 // -- expected calls 439 handler.interactor.EXPECT().NotifyInteractionSessionBegan(ctx, traceID, api.WalletConnectionWorkflow, uint8(4)).Times(1).Return(nil) 440 handler.interactor.EXPECT().NotifyInteractionSessionEnded(ctx, traceID).Times(1) 441 handler.interactor.EXPECT().RequestWalletConnectionReview(ctx, traceID, uint8(1), hostname).Times(1).Return(string(preferences.ApprovedOnlyThisTime), nil) 442 handler.walletStore.EXPECT().ListWallets(ctx).Times(1).Return([]string{wallet1.Name(), wallet2.Name()}, nil) 443 handler.interactor.EXPECT().RequestWalletSelection(ctx, traceID, uint8(2), hostname, []string{wallet1.Name(), wallet2.Name()}).Times(1).Return("", api.ErrRequestInterrupted) 444 handler.interactor.EXPECT().NotifyError(ctx, traceID, api.ServerErrorType, api.ErrRequestInterrupted).Times(1) 445 446 // when 447 result, errorDetails := handler.Handle(ctx, hostname) 448 449 // then 450 assertRequestInterruptionError(t, errorDetails) 451 assert.Empty(t, result) 452 } 453 454 func testGettingInternalErrorDuringWalletSelectionDoesNotConnectToWallet(t *testing.T) { 455 // given 456 ctx, traceID := clientContextForTest() 457 hostname := vgrand.RandomStr(5) + ".xyz" 458 wallet1 := walletWithPerms(t, hostname, wallet.Permissions{}) 459 wallet2 := walletWithPerms(t, hostname, wallet.Permissions{}) 460 461 // setup 462 handler := newConnectWalletHandler(t) 463 // -- expected calls 464 handler.interactor.EXPECT().NotifyInteractionSessionBegan(ctx, traceID, api.WalletConnectionWorkflow, uint8(4)).Times(1).Return(nil) 465 handler.interactor.EXPECT().NotifyInteractionSessionEnded(ctx, traceID).Times(1) 466 handler.interactor.EXPECT().RequestWalletConnectionReview(ctx, traceID, uint8(1), hostname).Times(1).Return(string(preferences.ApprovedOnlyThisTime), nil) 467 handler.walletStore.EXPECT().ListWallets(ctx).Times(1).Return([]string{wallet1.Name(), wallet2.Name()}, nil) 468 handler.interactor.EXPECT().RequestWalletSelection(ctx, traceID, uint8(2), hostname, []string{wallet1.Name(), wallet2.Name()}).Times(1).Return("", assert.AnError) 469 handler.interactor.EXPECT().NotifyError(ctx, traceID, api.InternalErrorType, fmt.Errorf("requesting the wallet selection failed: %w", assert.AnError)).Times(1) 470 471 // when 472 result, errorDetails := handler.Handle(ctx, hostname) 473 474 // then 475 assertInternalError(t, errorDetails, api.ErrCouldNotConnectToWallet) 476 assert.Empty(t, result) 477 } 478 479 func testSelectingNonExistingWalletDoesNotConnectToWallet(t *testing.T) { 480 // given 481 ctx, traceID := clientContextForTest() 482 cancelCtx, cancelFn := context.WithCancel(ctx) 483 hostname := vgrand.RandomStr(5) + ".xyz" 484 wallet1 := walletWithPerms(t, hostname, wallet.Permissions{}) 485 wallet2 := walletWithPerms(t, hostname, wallet.Permissions{}) 486 nonExistingWallet := vgrand.RandomStr(5) 487 488 // setup 489 handler := newConnectWalletHandler(t) 490 // -- expected calls 491 handler.interactor.EXPECT().NotifyInteractionSessionBegan(cancelCtx, traceID, api.WalletConnectionWorkflow, uint8(4)).Times(1).Return(nil) 492 handler.interactor.EXPECT().NotifyInteractionSessionEnded(cancelCtx, traceID).Times(1) 493 handler.interactor.EXPECT().RequestWalletConnectionReview(cancelCtx, traceID, uint8(1), hostname).Times(1).Return(string(preferences.ApprovedOnlyThisTime), nil) 494 handler.walletStore.EXPECT().ListWallets(cancelCtx).Times(1).Return([]string{wallet1.Name(), wallet2.Name()}, nil) 495 handler.interactor.EXPECT().RequestWalletSelection(cancelCtx, traceID, uint8(2), hostname, []string{wallet1.Name(), wallet2.Name()}).Times(1).Return(nonExistingWallet, nil) 496 handler.walletStore.EXPECT().WalletExists(cancelCtx, nonExistingWallet).Times(1).Return(false, nil) 497 gomock.InOrder( 498 handler.interactor.EXPECT().NotifyError(cancelCtx, traceID, api.UserErrorType, api.ErrWalletDoesNotExist).Times(1).Do(func(_ context.Context, _ string, _ api.ErrorType, _ error) { 499 // Once everything has been called once, we cancel the handler to break the loop. 500 cancelFn() 501 }), 502 handler.interactor.EXPECT().NotifyError(cancelCtx, traceID, api.ApplicationErrorType, api.ErrRequestInterrupted).Times(1), 503 ) 504 505 // when 506 result, errorDetails := handler.Handle(cancelCtx, hostname) 507 508 // then 509 assertRequestInterruptionError(t, errorDetails) 510 assert.Empty(t, result) 511 } 512 513 func testGettingInternalErrorDuringWalletRetrievalDoesNotConnectToWallet(t *testing.T) { 514 // given 515 ctx, traceID := clientContextForTest() 516 hostname := vgrand.RandomStr(5) + ".xyz" 517 wallet1 := walletWithPerms(t, hostname, wallet.Permissions{}) 518 wallet2 := walletWithPerms(t, hostname, wallet.Permissions{}) 519 520 // setup 521 handler := newConnectWalletHandler(t) 522 // -- expected calls 523 handler.interactor.EXPECT().NotifyInteractionSessionBegan(ctx, traceID, api.WalletConnectionWorkflow, uint8(4)).Times(1).Return(nil) 524 handler.interactor.EXPECT().NotifyInteractionSessionEnded(ctx, traceID).Times(1) 525 handler.interactor.EXPECT().RequestWalletConnectionReview(ctx, traceID, uint8(1), hostname).Times(1).Return(string(preferences.ApprovedOnlyThisTime), nil) 526 handler.walletStore.EXPECT().ListWallets(ctx).Times(1).Return([]string{wallet1.Name(), wallet2.Name()}, nil) 527 handler.interactor.EXPECT().RequestWalletSelection(ctx, traceID, uint8(2), hostname, []string{wallet1.Name(), wallet2.Name()}).Times(1).Return(wallet1.Name(), nil) 528 handler.walletStore.EXPECT().WalletExists(ctx, wallet1.Name()).Times(1).Return(false, assert.AnError) 529 handler.interactor.EXPECT().NotifyError(ctx, traceID, api.InternalErrorType, fmt.Errorf("could not verify the wallet existence: %w", assert.AnError)).Times(1) 530 531 // when 532 result, errorDetails := handler.Handle(ctx, hostname) 533 534 // then 535 assertInternalError(t, errorDetails, api.ErrCouldNotConnectToWallet) 536 assert.Empty(t, result) 537 } 538 539 func testUsingWrongPassphraseDoesNotConnectToWallet(t *testing.T) { 540 // given 541 ctx, traceID := clientContextForTest() 542 cancelCtx, cancelFn := context.WithCancel(ctx) 543 hostname := vgrand.RandomStr(5) + ".xyz" 544 wallet1 := walletWithPerms(t, hostname, wallet.Permissions{}) 545 wallet2 := walletWithPerms(t, hostname, wallet.Permissions{}) 546 passphrase := vgrand.RandomStr(4) 547 548 // setup 549 handler := newConnectWalletHandler(t) 550 // -- expected calls 551 handler.interactor.EXPECT().NotifyInteractionSessionBegan(cancelCtx, traceID, api.WalletConnectionWorkflow, uint8(4)).Times(1).Return(nil) 552 handler.interactor.EXPECT().NotifyInteractionSessionEnded(cancelCtx, traceID).Times(1) 553 handler.interactor.EXPECT().RequestWalletConnectionReview(cancelCtx, traceID, uint8(1), hostname).Times(1).Return(string(preferences.ApprovedOnlyThisTime), nil) 554 handler.walletStore.EXPECT().ListWallets(cancelCtx).Times(1).Return([]string{wallet1.Name(), wallet2.Name()}, nil) 555 handler.interactor.EXPECT().RequestWalletSelection(cancelCtx, traceID, uint8(2), hostname, []string{wallet1.Name(), wallet2.Name()}).Times(1).Return(wallet1.Name(), nil) 556 handler.walletStore.EXPECT().WalletExists(cancelCtx, wallet1.Name()).Times(1).Return(true, nil) 557 handler.walletStore.EXPECT().IsWalletAlreadyUnlocked(cancelCtx, wallet1.Name()).Times(1).Return(false, nil) 558 handler.walletStore.EXPECT().UnlockWallet(cancelCtx, wallet1.Name(), passphrase).Times(1).Return(wallet.ErrWrongPassphrase) 559 handler.interactor.EXPECT().RequestPassphrase(cancelCtx, traceID, uint8(3), wallet1.Name(), api.PassphraseRequestReasonUnlockWallet).Times(1).Return(passphrase, nil) 560 gomock.InOrder( 561 handler.interactor.EXPECT().NotifyError(cancelCtx, traceID, api.UserErrorType, wallet.ErrWrongPassphrase).Times(1).Do(func(_ context.Context, _ string, _ api.ErrorType, _ error) { 562 // Once everything has been called once, we cancel the handler to break the loop. 563 cancelFn() 564 }), 565 handler.interactor.EXPECT().NotifyError(cancelCtx, traceID, api.ApplicationErrorType, api.ErrRequestInterrupted).Times(1), 566 ) 567 568 // when 569 result, errorDetails := handler.Handle(cancelCtx, hostname) 570 571 // then 572 assertRequestInterruptionError(t, errorDetails) 573 assert.Empty(t, result) 574 } 575 576 func testGettingInternalErrorDuringWalletLockStateVerificationDoesNotConnectToWallet(t *testing.T) { 577 // given 578 ctx, traceID := clientContextForTest() 579 hostname := vgrand.RandomStr(5) + ".xyz" 580 wallet1 := walletWithPerms(t, hostname, wallet.Permissions{}) 581 wallet2 := walletWithPerms(t, hostname, wallet.Permissions{}) 582 583 // setup 584 handler := newConnectWalletHandler(t) 585 // -- expected calls 586 handler.interactor.EXPECT().NotifyInteractionSessionBegan(ctx, traceID, api.WalletConnectionWorkflow, uint8(4)).Times(1).Return(nil) 587 handler.interactor.EXPECT().NotifyInteractionSessionEnded(ctx, traceID).Times(1) 588 handler.interactor.EXPECT().RequestWalletConnectionReview(ctx, traceID, uint8(1), hostname).Times(1).Return(string(preferences.ApprovedOnlyThisTime), nil) 589 handler.walletStore.EXPECT().ListWallets(ctx).Times(1).Return([]string{wallet1.Name(), wallet2.Name()}, nil) 590 handler.interactor.EXPECT().RequestWalletSelection(ctx, traceID, uint8(2), hostname, []string{wallet1.Name(), wallet2.Name()}).Times(1).Return(wallet1.Name(), nil) 591 handler.walletStore.EXPECT().WalletExists(ctx, wallet1.Name()).Times(1).Return(true, nil) 592 handler.walletStore.EXPECT().IsWalletAlreadyUnlocked(ctx, wallet1.Name()).Times(1).Return(false, assert.AnError) 593 handler.interactor.EXPECT().NotifyError(ctx, traceID, api.InternalErrorType, fmt.Errorf("could not verify whether the wallet is already unlock or not: %w", assert.AnError)).Times(1) 594 595 // when 596 result, errorDetails := handler.Handle(ctx, hostname) 597 598 // then 599 assertInternalError(t, errorDetails, api.ErrCouldNotConnectToWallet) 600 assert.Empty(t, result) 601 } 602 603 func testGettingInternalErrorDuringPassphraseRequestDoesNotConnectToWallet(t *testing.T) { 604 // given 605 ctx, traceID := clientContextForTest() 606 hostname := vgrand.RandomStr(5) + ".xyz" 607 wallet1 := walletWithPerms(t, hostname, wallet.Permissions{}) 608 wallet2 := walletWithPerms(t, hostname, wallet.Permissions{}) 609 610 // setup 611 handler := newConnectWalletHandler(t) 612 // -- expected calls 613 handler.interactor.EXPECT().NotifyInteractionSessionBegan(ctx, traceID, api.WalletConnectionWorkflow, uint8(4)).Times(1).Return(nil) 614 handler.interactor.EXPECT().NotifyInteractionSessionEnded(ctx, traceID).Times(1) 615 handler.interactor.EXPECT().RequestWalletConnectionReview(ctx, traceID, uint8(1), hostname).Times(1).Return(string(preferences.ApprovedOnlyThisTime), nil) 616 handler.walletStore.EXPECT().ListWallets(ctx).Times(1).Return([]string{wallet1.Name(), wallet2.Name()}, nil) 617 handler.interactor.EXPECT().RequestWalletSelection(ctx, traceID, uint8(2), hostname, []string{wallet1.Name(), wallet2.Name()}).Times(1).Return(wallet1.Name(), nil) 618 handler.walletStore.EXPECT().WalletExists(ctx, wallet1.Name()).Times(1).Return(true, nil) 619 handler.walletStore.EXPECT().IsWalletAlreadyUnlocked(ctx, wallet1.Name()).Times(1).Return(false, nil) 620 handler.interactor.EXPECT().RequestPassphrase(ctx, traceID, uint8(3), wallet1.Name(), api.PassphraseRequestReasonUnlockWallet).Times(1).Return("", assert.AnError) 621 handler.interactor.EXPECT().NotifyError(ctx, traceID, api.InternalErrorType, fmt.Errorf("requesting the wallet passphrase failed: %w", assert.AnError)).Times(1) 622 623 // when 624 result, errorDetails := handler.Handle(ctx, hostname) 625 626 // then 627 assertInternalError(t, errorDetails, api.ErrCouldNotConnectToWallet) 628 assert.Empty(t, result) 629 } 630 631 func testInterruptingTheRequestDuringPassphraseRequestDoesNotConnectToWallet(t *testing.T) { 632 // given 633 ctx, traceID := clientContextForTest() 634 hostname := vgrand.RandomStr(5) + ".xyz" 635 wallet1 := walletWithPerms(t, hostname, wallet.Permissions{}) 636 wallet2 := walletWithPerms(t, hostname, wallet.Permissions{}) 637 638 // setup 639 handler := newConnectWalletHandler(t) 640 // -- expected calls 641 handler.interactor.EXPECT().NotifyInteractionSessionBegan(ctx, traceID, api.WalletConnectionWorkflow, uint8(4)).Times(1).Return(nil) 642 handler.interactor.EXPECT().NotifyInteractionSessionEnded(ctx, traceID).Times(1) 643 handler.interactor.EXPECT().RequestWalletConnectionReview(ctx, traceID, uint8(1), hostname).Times(1).Return(string(preferences.ApprovedOnlyThisTime), nil) 644 handler.walletStore.EXPECT().ListWallets(ctx).Times(1).Return([]string{wallet1.Name(), wallet2.Name()}, nil) 645 handler.interactor.EXPECT().RequestWalletSelection(ctx, traceID, uint8(2), hostname, []string{wallet1.Name(), wallet2.Name()}).Times(1).Return(wallet1.Name(), nil) 646 handler.walletStore.EXPECT().WalletExists(ctx, wallet1.Name()).Times(1).Return(true, nil) 647 handler.walletStore.EXPECT().IsWalletAlreadyUnlocked(ctx, wallet1.Name()).Times(1).Return(false, nil) 648 handler.interactor.EXPECT().RequestPassphrase(ctx, traceID, uint8(3), wallet1.Name(), api.PassphraseRequestReasonUnlockWallet).Times(1).Return("", api.ErrRequestInterrupted) 649 handler.interactor.EXPECT().NotifyError(ctx, traceID, api.ServerErrorType, api.ErrRequestInterrupted).Times(1) 650 651 // when 652 result, errorDetails := handler.Handle(ctx, hostname) 653 654 // then 655 assertRequestInterruptionError(t, errorDetails) 656 assert.Empty(t, result) 657 } 658 659 func testCancellingThePassphraseRequestDoesNotConnectToWallet(t *testing.T) { 660 // given 661 ctx, traceID := clientContextForTest() 662 hostname := vgrand.RandomStr(5) + ".xyz" 663 wallet1 := walletWithPerms(t, hostname, wallet.Permissions{}) 664 wallet2 := walletWithPerms(t, hostname, wallet.Permissions{}) 665 666 // setup 667 handler := newConnectWalletHandler(t) 668 // -- expected calls 669 handler.interactor.EXPECT().NotifyInteractionSessionBegan(ctx, traceID, api.WalletConnectionWorkflow, uint8(4)).Times(1).Return(nil) 670 handler.interactor.EXPECT().NotifyInteractionSessionEnded(ctx, traceID).Times(1) 671 handler.interactor.EXPECT().RequestWalletConnectionReview(ctx, traceID, uint8(1), hostname).Times(1).Return(string(preferences.ApprovedOnlyThisTime), nil) 672 handler.walletStore.EXPECT().ListWallets(ctx).Times(1).Return([]string{wallet1.Name(), wallet2.Name()}, nil) 673 handler.interactor.EXPECT().RequestWalletSelection(ctx, traceID, uint8(2), hostname, []string{wallet1.Name(), wallet2.Name()}).Times(1).Return(wallet1.Name(), nil) 674 handler.walletStore.EXPECT().WalletExists(ctx, wallet1.Name()).Times(1).Return(true, nil) 675 handler.walletStore.EXPECT().IsWalletAlreadyUnlocked(ctx, wallet1.Name()).Times(1).Return(false, nil) 676 handler.interactor.EXPECT().RequestPassphrase(ctx, traceID, uint8(3), wallet1.Name(), api.PassphraseRequestReasonUnlockWallet).Times(1).Return("", api.ErrUserCloseTheConnection) 677 handler.interactor.EXPECT().NotifyError(ctx, traceID, api.ApplicationErrorType, api.ErrConnectionClosed).Times(1) 678 679 // when 680 result, errorDetails := handler.Handle(ctx, hostname) 681 682 // then 683 assertConnectionClosedError(t, errorDetails) 684 assert.Empty(t, result) 685 } 686 687 func testGettingInternalErrorDuringWalletUnlockingDoesNotConnectToWallet(t *testing.T) { 688 // given 689 ctx, traceID := clientContextForTest() 690 hostname := vgrand.RandomStr(5) + ".xyz" 691 wallet1 := walletWithPerms(t, hostname, wallet.Permissions{}) 692 wallet2 := walletWithPerms(t, hostname, wallet.Permissions{}) 693 passphrase := vgrand.RandomStr(5) 694 695 // setup 696 handler := newConnectWalletHandler(t) 697 // -- expected calls 698 handler.interactor.EXPECT().NotifyInteractionSessionBegan(ctx, traceID, api.WalletConnectionWorkflow, uint8(4)).Times(1).Return(nil) 699 handler.interactor.EXPECT().NotifyInteractionSessionEnded(ctx, traceID).Times(1) 700 handler.interactor.EXPECT().RequestWalletConnectionReview(ctx, traceID, uint8(1), hostname).Times(1).Return(string(preferences.ApprovedOnlyThisTime), nil) 701 handler.walletStore.EXPECT().ListWallets(ctx).Times(1).Return([]string{wallet1.Name(), wallet2.Name()}, nil) 702 handler.interactor.EXPECT().RequestWalletSelection(ctx, traceID, uint8(2), hostname, []string{wallet1.Name(), wallet2.Name()}).Times(1).Return(wallet1.Name(), nil) 703 handler.walletStore.EXPECT().WalletExists(ctx, wallet1.Name()).Times(1).Return(true, nil) 704 handler.interactor.EXPECT().RequestPassphrase(ctx, traceID, uint8(3), wallet1.Name(), api.PassphraseRequestReasonUnlockWallet).Times(1).Return(passphrase, nil) 705 handler.walletStore.EXPECT().IsWalletAlreadyUnlocked(ctx, wallet1.Name()).Times(1).Return(false, nil) 706 handler.walletStore.EXPECT().UnlockWallet(ctx, wallet1.Name(), passphrase).Times(1).Return(assert.AnError) 707 handler.interactor.EXPECT().NotifyError(ctx, traceID, api.InternalErrorType, fmt.Errorf("could not unlock the wallet: %w", assert.AnError)).Times(1) 708 709 // when 710 result, errorDetails := handler.Handle(ctx, hostname) 711 712 // then 713 assertInternalError(t, errorDetails, api.ErrCouldNotConnectToWallet) 714 assert.Empty(t, result) 715 } 716 717 func testGettingInternalErrorDuringWalletVerificationDoesNotConnectToWallet(t *testing.T) { 718 // given 719 ctx, traceID := clientContextForTest() 720 hostname := vgrand.RandomStr(5) + ".xyz" 721 wallet1 := walletWithPerms(t, hostname, wallet.Permissions{}) 722 wallet2 := walletWithPerms(t, hostname, wallet.Permissions{}) 723 passphrase := vgrand.RandomStr(5) 724 725 // setup 726 handler := newConnectWalletHandler(t) 727 // -- expected calls 728 handler.interactor.EXPECT().NotifyInteractionSessionBegan(ctx, traceID, api.WalletConnectionWorkflow, uint8(4)).Times(1).Return(nil) 729 handler.interactor.EXPECT().NotifyInteractionSessionEnded(ctx, traceID).Times(1) 730 handler.interactor.EXPECT().RequestWalletConnectionReview(ctx, traceID, uint8(1), hostname).Times(1).Return(string(preferences.ApprovedOnlyThisTime), nil) 731 handler.walletStore.EXPECT().ListWallets(ctx).Times(1).Return([]string{wallet1.Name(), wallet2.Name()}, nil) 732 handler.interactor.EXPECT().RequestWalletSelection(ctx, traceID, uint8(2), hostname, []string{wallet1.Name(), wallet2.Name()}).Times(1).Return(wallet1.Name(), nil) 733 handler.walletStore.EXPECT().WalletExists(ctx, wallet1.Name()).Times(1).Return(true, nil) 734 handler.interactor.EXPECT().RequestPassphrase(ctx, traceID, uint8(3), wallet1.Name(), api.PassphraseRequestReasonUnlockWallet).Times(1).Return(passphrase, nil) 735 handler.walletStore.EXPECT().IsWalletAlreadyUnlocked(ctx, wallet1.Name()).Times(1).Return(false, nil) 736 handler.walletStore.EXPECT().UnlockWallet(ctx, wallet1.Name(), passphrase).Times(1).Return(nil) 737 handler.walletStore.EXPECT().GetWallet(ctx, wallet1.Name()).Times(1).Return(nil, assert.AnError) 738 handler.interactor.EXPECT().NotifyError(ctx, traceID, api.InternalErrorType, fmt.Errorf("could not retrieve the wallet: %w", assert.AnError)).Times(1) 739 740 // when 741 result, errorDetails := handler.Handle(ctx, hostname) 742 743 // then 744 assertInternalError(t, errorDetails, api.ErrCouldNotConnectToWallet) 745 assert.Empty(t, result) 746 } 747 748 type connectWalletHandler struct { 749 *api.ClientConnectWallet 750 ctrl *gomock.Controller 751 walletStore *mocks.MockWalletStore 752 interactor *mocks.MockInteractor 753 } 754 755 func newConnectWalletHandler(t *testing.T) *connectWalletHandler { 756 t.Helper() 757 758 ctrl := gomock.NewController(t) 759 walletStore := mocks.NewMockWalletStore(ctrl) 760 interactor := mocks.NewMockInteractor(ctrl) 761 762 return &connectWalletHandler{ 763 ClientConnectWallet: api.NewConnectWallet(walletStore, interactor), 764 ctrl: ctrl, 765 walletStore: walletStore, 766 interactor: interactor, 767 } 768 }