From a2a2e611633bda7264509e81e906c142e9e6d652 Mon Sep 17 00:00:00 2001 From: Patryk Osmaczko Date: Tue, 27 Jun 2023 14:20:20 +0200 Subject: [PATCH] refactor: extract communities_messenger_token_permissions_test `communities_messenger_test` was unnecessarily polluted with passwords and addresses. --- .../communities_messenger_helpers_test.go | 205 +++++++ protocol/communities_messenger_test.go | 539 +----------------- ...nities_messenger_token_permissions_test.go | 378 ++++++++++++ 3 files changed, 612 insertions(+), 510 deletions(-) create mode 100644 protocol/communities_messenger_helpers_test.go create mode 100644 protocol/communities_messenger_token_permissions_test.go diff --git a/protocol/communities_messenger_helpers_test.go b/protocol/communities_messenger_helpers_test.go new file mode 100644 index 000000000..f751f23c3 --- /dev/null +++ b/protocol/communities_messenger_helpers_test.go @@ -0,0 +1,205 @@ +package protocol + +import ( + "context" + "crypto/ecdsa" + "encoding/json" + "errors" + "io/ioutil" + + "github.com/google/uuid" + "github.com/stretchr/testify/suite" + "go.uber.org/zap" + + "github.com/status-im/status-go/account" + "github.com/status-im/status-go/account/generator" + "github.com/status-im/status-go/eth-node/types" + "github.com/status-im/status-go/multiaccounts" + "github.com/status-im/status-go/multiaccounts/settings" + "github.com/status-im/status-go/params" + "github.com/status-im/status-go/protocol/common" + "github.com/status-im/status-go/protocol/communities" + "github.com/status-im/status-go/protocol/protobuf" + "github.com/status-im/status-go/protocol/requests" + "github.com/status-im/status-go/protocol/sqlite" + "github.com/status-im/status-go/protocol/tt" +) + +func newCommunitiesTestMessenger(shh types.Waku, privateKey *ecdsa.PrivateKey, logger *zap.Logger, accountsManager account.Manager, tokenManager communities.TokenManager) (*Messenger, error) { + tmpfile, err := ioutil.TempFile("", "accounts-tests-") + if err != nil { + return nil, err + } + madb, err := multiaccounts.InitializeDB(tmpfile.Name()) + if err != nil { + return nil, err + } + + acc := generator.NewAccount(privateKey, nil) + iai := acc.ToIdentifiedAccountInfo("") + + options := []Option{ + WithCustomLogger(logger), + WithDatabaseConfig(":memory:", "somekey", sqlite.ReducedKDFIterationsNumber), + WithMultiAccounts(madb), + WithAccount(iai.ToMultiAccount()), + WithDatasync(), + WithTokenManager(tokenManager), + } + + m, err := NewMessenger( + "Test", + privateKey, + &testNode{shh: shh}, + uuid.New().String(), + nil, + accountsManager, + options..., + ) + if err != nil { + return nil, err + } + + err = m.Init() + if err != nil { + return nil, err + } + + config := params.NodeConfig{ + NetworkID: 10, + DataDir: "test", + } + + networks := json.RawMessage("{}") + setting := settings.Settings{ + Address: types.HexToAddress("0x1122334455667788990011223344556677889900"), + AnonMetricsShouldSend: false, + CurrentNetwork: "mainnet_rpc", + DappsAddress: types.HexToAddress("0x1122334455667788990011223344556677889900"), + InstallationID: "d3efcff6-cffa-560e-a547-21d3858cbc51", + KeyUID: "0x1122334455667788990011223344556677889900", + Name: "Test", + Networks: &networks, + LatestDerivedPath: 0, + PhotoPath: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAIAAACRXR/mAAAAjklEQVR4nOzXwQmFMBAAUZXUYh32ZB32ZB02sxYQQSZGsod55/91WFgSS0RM+SyjA56ZRZhFmEWYRRT6h+M6G16zrxv6fdJpmUWYRbxsYr13dKfanpN0WmYRZhGzXz6AWYRZRIfbaX26fT9Jk07LLMIsosPt9I/dTDotswizCG+nhFmEWYRZhFnEHQAA///z1CFkYamgfQAAAABJRU5ErkJggg==", + PreviewPrivacy: false, + PublicKey: "0x04112233445566778899001122334455667788990011223344556677889900112233445566778899001122334455667788990011223344556677889900", + SigningPhrase: "yurt joey vibe", + SendPushNotifications: true, + ProfilePicturesVisibility: 1, + DefaultSyncPeriod: 777600, + UseMailservers: true, + LinkPreviewRequestEnabled: true, + SendStatusUpdates: true, + WalletRootAddress: types.HexToAddress("0x1122334455667788990011223344556677889900")} + + _ = m.settings.CreateSettings(setting, config) + + return m, nil +} + +func createCommunity(s *suite.Suite, owner *Messenger) (*communities.Community, *Chat) { + description := &requests.CreateCommunity{ + Membership: protobuf.CommunityPermissions_NO_MEMBERSHIP, + Name: "status", + Color: "#ffffff", + Description: "status community description", + } + + // Create an community chat + response, err := owner.CreateCommunity(description, true) + s.Require().NoError(err) + s.Require().NotNil(response) + + community := response.Communities()[0] + orgChat := &protobuf.CommunityChat{ + Permissions: &protobuf.CommunityPermissions{ + Access: protobuf.CommunityPermissions_NO_MEMBERSHIP, + }, + Identity: &protobuf.ChatIdentity{ + DisplayName: "status-core", + Emoji: "😎", + Description: "status-core community chat", + }, + } + + response, err = owner.CreateCommunityChat(community.ID(), orgChat) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().Len(response.Chats(), 1) + + return community, response.Chats()[0] +} + +func advertiseCommunityTo(s *suite.Suite, community *communities.Community, owner *Messenger, user *Messenger) { + chat := CreateOneToOneChat(common.PubkeyToHex(&user.identity.PublicKey), &user.identity.PublicKey, user.transport) + + inputMessage := &common.Message{} + inputMessage.ChatId = chat.ID + inputMessage.Text = "some text" + inputMessage.CommunityID = community.IDString() + + err := owner.SaveChat(chat) + s.Require().NoError(err) + _, err = owner.SendChatMessage(context.Background(), inputMessage) + s.Require().NoError(err) + + // Ensure community is received + err = tt.RetryWithBackOff(func() error { + response, err := user.RetrieveAll() + if err != nil { + return err + } + if len(response.Communities()) == 0 { + return errors.New("community not received") + } + return nil + }) + s.Require().NoError(err) +} + +func joinCommunity(s *suite.Suite, community *communities.Community, owner *Messenger, user *Messenger, request *requests.RequestToJoinCommunity) { + response, err := user.RequestToJoinCommunity(request) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().Len(response.RequestsToJoinCommunity, 1) + s.Require().Len(response.ActivityCenterNotifications(), 1) + + notification := response.ActivityCenterNotifications()[0] + s.Require().NotNil(notification) + s.Require().Equal(notification.Type, ActivityCenterNotificationTypeCommunityRequest) + s.Require().Equal(notification.MembershipStatus, ActivityCenterMembershipStatusPending) + + // Retrieve and accept join request + err = tt.RetryWithBackOff(func() error { + response, err := owner.RetrieveAll() + if err != nil { + return err + } + if len(response.Communities()) == 0 { + return errors.New("no communities in response (accept join request)") + } + if !response.Communities()[0].HasMember(&user.identity.PublicKey) { + return errors.New("user not accepted") + } + return nil + }) + s.Require().NoError(err) + + // Retrieve join request response + err = tt.RetryWithBackOff(func() error { + response, err := user.RetrieveAll() + + if err != nil { + return err + } + if len(response.Communities()) == 0 { + return errors.New("no communities in response (join request response)") + } + if !response.Communities()[0].HasMember(&user.identity.PublicKey) { + return errors.New("user not a member") + } + return nil + }) + s.Require().NoError(err) +} diff --git a/protocol/communities_messenger_test.go b/protocol/communities_messenger_test.go index fb41dc159..792c350c0 100644 --- a/protocol/communities_messenger_test.go +++ b/protocol/communities_messenger_test.go @@ -14,73 +14,25 @@ import ( "time" "github.com/golang/protobuf/proto" - "github.com/google/uuid" "github.com/stretchr/testify/suite" "go.uber.org/zap" - gethcommon "github.com/ethereum/go-ethereum/common" - hexutil "github.com/ethereum/go-ethereum/common/hexutil" - - "github.com/status-im/status-go/account" - "github.com/status-im/status-go/account/generator" gethbridge "github.com/status-im/status-go/eth-node/bridge/geth" "github.com/status-im/status-go/eth-node/crypto" "github.com/status-im/status-go/eth-node/types" - "github.com/status-im/status-go/multiaccounts" "github.com/status-im/status-go/multiaccounts/accounts" - "github.com/status-im/status-go/multiaccounts/settings" - "github.com/status-im/status-go/params" "github.com/status-im/status-go/protocol/common" "github.com/status-im/status-go/protocol/communities" "github.com/status-im/status-go/protocol/discord" "github.com/status-im/status-go/protocol/encryption/multidevice" "github.com/status-im/status-go/protocol/protobuf" "github.com/status-im/status-go/protocol/requests" - "github.com/status-im/status-go/protocol/sqlite" "github.com/status-im/status-go/protocol/transport" "github.com/status-im/status-go/protocol/tt" v1protocol "github.com/status-im/status-go/protocol/v1" "github.com/status-im/status-go/waku" ) -const adminPassword = "123456" -const alicePassword = "qwerty" -const bobPassword = "bob123" - -const adminAddress = "0x0100000000000000000000000000000000000000" -const aliceAddress1 = "0x0200000000000000000000000000000000000000" -const aliceAddress2 = "0x0210000000000000000000000000000000000000" -const bobAddress = "0x0300000000000000000000000000000000000000" - -type AccountManagerMock struct { - AccountsMap map[string]string -} - -type TestTokenManager struct { -} - -func (m *TestTokenManager) GetAllChainIDs() ([]uint64, error) { - return []uint64{5}, nil -} - -func (m *TestTokenManager) GetBalancesByChain(ctx context.Context, accounts, tokenAddresses []gethcommon.Address, chainIDs []uint64) (map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big, error) { - return nil, nil -} - -func (m *AccountManagerMock) GetVerifiedWalletAccount(db *accounts.Database, address, password string) (*account.SelectedExtKey, error) { - return &account.SelectedExtKey{ - Address: types.HexToAddress(address), - }, nil -} - -func (m *AccountManagerMock) CanRecover(rpcParams account.RecoverParams, revealedAddress types.Address) (bool, error) { - return true, nil -} - -func (m *AccountManagerMock) Sign(rpcParams account.SignParams, verifiedAccount *account.SelectedExtKey) (result types.HexBytes, err error) { - return types.HexBytes{}, nil -} - func TestMessengerCommunitiesSuite(t *testing.T) { suite.Run(t, new(MessengerCommunitiesSuite)) } @@ -105,9 +57,9 @@ func (s *MessengerCommunitiesSuite) SetupTest() { s.shh = gethbridge.NewGethWakuWrapper(shh) s.Require().NoError(shh.Start()) - s.admin = s.newMessengerWithWallet(adminPassword, []string{adminAddress}) - s.bob = s.newMessengerWithWallet(bobPassword, []string{bobAddress}) - s.alice = s.newMessengerWithWallet(alicePassword, []string{aliceAddress1, aliceAddress2}) + s.admin = s.newMessenger() + s.bob = s.newMessenger() + s.alice = s.newMessenger() _, err := s.admin.Start() s.Require().NoError(err) _, err = s.bob.Start() @@ -123,112 +75,18 @@ func (s *MessengerCommunitiesSuite) TearDownTest() { _ = s.logger.Sync() } -func (s *MessengerCommunitiesSuite) newMessengerWithOptions(shh types.Waku, privateKey *ecdsa.PrivateKey, accountsManager account.Manager, options []Option) *Messenger { - m, err := NewMessenger( - "Test", - privateKey, - &testNode{shh: shh}, - uuid.New().String(), - nil, - accountsManager, - options..., - ) +func (s *MessengerCommunitiesSuite) newMessengerWithKey(privateKey *ecdsa.PrivateKey) *Messenger { + messenger, err := newCommunitiesTestMessenger(s.shh, privateKey, s.logger, nil, nil) s.Require().NoError(err) - err = m.Init() - s.Require().NoError(err) - - config := params.NodeConfig{ - NetworkID: 10, - DataDir: "test", - } - - networks := json.RawMessage("{}") - setting := settings.Settings{ - Address: types.HexToAddress("0x1122334455667788990011223344556677889900"), - AnonMetricsShouldSend: false, - CurrentNetwork: "mainnet_rpc", - DappsAddress: types.HexToAddress("0x1122334455667788990011223344556677889900"), - InstallationID: "d3efcff6-cffa-560e-a547-21d3858cbc51", - KeyUID: "0x1122334455667788990011223344556677889900", - Name: "Test", - Networks: &networks, - LatestDerivedPath: 0, - PhotoPath: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAIAAACRXR/mAAAAjklEQVR4nOzXwQmFMBAAUZXUYh32ZB32ZB02sxYQQSZGsod55/91WFgSS0RM+SyjA56ZRZhFmEWYRRT6h+M6G16zrxv6fdJpmUWYRbxsYr13dKfanpN0WmYRZhGzXz6AWYRZRIfbaX26fT9Jk07LLMIsosPt9I/dTDotswizCG+nhFmEWYRZhFnEHQAA///z1CFkYamgfQAAAABJRU5ErkJggg==", - PreviewPrivacy: false, - PublicKey: "0x04112233445566778899001122334455667788990011223344556677889900112233445566778899001122334455667788990011223344556677889900", - SigningPhrase: "yurt joey vibe", - SendPushNotifications: true, - ProfilePicturesVisibility: 1, - DefaultSyncPeriod: 777600, - UseMailservers: true, - LinkPreviewRequestEnabled: true, - SendStatusUpdates: true, - WalletRootAddress: types.HexToAddress("0x1122334455667788990011223344556677889900")} - - _ = m.settings.CreateSettings(setting, config) - - return m -} - -func (s *MessengerCommunitiesSuite) newMessengerWithKey(shh types.Waku, privateKey *ecdsa.PrivateKey, accountsManager account.Manager) *Messenger { - tmpfile, err := ioutil.TempFile("", "accounts-tests-") - s.Require().NoError(err) - madb, err := multiaccounts.InitializeDB(tmpfile.Name()) - s.Require().NoError(err) - - acc := generator.NewAccount(privateKey, nil) - iai := acc.ToIdentifiedAccountInfo("") - tm := &TestTokenManager{} - - options := []Option{ - WithCustomLogger(s.logger), - WithDatabaseConfig(":memory:", "somekey", sqlite.ReducedKDFIterationsNumber), - WithMultiAccounts(madb), - WithAccount(iai.ToMultiAccount()), - WithDatasync(), - WithTokenManager(tm), - } - return s.newMessengerWithOptions(shh, privateKey, accountsManager, options) -} - -func (s *MessengerCommunitiesSuite) newMessenger(accountsManager account.Manager) *Messenger { - privateKey, err := crypto.GenerateKey() - s.Require().NoError(err) - - return s.newMessengerWithKey(s.shh, privateKey, accountsManager) -} - -func (s *MessengerCommunitiesSuite) newMessengerWithWallet(password string, walletAddresses []string) *Messenger { - accountsManager := &AccountManagerMock{} - accountsManager.AccountsMap = make(map[string]string) - for _, walletAddress := range walletAddresses { - accountsManager.AccountsMap[walletAddress] = types.EncodeHex(crypto.Keccak256([]byte(password))) - } - - messenger := s.newMessenger(accountsManager) - - // add wallet account with keypair - for _, walletAddress := range walletAddresses { - kp := accounts.GetProfileKeypairForTest(false, true, false) - kp.Accounts[0].Address = types.HexToAddress(walletAddress) - err := messenger.settings.SaveOrUpdateKeypair(kp) - s.Require().NoError(err) - } - - walletAccounts, err := messenger.settings.GetAccounts() - s.Require().NoError(err) - s.Require().Len(walletAccounts, len(walletAddresses)) - for i := range walletAddresses { - s.Require().Equal(walletAccounts[i].Type, accounts.AccountTypeGenerated) - } return messenger } -func (s *MessengerCommunitiesSuite) requestToJoinCommunity(user *Messenger, communityID types.HexBytes, password string, addresses []string) (*MessengerResponse, error) { - passwdHash := types.EncodeHex(crypto.Keccak256([]byte(password))) - request := &requests.RequestToJoinCommunity{CommunityID: communityID, Password: passwdHash, AddressesToReveal: addresses} - return user.RequestToJoinCommunity(request) +func (s *MessengerCommunitiesSuite) newMessenger() *Messenger { + privateKey, err := crypto.GenerateKey() + s.Require().NoError(err) + + return s.newMessengerWithKey(privateKey) } func (s *MessengerCommunitiesSuite) TestCreateCommunity() { @@ -263,7 +121,7 @@ func (s *MessengerCommunitiesSuite) TestCreateCommunity_WithoutDefaultChannel() } func (s *MessengerCommunitiesSuite) TestRetrieveCommunity() { - alice := s.newMessengerWithWallet(alicePassword, []string{aliceAddress1}) + alice := s.newMessenger() description := &requests.CreateCommunity{ Membership: protobuf.CommunityPermissions_NO_MEMBERSHIP, @@ -520,114 +378,17 @@ func (s *MessengerCommunitiesSuite) TestJoinCommunity() { } func (s *MessengerCommunitiesSuite) createCommunity() *communities.Community { - description := &requests.CreateCommunity{ - Membership: protobuf.CommunityPermissions_NO_MEMBERSHIP, - Name: "status", - Color: "#ffffff", - Description: "status community description", - } - - // Create an community chat - response, err := s.admin.CreateCommunity(description, true) - s.Require().NoError(err) - s.Require().NotNil(response) - - community := response.Communities()[0] - orgChat := &protobuf.CommunityChat{ - Permissions: &protobuf.CommunityPermissions{ - Access: protobuf.CommunityPermissions_NO_MEMBERSHIP, - }, - Identity: &protobuf.ChatIdentity{ - DisplayName: "status-core", - Emoji: "😎", - Description: "status-core community chat", - }, - } - - response, err = s.admin.CreateCommunityChat(community.ID(), orgChat) - s.Require().NoError(err) - s.Require().NotNil(response) - + community, _ := createCommunity(&s.Suite, s.admin) return community } func (s *MessengerCommunitiesSuite) advertiseCommunityTo(community *communities.Community, user *Messenger) { - chat := CreateOneToOneChat(common.PubkeyToHex(&user.identity.PublicKey), &user.identity.PublicKey, user.transport) - - inputMessage := &common.Message{} - inputMessage.ChatId = chat.ID - inputMessage.Text = "some text" - inputMessage.CommunityID = community.IDString() - - err := s.admin.SaveChat(chat) - s.Require().NoError(err) - _, err = s.admin.SendChatMessage(context.Background(), inputMessage) - s.Require().NoError(err) - - // Ensure community is received - err = tt.RetryWithBackOff(func() error { - response, err := user.RetrieveAll() - if err != nil { - return err - } - if len(response.Communities()) == 0 { - return errors.New("community not received") - } - return nil - }) - s.Require().NoError(err) + advertiseCommunityTo(&s.Suite, community, s.admin, user) } -func (s *MessengerCommunitiesSuite) joinCommunityWithAddresses(community *communities.Community, user *Messenger, password string, addresses []string) { - // Request to join the community - response, err := s.requestToJoinCommunity(user, community.ID(), password, addresses) - - s.Require().NoError(err) - s.Require().NotNil(response) - s.Require().Len(response.RequestsToJoinCommunity, 1) - s.Require().Len(response.ActivityCenterNotifications(), 1) - - notification := response.ActivityCenterNotifications()[0] - s.Require().NotNil(notification) - s.Require().Equal(notification.Type, ActivityCenterNotificationTypeCommunityRequest) - s.Require().Equal(notification.MembershipStatus, ActivityCenterMembershipStatusPending) - - // Retrieve and accept join request - err = tt.RetryWithBackOff(func() error { - response, err := s.admin.RetrieveAll() - if err != nil { - return err - } - if len(response.Communities()) == 0 { - return errors.New("no communities in response (accept join request)") - } - if !response.Communities()[0].HasMember(&user.identity.PublicKey) { - return errors.New("user not accepted") - } - return nil - }) - s.Require().NoError(err) - - // Retrieve join request response - err = tt.RetryWithBackOff(func() error { - response, err := user.RetrieveAll() - - if err != nil { - return err - } - if len(response.Communities()) == 0 { - return errors.New("no communities in response (join request response)") - } - if !response.Communities()[0].HasMember(&user.identity.PublicKey) { - return errors.New("user not a member") - } - return nil - }) - s.Require().NoError(err) -} - -func (s *MessengerCommunitiesSuite) joinCommunity(community *communities.Community, user *Messenger, password string) { - s.joinCommunityWithAddresses(community, user, password, []string{}) +func (s *MessengerCommunitiesSuite) joinCommunity(community *communities.Community, user *Messenger) { + request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} + joinCommunity(&s.Suite, community, s.admin, user, request) } func (s *MessengerCommunitiesSuite) TestCommunityContactCodeAdvertisement() { @@ -644,8 +405,8 @@ func (s *MessengerCommunitiesSuite) TestCommunityContactCodeAdvertisement() { s.advertiseCommunityTo(community, s.bob) s.advertiseCommunityTo(community, s.alice) - s.joinCommunity(community, s.bob, bobPassword) - s.joinCommunity(community, s.alice, alicePassword) + s.joinCommunity(community, s.bob) + s.joinCommunity(community, s.alice) // Trigger ContactCodeAdvertisement err = s.bob.SetDisplayName("bobby") @@ -2291,151 +2052,13 @@ func (s *MessengerCommunitiesSuite) TestDeclineAccess() { s.Require().Len(requestsToJoin, 0) } -func (s *MessengerCommunitiesSuite) TestCreateTokenPermission() { - community := s.createCommunity() - - createTokenPermission := &requests.CreateCommunityTokenPermission{ - CommunityID: community.ID(), - Type: protobuf.CommunityTokenPermission_BECOME_MEMBER, - TokenCriteria: []*protobuf.TokenCriteria{ - &protobuf.TokenCriteria{ - Type: protobuf.CommunityTokenType_ERC20, - ContractAddresses: map[uint64]string{uint64(1): "0x123"}, - Symbol: "TEST", - Amount: "100", - Decimals: uint64(18), - }, - }, - } - - response, err := s.admin.CreateCommunityTokenPermission(createTokenPermission) - s.Require().NoError(err) - s.Require().NotNil(response) - s.Require().Len(response.Communities(), 1) - - tokenPermissions := response.Communities()[0].TokenPermissions() - for _, tokenPermission := range tokenPermissions { - for _, tc := range tokenPermission.TokenCriteria { - s.Require().Equal(tc.Type, protobuf.CommunityTokenType_ERC20) - s.Require().Equal(tc.Symbol, "TEST") - s.Require().Equal(tc.Amount, "100") - s.Require().Equal(tc.Decimals, uint64(18)) - } - } -} - -func (s *MessengerCommunitiesSuite) TestEditTokenPermission() { - community := s.createCommunity() - - tokenPermission := &requests.CreateCommunityTokenPermission{ - CommunityID: community.ID(), - Type: protobuf.CommunityTokenPermission_BECOME_MEMBER, - TokenCriteria: []*protobuf.TokenCriteria{ - &protobuf.TokenCriteria{ - Type: protobuf.CommunityTokenType_ERC20, - ContractAddresses: map[uint64]string{uint64(1): "0x123"}, - Symbol: "TEST", - Amount: "100", - Decimals: uint64(18), - }, - }, - } - - response, err := s.admin.CreateCommunityTokenPermission(tokenPermission) - s.Require().NoError(err) - s.Require().NotNil(response) - s.Require().Len(response.Communities(), 1) - - tokenPermissions := response.Communities()[0].TokenPermissions() - - var tokenPermissionID string - for id := range tokenPermissions { - tokenPermissionID = id - } - - tokenPermission.TokenCriteria[0].Symbol = "TESTUpdated" - tokenPermission.TokenCriteria[0].Amount = "200" - tokenPermission.TokenCriteria[0].Decimals = uint64(20) - - editTokenPermission := &requests.EditCommunityTokenPermission{ - PermissionID: tokenPermissionID, - CreateCommunityTokenPermission: *tokenPermission, - } - - response2, err := s.admin.EditCommunityTokenPermission(editTokenPermission) - s.Require().NoError(err) - // wait for `checkMemberPermissions` to finish - time.Sleep(1 * time.Second) - s.Require().NotNil(response2) - s.Require().Len(response2.Communities(), 1) - - tokenPermissions = response2.Communities()[0].TokenPermissions() - for _, tokenPermission := range tokenPermissions { - for _, tc := range tokenPermission.TokenCriteria { - s.Require().Equal(tc.Type, protobuf.CommunityTokenType_ERC20) - s.Require().Equal(tc.Symbol, "TESTUpdated") - s.Require().Equal(tc.Amount, "200") - s.Require().Equal(tc.Decimals, uint64(20)) - } - } -} - -func (s *MessengerCommunitiesSuite) TestRequestAccessWithENSTokenPermission() { - community := s.createCommunity() - - createTokenPermission := &requests.CreateCommunityTokenPermission{ - CommunityID: community.ID(), - Type: protobuf.CommunityTokenPermission_BECOME_MEMBER, - TokenCriteria: []*protobuf.TokenCriteria{ - &protobuf.TokenCriteria{ - Type: protobuf.CommunityTokenType_ENS, - EnsPattern: "test.stateofus.eth", - }, - }, - } - - response, err := s.admin.CreateCommunityTokenPermission(createTokenPermission) - s.Require().NoError(err) - s.Require().NotNil(response) - s.Require().Len(response.Communities(), 1) - - s.advertiseCommunityTo(community, s.alice) - - requestToJoin := &requests.RequestToJoinCommunity{CommunityID: community.ID()} - // We try to join the org - response, err = s.alice.RequestToJoinCommunity(requestToJoin) - s.Require().NoError(err) - s.Require().NotNil(response) - s.Require().Len(response.RequestsToJoinCommunity, 1) - - requestToJoin1 := response.RequestsToJoinCommunity[0] - s.Require().Equal(communities.RequestToJoinStatePending, requestToJoin1.State) - - // Retrieve request to join - err = tt.RetryWithBackOff(func() error { - response, err = s.admin.RetrieveAll() - return err - }) - s.Require().NoError(err) - // We don't expect a requestToJoin in the response because due - // to missing revealed wallet addresses, the request should've - // been declined right away - s.Require().Len(response.RequestsToJoinCommunity, 0) - - // Ensure alice is not a member of the community - allCommunities, err := s.admin.Communities() - if bytes.Equal(allCommunities[0].ID(), community.ID()) { - s.Require().False(allCommunities[0].HasMember(&s.alice.identity.PublicKey)) - } -} - func (s *MessengerCommunitiesSuite) TestLeaveAndRejoinCommunity() { community := s.createCommunity() s.advertiseCommunityTo(community, s.alice) s.advertiseCommunityTo(community, s.bob) - s.joinCommunity(community, s.alice, alicePassword) - s.joinCommunity(community, s.bob, bobPassword) + s.joinCommunity(community, s.alice) + s.joinCommunity(community, s.bob) joinedCommunities, err := s.admin.communitiesManager.Joined() s.Require().NoError(err) @@ -2498,7 +2121,7 @@ func (s *MessengerCommunitiesSuite) TestLeaveAndRejoinCommunity() { s.Require().Equal(3, numberInactiveChats) // alice can rejoin - s.joinCommunity(community, s.alice, alicePassword) + s.joinCommunity(community, s.alice) joinedCommunities, err = s.admin.communitiesManager.Joined() s.Require().NoError(err) @@ -2629,11 +2252,10 @@ func (s *MessengerCommunitiesSuite) TestBanUser() { func (s *MessengerCommunitiesSuite) TestSyncCommunitySettings() { // Create new device - alicesOtherDevice, err := newMessengerWithKey(s.shh, s.alice.identity, s.logger, nil) - s.Require().NoError(err) + alicesOtherDevice := s.newMessengerWithKey(s.alice.identity) // Pair devices - err = alicesOtherDevice.SetInstallationMetadata(alicesOtherDevice.installationID, &multidevice.InstallationMetadata{ + err := alicesOtherDevice.SetInstallationMetadata(alicesOtherDevice.installationID, &multidevice.InstallationMetadata{ Name: "their-name", DeviceType: "their-device-type", }) @@ -2690,11 +2312,10 @@ func (s *MessengerCommunitiesSuite) TestSyncCommunitySettings() { func (s *MessengerCommunitiesSuite) TestSyncCommunitySettings_EditCommunity() { // Create new device - alicesOtherDevice, err := newMessengerWithKey(s.shh, s.alice.identity, s.logger, nil) - s.Require().NoError(err) + alicesOtherDevice := s.newMessengerWithKey(s.alice.identity) // Pair devices - err = alicesOtherDevice.SetInstallationMetadata(alicesOtherDevice.installationID, &multidevice.InstallationMetadata{ + err := alicesOtherDevice.SetInstallationMetadata(alicesOtherDevice.installationID, &multidevice.InstallationMetadata{ Name: "their-name", DeviceType: "their-device-type", }) @@ -2787,8 +2408,7 @@ func (s *MessengerCommunitiesSuite) TestSyncCommunitySettings_EditCommunity() { // TestSyncCommunity tests basic sync functionality between 2 Messengers func (s *MessengerCommunitiesSuite) TestSyncCommunity() { // Create new device - alicesOtherDevice, err := newMessengerWithKey(s.shh, s.alice.identity, s.logger, nil) - s.Require().NoError(err) + alicesOtherDevice := s.newMessengerWithKey(s.alice.identity) tcs, err := alicesOtherDevice.communitiesManager.All() s.Require().NoError(err, "alicesOtherDevice.communitiesManager.All") @@ -2881,8 +2501,7 @@ func (s *MessengerCommunitiesSuite) TestSyncCommunity_RequestToJoin() { s.Require().NoError(err) // Create Alice's other device - alicesOtherDevice, err := newMessengerWithKey(s.shh, s.alice.identity, s.logger, nil) - s.Require().NoError(err) + alicesOtherDevice := s.newMessengerWithKey(s.alice.identity) im1 := &multidevice.InstallationMetadata{ Name: "alice's-other-device", @@ -3124,8 +2743,7 @@ func (s *MessengerCommunitiesSuite) TestSyncCommunity_Leave() { s.Require().NoError(err) // Create Alice's other device - alicesOtherDevice, err := newMessengerWithKey(s.shh, s.alice.identity, s.logger, nil) - s.Require().NoError(err) + alicesOtherDevice := s.newMessengerWithKey(s.alice.identity) im1 := &multidevice.InstallationMetadata{ Name: "alice's-other-device", @@ -3451,48 +3069,6 @@ func (s *MessengerCommunitiesSuite) TestExtractDiscordChannelsAndCategories_With s.Require().Len(errs, 1) } -func (s *MessengerCommunitiesSuite) TestCommunityTokensMetadata() { - - description := &requests.CreateCommunity{ - Membership: protobuf.CommunityPermissions_NO_MEMBERSHIP, - Name: "status", - Color: "#ffffff", - Description: "status community description", - } - - // Create an community chat - response, err := s.bob.CreateCommunity(description, true) - s.Require().NoError(err) - s.Require().NotNil(response) - s.Require().Len(response.Communities(), 1) - s.Require().Len(response.CommunitiesSettings(), 1) - - community := response.Communities()[0] - - tokensMetadata := community.CommunityTokensMetadata() - s.Require().Len(tokensMetadata, 0) - - newToken := &protobuf.CommunityTokenMetadata{ - ContractAddresses: map[uint64]string{3: "0xasd"}, - Description: "desc1", - Image: "IMG1", - TokenType: protobuf.CommunityTokenType_ERC721, - Symbol: "SMB", - } - - _, err = community.AddCommunityTokensMetadata(newToken) - s.Require().NoError(err) - tokensMetadata = community.CommunityTokensMetadata() - s.Require().Len(tokensMetadata, 1) - - s.Require().Equal(tokensMetadata[0].ContractAddresses, newToken.ContractAddresses) - s.Require().Equal(tokensMetadata[0].Description, newToken.Description) - s.Require().Equal(tokensMetadata[0].Image, newToken.Image) - s.Require().Equal(tokensMetadata[0].TokenType, newToken.TokenType) - s.Require().Equal(tokensMetadata[0].Symbol, newToken.Symbol) - s.Require().Equal(tokensMetadata[0].Name, newToken.Name) -} - func (s *MessengerCommunitiesSuite) TestCommunityBanUserRequesToJoin() { description := &requests.CreateCommunity{ Membership: protobuf.CommunityPermissions_NO_MEMBERSHIP, @@ -3545,8 +3121,7 @@ func (s *MessengerCommunitiesSuite) TestCommunityBanUserRequesToJoin() { s.Require().NoError(err) s.Require().Len(response.Communities(), 1) - passwdHash := types.EncodeHex(crypto.Keccak256([]byte(alicePassword))) - request := &requests.RequestToJoinCommunity{CommunityID: community.ID(), Password: passwdHash} + request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} // We try to join the org _, rtj, err := s.alice.communitiesManager.RequestToJoin(&s.alice.identity.PublicKey, request) @@ -3698,59 +3273,3 @@ func (s *MessengerCommunitiesSuite) TestHandleImport() { s.Require().NotNil(chat) s.Require().Equal(0, int(chat.UnviewedMessagesCount)) } - -func (s *MessengerCommunitiesSuite) TestJoinedCommunityMembersSharedAddress() { - community := s.createCommunity() - s.advertiseCommunityTo(community, s.alice) - s.advertiseCommunityTo(community, s.bob) - - s.joinCommunity(community, s.alice, alicePassword) - s.joinCommunity(community, s.bob, bobPassword) - - community, err := s.admin.GetCommunityByID(community.ID()) - s.Require().NoError(err) - - s.Require().Equal(3, community.MembersCount()) - - for pubKey, member := range community.Members() { - if pubKey != common.PubkeyToHex(&s.admin.identity.PublicKey) { - - switch pubKey { - case common.PubkeyToHex(&s.alice.identity.PublicKey): - s.Require().Len(member.RevealedAccounts, 2) - s.Require().Equal(member.RevealedAccounts[0].Address, aliceAddress1) - s.Require().Equal(member.RevealedAccounts[1].Address, aliceAddress2) - case common.PubkeyToHex(&s.bob.identity.PublicKey): - s.Require().Len(member.RevealedAccounts, 1) - s.Require().Equal(member.RevealedAccounts[0].Address, bobAddress) - default: - s.Require().Fail("pubKey does not match expected keys") - } - } - } -} - -func (s *MessengerCommunitiesSuite) TestJoinedCommunityMembersSelectedSharedAddress() { - community := s.createCommunity() - s.advertiseCommunityTo(community, s.alice) - - s.joinCommunityWithAddresses(community, s.alice, alicePassword, []string{aliceAddress2}) - - community, err := s.admin.GetCommunityByID(community.ID()) - s.Require().NoError(err) - - s.Require().Equal(2, community.MembersCount()) - - for pubKey, member := range community.Members() { - if pubKey != common.PubkeyToHex(&s.admin.identity.PublicKey) { - s.Require().Len(member.RevealedAccounts, 1) - - switch pubKey { - case common.PubkeyToHex(&s.alice.identity.PublicKey): - s.Require().Equal(member.RevealedAccounts[0].Address, aliceAddress2) - default: - s.Require().Fail("pubKey does not match expected keys") - } - } - } -} diff --git a/protocol/communities_messenger_token_permissions_test.go b/protocol/communities_messenger_token_permissions_test.go new file mode 100644 index 000000000..73ea55276 --- /dev/null +++ b/protocol/communities_messenger_token_permissions_test.go @@ -0,0 +1,378 @@ +package protocol + +import ( + "bytes" + "context" + "testing" + "time" + + "github.com/stretchr/testify/suite" + "go.uber.org/zap" + + gethcommon "github.com/ethereum/go-ethereum/common" + hexutil "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/status-im/status-go/account" + gethbridge "github.com/status-im/status-go/eth-node/bridge/geth" + "github.com/status-im/status-go/eth-node/crypto" + "github.com/status-im/status-go/eth-node/types" + "github.com/status-im/status-go/multiaccounts/accounts" + "github.com/status-im/status-go/protocol/common" + "github.com/status-im/status-go/protocol/communities" + "github.com/status-im/status-go/protocol/protobuf" + "github.com/status-im/status-go/protocol/requests" + "github.com/status-im/status-go/protocol/tt" + "github.com/status-im/status-go/waku" +) + +const ownerPassword = "123456" +const alicePassword = "qwerty" +const bobPassword = "bob123" + +const ownerAddress = "0x0100000000000000000000000000000000000000" +const aliceAddress1 = "0x0200000000000000000000000000000000000000" +const aliceAddress2 = "0x0210000000000000000000000000000000000000" +const bobAddress = "0x0300000000000000000000000000000000000000" + +type AccountManagerMock struct { + AccountsMap map[string]string +} + +func (m *AccountManagerMock) GetVerifiedWalletAccount(db *accounts.Database, address, password string) (*account.SelectedExtKey, error) { + return &account.SelectedExtKey{ + Address: types.HexToAddress(address), + }, nil +} + +func (m *AccountManagerMock) CanRecover(rpcParams account.RecoverParams, revealedAddress types.Address) (bool, error) { + return true, nil +} + +func (m *AccountManagerMock) Sign(rpcParams account.SignParams, verifiedAccount *account.SelectedExtKey) (result types.HexBytes, err error) { + return types.HexBytes{}, nil +} + +type TokenManagerMock struct { +} + +func (m *TokenManagerMock) GetAllChainIDs() ([]uint64, error) { + return []uint64{5}, nil +} + +func (m *TokenManagerMock) GetBalancesByChain(ctx context.Context, accounts, tokenAddresses []gethcommon.Address, chainIDs []uint64) (map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big, error) { + return nil, nil +} + +func TestMessengerCommunitiesTokenPermissionsSuite(t *testing.T) { + suite.Run(t, new(MessengerCommunitiesTokenPermissionsSuite)) +} + +type MessengerCommunitiesTokenPermissionsSuite struct { + suite.Suite + owner *Messenger + bob *Messenger + alice *Messenger + // If one wants to send messages between different instances of Messenger, + // a single Waku service should be shared. + shh types.Waku + logger *zap.Logger +} + +func (s *MessengerCommunitiesTokenPermissionsSuite) SetupTest() { + s.logger = tt.MustCreateTestLogger() + + config := waku.DefaultConfig + config.MinimumAcceptedPoW = 0 + shh := waku.New(&config, s.logger) + s.shh = gethbridge.NewGethWakuWrapper(shh) + s.Require().NoError(shh.Start()) + + s.owner = s.newMessenger(ownerPassword, []string{ownerAddress}) + s.bob = s.newMessenger(bobPassword, []string{bobAddress}) + s.alice = s.newMessenger(alicePassword, []string{aliceAddress1, aliceAddress2}) + _, err := s.owner.Start() + s.Require().NoError(err) + _, err = s.bob.Start() + s.Require().NoError(err) + _, err = s.alice.Start() + s.Require().NoError(err) +} + +func (s *MessengerCommunitiesTokenPermissionsSuite) TearDownTest() { + s.Require().NoError(s.owner.Shutdown()) + s.Require().NoError(s.bob.Shutdown()) + s.Require().NoError(s.alice.Shutdown()) + _ = s.logger.Sync() +} + +func (s *MessengerCommunitiesTokenPermissionsSuite) newMessenger(password string, walletAddresses []string) *Messenger { + accountsManagerMock := &AccountManagerMock{} + accountsManagerMock.AccountsMap = make(map[string]string) + for _, walletAddress := range walletAddresses { + accountsManagerMock.AccountsMap[walletAddress] = types.EncodeHex(crypto.Keccak256([]byte(password))) + } + + tokenManagerMock := &TokenManagerMock{} + + privateKey, err := crypto.GenerateKey() + s.Require().NoError(err) + + messenger, err := newCommunitiesTestMessenger(s.shh, privateKey, s.logger, accountsManagerMock, tokenManagerMock) + s.Require().NoError(err) + + // add wallet account with keypair + for _, walletAddress := range walletAddresses { + kp := accounts.GetProfileKeypairForTest(false, true, false) + kp.Accounts[0].Address = types.HexToAddress(walletAddress) + err := messenger.settings.SaveOrUpdateKeypair(kp) + s.Require().NoError(err) + } + + walletAccounts, err := messenger.settings.GetAccounts() + s.Require().NoError(err) + s.Require().Len(walletAccounts, len(walletAddresses)) + for i := range walletAddresses { + s.Require().Equal(walletAccounts[i].Type, accounts.AccountTypeGenerated) + } + return messenger +} + +func (s *MessengerCommunitiesTokenPermissionsSuite) joinCommunityWithAddresses(community *communities.Community, user *Messenger, password string, addresses []string) { + passwdHash := types.EncodeHex(crypto.Keccak256([]byte(password))) + request := &requests.RequestToJoinCommunity{CommunityID: community.ID(), Password: passwdHash, AddressesToReveal: addresses} + joinCommunity(&s.Suite, community, s.owner, user, request) +} + +func (s *MessengerCommunitiesTokenPermissionsSuite) TestCreateTokenPermission() { + community, _ := createCommunity(&s.Suite, s.owner) + + createTokenPermission := &requests.CreateCommunityTokenPermission{ + CommunityID: community.ID(), + Type: protobuf.CommunityTokenPermission_BECOME_MEMBER, + TokenCriteria: []*protobuf.TokenCriteria{ + &protobuf.TokenCriteria{ + Type: protobuf.CommunityTokenType_ERC20, + ContractAddresses: map[uint64]string{uint64(1): "0x123"}, + Symbol: "TEST", + Amount: "100", + Decimals: uint64(18), + }, + }, + } + + response, err := s.owner.CreateCommunityTokenPermission(createTokenPermission) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().Len(response.Communities(), 1) + + tokenPermissions := response.Communities()[0].TokenPermissions() + for _, tokenPermission := range tokenPermissions { + for _, tc := range tokenPermission.TokenCriteria { + s.Require().Equal(tc.Type, protobuf.CommunityTokenType_ERC20) + s.Require().Equal(tc.Symbol, "TEST") + s.Require().Equal(tc.Amount, "100") + s.Require().Equal(tc.Decimals, uint64(18)) + } + } +} + +func (s *MessengerCommunitiesTokenPermissionsSuite) TestEditTokenPermission() { + community, _ := createCommunity(&s.Suite, s.owner) + + tokenPermission := &requests.CreateCommunityTokenPermission{ + CommunityID: community.ID(), + Type: protobuf.CommunityTokenPermission_BECOME_MEMBER, + TokenCriteria: []*protobuf.TokenCriteria{ + &protobuf.TokenCriteria{ + Type: protobuf.CommunityTokenType_ERC20, + ContractAddresses: map[uint64]string{uint64(1): "0x123"}, + Symbol: "TEST", + Amount: "100", + Decimals: uint64(18), + }, + }, + } + + response, err := s.owner.CreateCommunityTokenPermission(tokenPermission) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().Len(response.Communities(), 1) + + tokenPermissions := response.Communities()[0].TokenPermissions() + + var tokenPermissionID string + for id := range tokenPermissions { + tokenPermissionID = id + } + + tokenPermission.TokenCriteria[0].Symbol = "TESTUpdated" + tokenPermission.TokenCriteria[0].Amount = "200" + tokenPermission.TokenCriteria[0].Decimals = uint64(20) + + editTokenPermission := &requests.EditCommunityTokenPermission{ + PermissionID: tokenPermissionID, + CreateCommunityTokenPermission: *tokenPermission, + } + + response2, err := s.owner.EditCommunityTokenPermission(editTokenPermission) + s.Require().NoError(err) + // wait for `checkMemberPermissions` to finish + time.Sleep(1 * time.Second) + s.Require().NotNil(response2) + s.Require().Len(response2.Communities(), 1) + + tokenPermissions = response2.Communities()[0].TokenPermissions() + for _, tokenPermission := range tokenPermissions { + for _, tc := range tokenPermission.TokenCriteria { + s.Require().Equal(tc.Type, protobuf.CommunityTokenType_ERC20) + s.Require().Equal(tc.Symbol, "TESTUpdated") + s.Require().Equal(tc.Amount, "200") + s.Require().Equal(tc.Decimals, uint64(20)) + } + } +} + +func (s *MessengerCommunitiesTokenPermissionsSuite) TestCommunityTokensMetadata() { + description := &requests.CreateCommunity{ + Membership: protobuf.CommunityPermissions_NO_MEMBERSHIP, + Name: "status", + Color: "#ffffff", + Description: "status community description", + } + + // Create an community chat + response, err := s.bob.CreateCommunity(description, true) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().Len(response.Communities(), 1) + s.Require().Len(response.CommunitiesSettings(), 1) + + community := response.Communities()[0] + + tokensMetadata := community.CommunityTokensMetadata() + s.Require().Len(tokensMetadata, 0) + + newToken := &protobuf.CommunityTokenMetadata{ + ContractAddresses: map[uint64]string{3: "0xasd"}, + Description: "desc1", + Image: "IMG1", + TokenType: protobuf.CommunityTokenType_ERC721, + Symbol: "SMB", + } + + _, err = community.AddCommunityTokensMetadata(newToken) + s.Require().NoError(err) + tokensMetadata = community.CommunityTokensMetadata() + s.Require().Len(tokensMetadata, 1) + + s.Require().Equal(tokensMetadata[0].ContractAddresses, newToken.ContractAddresses) + s.Require().Equal(tokensMetadata[0].Description, newToken.Description) + s.Require().Equal(tokensMetadata[0].Image, newToken.Image) + s.Require().Equal(tokensMetadata[0].TokenType, newToken.TokenType) + s.Require().Equal(tokensMetadata[0].Symbol, newToken.Symbol) + s.Require().Equal(tokensMetadata[0].Name, newToken.Name) +} + +func (s *MessengerCommunitiesTokenPermissionsSuite) TestRequestAccessWithENSTokenPermission() { + community, _ := createCommunity(&s.Suite, s.owner) + + createTokenPermission := &requests.CreateCommunityTokenPermission{ + CommunityID: community.ID(), + Type: protobuf.CommunityTokenPermission_BECOME_MEMBER, + TokenCriteria: []*protobuf.TokenCriteria{ + &protobuf.TokenCriteria{ + Type: protobuf.CommunityTokenType_ENS, + EnsPattern: "test.stateofus.eth", + }, + }, + } + + response, err := s.owner.CreateCommunityTokenPermission(createTokenPermission) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().Len(response.Communities(), 1) + + advertiseCommunityTo(&s.Suite, community, s.owner, s.alice) + + requestToJoin := &requests.RequestToJoinCommunity{CommunityID: community.ID()} + // We try to join the org + response, err = s.alice.RequestToJoinCommunity(requestToJoin) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().Len(response.RequestsToJoinCommunity, 1) + + requestToJoin1 := response.RequestsToJoinCommunity[0] + s.Require().Equal(communities.RequestToJoinStatePending, requestToJoin1.State) + + // Retrieve request to join + err = tt.RetryWithBackOff(func() error { + response, err = s.owner.RetrieveAll() + return err + }) + s.Require().NoError(err) + // We don't expect a requestToJoin in the response because due + // to missing revealed wallet addresses, the request should've + // been declined right away + s.Require().Len(response.RequestsToJoinCommunity, 0) + + // Ensure alice is not a member of the community + allCommunities, err := s.owner.Communities() + if bytes.Equal(allCommunities[0].ID(), community.ID()) { + s.Require().False(allCommunities[0].HasMember(&s.alice.identity.PublicKey)) + } +} + +func (s *MessengerCommunitiesTokenPermissionsSuite) TestJoinedCommunityMembersSharedAddress() { + community, _ := createCommunity(&s.Suite, s.owner) + advertiseCommunityTo(&s.Suite, community, s.owner, s.alice) + advertiseCommunityTo(&s.Suite, community, s.owner, s.bob) + + s.joinCommunityWithAddresses(community, s.alice, alicePassword, []string{}) + s.joinCommunityWithAddresses(community, s.bob, bobPassword, []string{}) + + community, err := s.owner.GetCommunityByID(community.ID()) + s.Require().NoError(err) + + s.Require().Equal(3, community.MembersCount()) + + for pubKey, member := range community.Members() { + if pubKey != common.PubkeyToHex(&s.owner.identity.PublicKey) { + + switch pubKey { + case common.PubkeyToHex(&s.alice.identity.PublicKey): + s.Require().Len(member.RevealedAccounts, 2) + s.Require().Equal(member.RevealedAccounts[0].Address, aliceAddress1) + s.Require().Equal(member.RevealedAccounts[1].Address, aliceAddress2) + case common.PubkeyToHex(&s.bob.identity.PublicKey): + s.Require().Len(member.RevealedAccounts, 1) + s.Require().Equal(member.RevealedAccounts[0].Address, bobAddress) + default: + s.Require().Fail("pubKey does not match expected keys") + } + } + } +} + +func (s *MessengerCommunitiesTokenPermissionsSuite) TestJoinedCommunityMembersSelectedSharedAddress() { + community, _ := createCommunity(&s.Suite, s.owner) + advertiseCommunityTo(&s.Suite, community, s.owner, s.alice) + + s.joinCommunityWithAddresses(community, s.alice, alicePassword, []string{aliceAddress2}) + + community, err := s.owner.GetCommunityByID(community.ID()) + s.Require().NoError(err) + + s.Require().Equal(2, community.MembersCount()) + + for pubKey, member := range community.Members() { + if pubKey != common.PubkeyToHex(&s.owner.identity.PublicKey) { + s.Require().Len(member.RevealedAccounts, 1) + + switch pubKey { + case common.PubkeyToHex(&s.alice.identity.PublicKey): + s.Require().Equal(member.RevealedAccounts[0].Address, aliceAddress2) + default: + s.Require().Fail("pubKey does not match expected keys") + } + } + } +}