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  }