github.com/hyperledger/aries-framework-go@v0.3.2/pkg/client/vcwallet/client_test.go (about) 1 /* 2 Copyright SecureKey Technologies Inc. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package vcwallet 8 9 import ( 10 "crypto/sha256" 11 "encoding/base64" 12 "encoding/json" 13 "errors" 14 "fmt" 15 "strings" 16 "testing" 17 "time" 18 19 "github.com/google/uuid" 20 "github.com/stretchr/testify/require" 21 22 "github.com/hyperledger/aries-framework-go/internal/testdata" 23 "github.com/hyperledger/aries-framework-go/pkg/client/outofband" 24 "github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto" 25 "github.com/hyperledger/aries-framework-go/pkg/didcomm/common/model" 26 "github.com/hyperledger/aries-framework-go/pkg/didcomm/common/service" 27 "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/didexchange" 28 issuecredentialsvc "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/issuecredential" 29 "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/mediator" 30 outofbandSvc "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/outofband" 31 oobv2 "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/outofbandv2" 32 presentproofSvc "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/presentproof" 33 "github.com/hyperledger/aries-framework-go/pkg/doc/did" 34 "github.com/hyperledger/aries-framework-go/pkg/doc/presexch" 35 "github.com/hyperledger/aries-framework-go/pkg/doc/util" 36 "github.com/hyperledger/aries-framework-go/pkg/doc/verifiable" 37 vdrapi "github.com/hyperledger/aries-framework-go/pkg/framework/aries/api/vdr" 38 mockoutofbandv2 "github.com/hyperledger/aries-framework-go/pkg/internal/gomocks/client/outofbandv2" 39 "github.com/hyperledger/aries-framework-go/pkg/internal/ldtestutil" 40 "github.com/hyperledger/aries-framework-go/pkg/kms" 41 cryptomock "github.com/hyperledger/aries-framework-go/pkg/mock/crypto" 42 mockdidexchange "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/didexchange" 43 mockissuecredential "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/issuecredential" 44 mockmediator "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/mediator" 45 mockoutofband "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/outofband" 46 mockpresentproof "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/presentproof" 47 mockprovider "github.com/hyperledger/aries-framework-go/pkg/mock/provider" 48 "github.com/hyperledger/aries-framework-go/pkg/mock/secretlock" 49 mockstorage "github.com/hyperledger/aries-framework-go/pkg/mock/storage" 50 mockvdr "github.com/hyperledger/aries-framework-go/pkg/mock/vdr" 51 "github.com/hyperledger/aries-framework-go/pkg/secretlock/local/masterlock/pbkdf2" 52 "github.com/hyperledger/aries-framework-go/pkg/store/connection" 53 "github.com/hyperledger/aries-framework-go/pkg/vdr/key" 54 "github.com/hyperledger/aries-framework-go/pkg/wallet" 55 "github.com/hyperledger/aries-framework-go/spi/storage" 56 ) 57 58 const ( 59 samplePassPhrase = "fakepassphrase" 60 sampleRemoteKMSAuth = "sample-auth-token" 61 sampleKeyServerURL = "sample/keyserver/test" 62 sampleUserID = "sample-user01" 63 toBeImplementedErr = "to be implemented" 64 sampleClientErr = "sample client err" 65 sampleDIDKey = "did:key:z6MknC1wwS6DEYwtGbZZo2QvjQjkh2qSBjb4GYmbye8dv4S5" 66 sampleDIDKey2 = "did:key:z6MkwFKUCsf8wvn6eSSu1WFAKatN1yexiDM7bf7pZLSFjdz6" 67 sampleInvalidDIDContent = `{"@context": ["https://w3id.org/did/v1"],"id": "did:example:sampleInvalidDIDContent"}` 68 webRedirectStatusKey = "status" 69 webRedirectURLKey = "url" 70 exampleWebRedirect = "http://example.com/sample" 71 sampleMsgComment = "sample mock msg" 72 ) 73 74 func TestCreateProfile(t *testing.T) { 75 t.Run("test create new wallet client using local kms passphrase", func(t *testing.T) { 76 mockctx := newMockProvider(t) 77 err := CreateProfile(sampleUserID, mockctx, wallet.WithPassphrase(samplePassPhrase)) 78 require.NoError(t, err) 79 require.NoError(t, ProfileExists(sampleUserID, mockctx)) 80 81 vcWallet, err := New(sampleUserID, mockctx) 82 require.NoError(t, err) 83 require.NotEmpty(t, vcWallet) 84 }) 85 86 t.Run("test create new wallet client using local kms secret lock service", func(t *testing.T) { 87 mockctx := newMockProvider(t) 88 err := CreateProfile(sampleUserID, mockctx, wallet.WithSecretLockService(&secretlock.MockSecretLock{})) 89 require.NoError(t, err) 90 require.NoError(t, ProfileExists(sampleUserID, mockctx)) 91 92 vcWallet, err := New(sampleUserID, mockctx) 93 require.NoError(t, err) 94 require.NotEmpty(t, vcWallet) 95 }) 96 97 t.Run("test create new wallet client using remote kms key server URL", func(t *testing.T) { 98 mockctx := newMockProvider(t) 99 err := CreateProfile(sampleUserID, mockctx, wallet.WithKeyServerURL(sampleKeyServerURL)) 100 require.NoError(t, err) 101 require.NoError(t, ProfileExists(sampleUserID, mockctx)) 102 103 vcWallet, err := New(sampleUserID, mockctx) 104 require.NoError(t, err) 105 require.NotEmpty(t, vcWallet) 106 }) 107 108 t.Run("test create new wallet failure", func(t *testing.T) { 109 mockctx := newMockProvider(t) 110 err := CreateProfile(sampleUserID, mockctx) 111 require.Error(t, err) 112 require.Contains(t, err.Error(), "invalid create profile options") 113 require.True(t, errors.Is(ProfileExists(sampleUserID, mockctx), wallet.ErrProfileNotFound)) 114 115 vcWallet, err := New(sampleUserID, mockctx) 116 require.Error(t, err) 117 require.Empty(t, vcWallet) 118 }) 119 120 t.Run("test create new wallet failure - create store error", func(t *testing.T) { 121 mockctx := newMockProvider(t) 122 mockctx.StorageProviderValue = &mockstorage.MockStoreProvider{ 123 ErrOpenStoreHandle: fmt.Errorf(sampleClientErr), 124 } 125 126 err := CreateProfile(sampleUserID, mockctx, wallet.WithKeyServerURL(sampleKeyServerURL)) 127 require.Error(t, err) 128 require.Contains(t, err.Error(), sampleClientErr) 129 130 vcWallet, err := New(sampleUserID, mockctx) 131 require.Error(t, err) 132 require.Empty(t, vcWallet) 133 134 err = ProfileExists(sampleUserID, mockctx) 135 require.Error(t, err) 136 require.Contains(t, err.Error(), sampleClientErr) 137 }) 138 139 t.Run("test create new wallet failure - save profile error", func(t *testing.T) { 140 mockctx := newMockProvider(t) 141 mockctx.StorageProviderValue = &mockstorage.MockStoreProvider{ 142 Store: &mockstorage.MockStore{ 143 ErrPut: fmt.Errorf(sampleClientErr), 144 }, 145 } 146 147 err := CreateProfile(sampleUserID, mockctx, wallet.WithKeyServerURL(sampleKeyServerURL)) 148 require.Error(t, err) 149 require.Contains(t, err.Error(), sampleClientErr) 150 151 vcWallet, err := New(sampleUserID, mockctx) 152 require.Error(t, err) 153 require.Empty(t, vcWallet) 154 }) 155 156 t.Run("test create new wallet failure - create content store error", func(t *testing.T) { 157 mockctx := newMockProvider(t) 158 mockctx.StorageProviderValue = &mockStorageProvider{ 159 MockStoreProvider: mockstorage.NewMockStoreProvider(), 160 failure: fmt.Errorf(sampleClientErr), 161 } 162 163 err := CreateProfile(sampleUserID, mockctx, wallet.WithKeyServerURL(sampleKeyServerURL)) 164 require.NoError(t, err) 165 166 vcWallet, err := New(sampleUserID, mockctx) 167 require.Error(t, err) 168 require.Contains(t, err.Error(), sampleClientErr) 169 require.Empty(t, vcWallet) 170 }) 171 } 172 173 func TestUpdate(t *testing.T) { 174 t.Run("test update wallet client using local kms passphrase", func(t *testing.T) { 175 mockctx := newMockProvider(t) 176 createSampleProfile(t, mockctx) 177 178 err := UpdateProfile(sampleUserID, mockctx, wallet.WithPassphrase(samplePassPhrase)) 179 require.NoError(t, err) 180 181 vcWallet, err := New(sampleUserID, mockctx) 182 require.NoError(t, err) 183 require.NotEmpty(t, vcWallet) 184 }) 185 186 t.Run("test update wallet client using local kms secret lock service", func(t *testing.T) { 187 mockctx := newMockProvider(t) 188 createSampleProfile(t, mockctx) 189 190 err := UpdateProfile(sampleUserID, mockctx, wallet.WithSecretLockService(&secretlock.MockSecretLock{})) 191 require.NoError(t, err) 192 193 vcWallet, err := New(sampleUserID, mockctx) 194 require.NoError(t, err) 195 require.NotEmpty(t, vcWallet) 196 }) 197 198 t.Run("test update wallet client using remote kms key server URL", func(t *testing.T) { 199 mockctx := newMockProvider(t) 200 createSampleProfile(t, mockctx) 201 202 err := UpdateProfile(sampleUserID, mockctx, wallet.WithKeyServerURL(sampleKeyServerURL)) 203 require.NoError(t, err) 204 205 vcWallet, err := New(sampleUserID, mockctx) 206 require.NoError(t, err) 207 require.NotEmpty(t, vcWallet) 208 }) 209 210 t.Run("test update wallet failure", func(t *testing.T) { 211 mockctx := newMockProvider(t) 212 createSampleProfile(t, mockctx) 213 214 err := UpdateProfile(sampleUserID, mockctx) 215 require.Error(t, err) 216 require.Contains(t, err.Error(), "invalid create profile options") 217 218 vcWallet, err := New(sampleUserID, mockctx) 219 require.NoError(t, err) 220 require.NotEmpty(t, vcWallet) 221 }) 222 223 t.Run("test update wallet failure - profile doesn't exists", func(t *testing.T) { 224 mockctx := newMockProvider(t) 225 err := UpdateProfile(sampleUserID, mockctx) 226 require.Error(t, err) 227 require.Contains(t, err.Error(), "profile does not exist") 228 229 vcWallet, err := New(sampleUserID, mockctx) 230 require.Error(t, err) 231 require.Empty(t, vcWallet) 232 }) 233 234 t.Run("test update wallet failure - create store error", func(t *testing.T) { 235 mockctx := newMockProvider(t) 236 mockctx.StorageProviderValue = &mockstorage.MockStoreProvider{ 237 ErrOpenStoreHandle: fmt.Errorf(sampleClientErr), 238 } 239 240 err := UpdateProfile(sampleUserID, mockctx, wallet.WithKeyServerURL(sampleKeyServerURL)) 241 require.Error(t, err) 242 require.Contains(t, err.Error(), sampleClientErr) 243 244 vcWallet, err := New(sampleUserID, mockctx) 245 require.Error(t, err) 246 require.Empty(t, vcWallet) 247 }) 248 249 t.Run("test update wallet failure - save profile error", func(t *testing.T) { 250 mockctx := newMockProvider(t) 251 createSampleProfile(t, mockctx) 252 253 mockctx.StorageProviderValue.(*mockstorage.MockStoreProvider).Store.ErrPut = fmt.Errorf(sampleClientErr) 254 255 err := UpdateProfile(sampleUserID, mockctx, wallet.WithKeyServerURL(sampleKeyServerURL)) 256 require.Error(t, err) 257 require.Contains(t, err.Error(), sampleClientErr) 258 259 vcWallet, err := New(sampleUserID, mockctx) 260 require.NoError(t, err) 261 require.NotEmpty(t, vcWallet) 262 }) 263 } 264 265 func TestNew(t *testing.T) { 266 t.Run("test get client", func(t *testing.T) { 267 mockctx := newMockProvider(t) 268 // create a wallet 269 err := CreateProfile(sampleUserID, mockctx, wallet.WithPassphrase(samplePassPhrase)) 270 require.NoError(t, err) 271 272 vcWallet, err := New(sampleUserID, mockctx) 273 require.NoError(t, err) 274 require.NotEmpty(t, vcWallet) 275 }) 276 277 t.Run("test get client unlocked", func(t *testing.T) { 278 mockctx := newMockProvider(t) 279 // create a wallet 280 err := CreateProfile(sampleUserID, mockctx, wallet.WithPassphrase(samplePassPhrase)) 281 require.NoError(t, err) 282 283 vcWallet, err := New(sampleUserID, mockctx, wallet.WithUnlockByPassphrase(samplePassPhrase)) 284 require.NoError(t, err) 285 require.NotEmpty(t, vcWallet) 286 287 token, err := vcWallet.auth() 288 require.NoError(t, err) 289 require.NotEmpty(t, token) 290 }) 291 292 t.Run("test get client unlock failure - wrong passphrase", func(t *testing.T) { 293 mockctx := newMockProvider(t) 294 // create a wallet 295 err := CreateProfile(sampleUserID, mockctx, wallet.WithPassphrase(samplePassPhrase)) 296 require.NoError(t, err) 297 298 vcWallet, err := New(sampleUserID, mockctx, wallet.WithUnlockByPassphrase(samplePassPhrase+"ss")) 299 require.Error(t, err) 300 require.Contains(t, err.Error(), "message authentication failed") 301 require.Empty(t, vcWallet) 302 }) 303 304 t.Run("test get client by invalid userID", func(t *testing.T) { 305 mockctx := newMockProvider(t) 306 err := CreateProfile(sampleUserID, mockctx, wallet.WithPassphrase(samplePassPhrase)) 307 require.NoError(t, err) 308 309 vcWallet, err := New(sampleUserID+"invalid", mockctx) 310 require.Empty(t, vcWallet) 311 require.Error(t, err) 312 require.Contains(t, err.Error(), "profile does not exist") 313 }) 314 315 t.Run("test update wallet failure - save profile error", func(t *testing.T) { 316 mockctx := newMockProvider(t) 317 mockctx.StorageProviderValue = &mockstorage.MockStoreProvider{ 318 ErrOpenStoreHandle: fmt.Errorf(sampleClientErr), 319 } 320 321 vcWallet, err := New(sampleUserID, mockctx) 322 require.Error(t, err) 323 require.Empty(t, vcWallet) 324 require.Contains(t, err.Error(), sampleClientErr) 325 }) 326 } 327 328 func TestClient_OpenClose(t *testing.T) { 329 t.Run("test open & close wallet using local kms passphrase", func(t *testing.T) { 330 sampleUser := uuid.New().String() 331 mockctx := newMockProvider(t) 332 333 err := CreateProfile(sampleUser, mockctx, wallet.WithPassphrase(samplePassPhrase)) 334 require.NoError(t, err) 335 336 vcWallet, err := New(sampleUser, mockctx) 337 require.NoError(t, err) 338 require.NotEmpty(t, vcWallet) 339 340 // get token 341 err = vcWallet.Open(wallet.WithUnlockByPassphrase(samplePassPhrase)) 342 require.NoError(t, err) 343 token, err := vcWallet.auth() 344 require.NoError(t, err) 345 require.NotEmpty(t, token) 346 347 defer vcWallet.Close() 348 349 // try again 350 err = vcWallet.Open(wallet.WithUnlockByPassphrase(samplePassPhrase)) 351 require.Error(t, err) 352 require.True(t, errors.Is(err, wallet.ErrAlreadyUnlocked)) 353 token, err = vcWallet.auth() 354 require.NoError(t, err) 355 require.NotEmpty(t, token) 356 357 // close wallet 358 require.True(t, vcWallet.Close()) 359 require.False(t, vcWallet.Close()) 360 361 // try to open with wrong passphrase 362 err = vcWallet.Open(wallet.WithUnlockByPassphrase(samplePassPhrase + "wrong")) 363 require.Error(t, err) 364 require.Contains(t, err.Error(), "message authentication failed") 365 token, err = vcWallet.auth() 366 require.Empty(t, token) 367 require.Error(t, err) 368 require.True(t, errors.Is(err, ErrWalletLocked)) 369 }) 370 371 t.Run("test open & close wallet using secret lock service", func(t *testing.T) { 372 sampleUser := uuid.New().String() 373 mockctx := newMockProvider(t) 374 375 masterLock, err := pbkdf2.NewMasterLock(samplePassPhrase, sha256.New, 0, nil) 376 require.NoError(t, err) 377 378 err = CreateProfile(sampleUser, mockctx, wallet.WithSecretLockService(masterLock)) 379 require.NoError(t, err) 380 381 vcWallet, err := New(sampleUser, mockctx) 382 require.NoError(t, err) 383 require.NotEmpty(t, vcWallet) 384 385 // get token 386 err = vcWallet.Open(wallet.WithUnlockBySecretLockService(masterLock)) 387 require.NoError(t, err) 388 token, err := vcWallet.auth() 389 require.NoError(t, err) 390 require.NotEmpty(t, token) 391 392 defer vcWallet.Close() 393 394 // try again 395 err = vcWallet.Open(wallet.WithUnlockBySecretLockService(masterLock)) 396 require.Error(t, err) 397 require.True(t, errors.Is(err, wallet.ErrAlreadyUnlocked)) 398 token, err = vcWallet.auth() 399 require.NoError(t, err) 400 require.NotEmpty(t, token) 401 402 // close wallet 403 require.True(t, vcWallet.Close()) 404 require.False(t, vcWallet.Close()) 405 406 // try to open with wrong secret lock service 407 badLock, err := pbkdf2.NewMasterLock(samplePassPhrase+"wrong", sha256.New, 0, nil) 408 require.NoError(t, err) 409 410 err = vcWallet.Open(wallet.WithUnlockBySecretLockService(badLock)) 411 require.Error(t, err) 412 require.Contains(t, err.Error(), "message authentication failed") 413 token, err = vcWallet.auth() 414 require.Empty(t, token) 415 require.Error(t, err) 416 require.True(t, errors.Is(err, ErrWalletLocked)) 417 }) 418 419 t.Run("test open & close wallet using remote kms URL", func(t *testing.T) { 420 sampleUser := uuid.New().String() 421 mockctx := newMockProvider(t) 422 423 err := CreateProfile(sampleUser, mockctx, wallet.WithKeyServerURL(sampleKeyServerURL)) 424 require.NoError(t, err) 425 426 vcWallet, err := New(sampleUser, mockctx) 427 require.NoError(t, err) 428 require.NotEmpty(t, vcWallet) 429 430 // get token 431 err = vcWallet.Open(wallet.WithUnlockByAuthorizationToken(sampleRemoteKMSAuth)) 432 require.NoError(t, err) 433 token, err := vcWallet.auth() 434 require.NoError(t, err) 435 require.NotEmpty(t, token) 436 437 defer vcWallet.Close() 438 439 // try again 440 err = vcWallet.Open(wallet.WithUnlockByAuthorizationToken(sampleRemoteKMSAuth)) 441 require.Error(t, err) 442 require.True(t, errors.Is(err, wallet.ErrAlreadyUnlocked)) 443 token, err = vcWallet.auth() 444 require.NoError(t, err) 445 require.NotEmpty(t, token) 446 447 // close wallet 448 require.True(t, vcWallet.Close()) 449 require.False(t, vcWallet.Close()) 450 token, err = vcWallet.auth() 451 require.Empty(t, token) 452 require.Error(t, err) 453 require.True(t, errors.Is(err, ErrWalletLocked)) 454 }) 455 } 456 457 func TestClient_Export(t *testing.T) { 458 mockctx := newMockProvider(t) 459 err := CreateProfile(sampleUserID, mockctx, wallet.WithKeyServerURL(sampleKeyServerURL)) 460 require.NoError(t, err) 461 462 vcWalletClient, err := New(sampleUserID, mockctx) 463 require.NotEmpty(t, vcWalletClient) 464 require.NoError(t, err) 465 466 result, err := vcWalletClient.Export("") 467 require.Empty(t, result) 468 require.Error(t, err) 469 require.EqualError(t, err, toBeImplementedErr) 470 } 471 472 func TestClient_Import(t *testing.T) { 473 mockctx := newMockProvider(t) 474 err := CreateProfile(sampleUserID, mockctx, wallet.WithKeyServerURL(sampleKeyServerURL)) 475 require.NoError(t, err) 476 477 vcWalletClient, err := New(sampleUserID, mockctx) 478 require.NotEmpty(t, vcWalletClient) 479 require.NoError(t, err) 480 481 err = vcWalletClient.Import("", nil) 482 require.Error(t, err) 483 require.EqualError(t, err, toBeImplementedErr) 484 } 485 486 func TestClient_Add(t *testing.T) { 487 mockctx := newMockProvider(t) 488 err := CreateProfile(sampleUserID, mockctx, wallet.WithKeyServerURL(sampleKeyServerURL)) 489 require.NoError(t, err) 490 491 vcWalletClient, err := New(sampleUserID, mockctx, wallet.WithUnlockByPassphrase(samplePassPhrase)) 492 require.NotEmpty(t, vcWalletClient) 493 require.NoError(t, err) 494 495 err = vcWalletClient.Add(wallet.Metadata, testdata.SampleWalletContentMetadata) 496 require.NoError(t, err) 497 498 // try locked wallet 499 vcWalletClient, err = New(sampleUserID, mockctx) 500 require.NotEmpty(t, vcWalletClient) 501 require.NoError(t, err) 502 503 err = vcWalletClient.Add(wallet.Metadata, testdata.SampleWalletContentMetadata) 504 require.Contains(t, err.Error(), "wallet locked") 505 } 506 507 func TestClient_Get(t *testing.T) { 508 mockctx := newMockProvider(t) 509 err := CreateProfile(sampleUserID, mockctx, wallet.WithKeyServerURL(sampleKeyServerURL)) 510 require.NoError(t, err) 511 512 vcWalletClient, err := New(sampleUserID, mockctx, wallet.WithUnlockByPassphrase(samplePassPhrase)) 513 require.NotEmpty(t, vcWalletClient) 514 require.NoError(t, err) 515 516 err = vcWalletClient.Add(wallet.Metadata, testdata.SampleWalletContentMetadata) 517 require.NoError(t, err) 518 519 content, err := vcWalletClient.Get(wallet.Metadata, "did:example:123456789abcdefghi") 520 require.NoError(t, err) 521 require.NotEmpty(t, content) 522 require.Equal(t, string(testdata.SampleWalletContentMetadata), string(content)) 523 524 // try locked wallet 525 require.True(t, vcWalletClient.Close()) 526 content, err = vcWalletClient.Get(wallet.Metadata, "did:example:123456789abcdefghi") 527 require.True(t, errors.Is(err, ErrWalletLocked)) 528 require.Empty(t, content) 529 } 530 531 func TestClient_GetAll(t *testing.T) { 532 const vcContent = `{ 533 "@context": [ 534 "https://www.w3.org/2018/credentials/v1", 535 "https://www.w3.org/2018/credentials/examples/v1" 536 ], 537 "id": "%s", 538 "issuer": { 539 "id": "did:example:76e12ec712ebc6f1c221ebfeb1f" 540 }, 541 "type": [ 542 "VerifiableCredential", 543 "UniversityDegreeCredential" 544 ] 545 }` 546 547 const orgCollection = `{ 548 "@context": ["https://w3id.org/wallet/v1"], 549 "id": "did:example:acme123456789abcdefghi", 550 "type": "Organization", 551 "name": "Acme Corp.", 552 "image": "https://via.placeholder.com/150", 553 "description" : "A software company.", 554 "tags": ["professional", "organization"], 555 "correlation": ["4058a72a-9523-11ea-bb37-0242ac130002"] 556 }` 557 558 const collectionID = "did:example:acme123456789abcdefghi" 559 560 mockctx := newMockProvider(t) 561 err := CreateProfile(sampleUserID, mockctx, wallet.WithPassphrase(samplePassPhrase)) 562 require.NoError(t, err) 563 564 vcWalletClient, err := New(sampleUserID, mockctx, wallet.WithUnlockByPassphrase(samplePassPhrase)) 565 require.NotEmpty(t, vcWalletClient) 566 require.NoError(t, err) 567 568 // save test data 569 const count = 5 570 571 for i := 0; i < count; i++ { 572 require.NoError(t, vcWalletClient.Add(wallet.Credential, []byte(fmt.Sprintf(vcContent, uuid.New().String())))) 573 } 574 575 // save a collection 576 require.NoError(t, vcWalletClient.Add(wallet.Collection, []byte(orgCollection))) 577 578 // save contents by collection 579 for i := 0; i < count; i++ { 580 require.NoError(t, vcWalletClient.Add(wallet.Credential, 581 []byte(fmt.Sprintf(vcContent, uuid.New().String())), wallet.AddByCollection(collectionID))) 582 } 583 584 // get all by content 585 vcs, err := vcWalletClient.GetAll(wallet.Credential) 586 require.NoError(t, err) 587 require.Len(t, vcs, count*2) 588 589 // get all by content & collection 590 vcs, err = vcWalletClient.GetAll(wallet.Credential, wallet.FilterByCollection(collectionID)) 591 require.NoError(t, err) 592 require.Len(t, vcs, count) 593 594 // try locked wallet 595 require.True(t, vcWalletClient.Close()) 596 vcs, err = vcWalletClient.GetAll(wallet.Credential, wallet.FilterByCollection(collectionID)) 597 require.True(t, errors.Is(err, ErrWalletLocked)) 598 require.Empty(t, vcs) 599 } 600 601 func TestClient_Remove(t *testing.T) { 602 mockctx := newMockProvider(t) 603 err := CreateProfile(sampleUserID, mockctx, wallet.WithKeyServerURL(sampleKeyServerURL)) 604 require.NoError(t, err) 605 606 vcWalletClient, err := New(sampleUserID, mockctx, wallet.WithUnlockByPassphrase(samplePassPhrase)) 607 require.NotEmpty(t, vcWalletClient) 608 require.NoError(t, err) 609 610 err = vcWalletClient.Add(wallet.Metadata, testdata.SampleWalletContentMetadata) 611 require.NoError(t, err) 612 613 content, err := vcWalletClient.Get(wallet.Metadata, "did:example:123456789abcdefghi") 614 require.NoError(t, err) 615 require.NotEmpty(t, content) 616 617 err = vcWalletClient.Remove(wallet.Metadata, "did:example:123456789abcdefghi") 618 require.NoError(t, err) 619 620 content, err = vcWalletClient.Get(wallet.Metadata, "did:example:123456789abcdefghi") 621 require.Empty(t, content) 622 require.Error(t, err) 623 require.True(t, errors.Is(err, storage.ErrDataNotFound)) 624 625 // try locked wallet 626 require.True(t, vcWalletClient.Close()) 627 err = vcWalletClient.Remove(wallet.Metadata, "did:example:123456789abcdefghi") 628 require.True(t, errors.Is(err, ErrWalletLocked)) 629 } 630 631 func TestClient_Query(t *testing.T) { 632 customVDR := &mockvdr.MockVDRegistry{ 633 ResolveFunc: func(didID string, opts ...vdrapi.DIDMethodOption) (*did.DocResolution, error) { 634 if strings.HasPrefix(didID, "did:key:") { 635 k := key.New() 636 637 d, e := k.Read(didID) 638 if e != nil { 639 return nil, e 640 } 641 642 return d, nil 643 } 644 645 return nil, fmt.Errorf("did not found") 646 }, 647 } 648 649 mockctx := newMockProvider(t) 650 mockctx.VDRegistryValue = customVDR 651 mockctx.CryptoValue = &cryptomock.Crypto{} 652 653 vc1, err := (&verifiable.Credential{ 654 Context: []string{verifiable.ContextURI}, 655 Types: []string{verifiable.VCType}, 656 ID: "http://example.edu/credentials/9999", 657 CustomFields: map[string]interface{}{ 658 "first_name": "Jesse", 659 }, 660 Issued: &util.TimeWrapper{ 661 Time: time.Now(), 662 }, 663 Issuer: verifiable.Issuer{ 664 ID: "did:example:76e12ec712ebc6f1c221ebfeb1f", 665 }, 666 Subject: uuid.New().String(), 667 }).MarshalJSON() 668 require.NoError(t, err) 669 670 sampleVC := strings.ReplaceAll(string(testdata.SampleUDCVCWithCredentialSchema), 671 "https://example.com/schema", verifiable.ContextURI) 672 vcForQuery := []byte(strings.ReplaceAll(sampleVC, 673 "http://example.edu/credentials/1872", "http://example.edu/credentials/1879")) 674 vcForDerive := testdata.SampleUDCVCWithProofBBS 675 676 err = CreateProfile(sampleUserID, mockctx, wallet.WithPassphrase(samplePassPhrase)) 677 require.NoError(t, err) 678 679 vcWalletClient, err := New(sampleUserID, mockctx, wallet.WithUnlockByPassphrase(samplePassPhrase)) 680 require.NotEmpty(t, vcWalletClient) 681 require.NoError(t, err) 682 683 require.NoError(t, vcWalletClient.Add(wallet.Credential, vc1)) 684 require.NoError(t, vcWalletClient.Add(wallet.Credential, vcForQuery)) 685 require.NoError(t, vcWalletClient.Add(wallet.Credential, vcForDerive)) 686 687 pd := &presexch.PresentationDefinition{ 688 ID: uuid.New().String(), 689 InputDescriptors: []*presexch.InputDescriptor{{ 690 ID: uuid.New().String(), 691 Schema: []*presexch.Schema{{ 692 URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType), 693 }}, 694 Constraints: &presexch.Constraints{ 695 Fields: []*presexch.Field{{ 696 Path: []string{"$.first_name"}, 697 }}, 698 }, 699 }}, 700 } 701 702 // presentation exchange 703 pdJSON, err := json.Marshal(pd) 704 require.NoError(t, err) 705 require.NotEmpty(t, pdJSON) 706 707 // query by example 708 queryByExample := []byte(strings.ReplaceAll(string(testdata.SampleWalletQueryByExample), 709 "did:example:abcd", verifiable.ContextURI)) 710 // query by frame 711 queryByFrame := testdata.SampleWalletQueryByFrame 712 713 t.Run("test wallet queries", func(t *testing.T) { 714 tests := []struct { 715 name string 716 params []*wallet.QueryParams 717 resultCount int 718 vcCount map[int]int 719 error string 720 }{ 721 { 722 name: "query by presentation exchange - success", 723 params: []*wallet.QueryParams{ 724 {Type: "PresentationExchange", Query: []json.RawMessage{pdJSON}}, 725 }, 726 resultCount: 1, 727 vcCount: map[int]int{0: 1}, 728 }, 729 { 730 name: "query by example - success", 731 params: []*wallet.QueryParams{ 732 {Type: "QueryByExample", Query: []json.RawMessage{queryByExample}}, 733 }, 734 resultCount: 1, 735 vcCount: map[int]int{0: 1}, 736 }, 737 { 738 name: "query by frame - success", 739 params: []*wallet.QueryParams{ 740 {Type: "QueryByFrame", Query: []json.RawMessage{queryByFrame}}, 741 }, 742 resultCount: 1, 743 vcCount: map[int]int{0: 1}, 744 }, 745 { 746 name: "did authorization - success", 747 params: []*wallet.QueryParams{ 748 {Type: "DIDAuth"}, 749 }, 750 resultCount: 1, 751 vcCount: map[int]int{0: 0}, 752 }, 753 { 754 name: "multiple queries - success", 755 params: []*wallet.QueryParams{ 756 {Type: "PresentationExchange", Query: []json.RawMessage{pdJSON}}, 757 {Type: "QueryByExample", Query: []json.RawMessage{queryByExample}}, 758 {Type: "QueryByFrame", Query: []json.RawMessage{queryByFrame}}, 759 }, 760 resultCount: 2, 761 vcCount: map[int]int{0: 1, 1: 2}, 762 }, 763 { 764 name: "invalid query type", 765 params: []*wallet.QueryParams{ 766 {Type: "invalid"}, 767 }, 768 error: "unsupported query type", 769 }, 770 { 771 name: "empty query type", 772 params: []*wallet.QueryParams{}, 773 error: "no result found", 774 }, 775 } 776 777 t.Parallel() 778 779 for _, test := range tests { 780 tc := test 781 t.Run(tc.name, func(t *testing.T) { 782 results, err := vcWalletClient.Query(tc.params...) 783 784 if tc.error != "" { 785 require.Empty(t, results) 786 require.Error(t, err) 787 require.Contains(t, err.Error(), tc.error) 788 789 return 790 } 791 792 require.NoError(t, err) 793 require.Len(t, results, tc.resultCount) 794 795 for i, result := range results { 796 require.Len(t, result.Credentials(), tc.vcCount[i]) 797 } 798 }) 799 } 800 801 // test wallet locked 802 require.True(t, vcWalletClient.Close()) 803 804 results, err := vcWalletClient.Query(&wallet.QueryParams{ 805 Type: "DIDAuth", 806 }) 807 require.True(t, errors.Is(err, ErrWalletLocked)) 808 require.Empty(t, results) 809 }) 810 } 811 812 func TestClient_Issue(t *testing.T) { 813 customVDR := &mockvdr.MockVDRegistry{ 814 ResolveFunc: func(didID string, opts ...vdrapi.DIDMethodOption) (*did.DocResolution, error) { 815 if strings.HasPrefix(didID, "did:key:") { 816 k := key.New() 817 818 d, e := k.Read(didID) 819 if e != nil { 820 return nil, e 821 } 822 823 return d, nil 824 } 825 826 return nil, fmt.Errorf("did not found") 827 }, 828 } 829 830 mockctx := newMockProvider(t) 831 mockctx.VDRegistryValue = customVDR 832 mockctx.CryptoValue = &cryptomock.Crypto{} 833 834 err := CreateProfile(sampleUserID, mockctx, wallet.WithPassphrase(samplePassPhrase)) 835 require.NoError(t, err) 836 837 t.Run("Test VC wallet client issue using controller - success", func(t *testing.T) { 838 vcWalletClient, err := New(sampleUserID, mockctx, wallet.WithUnlockByPassphrase(samplePassPhrase)) 839 require.NotEmpty(t, vcWalletClient) 840 require.NoError(t, err) 841 842 defer vcWalletClient.Close() 843 844 // save a DID & corresponding key 845 require.NoError(t, vcWalletClient.Add(wallet.Key, testdata.SampleWalletContentKeyBase58)) 846 require.NoError(t, vcWalletClient.Add(wallet.DIDResolutionResponse, testdata.SampleDocResolutionResponse)) 847 848 result, err := vcWalletClient.Issue(testdata.SampleUDCVC, &wallet.ProofOptions{ 849 Controller: sampleDIDKey, 850 }) 851 852 require.NoError(t, err) 853 require.NotEmpty(t, result) 854 require.NotEmpty(t, result.Proofs) 855 }) 856 857 t.Run("Test VC wallet client issue using controller - failure", func(t *testing.T) { 858 vcWalletClient, err := New(sampleUserID, mockctx, wallet.WithUnlockByPassphrase(samplePassPhrase)) 859 require.NotEmpty(t, vcWalletClient) 860 require.NoError(t, err) 861 862 defer vcWalletClient.Close() 863 864 // sign with just controller 865 result, err := vcWalletClient.Issue(testdata.SampleUDCVC, &wallet.ProofOptions{ 866 Controller: sampleDIDKey2, 867 }) 868 require.Error(t, err) 869 require.Contains(t, err.Error(), "failed to read json keyset from reader") 870 require.Empty(t, result) 871 }) 872 873 t.Run("Test VC wallet client issue using controller - wallet locked", func(t *testing.T) { 874 vcWalletClient, err := New(sampleUserID, mockctx) 875 require.NotEmpty(t, vcWalletClient) 876 require.NoError(t, err) 877 878 defer vcWalletClient.Close() 879 880 // sign with just controller 881 result, err := vcWalletClient.Issue(testdata.SampleUDCVC, &wallet.ProofOptions{ 882 Controller: sampleDIDKey, 883 }) 884 require.Error(t, err) 885 require.True(t, errors.Is(err, ErrWalletLocked)) 886 require.Empty(t, result) 887 }) 888 } 889 890 func TestClient_Prove(t *testing.T) { 891 customVDR := &mockvdr.MockVDRegistry{ 892 ResolveFunc: func(didID string, opts ...vdrapi.DIDMethodOption) (*did.DocResolution, error) { 893 if strings.HasPrefix(didID, "did:key:") { 894 k := key.New() 895 896 d, e := k.Read(didID) 897 if e != nil { 898 return nil, e 899 } 900 901 return d, nil 902 } 903 904 return nil, fmt.Errorf("did not found") 905 }, 906 } 907 908 mockctx := newMockProvider(t) 909 mockctx.VDRegistryValue = customVDR 910 mockctx.CryptoValue = &cryptomock.Crypto{} 911 912 err := CreateProfile(sampleUserID, mockctx, wallet.WithPassphrase(samplePassPhrase)) 913 require.NoError(t, err) 914 915 t.Run("Test VC wallet client prove using controller - success", func(t *testing.T) { 916 vcWalletClient, err := New(sampleUserID, mockctx, wallet.WithUnlockByPassphrase(samplePassPhrase)) 917 require.NotEmpty(t, vcWalletClient) 918 require.NoError(t, err) 919 920 defer vcWalletClient.Close() 921 922 // save a credential, DID & key 923 require.NoError(t, vcWalletClient.Add(wallet.Credential, testdata.SampleUDCVC)) 924 require.NoError(t, vcWalletClient.Add(wallet.Key, testdata.SampleWalletContentKeyBase58)) 925 require.NoError(t, vcWalletClient.Add(wallet.DIDResolutionResponse, testdata.SampleDocResolutionResponse)) 926 927 result, err := vcWalletClient.Prove(&wallet.ProofOptions{Controller: sampleDIDKey}, 928 wallet.WithStoredCredentialsToProve("http://example.edu/credentials/1872"), 929 wallet.WithRawCredentialsToProve(testdata.SampleUDCVC), 930 ) 931 require.NoError(t, err) 932 require.NotEmpty(t, result) 933 require.NotEmpty(t, result.Proofs) 934 }) 935 936 t.Run("Test VC wallet client prove using controller - failure", func(t *testing.T) { 937 vcWalletClient, err := New(sampleUserID, mockctx, wallet.WithUnlockByPassphrase(samplePassPhrase)) 938 require.NotEmpty(t, vcWalletClient) 939 require.NoError(t, err) 940 941 defer vcWalletClient.Close() 942 943 require.NoError(t, vcWalletClient.Remove(wallet.Credential, "http://example.edu/credentials/1872")) 944 require.NoError(t, vcWalletClient.Add(wallet.Credential, testdata.SampleUDCVC)) 945 946 result, err := vcWalletClient.Prove(&wallet.ProofOptions{Controller: sampleDIDKey2}, 947 wallet.WithStoredCredentialsToProve("http://example.edu/credentials/1872"), 948 wallet.WithRawCredentialsToProve(testdata.SampleUDCVC), 949 ) 950 require.Error(t, err) 951 require.Contains(t, err.Error(), "failed to read json keyset from reader") 952 require.Empty(t, result) 953 }) 954 955 t.Run("Test VC wallet client prove using controller - wallet locked", func(t *testing.T) { 956 vcWalletClient, err := New(sampleUserID, mockctx, wallet.WithUnlockByPassphrase(samplePassPhrase)) 957 require.NotEmpty(t, vcWalletClient) 958 require.NoError(t, err) 959 960 defer vcWalletClient.Close() 961 962 require.NoError(t, vcWalletClient.Remove(wallet.Credential, "http://example.edu/credentials/1872")) 963 require.NoError(t, vcWalletClient.Add(wallet.Credential, testdata.SampleUDCVC)) 964 965 vcWalletClient.Close() 966 967 result, err := vcWalletClient.Prove(&wallet.ProofOptions{Controller: sampleDIDKey}, 968 wallet.WithStoredCredentialsToProve("http://example.edu/credentials/1872"), 969 wallet.WithRawCredentialsToProve(testdata.SampleUDCVC), 970 ) 971 require.Error(t, err) 972 require.True(t, errors.Is(err, ErrWalletLocked)) 973 require.Empty(t, result) 974 }) 975 } 976 977 func TestClient_Verify(t *testing.T) { 978 customVDR := &mockvdr.MockVDRegistry{ 979 ResolveFunc: func(didID string, opts ...vdrapi.DIDMethodOption) (*did.DocResolution, error) { 980 if strings.HasPrefix(didID, "did:key:") { 981 k := key.New() 982 983 d, e := k.Read(didID) 984 if e != nil { 985 return nil, e 986 } 987 988 return d, nil 989 } 990 991 return nil, fmt.Errorf("did not found") 992 }, 993 } 994 995 mockctx := newMockProvider(t) 996 mockctx.VDRegistryValue = customVDR 997 mockctx.CryptoValue = &cryptomock.Crypto{} 998 999 err := CreateProfile(sampleUserID, mockctx, wallet.WithPassphrase(samplePassPhrase)) 1000 require.NoError(t, err) 1001 1002 t.Run("Test VC wallet verify credential - success", func(t *testing.T) { 1003 vcWalletClient, err := New(sampleUserID, mockctx, wallet.WithUnlockByPassphrase(samplePassPhrase)) 1004 require.NotEmpty(t, vcWalletClient) 1005 require.NoError(t, err) 1006 1007 defer vcWalletClient.Close() 1008 1009 // store credential in wallet 1010 require.NoError(t, vcWalletClient.Add(wallet.Credential, testdata.SampleUDCVCWithProof)) 1011 1012 // verify stored VC 1013 ok, err := vcWalletClient.Verify(wallet.WithStoredCredentialToVerify("http://example.edu/credentials/1872")) 1014 require.NoError(t, err) 1015 require.True(t, ok) 1016 1017 // verify raw VC 1018 ok, err = vcWalletClient.Verify(wallet.WithRawCredentialToVerify(testdata.SampleUDCVCWithProof)) 1019 require.NoError(t, err) 1020 require.True(t, ok) 1021 }) 1022 1023 t.Run("Test VC wallet verify credential - invalid signature", func(t *testing.T) { 1024 vcWalletClient, err := New(sampleUserID, mockctx, wallet.WithUnlockByPassphrase(samplePassPhrase)) 1025 require.NotEmpty(t, vcWalletClient) 1026 require.NoError(t, err) 1027 1028 defer vcWalletClient.Close() 1029 1030 // store tampered credential in wallet 1031 tamperedVC := strings.ReplaceAll(string(testdata.SampleUDCVCWithProof), 1032 `"name": "Example University"`, `"name": "Fake University"`) 1033 require.NoError(t, vcWalletClient.Remove(wallet.Credential, "http://example.edu/credentials/1872")) 1034 require.NoError(t, vcWalletClient.Add(wallet.Credential, []byte(tamperedVC))) 1035 1036 ok, err := vcWalletClient.Verify(wallet.WithStoredCredentialToVerify("http://example.edu/credentials/1872")) 1037 require.Error(t, err) 1038 require.Contains(t, err.Error(), "invalid signature") 1039 require.False(t, ok) 1040 1041 ok, err = vcWalletClient.Verify(wallet.WithRawCredentialToVerify([]byte(tamperedVC))) 1042 require.Error(t, err) 1043 require.Contains(t, err.Error(), "invalid signature") 1044 require.False(t, ok) 1045 }) 1046 1047 t.Run("Test VC wallet verify presentation - success", func(t *testing.T) { 1048 vcWalletClient, err := New(sampleUserID, mockctx, wallet.WithUnlockByPassphrase(samplePassPhrase)) 1049 require.NotEmpty(t, vcWalletClient) 1050 require.NoError(t, err) 1051 1052 defer vcWalletClient.Close() 1053 1054 // verify raw VC 1055 ok, err := vcWalletClient.Verify(wallet.WithRawPresentationToVerify(testdata.SampleUDCPresentation)) 1056 require.NoError(t, err) 1057 require.True(t, ok) 1058 }) 1059 1060 t.Run("Test VC wallet verify presentation - invalid signature", func(t *testing.T) { 1061 vcWalletClient, err := New(sampleUserID, mockctx, wallet.WithUnlockByPassphrase(samplePassPhrase)) 1062 require.NotEmpty(t, vcWalletClient) 1063 require.NoError(t, err) 1064 1065 defer vcWalletClient.Close() 1066 1067 tamperedVP := strings.ReplaceAll(string(testdata.SampleUDCPresentation), 1068 `"holder": "did:key:z6MknC1wwS6DEYwtGbZZo2QvjQjkh2qSBjb4GYmbye8dv4S5"`, 1069 `"holder": "did:key:z6MknC1wwS6DEYwtGbZZo2QvjQjkh2qSBjb4GYmbye8dv464"`) 1070 1071 ok, err := vcWalletClient.Verify(wallet.WithRawPresentationToVerify([]byte(tamperedVP))) 1072 require.Error(t, err) 1073 require.Contains(t, err.Error(), "invalid signature") 1074 require.False(t, ok) 1075 }) 1076 1077 t.Run("Test VC wallet verify presentation - test wallet locked", func(t *testing.T) { 1078 vcWalletClient, err := New(sampleUserID, mockctx) 1079 require.NotEmpty(t, vcWalletClient) 1080 require.NoError(t, err) 1081 1082 ok, err := vcWalletClient.Verify(wallet.WithRawPresentationToVerify(testdata.SampleUDCPresentation)) 1083 require.True(t, errors.Is(err, ErrWalletLocked)) 1084 require.False(t, ok) 1085 }) 1086 } 1087 1088 func TestWallet_Derive(t *testing.T) { 1089 customVDR := &mockvdr.MockVDRegistry{ 1090 ResolveFunc: func(didID string, opts ...vdrapi.DIDMethodOption) (*did.DocResolution, error) { 1091 if strings.HasPrefix(didID, "did:key:") { 1092 k := key.New() 1093 1094 d, e := k.Read(didID) 1095 if e != nil { 1096 return nil, e 1097 } 1098 1099 return d, nil 1100 } 1101 1102 return nil, fmt.Errorf("did not found") 1103 }, 1104 } 1105 1106 mockctx := newMockProvider(t) 1107 mockctx.VDRegistryValue = customVDR 1108 1109 customCrypto, err := tinkcrypto.New() 1110 require.NoError(t, err) 1111 1112 mockctx.CryptoValue = customCrypto 1113 1114 // create profile 1115 err = CreateProfile(sampleUserID, mockctx, wallet.WithPassphrase(samplePassPhrase)) 1116 require.NoError(t, err) 1117 1118 // prepare frame 1119 var frameDoc map[string]interface{} 1120 1121 require.NoError(t, json.Unmarshal(testdata.SampleFrame, &frameDoc)) 1122 1123 t.Run("Test derive a credential from wallet - success", func(t *testing.T) { 1124 walletInstance, err := New(sampleUserID, mockctx, wallet.WithUnlockByPassphrase(samplePassPhrase)) 1125 require.NoError(t, err) 1126 require.NotEmpty(t, walletInstance) 1127 1128 // save BBS VC in store 1129 require.NoError(t, walletInstance.Add(wallet.Credential, testdata.SampleUDCVCWithProofBBS)) 1130 1131 sampleNonce := uuid.New().String() 1132 1133 verifyBBSProof := func(proofs []verifiable.Proof) { 1134 require.Len(t, proofs, 1) 1135 require.NotEmpty(t, proofs[0]) 1136 require.Equal(t, proofs[0]["type"], "BbsBlsSignatureProof2020") 1137 require.NotEmpty(t, proofs[0]["nonce"]) 1138 require.EqualValues(t, proofs[0]["nonce"], base64.StdEncoding.EncodeToString([]byte(sampleNonce))) 1139 require.NotEmpty(t, proofs[0]["proofValue"]) 1140 } 1141 1142 // derive stored credential 1143 vc, err := walletInstance.Derive(wallet.FromStoredCredential("http://example.edu/credentials/1872"), 1144 &wallet.DeriveOptions{ 1145 Nonce: sampleNonce, 1146 Frame: frameDoc, 1147 }) 1148 require.NoError(t, err) 1149 require.NotEmpty(t, vc) 1150 verifyBBSProof(vc.Proofs) 1151 1152 // derive raw credential 1153 vc, err = walletInstance.Derive(wallet.FromRawCredential(testdata.SampleUDCVCWithProofBBS), &wallet.DeriveOptions{ 1154 Nonce: sampleNonce, 1155 Frame: frameDoc, 1156 }) 1157 require.NoError(t, err) 1158 require.NotEmpty(t, vc) 1159 verifyBBSProof(vc.Proofs) 1160 1161 // derive from credential instance 1162 pkFetcher := verifiable.WithPublicKeyFetcher( 1163 verifiable.NewVDRKeyResolver(customVDR).PublicKeyFetcher(), 1164 ) 1165 1166 loader, err := ldtestutil.DocumentLoader() 1167 require.NoError(t, err) 1168 1169 credential, err := verifiable.ParseCredential(testdata.SampleUDCVCWithProofBBS, pkFetcher, 1170 verifiable.WithJSONLDDocumentLoader(loader)) 1171 require.NoError(t, err) 1172 vc, err = walletInstance.Derive(wallet.FromCredential(credential), &wallet.DeriveOptions{ 1173 Nonce: sampleNonce, 1174 Frame: frameDoc, 1175 }) 1176 require.NoError(t, err) 1177 require.NotEmpty(t, vc) 1178 verifyBBSProof(vc.Proofs) 1179 }) 1180 1181 t.Run("Test derive credential failures", func(t *testing.T) { 1182 walletInstance, err := New(sampleUserID, mockctx, wallet.WithUnlockByPassphrase(samplePassPhrase)) 1183 require.NotEmpty(t, walletInstance) 1184 require.NoError(t, err) 1185 1186 // invalid request 1187 vc, err := walletInstance.Derive(wallet.FromStoredCredential(""), &wallet.DeriveOptions{}) 1188 require.Empty(t, vc) 1189 require.Error(t, err) 1190 require.Contains(t, err.Error(), "invalid request to derive credential") 1191 1192 // credential not found in store 1193 vc, err = walletInstance.Derive(wallet.FromStoredCredential("invalid-id"), &wallet.DeriveOptions{}) 1194 require.Empty(t, vc) 1195 require.Error(t, err) 1196 require.Contains(t, err.Error(), "data not found") 1197 1198 // invalid credential in store 1199 require.NoError(t, walletInstance.Add(wallet.Credential, []byte(sampleInvalidDIDContent))) 1200 1201 vc, err = walletInstance.Derive(wallet.FromStoredCredential("did:example:sampleInvalidDIDContent"), 1202 &wallet.DeriveOptions{}) 1203 require.Empty(t, vc) 1204 require.Error(t, err) 1205 require.Contains(t, err.Error(), "credential type of unknown structure") 1206 1207 // invalid raw credential 1208 vc, err = walletInstance.Derive(wallet.FromRawCredential([]byte(sampleInvalidDIDContent)), &wallet.DeriveOptions{}) 1209 require.Empty(t, vc) 1210 require.Error(t, err) 1211 require.Contains(t, err.Error(), "credential type of unknown structure") 1212 1213 // try deriving wrong proof type - no BbsBlsSignature2020 proof present 1214 vc, err = walletInstance.Derive(wallet.FromRawCredential(testdata.SampleUDCVCWithProof), &wallet.DeriveOptions{ 1215 Frame: frameDoc, 1216 }) 1217 require.Empty(t, vc) 1218 require.Error(t, err) 1219 require.Contains(t, err.Error(), "no BbsBlsSignature2020 proof present") 1220 }) 1221 1222 t.Run("Test derive credential failures - test wallet locked", func(t *testing.T) { 1223 vcWalletClient, err := New(sampleUserID, mockctx) 1224 require.NotEmpty(t, vcWalletClient) 1225 require.NoError(t, err) 1226 1227 result, err := vcWalletClient.Derive(wallet.FromRawCredential(testdata.SampleUDCVCWithProof), &wallet.DeriveOptions{ 1228 Frame: frameDoc, 1229 }) 1230 require.True(t, errors.Is(err, ErrWalletLocked)) 1231 require.Empty(t, result) 1232 }) 1233 } 1234 1235 func TestClient_CreateKeyPair(t *testing.T) { 1236 sampleUser := uuid.New().String() 1237 mockctx := newMockProvider(t) 1238 1239 err := CreateProfile(sampleUser, mockctx, wallet.WithPassphrase(samplePassPhrase)) 1240 require.NoError(t, err) 1241 1242 vcWallet, err := New(sampleUser, mockctx) 1243 require.NoError(t, err) 1244 require.NotEmpty(t, vcWallet) 1245 1246 err = vcWallet.Open(wallet.WithUnlockByPassphrase(samplePassPhrase)) 1247 require.NoError(t, err) 1248 1249 t.Run("test creating key pair", func(t *testing.T) { 1250 keyPair, err := vcWallet.CreateKeyPair(kms.ED25519) 1251 require.NoError(t, err) 1252 require.NotEmpty(t, keyPair) 1253 require.NotEmpty(t, keyPair.KeyID) 1254 require.NotEmpty(t, keyPair.PublicKey) 1255 }) 1256 1257 t.Run("test failure while creating key pair", func(t *testing.T) { 1258 keyPair, err := vcWallet.CreateKeyPair(kms.KeyType("invalid")) 1259 require.Error(t, err) 1260 require.Contains(t, err.Error(), "failed to create new key") 1261 require.Empty(t, keyPair) 1262 }) 1263 1264 t.Run("test failure while creating key pair (closed wallet)", func(t *testing.T) { 1265 require.True(t, vcWallet.Close()) 1266 1267 keyPair, err := vcWallet.CreateKeyPair(kms.KeyType("invalid")) 1268 require.True(t, errors.Is(err, ErrWalletLocked)) 1269 require.Empty(t, keyPair) 1270 }) 1271 } 1272 1273 func TestClient_Connect(t *testing.T) { 1274 sampleUser := uuid.New().String() 1275 mockctx := newMockProvider(t) 1276 1277 err := CreateProfile(sampleUser, mockctx, wallet.WithPassphrase(samplePassPhrase)) 1278 require.NoError(t, err) 1279 1280 t.Run("test did connect success", func(t *testing.T) { 1281 sampleConnID := uuid.New().String() 1282 1283 oobSvc := &mockoutofband.MockOobService{ 1284 AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { 1285 return sampleConnID, nil 1286 }, 1287 } 1288 mockctx.ServiceMap[outofbandSvc.Name] = oobSvc 1289 1290 didexSvc := &mockdidexchange.MockDIDExchangeSvc{ 1291 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 1292 ch <- service.StateMsg{ 1293 Type: service.PostState, 1294 StateID: didexchange.StateIDCompleted, 1295 Properties: &mockdidexchange.MockEventProperties{ConnID: sampleConnID}, 1296 } 1297 1298 return nil 1299 }, 1300 } 1301 mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc 1302 1303 vcWallet, err := New(sampleUser, mockctx) 1304 require.NoError(t, err) 1305 require.NotEmpty(t, vcWallet) 1306 1307 err = vcWallet.Open(wallet.WithUnlockByPassphrase(samplePassPhrase)) 1308 require.NoError(t, err) 1309 defer vcWallet.Close() 1310 1311 connectionID, err := vcWallet.Connect(&outofband.Invitation{}) 1312 require.NoError(t, err) 1313 require.Equal(t, sampleConnID, connectionID) 1314 }) 1315 1316 t.Run("test did connect failure", func(t *testing.T) { 1317 didexSvc := &mockdidexchange.MockDIDExchangeSvc{ 1318 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 1319 return fmt.Errorf(sampleClientErr) 1320 }, 1321 } 1322 mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc 1323 1324 vcWallet, err := New(sampleUser, mockctx) 1325 require.NoError(t, err) 1326 require.NotEmpty(t, vcWallet) 1327 1328 err = vcWallet.Open(wallet.WithUnlockByPassphrase(samplePassPhrase)) 1329 require.NoError(t, err) 1330 defer vcWallet.Close() 1331 1332 connectionID, err := vcWallet.Connect(&outofband.Invitation{}) 1333 require.Error(t, err) 1334 require.Contains(t, err.Error(), sampleClientErr) 1335 require.Empty(t, connectionID) 1336 }) 1337 1338 t.Run("test did connect failure - auth error", func(t *testing.T) { 1339 vcWallet, err := New(sampleUser, mockctx) 1340 require.NoError(t, err) 1341 require.NotEmpty(t, vcWallet) 1342 1343 connectionID, err := vcWallet.Connect(&outofband.Invitation{}) 1344 require.True(t, errors.Is(err, ErrWalletLocked)) 1345 require.Empty(t, connectionID) 1346 }) 1347 } 1348 1349 func TestClient_ProposePresentation(t *testing.T) { 1350 sampleUser := uuid.New().String() 1351 mockctx := newMockProvider(t) 1352 1353 err := CreateProfile(sampleUser, mockctx, wallet.WithPassphrase(samplePassPhrase)) 1354 require.NoError(t, err) 1355 1356 const ( 1357 myDID = "did:mydid:123" 1358 theirDID = "did:theirdid:123" 1359 ) 1360 1361 t.Run("test propose presentation success", func(t *testing.T) { 1362 sampleConnID := uuid.New().String() 1363 1364 oobSvc := &mockoutofband.MockOobService{ 1365 AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { 1366 return sampleConnID, nil 1367 }, 1368 } 1369 mockctx.ServiceMap[outofbandSvc.Name] = oobSvc 1370 1371 didexSvc := &mockdidexchange.MockDIDExchangeSvc{ 1372 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 1373 ch <- service.StateMsg{ 1374 Type: service.PostState, 1375 StateID: didexchange.StateIDCompleted, 1376 Properties: &mockdidexchange.MockEventProperties{ConnID: sampleConnID}, 1377 } 1378 1379 return nil 1380 }, 1381 } 1382 mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc 1383 1384 thID := uuid.New().String() 1385 1386 ppSvc := &mockpresentproof.MockPresentProofSvc{ 1387 ActionsFunc: func() ([]presentproofSvc.Action, error) { 1388 return []presentproofSvc.Action{ 1389 { 1390 PIID: thID, 1391 Msg: service.NewDIDCommMsgMap(&presentproofSvc.RequestPresentationV2{ 1392 Comment: "mock msg", 1393 }), 1394 MyDID: myDID, 1395 TheirDID: theirDID, 1396 }, 1397 }, nil 1398 }, 1399 HandleFunc: func(service.DIDCommMsg) (string, error) { 1400 return thID, nil 1401 }, 1402 } 1403 mockctx.ServiceMap[presentproofSvc.Name] = ppSvc 1404 1405 store, err := mockctx.StorageProvider().OpenStore(connection.Namespace) 1406 require.NoError(t, err) 1407 1408 record := &connection.Record{ 1409 ConnectionID: sampleConnID, 1410 MyDID: myDID, 1411 TheirDID: theirDID, 1412 } 1413 recordBytes, err := json.Marshal(record) 1414 require.NoError(t, err) 1415 require.NoError(t, store.Put(fmt.Sprintf("conn_%s", sampleConnID), recordBytes)) 1416 1417 vcWallet, err := New(sampleUser, mockctx) 1418 require.NoError(t, err) 1419 require.NotEmpty(t, vcWallet) 1420 1421 err = vcWallet.Open(wallet.WithUnlockByPassphrase(samplePassPhrase)) 1422 require.NoError(t, err) 1423 defer vcWallet.Close() 1424 1425 msg, err := vcWallet.ProposePresentation(&wallet.GenericInvitation{}) 1426 require.NoError(t, err) 1427 require.NotEmpty(t, msg) 1428 }) 1429 1430 t.Run("test propose presentation failure", func(t *testing.T) { 1431 oobSvc := &mockoutofband.MockOobService{ 1432 AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { 1433 return "", fmt.Errorf(sampleClientErr) 1434 }, 1435 } 1436 mockctx.ServiceMap[outofbandSvc.Name] = oobSvc 1437 1438 vcWallet, err := New(sampleUser, mockctx) 1439 require.NoError(t, err) 1440 require.NotEmpty(t, vcWallet) 1441 1442 err = vcWallet.Open(wallet.WithUnlockByPassphrase(samplePassPhrase)) 1443 require.NoError(t, err) 1444 defer vcWallet.Close() 1445 1446 msg, err := vcWallet.ProposePresentation(&wallet.GenericInvitation{}) 1447 require.Error(t, err) 1448 require.Empty(t, msg) 1449 }) 1450 1451 t.Run("test propose presentation failure - auth error", func(t *testing.T) { 1452 vcWallet, err := New(sampleUser, mockctx) 1453 require.NoError(t, err) 1454 require.NotEmpty(t, vcWallet) 1455 1456 msg, err := vcWallet.ProposePresentation(&wallet.GenericInvitation{}) 1457 require.True(t, errors.Is(err, ErrWalletLocked)) 1458 require.Empty(t, msg) 1459 }) 1460 } 1461 1462 func TestClient_PresentProof(t *testing.T) { 1463 sampleUser := uuid.New().String() 1464 mockctx := newMockProvider(t) 1465 1466 err := CreateProfile(sampleUser, mockctx, wallet.WithPassphrase(samplePassPhrase)) 1467 require.NoError(t, err) 1468 1469 t.Run("test present proof success", func(t *testing.T) { 1470 vcWallet, err := New(sampleUser, mockctx) 1471 require.NoError(t, err) 1472 require.NotEmpty(t, vcWallet) 1473 1474 err = vcWallet.Open(wallet.WithUnlockByPassphrase(samplePassPhrase)) 1475 require.NoError(t, err) 1476 defer vcWallet.Close() 1477 1478 response, err := vcWallet.PresentProof(uuid.New().String(), wallet.FromPresentation(&verifiable.Presentation{})) 1479 require.NoError(t, err) 1480 require.NotEmpty(t, response) 1481 require.Equal(t, model.AckStatusPENDING, response.Status) 1482 }) 1483 1484 t.Run("test present proof success - wait for done", func(t *testing.T) { 1485 thID := uuid.New().String() 1486 mockPresentProofSvc := &mockpresentproof.MockPresentProofSvc{ 1487 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 1488 ch <- service.StateMsg{ 1489 Type: service.PostState, 1490 StateID: presentproofSvc.StateNameDone, 1491 Properties: &mockdidexchange.MockEventProperties{ 1492 Properties: map[string]interface{}{ 1493 webRedirectStatusKey: model.AckStatusOK, 1494 webRedirectURLKey: exampleWebRedirect, 1495 }, 1496 }, 1497 Msg: &mockMsg{thID: thID}, 1498 } 1499 1500 return nil 1501 }, 1502 } 1503 mockctx.ServiceMap[presentproofSvc.Name] = mockPresentProofSvc 1504 1505 vcWallet, err := New(sampleUser, mockctx) 1506 require.NoError(t, err) 1507 require.NotEmpty(t, vcWallet) 1508 1509 err = vcWallet.Open(wallet.WithUnlockByPassphrase(samplePassPhrase)) 1510 require.NoError(t, err) 1511 defer vcWallet.Close() 1512 1513 response, err := vcWallet.PresentProof(thID, wallet.FromPresentation(&verifiable.Presentation{}), 1514 wallet.WaitForDone(1*time.Millisecond)) 1515 require.NoError(t, err) 1516 require.NotEmpty(t, response) 1517 require.Equal(t, model.AckStatusOK, response.Status) 1518 require.Equal(t, exampleWebRedirect, response.RedirectURL) 1519 }) 1520 1521 t.Run("test present proof failure - auth error", func(t *testing.T) { 1522 vcWallet, err := New(sampleUser, mockctx) 1523 require.NoError(t, err) 1524 require.NotEmpty(t, vcWallet) 1525 1526 response, err := vcWallet.PresentProof(uuid.New().String(), wallet.FromPresentation(&verifiable.Presentation{})) 1527 require.True(t, errors.Is(err, ErrWalletLocked)) 1528 require.Empty(t, response) 1529 }) 1530 } 1531 1532 func TestClient_ProposeCredential(t *testing.T) { 1533 sampleUser := uuid.New().String() 1534 mockctx := newMockProvider(t) 1535 1536 err := CreateProfile(sampleUser, mockctx, wallet.WithPassphrase(samplePassPhrase)) 1537 require.NoError(t, err) 1538 1539 const ( 1540 myDID = "did:mydid:123" 1541 theirDID = "did:theirdid:123" 1542 ) 1543 1544 t.Run("test propose credential success", func(t *testing.T) { 1545 sampleConnID := uuid.New().String() 1546 1547 oobSvc := &mockoutofband.MockOobService{ 1548 AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { 1549 return sampleConnID, nil 1550 }, 1551 } 1552 mockctx.ServiceMap[outofbandSvc.Name] = oobSvc 1553 1554 didexSvc := &mockdidexchange.MockDIDExchangeSvc{ 1555 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 1556 ch <- service.StateMsg{ 1557 Type: service.PostState, 1558 StateID: didexchange.StateIDCompleted, 1559 Properties: &mockdidexchange.MockEventProperties{ConnID: sampleConnID}, 1560 } 1561 1562 return nil 1563 }, 1564 } 1565 mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc 1566 1567 thID := uuid.New().String() 1568 1569 icSvc := &mockissuecredential.MockIssueCredentialSvc{ 1570 ActionsFunc: func() ([]issuecredentialsvc.Action, error) { 1571 return []issuecredentialsvc.Action{ 1572 { 1573 PIID: thID, 1574 Msg: service.NewDIDCommMsgMap(&issuecredentialsvc.OfferCredentialV2{ 1575 Comment: sampleMsgComment, 1576 }), 1577 MyDID: myDID, 1578 TheirDID: theirDID, 1579 }, 1580 }, nil 1581 }, 1582 HandleFunc: func(service.DIDCommMsg) (string, error) { 1583 return thID, nil 1584 }, 1585 } 1586 mockctx.ServiceMap[issuecredentialsvc.Name] = icSvc 1587 1588 store, err := mockctx.StorageProvider().OpenStore(connection.Namespace) 1589 require.NoError(t, err) 1590 1591 record := &connection.Record{ 1592 ConnectionID: sampleConnID, 1593 MyDID: myDID, 1594 TheirDID: theirDID, 1595 } 1596 recordBytes, err := json.Marshal(record) 1597 require.NoError(t, err) 1598 require.NoError(t, store.Put(fmt.Sprintf("conn_%s", sampleConnID), recordBytes)) 1599 1600 vcWallet, err := New(sampleUser, mockctx) 1601 require.NoError(t, err) 1602 require.NotEmpty(t, vcWallet) 1603 1604 err = vcWallet.Open(wallet.WithUnlockByPassphrase(samplePassPhrase)) 1605 require.NoError(t, err) 1606 defer vcWallet.Close() 1607 1608 msg, err := vcWallet.ProposeCredential(&wallet.GenericInvitation{}) 1609 require.NoError(t, err) 1610 require.NotEmpty(t, msg) 1611 1612 offer := &issuecredentialsvc.OfferCredentialV2{} 1613 1614 err = msg.Decode(offer) 1615 require.NoError(t, err) 1616 require.NotEmpty(t, offer) 1617 require.Equal(t, sampleMsgComment, offer.Comment) 1618 }) 1619 1620 t.Run("test propose presentation failure", func(t *testing.T) { 1621 oobSvc := &mockoutofband.MockOobService{ 1622 AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { 1623 return "", fmt.Errorf(sampleClientErr) 1624 }, 1625 } 1626 mockctx.ServiceMap[outofbandSvc.Name] = oobSvc 1627 1628 vcWallet, err := New(sampleUser, mockctx) 1629 require.NoError(t, err) 1630 require.NotEmpty(t, vcWallet) 1631 1632 err = vcWallet.Open(wallet.WithUnlockByPassphrase(samplePassPhrase)) 1633 require.NoError(t, err) 1634 defer vcWallet.Close() 1635 1636 msg, err := vcWallet.ProposeCredential(&wallet.GenericInvitation{}) 1637 require.Error(t, err) 1638 require.Empty(t, msg) 1639 }) 1640 1641 t.Run("test propose presentation failure - auth error", func(t *testing.T) { 1642 vcWallet, err := New(sampleUser, mockctx) 1643 require.NoError(t, err) 1644 require.NotEmpty(t, vcWallet) 1645 1646 msg, err := vcWallet.ProposeCredential(&wallet.GenericInvitation{}) 1647 require.True(t, errors.Is(err, ErrWalletLocked)) 1648 require.Empty(t, msg) 1649 }) 1650 } 1651 1652 func TestClient_RequestCredential(t *testing.T) { 1653 sampleUser := uuid.New().String() 1654 mockctx := newMockProvider(t) 1655 1656 err := CreateProfile(sampleUser, mockctx, wallet.WithPassphrase(samplePassPhrase)) 1657 require.NoError(t, err) 1658 1659 t.Run("test present proof success", func(t *testing.T) { 1660 vcWallet, err := New(sampleUser, mockctx) 1661 require.NoError(t, err) 1662 require.NotEmpty(t, vcWallet) 1663 1664 err = vcWallet.Open(wallet.WithUnlockByPassphrase(samplePassPhrase)) 1665 require.NoError(t, err) 1666 defer vcWallet.Close() 1667 1668 response, err := vcWallet.RequestCredential(uuid.New().String(), wallet.FromPresentation(&verifiable.Presentation{})) 1669 require.NoError(t, err) 1670 require.NotEmpty(t, response) 1671 require.Equal(t, model.AckStatusPENDING, response.Status) 1672 }) 1673 1674 t.Run("test present proof success - wait for done", func(t *testing.T) { 1675 thID := uuid.New().String() 1676 1677 icSvc := &mockissuecredential.MockIssueCredentialSvc{ 1678 RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { 1679 ch <- service.StateMsg{ 1680 Type: service.PostState, 1681 StateID: "done", 1682 Properties: &mockdidexchange.MockEventProperties{ 1683 Properties: map[string]interface{}{ 1684 webRedirectStatusKey: model.AckStatusOK, 1685 webRedirectURLKey: exampleWebRedirect, 1686 }, 1687 }, 1688 Msg: &mockMsg{thID: thID}, 1689 } 1690 1691 return nil 1692 }, 1693 } 1694 mockctx.ServiceMap[issuecredentialsvc.Name] = icSvc 1695 1696 vcWallet, err := New(sampleUser, mockctx) 1697 require.NoError(t, err) 1698 require.NotEmpty(t, vcWallet) 1699 1700 err = vcWallet.Open(wallet.WithUnlockByPassphrase(samplePassPhrase)) 1701 require.NoError(t, err) 1702 defer vcWallet.Close() 1703 1704 response, err := vcWallet.RequestCredential(thID, wallet.FromPresentation(&verifiable.Presentation{}), 1705 wallet.WaitForDone(0)) 1706 require.NoError(t, err) 1707 require.NotEmpty(t, response) 1708 require.Equal(t, model.AckStatusOK, response.Status) 1709 require.Equal(t, exampleWebRedirect, response.RedirectURL) 1710 }) 1711 1712 t.Run("test present proof failure - auth error", func(t *testing.T) { 1713 vcWallet, err := New(sampleUser, mockctx) 1714 require.NoError(t, err) 1715 require.NotEmpty(t, vcWallet) 1716 1717 response, err := vcWallet.RequestCredential(uuid.New().String(), wallet.FromPresentation(&verifiable.Presentation{})) 1718 require.True(t, errors.Is(err, ErrWalletLocked)) 1719 require.Empty(t, response) 1720 }) 1721 } 1722 1723 func TestClient_ResolveCredentialManifest(t *testing.T) { 1724 sampleUser := uuid.New().String() 1725 mockctx := newMockProvider(t) 1726 1727 err := CreateProfile(sampleUser, mockctx, wallet.WithPassphrase(samplePassPhrase)) 1728 require.NoError(t, err) 1729 1730 vcWallet, err := New(sampleUser, mockctx) 1731 require.NoError(t, err) 1732 require.NotEmpty(t, vcWallet) 1733 1734 err = vcWallet.Open(wallet.WithUnlockByPassphrase(samplePassPhrase)) 1735 require.NoError(t, err) 1736 1737 t.Run("test resolving credential response", func(t *testing.T) { 1738 resolved, err := vcWallet.ResolveCredentialManifest(testdata.CredentialManifestMultipleVCs, 1739 wallet.ResolveRawResponse(testdata.CredentialResponseWithMultipleVCs)) 1740 require.NoError(t, err) 1741 require.Len(t, resolved, 2) 1742 }) 1743 1744 t.Run("test resolving credential by descriptor ID", func(t *testing.T) { 1745 resolved, err := vcWallet.ResolveCredentialManifest(testdata.CredentialManifestMultipleVCs, 1746 wallet.ResolveRawCredential("udc_output", testdata.SampleUDCVC)) 1747 require.NoError(t, err) 1748 require.Len(t, resolved, 1) 1749 }) 1750 1751 t.Run("test failure while resolving (closed wallet)", func(t *testing.T) { 1752 require.True(t, vcWallet.Close()) 1753 1754 resolved, err := vcWallet.ResolveCredentialManifest(testdata.CredentialManifestMultipleVCs, 1755 wallet.ResolveRawCredential("udc_output", testdata.SampleUDCVC)) 1756 require.True(t, errors.Is(err, ErrWalletLocked)) 1757 require.Empty(t, resolved) 1758 }) 1759 } 1760 1761 func newMockProvider(t *testing.T) *mockprovider.Provider { 1762 t.Helper() 1763 1764 loader, err := ldtestutil.DocumentLoader() 1765 require.NoError(t, err) 1766 1767 serviceMap := map[string]interface{}{ 1768 presentproofSvc.Name: &mockpresentproof.MockPresentProofSvc{}, 1769 outofbandSvc.Name: &mockoutofband.MockOobService{}, 1770 didexchange.DIDExchange: &mockdidexchange.MockDIDExchangeSvc{}, 1771 mediator.Coordination: &mockmediator.MockMediatorSvc{}, 1772 issuecredentialsvc.Name: &mockissuecredential.MockIssueCredentialSvc{}, 1773 oobv2.Name: &mockoutofbandv2.MockOobService{}, 1774 } 1775 1776 return &mockprovider.Provider{ 1777 StorageProviderValue: mockstorage.NewMockStoreProvider(), 1778 ProtocolStateStorageProviderValue: mockstorage.NewMockStoreProvider(), 1779 DocumentLoaderValue: loader, 1780 ServiceMap: serviceMap, 1781 } 1782 } 1783 1784 func createSampleProfile(t *testing.T, mockctx *mockprovider.Provider) { 1785 t.Helper() 1786 1787 err := CreateProfile(sampleUserID, mockctx, wallet.WithPassphrase(samplePassPhrase)) 1788 require.NoError(t, err) 1789 1790 vcWallet, err := New(sampleUserID, mockctx) 1791 require.NoError(t, err) 1792 require.NotEmpty(t, vcWallet) 1793 } 1794 1795 type mockStorageProvider struct { 1796 *mockstorage.MockStoreProvider 1797 config storage.StoreConfiguration 1798 failure error 1799 } 1800 1801 func (s *mockStorageProvider) SetStoreConfig(name string, config storage.StoreConfiguration) error { 1802 s.config = config 1803 1804 return s.failure 1805 } 1806 1807 func (s *mockStorageProvider) GetStoreConfig(name string) (storage.StoreConfiguration, error) { 1808 return s.config, nil 1809 } 1810 1811 // mockMsg containing custom parent thread ID. 1812 type mockMsg struct { 1813 *service.DIDCommMsgMap 1814 thID string 1815 } 1816 1817 func (m *mockMsg) ParentThreadID() string { 1818 return m.thID 1819 } 1820 1821 func (m *mockMsg) ThreadID() (string, error) { 1822 return m.thID, nil 1823 }