github.com/status-im/status-go@v1.1.0/protocol/messenger_profile_showcase_test.go (about) 1 package protocol 2 3 import ( 4 "context" 5 "errors" 6 "math/big" 7 "testing" 8 "time" 9 10 gethcommon "github.com/ethereum/go-ethereum/common" 11 12 "github.com/status-im/status-go/eth-node/crypto" 13 "github.com/status-im/status-go/eth-node/types" 14 "github.com/status-im/status-go/multiaccounts/accounts" 15 "github.com/status-im/status-go/protocol/common" 16 "github.com/status-im/status-go/protocol/communities" 17 "github.com/status-im/status-go/protocol/identity" 18 "github.com/status-im/status-go/protocol/protobuf" 19 "github.com/status-im/status-go/protocol/requests" 20 "github.com/status-im/status-go/protocol/tt" 21 "github.com/status-im/status-go/services/wallet/bigint" 22 "github.com/status-im/status-go/services/wallet/thirdparty" 23 24 "github.com/stretchr/testify/suite" 25 ) 26 27 func TestMessengerProfileShowcaseSuite(t *testing.T) { // nolint: deadcode,unused 28 suite.Run(t, new(TestMessengerProfileShowcase)) 29 } 30 31 type TestMessengerProfileShowcase struct { 32 CommunitiesMessengerTestSuiteBase 33 m *Messenger // main instance of Messenger 34 } 35 36 func (s *TestMessengerProfileShowcase) SetupTest() { 37 s.CommunitiesMessengerTestSuiteBase.SetupTest() 38 s.m = s.newMessenger("", []string{}) 39 _, err := s.m.Start() 40 s.Require().NoError(err) 41 } 42 43 func (s *TestMessengerProfileShowcase) TearDownTest() { 44 TearDownMessenger(&s.Suite, s.m) 45 s.CommunitiesMessengerTestSuiteBase.TearDownTest() 46 } 47 48 func (s *TestMessengerProfileShowcase) mutualContact(theirMessenger *Messenger) { 49 messageText := "hello!" 50 51 contactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey)) 52 request := &requests.SendContactRequest{ 53 ID: contactID, 54 Message: messageText, 55 } 56 57 // Send contact request 58 _, err := s.m.SendContactRequest(context.Background(), request) 59 s.Require().NoError(err) 60 61 // Wait for the message to reach its destination 62 _, err = WaitOnMessengerResponse( 63 theirMessenger, 64 func(r *MessengerResponse) bool { 65 return len(r.Contacts) > 0 && len(r.Messages()) > 0 66 }, 67 "no messages", 68 ) 69 s.Require().NoError(err) 70 71 // Make sure it's the pending contact requests 72 contactRequests, _, err := theirMessenger.PendingContactRequests("", 10) 73 s.Require().NoError(err) 74 s.Require().Len(contactRequests, 1) 75 s.Require().Equal(contactRequests[0].ContactRequestState, common.ContactRequestStatePending) 76 77 // Accept contact request, receiver side 78 _, err = theirMessenger.AcceptContactRequest(context.Background(), &requests.AcceptContactRequest{ID: types.Hex2Bytes(contactRequests[0].ID)}) 79 s.Require().NoError(err) 80 81 // Wait for the message to reach its destination 82 resp, err := WaitOnMessengerResponse( 83 s.m, 84 func(r *MessengerResponse) bool { 85 return len(r.Contacts) == 1 && len(r.Messages()) == 2 && len(r.ActivityCenterNotifications()) == 1 86 }, 87 "no messages", 88 ) 89 s.Require().NoError(err) 90 91 // Check the contact state is correctly set 92 s.Require().Len(resp.Contacts, 1) 93 s.Require().True(resp.Contacts[0].mutual()) 94 } 95 96 func (s *TestMessengerProfileShowcase) verifiedContact(theirMessenger *Messenger) { 97 theirPk := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey)) 98 challenge := "Want to see what I'm hiding in my profile showcase?" 99 100 _, err := s.m.SendContactVerificationRequest(context.Background(), theirPk, challenge) 101 s.Require().NoError(err) 102 103 // Wait for the message to reach its destination 104 resp, err := WaitOnMessengerResponse( 105 theirMessenger, 106 func(r *MessengerResponse) bool { 107 return len(r.VerificationRequests()) == 1 && len(r.ActivityCenterNotifications()) == 1 108 }, 109 "no messages", 110 ) 111 s.Require().NoError(err) 112 s.Require().Len(resp.VerificationRequests(), 1) 113 verificationRequestID := resp.VerificationRequests()[0].ID 114 115 _, err = theirMessenger.AcceptContactVerificationRequest(context.Background(), verificationRequestID, "For sure!") 116 s.Require().NoError(err) 117 118 s.Require().NoError(err) 119 120 // Wait for the message to reach its destination 121 _, err = WaitOnMessengerResponse( 122 s.m, 123 func(r *MessengerResponse) bool { 124 return len(r.VerificationRequests()) == 1 125 }, 126 "no messages", 127 ) 128 s.Require().NoError(err) 129 130 resp, err = s.m.VerifiedTrusted(context.Background(), &requests.VerifiedTrusted{ID: types.FromHex(verificationRequestID)}) 131 s.Require().NoError(err) 132 133 s.Require().Len(resp.Messages(), 1) 134 s.Require().Equal(common.ContactVerificationStateTrusted, resp.Messages()[0].ContactVerificationState) 135 } 136 137 func (s *TestMessengerProfileShowcase) TestSaveAndGetProfileShowcasePreferences() { 138 request := DummyProfileShowcasePreferences(true) 139 140 // Provide collectible balances test response 141 collectible := request.Collectibles[0] 142 collectibleID, err := toCollectibleUniqueID(collectible.ContractAddress, collectible.TokenID, collectible.ChainID) 143 s.Require().NoError(err) 144 balances := []thirdparty.AccountBalance{ 145 thirdparty.AccountBalance{ 146 Address: gethcommon.HexToAddress(request.Accounts[0].Address), 147 Balance: &bigint.BigInt{Int: big.NewInt(5)}, 148 TxTimestamp: 0, 149 }, 150 } 151 s.collectiblesManagerMock.SetCollectibleOwnershipResponse(collectibleID, balances) 152 153 err = s.m.SetProfileShowcasePreferences(request, false) 154 s.Require().NoError(err) 155 156 // Restored preferences shoulf be same as stored 157 response, err := s.m.GetProfileShowcasePreferences() 158 s.Require().NoError(err) 159 160 s.Require().Equal(len(response.Communities), len(request.Communities)) 161 for i := 0; i < len(response.Communities); i++ { 162 s.Require().Equal(*response.Communities[i], *request.Communities[i]) 163 } 164 165 s.Require().Equal(len(response.Accounts), len(request.Accounts)) 166 for i := 0; i < len(response.Accounts); i++ { 167 s.Require().Equal(*response.Accounts[i], *request.Accounts[i]) 168 } 169 170 s.Require().Equal(len(response.Collectibles), len(request.Collectibles)) 171 for i := 0; i < len(response.Collectibles); i++ { 172 s.Require().Equal(*response.Collectibles[i], *request.Collectibles[i]) 173 } 174 175 s.Require().Equal(len(response.VerifiedTokens), len(request.VerifiedTokens)) 176 for i := 0; i < len(response.VerifiedTokens); i++ { 177 s.Require().Equal(*response.VerifiedTokens[i], *request.VerifiedTokens[i]) 178 } 179 180 s.Require().Equal(len(response.UnverifiedTokens), len(request.UnverifiedTokens)) 181 for i := 0; i < len(response.UnverifiedTokens); i++ { 182 s.Require().Equal(*response.UnverifiedTokens[i], *request.UnverifiedTokens[i]) 183 } 184 185 s.Require().Equal(len(response.SocialLinks), len(request.SocialLinks)) 186 for i := 0; i < len(response.SocialLinks); i++ { 187 s.Require().Equal(*response.SocialLinks[i], *request.SocialLinks[i]) 188 } 189 } 190 191 func (s *TestMessengerProfileShowcase) TestFailToSaveProfileShowcasePreferencesWithWrongVisibility() { 192 accountEntry := &identity.ProfileShowcaseAccountPreference{ 193 Address: "0x0000000000000000000000000032433445133424", 194 ShowcaseVisibility: identity.ProfileShowcaseVisibilityIDVerifiedContacts, 195 Order: 17, 196 } 197 198 collectibleEntry := &identity.ProfileShowcaseCollectiblePreference{ 199 ContractAddress: "0x12378534257568678487683576", 200 ChainID: 11155111, 201 TokenID: "12321389592999903", 202 ShowcaseVisibility: identity.ProfileShowcaseVisibilityContacts, 203 Order: 17, 204 } 205 206 request := &identity.ProfileShowcasePreferences{ 207 Accounts: []*identity.ProfileShowcaseAccountPreference{accountEntry}, 208 Collectibles: []*identity.ProfileShowcaseCollectiblePreference{collectibleEntry}, 209 } 210 211 // Provide collectible balances test response 212 collectible := request.Collectibles[0] 213 collectibleID, err := toCollectibleUniqueID(collectible.ContractAddress, collectible.TokenID, collectible.ChainID) 214 s.Require().NoError(err) 215 balances := []thirdparty.AccountBalance{ 216 thirdparty.AccountBalance{ 217 Address: gethcommon.HexToAddress(request.Accounts[0].Address), 218 Balance: &bigint.BigInt{Int: big.NewInt(5)}, 219 TxTimestamp: 0, 220 }, 221 } 222 s.collectiblesManagerMock.SetCollectibleOwnershipResponse(collectibleID, balances) 223 224 err = s.m.SetProfileShowcasePreferences(request, false) 225 s.Require().Equal(errorAccountVisibilityLowerThanCollectible, err) 226 } 227 228 func (s *TestMessengerProfileShowcase) TestEncryptAndDecryptProfileShowcaseEntries() { 229 // Add mutual contact 230 theirMessenger := s.newMessenger(accountPassword, []string{commonAccountAddress}) 231 _, err := theirMessenger.Start() 232 s.Require().NoError(err) 233 234 defer TearDownMessenger(&s.Suite, theirMessenger) 235 236 s.mutualContact(theirMessenger) 237 238 entries := &protobuf.ProfileShowcaseEntries{ 239 Communities: []*protobuf.ProfileShowcaseCommunity{ 240 &protobuf.ProfileShowcaseCommunity{ 241 CommunityId: "0x01312357798976535235432345", 242 Order: 12, 243 }, 244 &protobuf.ProfileShowcaseCommunity{ 245 CommunityId: "0x12378534257568678487683576", 246 Order: 11, 247 }, 248 }, 249 Accounts: []*protobuf.ProfileShowcaseAccount{ 250 &protobuf.ProfileShowcaseAccount{ 251 Address: "0x00000323245", 252 Name: "Default", 253 ColorId: "red", 254 Emoji: "(=^ ◡ ^=)", 255 Order: 1, 256 }, 257 }, 258 Collectibles: []*protobuf.ProfileShowcaseCollectible{ 259 &protobuf.ProfileShowcaseCollectible{ 260 ContractAddress: "0x12378534257568678487683576", 261 ChainId: 1, 262 TokenId: "12321389592999903", 263 AccountAddress: "0x32433445133424", 264 CommunityId: "0x12378534257568678487683576", 265 Order: 0, 266 }, 267 }, 268 VerifiedTokens: []*protobuf.ProfileShowcaseVerifiedToken{ 269 &protobuf.ProfileShowcaseVerifiedToken{ 270 Symbol: "ETH", 271 Order: 1, 272 }, 273 &protobuf.ProfileShowcaseVerifiedToken{ 274 Symbol: "DAI", 275 Order: 2, 276 }, 277 &protobuf.ProfileShowcaseVerifiedToken{ 278 Symbol: "SNT", 279 Order: 3, 280 }, 281 }, 282 UnverifiedTokens: []*protobuf.ProfileShowcaseUnverifiedToken{ 283 &protobuf.ProfileShowcaseUnverifiedToken{ 284 ContractAddress: "0x454525452023452", 285 ChainId: 11155111, 286 Order: 0, 287 }, 288 &protobuf.ProfileShowcaseUnverifiedToken{ 289 ContractAddress: "0x12312323323233", 290 ChainId: 1, 291 Order: 1, 292 }, 293 }, 294 SocialLinks: []*protobuf.ProfileShowcaseSocialLink{ 295 &protobuf.ProfileShowcaseSocialLink{ 296 Text: identity.TwitterID, 297 Url: "https://twitter.com/ethstatus", 298 Order: 1, 299 }, 300 &protobuf.ProfileShowcaseSocialLink{ 301 Text: identity.TwitterID, 302 Url: "https://twitter.com/StatusIMBlog", 303 Order: 2, 304 }, 305 &protobuf.ProfileShowcaseSocialLink{ 306 Text: identity.GithubID, 307 Url: "https://github.com/status-im", 308 Order: 3, 309 }, 310 }, 311 } 312 data, err := s.m.EncryptProfileShowcaseEntriesWithContactPubKeys(entries, s.m.Contacts()) 313 s.Require().NoError(err) 314 315 entriesBack, err := theirMessenger.DecryptProfileShowcaseEntriesWithPubKey(&s.m.identity.PublicKey, data) 316 s.Require().NoError(err) 317 318 s.Require().Equal(len(entries.Communities), len(entriesBack.Communities)) 319 for i := 0; i < len(entriesBack.Communities); i++ { 320 s.Require().Equal(entries.Communities[i].CommunityId, entriesBack.Communities[i].CommunityId) 321 s.Require().Equal(entries.Communities[i].Order, entriesBack.Communities[i].Order) 322 } 323 324 s.Require().Equal(len(entries.Accounts), len(entriesBack.Accounts)) 325 for i := 0; i < len(entriesBack.Accounts); i++ { 326 s.Require().Equal(entries.Accounts[i].Address, entriesBack.Accounts[i].Address) 327 s.Require().Equal(entries.Accounts[i].Name, entriesBack.Accounts[i].Name) 328 s.Require().Equal(entries.Accounts[i].ColorId, entriesBack.Accounts[i].ColorId) 329 s.Require().Equal(entries.Accounts[i].Emoji, entriesBack.Accounts[i].Emoji) 330 s.Require().Equal(entries.Accounts[i].Order, entriesBack.Accounts[i].Order) 331 } 332 333 s.Require().Equal(len(entries.Collectibles), len(entriesBack.Collectibles)) 334 for i := 0; i < len(entriesBack.Collectibles); i++ { 335 s.Require().Equal(entries.Collectibles[i].TokenId, entriesBack.Collectibles[i].TokenId) 336 s.Require().Equal(entries.Collectibles[i].ChainId, entriesBack.Collectibles[i].ChainId) 337 s.Require().Equal(entries.Collectibles[i].ContractAddress, entriesBack.Collectibles[i].ContractAddress) 338 s.Require().Equal(entries.Collectibles[i].AccountAddress, entriesBack.Collectibles[i].AccountAddress) 339 s.Require().Equal(entries.Collectibles[i].CommunityId, entriesBack.Collectibles[i].CommunityId) 340 s.Require().Equal(entries.Collectibles[i].Order, entriesBack.Collectibles[i].Order) 341 } 342 343 s.Require().Equal(len(entries.VerifiedTokens), len(entriesBack.VerifiedTokens)) 344 for i := 0; i < len(entriesBack.VerifiedTokens); i++ { 345 s.Require().Equal(entries.VerifiedTokens[i].Symbol, entriesBack.VerifiedTokens[i].Symbol) 346 s.Require().Equal(entries.VerifiedTokens[i].Order, entriesBack.VerifiedTokens[i].Order) 347 } 348 349 s.Require().Equal(len(entries.UnverifiedTokens), len(entriesBack.UnverifiedTokens)) 350 for i := 0; i < len(entriesBack.UnverifiedTokens); i++ { 351 s.Require().Equal(entries.UnverifiedTokens[i].ContractAddress, entriesBack.UnverifiedTokens[i].ContractAddress) 352 s.Require().Equal(entries.UnverifiedTokens[i].ChainId, entriesBack.UnverifiedTokens[i].ChainId) 353 s.Require().Equal(entries.UnverifiedTokens[i].Order, entriesBack.UnverifiedTokens[i].Order) 354 } 355 356 s.Require().Equal(len(entries.SocialLinks), len(entriesBack.SocialLinks)) 357 for i := 0; i < len(entriesBack.SocialLinks); i++ { 358 s.Require().Equal(entries.SocialLinks[i].Text, entriesBack.SocialLinks[i].Text) 359 s.Require().Equal(entries.SocialLinks[i].Url, entriesBack.SocialLinks[i].Url) 360 s.Require().Equal(entries.SocialLinks[i].Order, entriesBack.SocialLinks[i].Order) 361 } 362 } 363 364 func (s *TestMessengerProfileShowcase) TestShareShowcasePreferences() { 365 // Set Display name to pass shouldPublishChatIdentity check 366 profileKp := accounts.GetProfileKeypairForTest(true, false, false) 367 profileKp.KeyUID = s.m.account.KeyUID 368 profileKp.Accounts[0].KeyUID = s.m.account.KeyUID 369 370 err := s.m.settings.SaveOrUpdateKeypair(profileKp) 371 s.Require().NoError(err) 372 373 err = s.m.SetDisplayName("bobby") 374 s.Require().NoError(err) 375 376 // Save preferences to dispatch changes 377 request := DummyProfileShowcasePreferences(true) 378 379 // Save wallet accounts to pass the validation 380 acc1 := &accounts.Account{ 381 Address: types.HexToAddress(request.Accounts[0].Address), 382 Type: accounts.AccountTypeGenerated, 383 Name: "Test Account 1", 384 ColorID: "", 385 Emoji: "emoji", 386 } 387 acc2 := &accounts.Account{ 388 Address: types.HexToAddress(request.Accounts[1].Address), 389 Type: accounts.AccountTypeSeed, 390 Name: "Test Account 2", 391 ColorID: "", 392 Emoji: "emoji", 393 } 394 err = s.m.settings.SaveOrUpdateAccounts([]*accounts.Account{acc1, acc2}, true) 395 s.Require().NoError(err) 396 397 // Provide collectible balances test response 398 collectible := request.Collectibles[0] 399 collectibleID, err := toCollectibleUniqueID(collectible.ContractAddress, collectible.TokenID, collectible.ChainID) 400 s.Require().NoError(err) 401 balances := []thirdparty.AccountBalance{ 402 thirdparty.AccountBalance{ 403 Address: gethcommon.HexToAddress(request.Accounts[0].Address), 404 Balance: &bigint.BigInt{Int: big.NewInt(1)}, 405 TxTimestamp: 32443424, 406 }, 407 } 408 s.collectiblesManagerMock.SetCollectibleOwnershipResponse(collectibleID, balances) 409 410 err = s.m.SetProfileShowcasePreferences(request, false) 411 s.Require().NoError(err) 412 413 profileShowcasePreferences, err := s.m.GetProfileShowcasePreferences() 414 s.Require().NoError(err) 415 416 // Make sure the count for entries is correct 417 s.Require().Len(profileShowcasePreferences.Communities, 2) 418 s.Require().Len(profileShowcasePreferences.Accounts, 2) 419 s.Require().Len(profileShowcasePreferences.Collectibles, 1) 420 s.Require().Len(profileShowcasePreferences.VerifiedTokens, 3) 421 s.Require().Len(profileShowcasePreferences.UnverifiedTokens, 2) 422 423 // Add mutual contact 424 mutualContact := s.newMessenger(alicePassword, []string{aliceAccountAddress}) 425 _, err = mutualContact.Start() 426 s.Require().NoError(err) 427 defer TearDownMessenger(&s.Suite, mutualContact) 428 429 s.mutualContact(mutualContact) 430 431 // Add identity verified contact 432 verifiedContact := s.newMessenger(bobPassword, []string{bobAccountAddress}) 433 _, err = verifiedContact.Start() 434 s.Require().NoError(err) 435 defer TearDownMessenger(&s.Suite, verifiedContact) 436 437 s.mutualContact(verifiedContact) 438 s.verifiedContact(verifiedContact) 439 440 contactID := types.EncodeHex(crypto.FromECDSAPub(&s.m.identity.PublicKey)) 441 // Get summarised profile data for mutual contact 442 _, err = WaitOnMessengerResponse( 443 mutualContact, 444 func(r *MessengerResponse) bool { 445 return r.updatedProfileShowcaseContactIDs[contactID] == true 446 }, 447 "no messages", 448 ) 449 s.Require().NoError(err) 450 451 profileShowcase, err := mutualContact.GetProfileShowcaseForContact(contactID, false) 452 s.Require().NoError(err) 453 454 s.Require().Len(profileShowcase.Communities, 2) 455 s.Require().Equal(profileShowcase.Communities[0].CommunityID, request.Communities[0].CommunityID) 456 s.Require().Equal(profileShowcase.Communities[0].Order, request.Communities[0].Order) 457 s.Require().Equal(profileShowcase.Communities[1].CommunityID, request.Communities[1].CommunityID) 458 s.Require().Equal(profileShowcase.Communities[1].Order, request.Communities[1].Order) 459 460 s.Require().Len(profileShowcase.Accounts, 2) 461 s.Require().Equal(profileShowcase.Accounts[0].Address, request.Accounts[0].Address) 462 s.Require().Equal(profileShowcase.Accounts[0].Order, request.Accounts[0].Order) 463 s.Require().Equal(profileShowcase.Accounts[1].Address, request.Accounts[1].Address) 464 s.Require().Equal(profileShowcase.Accounts[1].Order, request.Accounts[1].Order) 465 466 s.Require().Len(profileShowcase.Collectibles, 1) 467 s.Require().Equal(profileShowcase.Collectibles[0].TokenID, request.Collectibles[0].TokenID) 468 s.Require().Equal(profileShowcase.Collectibles[0].ChainID, request.Collectibles[0].ChainID) 469 s.Require().Equal(profileShowcase.Collectibles[0].ContractAddress, request.Collectibles[0].ContractAddress) 470 s.Require().Equal(profileShowcase.Collectibles[0].Order, request.Collectibles[0].Order) 471 472 s.Require().Len(profileShowcase.VerifiedTokens, 1) 473 s.Require().Equal(profileShowcase.VerifiedTokens[0].Symbol, request.VerifiedTokens[0].Symbol) 474 s.Require().Equal(profileShowcase.VerifiedTokens[0].Order, request.VerifiedTokens[0].Order) 475 476 s.Require().Len(profileShowcase.UnverifiedTokens, 2) 477 s.Require().Equal(profileShowcase.UnverifiedTokens[0].ContractAddress, request.UnverifiedTokens[0].ContractAddress) 478 s.Require().Equal(profileShowcase.UnverifiedTokens[0].ChainID, request.UnverifiedTokens[0].ChainID) 479 s.Require().Equal(profileShowcase.UnverifiedTokens[0].Order, request.UnverifiedTokens[0].Order) 480 s.Require().Equal(profileShowcase.UnverifiedTokens[1].ContractAddress, request.UnverifiedTokens[1].ContractAddress) 481 s.Require().Equal(profileShowcase.UnverifiedTokens[1].ChainID, request.UnverifiedTokens[1].ChainID) 482 s.Require().Equal(profileShowcase.UnverifiedTokens[1].Order, request.UnverifiedTokens[1].Order) 483 484 s.Require().Len(profileShowcase.SocialLinks, 2) 485 s.Require().Equal(profileShowcase.SocialLinks[0].Text, request.SocialLinks[0].Text) 486 s.Require().Equal(profileShowcase.SocialLinks[0].URL, request.SocialLinks[0].URL) 487 s.Require().Equal(profileShowcase.SocialLinks[0].Order, request.SocialLinks[0].Order) 488 s.Require().Equal(profileShowcase.SocialLinks[1].Text, request.SocialLinks[2].Text) 489 s.Require().Equal(profileShowcase.SocialLinks[1].URL, request.SocialLinks[2].URL) 490 s.Require().Equal(profileShowcase.SocialLinks[1].Order, request.SocialLinks[2].Order) 491 492 // Get summarised profile data for verified contact 493 _, err = WaitOnMessengerResponse( 494 verifiedContact, 495 func(r *MessengerResponse) bool { 496 return r.updatedProfileShowcaseContactIDs[contactID] == true 497 }, 498 "no messages", 499 ) 500 s.Require().NoError(err) 501 502 profileShowcase, err = verifiedContact.GetProfileShowcaseForContact(contactID, false) 503 s.Require().NoError(err) 504 505 s.Require().Len(profileShowcase.Accounts, 2) 506 s.Require().Equal(profileShowcase.Accounts[0].Address, request.Accounts[0].Address) 507 s.Require().Equal(profileShowcase.Accounts[0].Order, request.Accounts[0].Order) 508 s.Require().Equal(profileShowcase.Accounts[1].Address, request.Accounts[1].Address) 509 s.Require().Equal(profileShowcase.Accounts[1].Order, request.Accounts[1].Order) 510 511 s.Require().Len(profileShowcase.Collectibles, 1) 512 s.Require().Equal(profileShowcase.Collectibles[0].ContractAddress, request.Collectibles[0].ContractAddress) 513 s.Require().Equal(profileShowcase.Collectibles[0].ChainID, request.Collectibles[0].ChainID) 514 s.Require().Equal(profileShowcase.Collectibles[0].TokenID, request.Collectibles[0].TokenID) 515 s.Require().Equal(profileShowcase.Collectibles[0].Order, request.Collectibles[0].Order) 516 517 s.Require().Len(profileShowcase.VerifiedTokens, 2) 518 s.Require().Equal(profileShowcase.VerifiedTokens[0].Symbol, request.VerifiedTokens[0].Symbol) 519 s.Require().Equal(profileShowcase.VerifiedTokens[0].Order, request.VerifiedTokens[0].Order) 520 s.Require().Equal(profileShowcase.VerifiedTokens[1].Symbol, request.VerifiedTokens[1].Symbol) 521 s.Require().Equal(profileShowcase.VerifiedTokens[1].Order, request.VerifiedTokens[1].Order) 522 523 s.Require().Len(profileShowcase.UnverifiedTokens, 2) 524 s.Require().Equal(profileShowcase.UnverifiedTokens[0].ContractAddress, request.UnverifiedTokens[0].ContractAddress) 525 s.Require().Equal(profileShowcase.UnverifiedTokens[0].ChainID, request.UnverifiedTokens[0].ChainID) 526 s.Require().Equal(profileShowcase.UnverifiedTokens[0].Order, request.UnverifiedTokens[0].Order) 527 s.Require().Equal(profileShowcase.UnverifiedTokens[1].ContractAddress, request.UnverifiedTokens[1].ContractAddress) 528 s.Require().Equal(profileShowcase.UnverifiedTokens[1].ChainID, request.UnverifiedTokens[1].ChainID) 529 s.Require().Equal(profileShowcase.UnverifiedTokens[1].Order, request.UnverifiedTokens[1].Order) 530 531 s.Require().Len(profileShowcase.SocialLinks, 3) 532 s.Require().Equal(profileShowcase.SocialLinks[0].Text, request.SocialLinks[0].Text) 533 s.Require().Equal(profileShowcase.SocialLinks[0].URL, request.SocialLinks[0].URL) 534 s.Require().Equal(profileShowcase.SocialLinks[0].Order, request.SocialLinks[0].Order) 535 s.Require().Equal(profileShowcase.SocialLinks[1].Text, request.SocialLinks[1].Text) 536 s.Require().Equal(profileShowcase.SocialLinks[1].URL, request.SocialLinks[1].URL) 537 s.Require().Equal(profileShowcase.SocialLinks[1].Order, request.SocialLinks[1].Order) 538 s.Require().Equal(profileShowcase.SocialLinks[2].Text, request.SocialLinks[2].Text) 539 s.Require().Equal(profileShowcase.SocialLinks[2].URL, request.SocialLinks[2].URL) 540 s.Require().Equal(profileShowcase.SocialLinks[2].Order, request.SocialLinks[2].Order) 541 } 542 543 func (s *TestMessengerProfileShowcase) TestProfileShowcaseProofOfMembershipUnencryptedCommunities() { 544 alice := s.m 545 546 // Set Display name to pass shouldPublishChatIdentity check 547 profileKp := accounts.GetProfileKeypairForTest(true, false, false) 548 profileKp.KeyUID = alice.account.KeyUID 549 profileKp.Accounts[0].KeyUID = alice.account.KeyUID 550 551 err := alice.settings.SaveOrUpdateKeypair(profileKp) 552 s.Require().NoError(err) 553 554 err = alice.SetDisplayName("Alice") 555 s.Require().NoError(err) 556 557 // Add bob as a mutual contact 558 bob := s.newMessenger(bobPassword, []string{bobAccountAddress}) 559 _, err = bob.Start() 560 s.Require().NoError(err) 561 defer TearDownMessenger(&s.Suite, bob) 562 563 s.mutualContact(bob) 564 565 // Alice creates a community 566 aliceCommunity, _ := createCommunityConfigurable(&s.Suite, alice, protobuf.CommunityPermissions_MANUAL_ACCEPT) 567 advertiseCommunityTo(&s.Suite, aliceCommunity, alice, bob) 568 569 // Bobs creates an another community 570 bobCommunity, _ := createCommunityConfigurable(&s.Suite, bob, protobuf.CommunityPermissions_AUTO_ACCEPT) 571 572 // Add community to the Alice's profile showcase & get it on the Bob's side 573 err = alice.SetProfileShowcasePreferences(&identity.ProfileShowcasePreferences{ 574 Communities: []*identity.ProfileShowcaseCommunityPreference{ 575 &identity.ProfileShowcaseCommunityPreference{ 576 CommunityID: aliceCommunity.IDString(), 577 ShowcaseVisibility: identity.ProfileShowcaseVisibilityContacts, 578 Order: 0, 579 }, 580 &identity.ProfileShowcaseCommunityPreference{ 581 CommunityID: bobCommunity.IDString(), 582 ShowcaseVisibility: identity.ProfileShowcaseVisibilityEveryone, 583 Order: 2, 584 }, 585 }, 586 }, false) 587 s.Require().NoError(err) 588 589 contactID := types.EncodeHex(crypto.FromECDSAPub(&alice.identity.PublicKey)) 590 _, err = WaitOnMessengerResponse( 591 bob, 592 func(r *MessengerResponse) bool { 593 return r.updatedProfileShowcaseContactIDs[contactID] == true 594 }, 595 "no messages", 596 ) 597 s.Require().NoError(err) 598 599 profileShowcase, err := bob.GetProfileShowcaseForContact(contactID, true) 600 s.Require().NoError(err) 601 602 // Verify community's data 603 s.Require().Len(profileShowcase.Communities, 2) 604 s.Require().Equal(profileShowcase.Communities[0].CommunityID, aliceCommunity.IDString()) 605 s.Require().Equal(profileShowcase.Communities[0].MembershipStatus, identity.ProfileShowcaseMembershipStatusProvenMember) 606 s.Require().Equal(profileShowcase.Communities[1].CommunityID, bobCommunity.IDString()) 607 s.Require().Equal(profileShowcase.Communities[1].MembershipStatus, identity.ProfileShowcaseMembershipStatusNotAMember) 608 } 609 610 func (s *TestMessengerProfileShowcase) TestProfileShowcaseProofOfMembershipEncryptedCommunity() { 611 alice := s.m 612 613 // Set Display name to pass shouldPublishChatIdentity check 614 profileKp := accounts.GetProfileKeypairForTest(true, false, false) 615 profileKp.KeyUID = alice.account.KeyUID 616 profileKp.Accounts[0].KeyUID = alice.account.KeyUID 617 618 err := alice.settings.SaveOrUpdateKeypair(profileKp) 619 s.Require().NoError(err) 620 621 err = alice.SetDisplayName("Alice") 622 s.Require().NoError(err) 623 624 // Add bob as a mutual contact 625 bob := s.newMessenger(bobPassword, []string{bobAccountAddress}) 626 _, err = bob.Start() 627 s.Require().NoError(err) 628 defer TearDownMessenger(&s.Suite, bob) 629 630 s.mutualContact(bob) 631 632 // Alice creates an ecrypted community 633 aliceCommunity, _ := createEncryptedCommunity(&s.Suite, alice) 634 s.Require().True(aliceCommunity.Encrypted()) 635 advertiseCommunityTo(&s.Suite, aliceCommunity, alice, bob) 636 637 // Bob creates an another encryped community 638 bobCommunity, _ := createEncryptedCommunity(&s.Suite, bob) 639 s.Require().True(bobCommunity.Encrypted()) 640 advertiseCommunityTo(&s.Suite, bobCommunity, bob, alice) 641 642 // Add community to the Alice's profile showcase & get it on the Bob's side 643 err = alice.SetProfileShowcasePreferences(&identity.ProfileShowcasePreferences{ 644 Communities: []*identity.ProfileShowcaseCommunityPreference{ 645 &identity.ProfileShowcaseCommunityPreference{ 646 CommunityID: aliceCommunity.IDString(), 647 ShowcaseVisibility: identity.ProfileShowcaseVisibilityContacts, 648 Order: 0, 649 }, 650 &identity.ProfileShowcaseCommunityPreference{ 651 CommunityID: bobCommunity.IDString(), 652 ShowcaseVisibility: identity.ProfileShowcaseVisibilityEveryone, 653 Order: 1, 654 }, 655 }, 656 }, false) 657 s.Require().NoError(err) 658 659 contactID := types.EncodeHex(crypto.FromECDSAPub(&alice.identity.PublicKey)) 660 _, err = WaitOnMessengerResponse( 661 bob, 662 func(r *MessengerResponse) bool { 663 return r.updatedProfileShowcaseContactIDs[contactID] == true 664 }, 665 "no messages", 666 ) 667 s.Require().NoError(err) 668 669 profileShowcase, err := bob.GetProfileShowcaseForContact(contactID, true) 670 s.Require().NoError(err) 671 672 // Verify community's data 673 s.Require().Len(profileShowcase.Communities, 2) 674 s.Require().Equal(profileShowcase.Communities[0].CommunityID, aliceCommunity.IDString()) 675 s.Require().Equal(profileShowcase.Communities[0].MembershipStatus, identity.ProfileShowcaseMembershipStatusProvenMember) 676 s.Require().Equal(profileShowcase.Communities[1].CommunityID, bobCommunity.IDString()) 677 s.Require().Equal(profileShowcase.Communities[1].MembershipStatus, identity.ProfileShowcaseMembershipStatusUnproven) 678 } 679 680 // The scenario tested is as follow: 681 // 1) Alice creates an encrypted community 682 // 2) Bob add Alice become a mutual contacts 683 // 4) Alice presents the community in her profile showcase 684 // 5) Bob gets the community from Alice's profile showcase and tries to validate community's membership with expired grant 685 func (s *TestMessengerProfileShowcase) TestProfileShowcaseCommuniesGrantExpires() { 686 grantInvokesProfileDispatchIntervalBackup := grantInvokesProfileDispatchInterval 687 grantInvokesProfileDispatchInterval = 1 * time.Millisecond 688 communitiesGrantExpirationTimeBackup := communities.GrantExpirationTime 689 communities.GrantExpirationTime = 1 * time.Millisecond 690 alice := s.m 691 692 // Set Display name to pass shouldPublishChatIdentity check 693 profileKp := accounts.GetProfileKeypairForTest(true, false, false) 694 profileKp.KeyUID = alice.account.KeyUID 695 profileKp.Accounts[0].KeyUID = alice.account.KeyUID 696 697 err := alice.settings.SaveOrUpdateKeypair(profileKp) 698 s.Require().NoError(err) 699 700 err = alice.SetDisplayName("Alice") 701 s.Require().NoError(err) 702 703 // 1) Alice creates an encrypted community 704 alice.communitiesManager.PermissionChecker = &testPermissionChecker{} 705 706 community, _ := createEncryptedCommunity(&s.Suite, alice) 707 s.Require().True(community.Encrypted()) 708 709 // 2) Bob add Alice become a mutual contacts 710 bob := s.newMessenger(bobPassword, []string{bobAccountAddress}) 711 _, err = bob.Start() 712 s.Require().NoError(err) 713 defer TearDownMessenger(&s.Suite, bob) 714 715 s.mutualContact(bob) 716 advertiseCommunityTo(&s.Suite, community, alice, bob) 717 718 // 3) Alice presents the community in her profile showcase 719 err = alice.SetProfileShowcasePreferences(&identity.ProfileShowcasePreferences{ 720 Communities: []*identity.ProfileShowcaseCommunityPreference{ 721 &identity.ProfileShowcaseCommunityPreference{ 722 CommunityID: community.IDString(), 723 ShowcaseVisibility: identity.ProfileShowcaseVisibilityEveryone, 724 Order: 0, 725 }, 726 }, 727 }, false) 728 s.Require().NoError(err) 729 730 // 5) Bob gets the community from Alice's profile showcase and tries to validate community's membership with expired grant 731 contactID := types.EncodeHex(crypto.FromECDSAPub(&alice.identity.PublicKey)) 732 _, err = WaitOnMessengerResponse( 733 bob, 734 func(r *MessengerResponse) bool { 735 return r.updatedProfileShowcaseContactIDs[contactID] == true 736 }, 737 "no messages", 738 ) 739 s.Require().NoError(err) 740 741 profileShowcase, err := bob.GetProfileShowcaseForContact(contactID, true) 742 s.Require().NoError(err) 743 s.Require().Len(profileShowcase.Communities, 1) 744 s.Require().Equal(community.IDString(), profileShowcase.Communities[0].CommunityID) 745 s.Require().Equal(identity.ProfileShowcaseMembershipStatusUnproven, profileShowcase.Communities[0].MembershipStatus) 746 747 // Return values back because they can affect other tests 748 grantInvokesProfileDispatchInterval = grantInvokesProfileDispatchIntervalBackup 749 communities.GrantExpirationTime = communitiesGrantExpirationTimeBackup 750 } 751 752 // The scenario tested is as follow: 753 // 1) Owner creates an encrypted community 754 // 2) Bob add Alice become a mutual contacts 755 // 3) Alice joins the community 756 // 4) Alice presents the community in her profile showcase 757 // 5) Bob gets the community from Alice's profile showcase and validates community's membership with grant 758 // 6) Owner updates the grant 759 // 7) Bob should be able to validate the membership again 760 func (s *TestMessengerProfileShowcase) TestProfileShowcaseCommuniesDispatchOnGrantUpdate() { 761 grantInvokesProfileDispatchIntervalBackup := grantInvokesProfileDispatchInterval 762 grantInvokesProfileDispatchInterval = 1 * time.Millisecond 763 alice := s.m 764 765 // Set Display name to pass shouldPublishChatIdentity check 766 profileKp := accounts.GetProfileKeypairForTest(true, false, false) 767 profileKp.KeyUID = alice.account.KeyUID 768 profileKp.Accounts[0].KeyUID = alice.account.KeyUID 769 770 err := alice.settings.SaveOrUpdateKeypair(profileKp) 771 s.Require().NoError(err) 772 773 err = alice.SetDisplayName("Alice") 774 s.Require().NoError(err) 775 776 // 1) Owner creates an encrypted community 777 owner := s.newMessenger("", []string{}) 778 _, err = owner.Start() 779 s.Require().NoError(err) 780 defer TearDownMessenger(&s.Suite, owner) 781 782 owner.communitiesManager.PermissionChecker = &testPermissionChecker{} 783 784 community, _ := createEncryptedCommunity(&s.Suite, owner) 785 s.Require().True(community.Encrypted()) 786 787 // 2) Bob add Alice become a mutual contacts 788 bob := s.newMessenger(bobPassword, []string{bobAccountAddress}) 789 _, err = bob.Start() 790 s.Require().NoError(err) 791 defer TearDownMessenger(&s.Suite, bob) 792 793 s.mutualContact(bob) 794 795 // 3) Alice joins the community 796 advertiseCommunityTo(&s.Suite, community, owner, alice) 797 advertiseCommunityTo(&s.Suite, community, owner, bob) 798 799 alice.communitiesManager.PermissionChecker = &testPermissionChecker{} 800 joinCommunity(&s.Suite, community.ID(), owner, alice, aliceAccountAddress, []string{aliceAddress1}) 801 802 joinedCommunities, err := alice.communitiesManager.Joined() 803 s.Require().NoError(err) 804 s.Require().Len(joinedCommunities, 1) 805 s.Require().Equal(joinedCommunities[0].IDString(), community.IDString()) 806 s.Require().True(joinedCommunities[0].Encrypted()) 807 808 grant, clock, err := alice.communitiesManager.GetCommunityGrant(community.IDString()) 809 s.Require().NoError(err) 810 s.Require().NotEqual(grant, []byte{}) 811 s.Require().True(clock > 0) 812 813 // 4) Alice presents the community in her profile showcase 814 err = alice.SetProfileShowcasePreferences(&identity.ProfileShowcasePreferences{ 815 Communities: []*identity.ProfileShowcaseCommunityPreference{ 816 &identity.ProfileShowcaseCommunityPreference{ 817 CommunityID: community.IDString(), 818 ShowcaseVisibility: identity.ProfileShowcaseVisibilityEveryone, 819 Order: 0, 820 }, 821 }, 822 }, false) 823 s.Require().NoError(err) 824 825 // 5) Bob gets the community from Alice's profile showcase and validates community's membership with grant 826 contactID := types.EncodeHex(crypto.FromECDSAPub(&alice.identity.PublicKey)) 827 _, err = WaitOnMessengerResponse( 828 bob, 829 func(r *MessengerResponse) bool { 830 return r.updatedProfileShowcaseContactIDs[contactID] == true 831 }, 832 "no messages", 833 ) 834 s.Require().NoError(err) 835 836 profileShowcase, err := bob.GetProfileShowcaseForContact(contactID, true) 837 s.Require().NoError(err) 838 s.Require().Len(profileShowcase.Communities, 1) 839 s.Require().Equal(community.IDString(), profileShowcase.Communities[0].CommunityID) 840 s.Require().Equal(identity.ProfileShowcaseMembershipStatusProvenMember, profileShowcase.Communities[0].MembershipStatus) 841 842 // 6) Owner updates the grant 843 owner.updateGrantsForControlledCommunities() 844 845 // Retrieve for grant clock update 846 err = tt.RetryWithBackOff(func() error { 847 _, err = alice.RetrieveAll() 848 if err != nil { 849 return err 850 } 851 _, updatedClock, err := alice.communitiesManager.GetCommunityGrant(community.IDString()) 852 if err != nil { 853 return err 854 } 855 856 if clock == updatedClock { 857 return errors.New("can't recive an updated grant") 858 } 859 return nil 860 }) 861 s.Require().NoError(err) 862 863 // 7) Bob should be able to validate the membership again 864 _, err = WaitOnMessengerResponse( 865 bob, 866 func(r *MessengerResponse) bool { 867 return r.updatedProfileShowcaseContactIDs[contactID] == true 868 }, 869 "no messages", 870 ) 871 s.Require().NoError(err) 872 873 profileShowcase, err = bob.GetProfileShowcaseForContact(contactID, true) 874 s.Require().NoError(err) 875 s.Require().Len(profileShowcase.Communities, 1) 876 s.Require().Equal(profileShowcase.Communities[0].CommunityID, community.IDString()) 877 s.Require().Equal(profileShowcase.Communities[0].MembershipStatus, identity.ProfileShowcaseMembershipStatusProvenMember) 878 879 // Return values back because they can affect other tests 880 grantInvokesProfileDispatchInterval = grantInvokesProfileDispatchIntervalBackup 881 }