github.com/status-im/status-go@v1.1.0/protocol/push_notification_test.go (about)

     1  package protocol
     2  
     3  import (
     4  	"context"
     5  	"crypto/ecdsa"
     6  	"encoding/hex"
     7  	"errors"
     8  	"testing"
     9  
    10  	"github.com/stretchr/testify/suite"
    11  	"go.uber.org/zap"
    12  
    13  	gethbridge "github.com/status-im/status-go/eth-node/bridge/geth"
    14  	"github.com/status-im/status-go/eth-node/crypto"
    15  	"github.com/status-im/status-go/eth-node/types"
    16  	"github.com/status-im/status-go/protocol/common"
    17  	"github.com/status-im/status-go/protocol/communities"
    18  	"github.com/status-im/status-go/protocol/protobuf"
    19  	"github.com/status-im/status-go/protocol/pushnotificationclient"
    20  	"github.com/status-im/status-go/protocol/pushnotificationserver"
    21  	"github.com/status-im/status-go/protocol/requests"
    22  	"github.com/status-im/status-go/protocol/tt"
    23  	"github.com/status-im/status-go/waku"
    24  )
    25  
    26  const (
    27  	bob1DeviceToken = "token-1"
    28  	bob2DeviceToken = "token-2"
    29  	testAPNTopic    = "topic"
    30  )
    31  
    32  func TestMessengerPushNotificationSuite(t *testing.T) {
    33  	suite.Run(t, new(MessengerPushNotificationSuite))
    34  }
    35  
    36  type MessengerPushNotificationSuite struct {
    37  	suite.Suite
    38  	m          *Messenger        // main instance of Messenger
    39  	privateKey *ecdsa.PrivateKey // private key for the main instance of Messenger
    40  	// If one wants to send messages between different instances of Messenger,
    41  	// a single Waku service should be shared.
    42  	shh    types.Waku
    43  	logger *zap.Logger
    44  }
    45  
    46  func (s *MessengerPushNotificationSuite) SetupTest() {
    47  	s.logger = tt.MustCreateTestLogger()
    48  
    49  	config := waku.DefaultConfig
    50  	config.MinimumAcceptedPoW = 0
    51  	shh := waku.New(&config, s.logger)
    52  	s.shh = gethbridge.NewGethWakuWrapper(shh)
    53  	s.Require().NoError(shh.Start())
    54  
    55  	s.m = s.newMessenger(s.shh)
    56  	s.privateKey = s.m.identity
    57  }
    58  
    59  func (s *MessengerPushNotificationSuite) TearDownTest() {
    60  	TearDownMessenger(&s.Suite, s.m)
    61  	_ = s.logger.Sync()
    62  }
    63  
    64  func (s *MessengerPushNotificationSuite) newMessenger(shh types.Waku) *Messenger {
    65  	privateKey, err := crypto.GenerateKey()
    66  	s.Require().NoError(err)
    67  
    68  	messenger, err := newMessengerWithKey(s.shh, privateKey, s.logger, []Option{WithPushNotifications()})
    69  	s.Require().NoError(err)
    70  	return messenger
    71  }
    72  
    73  func (s *MessengerPushNotificationSuite) newPushNotificationServer(shh types.Waku, privateKey *ecdsa.PrivateKey) *Messenger {
    74  
    75  	serverConfig := &pushnotificationserver.Config{
    76  		Enabled:  true,
    77  		Logger:   s.logger,
    78  		Identity: privateKey,
    79  	}
    80  
    81  	options := []Option{
    82  		WithPushNotificationServerConfig(serverConfig),
    83  	}
    84  	messenger, err := newMessengerWithKey(shh, privateKey, s.logger, options)
    85  	s.Require().NoError(err)
    86  	return messenger
    87  }
    88  
    89  func (s *MessengerPushNotificationSuite) TestReceivePushNotification() {
    90  
    91  	bob1 := s.m
    92  	bob2, err := newMessengerWithKey(s.shh, s.m.identity, s.logger, []Option{WithPushNotifications()})
    93  	s.Require().NoError(err)
    94  	defer TearDownMessenger(&s.Suite, bob2)
    95  
    96  	serverKey, err := crypto.GenerateKey()
    97  	s.Require().NoError(err)
    98  	server := s.newPushNotificationServer(s.shh, serverKey)
    99  	defer TearDownMessenger(&s.Suite, server)
   100  
   101  	alice := s.newMessenger(s.shh)
   102  	defer TearDownMessenger(&s.Suite, alice)
   103  	s.Require().NoError(alice.EnableSendingPushNotifications())
   104  	bobInstallationIDs := []string{bob1.installationID, bob2.installationID}
   105  
   106  	// Register bob1
   107  	err = bob1.AddPushNotificationsServer(context.Background(), &server.identity.PublicKey, pushnotificationclient.ServerTypeCustom)
   108  	s.Require().NoError(err)
   109  
   110  	err = bob1.RegisterForPushNotifications(context.Background(), bob1DeviceToken, testAPNTopic, protobuf.PushNotificationRegistration_APN_TOKEN)
   111  
   112  	// Pull servers  and check we registered
   113  	err = tt.RetryWithBackOff(func() error {
   114  		_, err = server.RetrieveAll()
   115  		if err != nil {
   116  			return err
   117  		}
   118  		_, err = bob1.RetrieveAll()
   119  		if err != nil {
   120  			return err
   121  		}
   122  		registered, err := bob1.RegisteredForPushNotifications()
   123  		if err != nil {
   124  			return err
   125  		}
   126  		if !registered {
   127  			return errors.New("not registered")
   128  		}
   129  		bobServers, err := bob1.GetPushNotificationsServers()
   130  		if err != nil {
   131  			return err
   132  		}
   133  
   134  		if len(bobServers) == 0 {
   135  			return errors.New("not registered")
   136  		}
   137  
   138  		return nil
   139  	})
   140  	// Make sure we receive it
   141  	s.Require().NoError(err)
   142  	bob1Servers, err := bob1.GetPushNotificationsServers()
   143  	s.Require().NoError(err)
   144  
   145  	// Register bob2
   146  	err = bob2.AddPushNotificationsServer(context.Background(), &server.identity.PublicKey, pushnotificationclient.ServerTypeCustom)
   147  	s.Require().NoError(err)
   148  
   149  	err = bob2.RegisterForPushNotifications(context.Background(), bob2DeviceToken, testAPNTopic, protobuf.PushNotificationRegistration_APN_TOKEN)
   150  	s.Require().NoError(err)
   151  
   152  	err = tt.RetryWithBackOff(func() error {
   153  		_, err = server.RetrieveAll()
   154  		if err != nil {
   155  			return err
   156  		}
   157  		_, err = bob2.RetrieveAll()
   158  		if err != nil {
   159  			return err
   160  		}
   161  
   162  		registered, err := bob2.RegisteredForPushNotifications()
   163  		if err != nil {
   164  			return err
   165  		}
   166  		if !registered {
   167  			return errors.New("not registered")
   168  		}
   169  		bobServers, err := bob2.GetPushNotificationsServers()
   170  		if err != nil {
   171  			return err
   172  		}
   173  
   174  		if len(bobServers) == 0 {
   175  			return errors.New("not registered")
   176  		}
   177  
   178  		return nil
   179  	})
   180  	// Make sure we receive it
   181  	s.Require().NoError(err)
   182  	bob2Servers, err := bob2.GetPushNotificationsServers()
   183  	s.Require().NoError(err)
   184  
   185  	// Create one to one chat & send message
   186  	pkString := hex.EncodeToString(crypto.FromECDSAPub(&s.m.identity.PublicKey))
   187  	chat := CreateOneToOneChat(pkString, &s.m.identity.PublicKey, alice.transport)
   188  	s.Require().NoError(alice.SaveChat(chat))
   189  	inputMessage := buildTestMessage(*chat)
   190  	response, err := alice.SendChatMessage(context.Background(), inputMessage)
   191  	s.Require().NoError(err)
   192  	messageIDString := response.Messages()[0].ID
   193  	messageID, err := hex.DecodeString(messageIDString[2:])
   194  	s.Require().NoError(err)
   195  
   196  	infoMap := make(map[string]*pushnotificationclient.PushNotificationInfo)
   197  	err = tt.RetryWithBackOff(func() error {
   198  		_, err = server.RetrieveAll()
   199  		if err != nil {
   200  			return err
   201  		}
   202  		_, err = alice.RetrieveAll()
   203  		if err != nil {
   204  			return err
   205  		}
   206  
   207  		info, err := alice.pushNotificationClient.GetPushNotificationInfo(&bob1.identity.PublicKey, bobInstallationIDs)
   208  		if err != nil {
   209  			return err
   210  		}
   211  		for _, i := range info {
   212  			infoMap[i.AccessToken] = i
   213  		}
   214  
   215  		// Check we have replies for both bob1 and bob2
   216  		if len(infoMap) != 2 {
   217  			return errors.New("info not fetched")
   218  		}
   219  		return nil
   220  
   221  	})
   222  
   223  	s.Require().Len(infoMap, 2)
   224  
   225  	// Check we have replies for both bob1 and bob2
   226  	var bob1Info, bob2Info *pushnotificationclient.PushNotificationInfo
   227  
   228  	bob1Info = infoMap[bob1Servers[0].AccessToken]
   229  	bob2Info = infoMap[bob2Servers[0].AccessToken]
   230  
   231  	s.Require().NotNil(bob1Info)
   232  	s.Require().Equal(bob1.installationID, bob1Info.InstallationID)
   233  	s.Require().Equal(bob1Servers[0].AccessToken, bob1Info.AccessToken)
   234  	s.Require().Equal(&bob1.identity.PublicKey, bob1Info.PublicKey)
   235  
   236  	s.Require().NotNil(bob2Info)
   237  	s.Require().Equal(bob2.installationID, bob2Info.InstallationID)
   238  	s.Require().Equal(bob2Servers[0].AccessToken, bob2Info.AccessToken)
   239  	s.Require().Equal(&bob2.identity.PublicKey, bob2Info.PublicKey)
   240  
   241  	retrievedNotificationInfo, err := alice.pushNotificationClient.GetPushNotificationInfo(&bob1.identity.PublicKey, bobInstallationIDs)
   242  
   243  	s.Require().NoError(err)
   244  	s.Require().NotNil(retrievedNotificationInfo)
   245  	s.Require().Len(retrievedNotificationInfo, 2)
   246  
   247  	var sentNotification *pushnotificationclient.SentNotification
   248  	err = tt.RetryWithBackOff(func() error {
   249  		_, err = server.RetrieveAll()
   250  		if err != nil {
   251  			return err
   252  		}
   253  		_, err = alice.RetrieveAll()
   254  		if err != nil {
   255  			return err
   256  		}
   257  		sentNotification, err = alice.pushNotificationClient.GetSentNotification(common.HashPublicKey(&bob1.identity.PublicKey), bob1.installationID, messageID)
   258  		if err != nil {
   259  			return err
   260  		}
   261  		if sentNotification == nil {
   262  			return errors.New("sent notification not found")
   263  		}
   264  		if !sentNotification.Success {
   265  			return errors.New("sent notification not successul")
   266  		}
   267  		return nil
   268  	})
   269  	s.Require().NoError(err)
   270  }
   271  
   272  func (s *MessengerPushNotificationSuite) TestReceivePushNotificationFromContactOnly() {
   273  
   274  	bob := s.m
   275  
   276  	serverKey, err := crypto.GenerateKey()
   277  	s.Require().NoError(err)
   278  	server := s.newPushNotificationServer(s.shh, serverKey)
   279  	defer TearDownMessenger(&s.Suite, server)
   280  
   281  	alice := s.newMessenger(s.shh)
   282  	defer TearDownMessenger(&s.Suite, alice)
   283  	s.Require().NoError(alice.EnableSendingPushNotifications())
   284  	bobInstallationIDs := []string{bob.installationID}
   285  
   286  	// Register bob
   287  	err = bob.AddPushNotificationsServer(context.Background(), &server.identity.PublicKey, pushnotificationclient.ServerTypeCustom)
   288  	s.Require().NoError(err)
   289  
   290  	// Add alice has a contact
   291  	aliceContact := &Contact{
   292  		ID:                       types.EncodeHex(crypto.FromECDSAPub(&alice.identity.PublicKey)),
   293  		EnsName:                  "Some Contact",
   294  		ContactRequestLocalState: ContactRequestStateSent,
   295  	}
   296  
   297  	_, err = bob.AddContact(context.Background(), &requests.AddContact{ID: aliceContact.ID})
   298  	s.Require().NoError(err)
   299  
   300  	// Enable from contacts only
   301  	err = bob.EnablePushNotificationsFromContactsOnly()
   302  	s.Require().NoError(err)
   303  
   304  	err = bob.RegisterForPushNotifications(context.Background(), bob1DeviceToken, testAPNTopic, protobuf.PushNotificationRegistration_APN_TOKEN)
   305  	s.Require().NoError(err)
   306  
   307  	// Pull servers  and check we registered
   308  	err = tt.RetryWithBackOff(func() error {
   309  		_, err = server.RetrieveAll()
   310  		if err != nil {
   311  			return err
   312  		}
   313  		_, err = bob.RetrieveAll()
   314  		if err != nil {
   315  			return err
   316  		}
   317  		registered, err := bob.RegisteredForPushNotifications()
   318  		if err != nil {
   319  			return err
   320  		}
   321  		if !registered {
   322  			return errors.New("not registered")
   323  		}
   324  		bobServers, err := bob.GetPushNotificationsServers()
   325  		if err != nil {
   326  			return err
   327  		}
   328  
   329  		if len(bobServers) == 0 {
   330  			return errors.New("not registered")
   331  		}
   332  
   333  		return nil
   334  	})
   335  	// Make sure we receive it
   336  	s.Require().NoError(err)
   337  	bobServers, err := bob.GetPushNotificationsServers()
   338  	s.Require().NoError(err)
   339  
   340  	// Create one to one chat & send message
   341  	pkString := hex.EncodeToString(crypto.FromECDSAPub(&s.m.identity.PublicKey))
   342  	chat := CreateOneToOneChat(pkString, &s.m.identity.PublicKey, alice.transport)
   343  	s.Require().NoError(alice.SaveChat(chat))
   344  	inputMessage := buildTestMessage(*chat)
   345  	response, err := alice.SendChatMessage(context.Background(), inputMessage)
   346  	s.Require().NoError(err)
   347  	messageIDString := response.Messages()[0].ID
   348  	messageID, err := hex.DecodeString(messageIDString[2:])
   349  	s.Require().NoError(err)
   350  
   351  	var info []*pushnotificationclient.PushNotificationInfo
   352  	err = tt.RetryWithBackOff(func() error {
   353  		_, err = server.RetrieveAll()
   354  		if err != nil {
   355  			return err
   356  		}
   357  		_, err = alice.RetrieveAll()
   358  		if err != nil {
   359  			return err
   360  		}
   361  
   362  		info, err = alice.pushNotificationClient.GetPushNotificationInfo(&bob.identity.PublicKey, bobInstallationIDs)
   363  		if err != nil {
   364  			return err
   365  		}
   366  		// Check we have replies for bob
   367  		if len(info) != 1 {
   368  			return errors.New("info not fetched")
   369  		}
   370  		return nil
   371  
   372  	})
   373  	s.Require().NoError(err)
   374  
   375  	s.Require().NotNil(info)
   376  	s.Require().Equal(bob.installationID, info[0].InstallationID)
   377  	s.Require().Equal(bobServers[0].AccessToken, info[0].AccessToken)
   378  	s.Require().Equal(&bob.identity.PublicKey, info[0].PublicKey)
   379  
   380  	retrievedNotificationInfo, err := alice.pushNotificationClient.GetPushNotificationInfo(&bob.identity.PublicKey, bobInstallationIDs)
   381  	s.Require().NoError(err)
   382  	s.Require().NotNil(retrievedNotificationInfo)
   383  	s.Require().Len(retrievedNotificationInfo, 1)
   384  
   385  	var sentNotification *pushnotificationclient.SentNotification
   386  	err = tt.RetryWithBackOff(func() error {
   387  		_, err = server.RetrieveAll()
   388  		if err != nil {
   389  			return err
   390  		}
   391  		_, err = alice.RetrieveAll()
   392  		if err != nil {
   393  			return err
   394  		}
   395  		sentNotification, err = alice.pushNotificationClient.GetSentNotification(common.HashPublicKey(&bob.identity.PublicKey), bob.installationID, messageID)
   396  		if err != nil {
   397  			return err
   398  		}
   399  		if sentNotification == nil {
   400  			return errors.New("sent notification not found")
   401  		}
   402  		if !sentNotification.Success {
   403  			return errors.New("sent notification not successul")
   404  		}
   405  		return nil
   406  	})
   407  
   408  	s.Require().NoError(err)
   409  }
   410  
   411  func (s *MessengerPushNotificationSuite) TestReceivePushNotificationRetries() {
   412  
   413  	bob := s.m
   414  
   415  	serverKey, err := crypto.GenerateKey()
   416  	s.Require().NoError(err)
   417  	server := s.newPushNotificationServer(s.shh, serverKey)
   418  	defer TearDownMessenger(&s.Suite, server)
   419  
   420  	alice := s.newMessenger(s.shh)
   421  	// another contact to invalidate the token
   422  	frank := s.newMessenger(s.shh)
   423  	defer TearDownMessenger(&s.Suite, frank)
   424  	defer TearDownMessenger(&s.Suite, alice)
   425  
   426  	s.Require().NoError(alice.EnableSendingPushNotifications())
   427  	bobInstallationIDs := []string{bob.installationID}
   428  
   429  	// Register bob
   430  	err = bob.AddPushNotificationsServer(context.Background(), &server.identity.PublicKey, pushnotificationclient.ServerTypeCustom)
   431  	s.Require().NoError(err)
   432  
   433  	// Add alice has a contact
   434  	aliceContact := &Contact{
   435  		ID:                       types.EncodeHex(crypto.FromECDSAPub(&alice.identity.PublicKey)),
   436  		EnsName:                  "Some Contact",
   437  		ContactRequestLocalState: ContactRequestStateSent,
   438  	}
   439  
   440  	_, err = bob.AddContact(context.Background(), &requests.AddContact{ID: aliceContact.ID})
   441  	s.Require().NoError(err)
   442  
   443  	// Add frank has a contact
   444  	frankContact := &Contact{
   445  		ID:                       types.EncodeHex(crypto.FromECDSAPub(&frank.identity.PublicKey)),
   446  		EnsName:                  "Some Contact",
   447  		ContactRequestLocalState: ContactRequestStateSent,
   448  	}
   449  
   450  	_, err = bob.AddContact(context.Background(), &requests.AddContact{ID: frankContact.ID})
   451  	s.Require().NoError(err)
   452  
   453  	// Enable from contacts only
   454  	err = bob.EnablePushNotificationsFromContactsOnly()
   455  	s.Require().NoError(err)
   456  
   457  	err = bob.RegisterForPushNotifications(context.Background(), bob1DeviceToken, testAPNTopic, protobuf.PushNotificationRegistration_APN_TOKEN)
   458  	s.Require().NoError(err)
   459  
   460  	// Pull servers  and check we registered
   461  	err = tt.RetryWithBackOff(func() error {
   462  		_, err = server.RetrieveAll()
   463  		if err != nil {
   464  			return err
   465  		}
   466  		_, err = bob.RetrieveAll()
   467  		if err != nil {
   468  			return err
   469  		}
   470  		registered, err := bob.RegisteredForPushNotifications()
   471  		if err != nil {
   472  			return err
   473  		}
   474  		if !registered {
   475  			return errors.New("not registered")
   476  		}
   477  		bobServers, err := bob.GetPushNotificationsServers()
   478  		if err != nil {
   479  			return err
   480  		}
   481  
   482  		if len(bobServers) == 0 {
   483  			return errors.New("not registered")
   484  		}
   485  
   486  		return nil
   487  	})
   488  	// Make sure we receive it
   489  	s.Require().NoError(err)
   490  	bobServers, err := bob.GetPushNotificationsServers()
   491  	s.Require().NoError(err)
   492  
   493  	// Create one to one chat & send message
   494  	pkString := hex.EncodeToString(crypto.FromECDSAPub(&s.m.identity.PublicKey))
   495  	chat := CreateOneToOneChat(pkString, &s.m.identity.PublicKey, alice.transport)
   496  	s.Require().NoError(alice.SaveChat(chat))
   497  	inputMessage := buildTestMessage(*chat)
   498  	_, err = alice.SendChatMessage(context.Background(), inputMessage)
   499  	s.Require().NoError(err)
   500  
   501  	// We check that alice retrieves the info from the server
   502  	var info []*pushnotificationclient.PushNotificationInfo
   503  	err = tt.RetryWithBackOff(func() error {
   504  		_, err = server.RetrieveAll()
   505  		if err != nil {
   506  			return err
   507  		}
   508  		_, err = alice.RetrieveAll()
   509  		if err != nil {
   510  			return err
   511  		}
   512  
   513  		info, err = alice.pushNotificationClient.GetPushNotificationInfo(&bob.identity.PublicKey, bobInstallationIDs)
   514  		if err != nil {
   515  			return err
   516  		}
   517  		// Check we have replies for bob
   518  		if len(info) != 1 {
   519  			return errors.New("info not fetched")
   520  		}
   521  		return nil
   522  
   523  	})
   524  	s.Require().NoError(err)
   525  
   526  	s.Require().NotNil(info)
   527  	s.Require().Equal(bob.installationID, info[0].InstallationID)
   528  	s.Require().Equal(bobServers[0].AccessToken, info[0].AccessToken)
   529  	s.Require().Equal(&bob.identity.PublicKey, info[0].PublicKey)
   530  
   531  	// The message has been sent, but not received, now we remove a contact so that the token is invalidated
   532  	frankContact = &Contact{
   533  		ID:      types.EncodeHex(crypto.FromECDSAPub(&frank.identity.PublicKey)),
   534  		EnsName: "Some Contact",
   535  	}
   536  	_, err = bob.RemoveContact(context.Background(), frankContact.ID)
   537  	s.Require().NoError(err)
   538  
   539  	// Re-registration should be triggered, pull from server and bob to check we are correctly registered
   540  	// Pull servers  and check we registered
   541  	err = tt.RetryWithBackOff(func() error {
   542  		_, err = server.RetrieveAll()
   543  		if err != nil {
   544  			return err
   545  		}
   546  		_, err = bob.RetrieveAll()
   547  		if err != nil {
   548  			return err
   549  		}
   550  		registered, err := bob.RegisteredForPushNotifications()
   551  		if err != nil {
   552  			return err
   553  		}
   554  		if !registered {
   555  			return errors.New("not registered")
   556  		}
   557  		return nil
   558  	})
   559  
   560  	newBobServers, err := bob.GetPushNotificationsServers()
   561  	s.Require().NoError(err)
   562  	// Make sure access token is not the same
   563  	s.Require().NotEqual(newBobServers[0].AccessToken, bobServers[0].AccessToken)
   564  
   565  	// Send another message, here the token will not be valid
   566  	inputMessage = buildTestMessage(*chat)
   567  	response, err := alice.SendChatMessage(context.Background(), inputMessage)
   568  	s.Require().NoError(err)
   569  	messageIDString := response.Messages()[0].ID
   570  	messageID, err := hex.DecodeString(messageIDString[2:])
   571  	s.Require().NoError(err)
   572  
   573  	err = tt.RetryWithBackOff(func() error {
   574  		_, err = server.RetrieveAll()
   575  		if err != nil {
   576  			return err
   577  		}
   578  		_, err = alice.RetrieveAll()
   579  		if err != nil {
   580  			return err
   581  		}
   582  
   583  		info, err = alice.pushNotificationClient.GetPushNotificationInfo(&bob.identity.PublicKey, bobInstallationIDs)
   584  		if err != nil {
   585  			return err
   586  		}
   587  		// Check we have replies for bob
   588  		if len(info) != 1 {
   589  			return errors.New("info not fetched")
   590  		}
   591  		if newBobServers[0].AccessToken != info[0].AccessToken {
   592  			return errors.New("still using the old access token")
   593  		}
   594  		return nil
   595  
   596  	})
   597  	s.Require().NoError(err)
   598  
   599  	s.Require().NotNil(info)
   600  	s.Require().Equal(bob.installationID, info[0].InstallationID)
   601  	s.Require().Equal(newBobServers[0].AccessToken, info[0].AccessToken)
   602  	s.Require().Equal(&bob.identity.PublicKey, info[0].PublicKey)
   603  
   604  	retrievedNotificationInfo, err := alice.pushNotificationClient.GetPushNotificationInfo(&bob.identity.PublicKey, bobInstallationIDs)
   605  	s.Require().NoError(err)
   606  	s.Require().NotNil(retrievedNotificationInfo)
   607  	s.Require().Len(retrievedNotificationInfo, 1)
   608  
   609  	var sentNotification *pushnotificationclient.SentNotification
   610  	err = tt.RetryWithBackOff(func() error {
   611  		_, err = server.RetrieveAll()
   612  		if err != nil {
   613  			return err
   614  		}
   615  		_, err = alice.RetrieveAll()
   616  		if err != nil {
   617  			return err
   618  		}
   619  		sentNotification, err = alice.pushNotificationClient.GetSentNotification(common.HashPublicKey(&bob.identity.PublicKey), bob.installationID, messageID)
   620  		if err != nil {
   621  			return err
   622  		}
   623  		if sentNotification == nil {
   624  			return errors.New("sent notification not found")
   625  		}
   626  		if !sentNotification.Success {
   627  			return errors.New("sent notification not successul")
   628  		}
   629  		return nil
   630  	})
   631  
   632  	s.Require().NoError(err)
   633  }
   634  
   635  func (s *MessengerPushNotificationSuite) TestContactCode() {
   636  
   637  	bob1 := s.m
   638  
   639  	serverKey, err := crypto.GenerateKey()
   640  	s.Require().NoError(err)
   641  	server := s.newPushNotificationServer(s.shh, serverKey)
   642  	defer TearDownMessenger(&s.Suite, server)
   643  
   644  	alice := s.newMessenger(s.shh)
   645  	s.Require().NoError(err)
   646  	defer TearDownMessenger(&s.Suite, alice)
   647  	s.Require().NoError(alice.EnableSendingPushNotifications())
   648  
   649  	// Register bob1
   650  	err = bob1.AddPushNotificationsServer(context.Background(), &server.identity.PublicKey, pushnotificationclient.ServerTypeCustom)
   651  	s.Require().NoError(err)
   652  
   653  	err = bob1.RegisterForPushNotifications(context.Background(), bob1DeviceToken, testAPNTopic, protobuf.PushNotificationRegistration_APN_TOKEN)
   654  
   655  	// Pull servers  and check we registered
   656  	err = tt.RetryWithBackOff(func() error {
   657  		_, err = server.RetrieveAll()
   658  		if err != nil {
   659  			return err
   660  		}
   661  		_, err = bob1.RetrieveAll()
   662  		if err != nil {
   663  			return err
   664  		}
   665  		registered, err := bob1.RegisteredForPushNotifications()
   666  		if err != nil {
   667  			return err
   668  		}
   669  		if !registered {
   670  			return errors.New("not registered")
   671  		}
   672  		bobServers, err := bob1.GetPushNotificationsServers()
   673  		if err != nil {
   674  			return err
   675  		}
   676  
   677  		if len(bobServers) == 0 {
   678  			return errors.New("not registered")
   679  		}
   680  
   681  		return nil
   682  	})
   683  	// Make sure we receive it
   684  	s.Require().NoError(err)
   685  
   686  	contactCodeAdvertisement, err := bob1.buildContactCodeAdvertisement()
   687  	s.Require().NoError(err)
   688  	s.Require().NotNil(contactCodeAdvertisement)
   689  
   690  	s.Require().NoError(alice.pushNotificationClient.HandleContactCodeAdvertisement(&bob1.identity.PublicKey, contactCodeAdvertisement))
   691  
   692  }
   693  
   694  func (s *MessengerPushNotificationSuite) TestReceivePushNotificationMention() {
   695  
   696  	bob := s.m
   697  
   698  	serverKey, err := crypto.GenerateKey()
   699  	s.Require().NoError(err)
   700  	server := s.newPushNotificationServer(s.shh, serverKey)
   701  	defer TearDownMessenger(&s.Suite, server)
   702  
   703  	alice := s.newMessenger(s.shh)
   704  	s.Require().NoError(err)
   705  	defer TearDownMessenger(&s.Suite, alice)
   706  	s.Require().NoError(alice.EnableSendingPushNotifications())
   707  	bobInstallationIDs := []string{bob.installationID}
   708  
   709  	// Create public chat and join for both alice and bob
   710  	chat := CreatePublicChat("status", s.m.transport)
   711  	err = bob.SaveChat(chat)
   712  	s.Require().NoError(err)
   713  
   714  	_, err = bob.Join(chat)
   715  	s.Require().NoError(err)
   716  
   717  	err = alice.SaveChat(chat)
   718  	s.Require().NoError(err)
   719  
   720  	_, err = alice.Join(chat)
   721  	s.Require().NoError(err)
   722  
   723  	// Register bob
   724  	err = bob.AddPushNotificationsServer(context.Background(), &server.identity.PublicKey, pushnotificationclient.ServerTypeCustom)
   725  	s.Require().NoError(err)
   726  
   727  	err = bob.RegisterForPushNotifications(context.Background(), bob1DeviceToken, testAPNTopic, protobuf.PushNotificationRegistration_APN_TOKEN)
   728  
   729  	// Pull servers  and check we registered
   730  	err = tt.RetryWithBackOff(func() error {
   731  		_, err = server.RetrieveAll()
   732  		if err != nil {
   733  			return err
   734  		}
   735  		_, err = bob.RetrieveAll()
   736  		if err != nil {
   737  			return err
   738  		}
   739  		registered, err := bob.RegisteredForPushNotifications()
   740  		if err != nil {
   741  			return err
   742  		}
   743  		if !registered {
   744  			return errors.New("not registered")
   745  		}
   746  
   747  		bobServers, err := bob.GetPushNotificationsServers()
   748  		if err != nil {
   749  			return err
   750  		}
   751  
   752  		if len(bobServers) == 0 {
   753  			return errors.New("not registered")
   754  		}
   755  
   756  		return nil
   757  	})
   758  	// Make sure we receive it
   759  	s.Require().NoError(err)
   760  	bobServers, err := bob.GetPushNotificationsServers()
   761  	s.Require().NoError(err)
   762  
   763  	inputMessage := buildTestMessage(*chat)
   764  	// message contains a mention
   765  	inputMessage.Text = "Hey @" + types.EncodeHex(crypto.FromECDSAPub(&bob.identity.PublicKey))
   766  	response, err := alice.SendChatMessage(context.Background(), inputMessage)
   767  	s.Require().NoError(err)
   768  	messageIDString := response.Messages()[0].ID
   769  	messageID, err := hex.DecodeString(messageIDString[2:])
   770  	s.Require().NoError(err)
   771  
   772  	var bobInfo []*pushnotificationclient.PushNotificationInfo
   773  	err = tt.RetryWithBackOff(func() error {
   774  		_, err = server.RetrieveAll()
   775  		if err != nil {
   776  			return err
   777  		}
   778  		_, err = alice.RetrieveAll()
   779  		if err != nil {
   780  			return err
   781  		}
   782  
   783  		bobInfo, err = alice.pushNotificationClient.GetPushNotificationInfo(&bob.identity.PublicKey, bobInstallationIDs)
   784  		if err != nil {
   785  			return err
   786  		}
   787  		// Check we have replies for bob
   788  		if len(bobInfo) != 1 {
   789  			return errors.New("info not fetched")
   790  		}
   791  		return nil
   792  
   793  	})
   794  
   795  	s.Require().NoError(err)
   796  
   797  	s.Require().NotEmpty(bobInfo)
   798  	s.Require().Equal(bob.installationID, bobInfo[0].InstallationID)
   799  	s.Require().Equal(bobServers[0].AccessToken, bobInfo[0].AccessToken)
   800  	s.Require().Equal(&bob.identity.PublicKey, bobInfo[0].PublicKey)
   801  
   802  	retrievedNotificationInfo, err := alice.pushNotificationClient.GetPushNotificationInfo(&bob.identity.PublicKey, bobInstallationIDs)
   803  
   804  	s.Require().NoError(err)
   805  	s.Require().NotNil(retrievedNotificationInfo)
   806  	s.Require().Len(retrievedNotificationInfo, 1)
   807  
   808  	var sentNotification *pushnotificationclient.SentNotification
   809  	err = tt.RetryWithBackOff(func() error {
   810  		_, err = server.RetrieveAll()
   811  		if err != nil {
   812  			return err
   813  		}
   814  		_, err = alice.RetrieveAll()
   815  		if err != nil {
   816  			return err
   817  		}
   818  		sentNotification, err = alice.pushNotificationClient.GetSentNotification(common.HashPublicKey(&bob.identity.PublicKey), bob.installationID, messageID)
   819  		if err != nil {
   820  			return err
   821  		}
   822  		if sentNotification == nil {
   823  			return errors.New("sent notification not found")
   824  		}
   825  		if !sentNotification.Success {
   826  			return errors.New("sent notification not successul")
   827  		}
   828  		return nil
   829  	})
   830  	s.Require().NoError(err)
   831  }
   832  
   833  func (s *MessengerPushNotificationSuite) TestReceivePushNotificationCommunityRequest() {
   834  
   835  	bob := s.m
   836  
   837  	serverKey, err := crypto.GenerateKey()
   838  	s.Require().NoError(err)
   839  	server := s.newPushNotificationServer(s.shh, serverKey)
   840  	defer TearDownMessenger(&s.Suite, server)
   841  
   842  	alice := s.newMessenger(s.shh)
   843  	s.Require().NoError(err)
   844  	defer TearDownMessenger(&s.Suite, alice)
   845  	s.Require().NoError(alice.EnableSendingPushNotifications())
   846  
   847  	// Register bob
   848  	err = bob.AddPushNotificationsServer(context.Background(), &server.identity.PublicKey, pushnotificationclient.ServerTypeCustom)
   849  	s.Require().NoError(err)
   850  
   851  	err = bob.RegisterForPushNotifications(context.Background(), bob1DeviceToken, testAPNTopic, protobuf.PushNotificationRegistration_APN_TOKEN)
   852  
   853  	// Pull servers  and check we registered
   854  	err = tt.RetryWithBackOff(func() error {
   855  		_, err = server.RetrieveAll()
   856  		if err != nil {
   857  			return err
   858  		}
   859  		_, err = bob.RetrieveAll()
   860  		if err != nil {
   861  			return err
   862  		}
   863  		registered, err := bob.RegisteredForPushNotifications()
   864  		if err != nil {
   865  			return err
   866  		}
   867  		if !registered {
   868  			return errors.New("not registered")
   869  		}
   870  
   871  		bobServers, err := bob.GetPushNotificationsServers()
   872  		if err != nil {
   873  			return err
   874  		}
   875  
   876  		if len(bobServers) == 0 {
   877  			return errors.New("not registered")
   878  		}
   879  
   880  		return nil
   881  	})
   882  	// Make sure we receive it
   883  	s.Require().NoError(err)
   884  	_, err = bob.GetPushNotificationsServers()
   885  	s.Require().NoError(err)
   886  
   887  	description := &requests.CreateCommunity{
   888  		Membership:  protobuf.CommunityPermissions_MANUAL_ACCEPT,
   889  		Name:        "status",
   890  		Color:       "#ffffff",
   891  		Description: "status community description",
   892  	}
   893  
   894  	response, err := bob.CreateCommunity(description, true)
   895  	s.Require().NoError(err)
   896  	s.Require().NotNil(response)
   897  	s.Require().Len(response.Communities(), 1)
   898  	community := response.Communities()[0]
   899  
   900  	// Send a community message
   901  	chat := CreateOneToOneChat(common.PubkeyToHex(&alice.identity.PublicKey), &alice.identity.PublicKey, alice.transport)
   902  
   903  	inputMessage := common.NewMessage()
   904  	inputMessage.ChatId = chat.ID
   905  	inputMessage.Text = "some text"
   906  	inputMessage.CommunityID = community.IDString()
   907  
   908  	err = bob.SaveChat(chat)
   909  	s.NoError(err)
   910  	_, err = bob.SendChatMessage(context.Background(), inputMessage)
   911  	s.NoError(err)
   912  
   913  	// Pull message and make sure org is received
   914  	err = tt.RetryWithBackOff(func() error {
   915  		response, err = alice.RetrieveAll()
   916  		if err != nil {
   917  			return err
   918  		}
   919  		if len(response.Communities()) == 0 {
   920  			return errors.New("community not received")
   921  		}
   922  		return nil
   923  	})
   924  
   925  	request := createRequestToJoinCommunity(&s.Suite, community.ID(), alice, alicePassword, []string{aliceAddress1})
   926  	alice.communitiesManager.PermissionChecker = &testPermissionChecker{}
   927  	// We try to join the org
   928  	response, err = alice.RequestToJoinCommunity(request)
   929  	s.Require().NoError(err)
   930  	s.Require().NotNil(response)
   931  	s.Require().Len(response.RequestsToJoinCommunity(), 1)
   932  
   933  	requestToJoin1 := response.RequestsToJoinCommunity()[0]
   934  	s.Require().NotNil(requestToJoin1)
   935  	s.Require().Equal(community.ID(), requestToJoin1.CommunityID)
   936  	s.Require().True(requestToJoin1.Our)
   937  	s.Require().NotEmpty(requestToJoin1.ID)
   938  	s.Require().NotEmpty(requestToJoin1.Clock)
   939  	s.Require().Equal(requestToJoin1.PublicKey, common.PubkeyToHex(&alice.identity.PublicKey))
   940  	s.Require().Equal(communities.RequestToJoinStatePending, requestToJoin1.State)
   941  
   942  	err = tt.RetryWithBackOff(func() error {
   943  		_, err = server.RetrieveAll()
   944  		if err != nil {
   945  			return err
   946  		}
   947  		_, err = alice.RetrieveAll()
   948  		if err != nil {
   949  			return err
   950  		}
   951  
   952  		if server.pushNotificationServer.SentRequests != 1 {
   953  			return errors.New("request not sent")
   954  		}
   955  
   956  		return nil
   957  
   958  	})
   959  
   960  	s.Require().NoError(err)
   961  
   962  }
   963  
   964  func (s *MessengerPushNotificationSuite) TestReceivePushNotificationPairedDevices() {
   965  
   966  	bob1 := s.m
   967  	bob2, err := newMessengerWithKey(s.shh, s.m.identity, s.logger, []Option{WithPushNotifications()})
   968  	s.Require().NoError(err)
   969  	defer TearDownMessenger(&s.Suite, bob2)
   970  
   971  	serverKey, err := crypto.GenerateKey()
   972  	s.Require().NoError(err)
   973  	server := s.newPushNotificationServer(s.shh, serverKey)
   974  	defer TearDownMessenger(&s.Suite, server)
   975  
   976  	alice := s.newMessenger(s.shh)
   977  	s.Require().NoError(err)
   978  	defer TearDownMessenger(&s.Suite, alice)
   979  	s.Require().NoError(alice.EnableSendingPushNotifications())
   980  	bobInstallationIDs := []string{bob1.installationID, bob2.installationID}
   981  
   982  	// Register bob1
   983  	err = bob1.AddPushNotificationsServer(context.Background(), &server.identity.PublicKey, pushnotificationclient.ServerTypeCustom)
   984  	s.Require().NoError(err)
   985  
   986  	err = bob1.RegisterForPushNotifications(context.Background(), bob1DeviceToken, testAPNTopic, protobuf.PushNotificationRegistration_APN_TOKEN)
   987  
   988  	// Pull servers  and check we registered
   989  	err = tt.RetryWithBackOff(func() error {
   990  		_, err = server.RetrieveAll()
   991  		if err != nil {
   992  			return err
   993  		}
   994  		_, err = bob1.RetrieveAll()
   995  		if err != nil {
   996  			return err
   997  		}
   998  		registered, err := bob1.RegisteredForPushNotifications()
   999  		if err != nil {
  1000  			return err
  1001  		}
  1002  		if !registered {
  1003  			return errors.New("not registered")
  1004  		}
  1005  		bobServers, err := bob1.GetPushNotificationsServers()
  1006  		if err != nil {
  1007  			return err
  1008  		}
  1009  
  1010  		if len(bobServers) == 0 {
  1011  			return errors.New("not registered")
  1012  		}
  1013  
  1014  		return nil
  1015  	})
  1016  	// Make sure we receive it
  1017  	s.Require().NoError(err)
  1018  	bob1Servers, err := bob1.GetPushNotificationsServers()
  1019  	s.Require().NoError(err)
  1020  
  1021  	// Register bob2
  1022  	err = bob2.AddPushNotificationsServer(context.Background(), &server.identity.PublicKey, pushnotificationclient.ServerTypeCustom)
  1023  	s.Require().NoError(err)
  1024  
  1025  	err = bob2.RegisterForPushNotifications(context.Background(), bob2DeviceToken, testAPNTopic, protobuf.PushNotificationRegistration_APN_TOKEN)
  1026  	s.Require().NoError(err)
  1027  
  1028  	err = tt.RetryWithBackOff(func() error {
  1029  		_, err = server.RetrieveAll()
  1030  		if err != nil {
  1031  			return err
  1032  		}
  1033  		_, err = bob2.RetrieveAll()
  1034  		if err != nil {
  1035  			return err
  1036  		}
  1037  
  1038  		registered, err := bob2.RegisteredForPushNotifications()
  1039  		if err != nil {
  1040  			return err
  1041  		}
  1042  		if !registered {
  1043  			return errors.New("not registered")
  1044  		}
  1045  		bobServers, err := bob2.GetPushNotificationsServers()
  1046  		if err != nil {
  1047  			return err
  1048  		}
  1049  
  1050  		if len(bobServers) == 0 {
  1051  			return errors.New("not registered")
  1052  		}
  1053  
  1054  		return nil
  1055  	})
  1056  	// Make sure we receive it
  1057  	s.Require().NoError(err)
  1058  	bob2Servers, err := bob2.GetPushNotificationsServers()
  1059  	s.Require().NoError(err)
  1060  
  1061  	// Create one to one chat & send message
  1062  	pkString := hex.EncodeToString(crypto.FromECDSAPub(&s.m.identity.PublicKey))
  1063  	chat := CreateOneToOneChat(pkString, &s.m.identity.PublicKey, alice.transport)
  1064  	s.Require().NoError(alice.SaveChat(chat))
  1065  	inputMessage := buildTestMessage(*chat)
  1066  	response, err := alice.SendChatMessage(context.Background(), inputMessage)
  1067  	s.Require().NoError(err)
  1068  	messageIDString := response.Messages()[0].ID
  1069  	messageID, err := hex.DecodeString(messageIDString[2:])
  1070  	s.Require().NoError(err)
  1071  
  1072  	infoMap := make(map[string]*pushnotificationclient.PushNotificationInfo)
  1073  	err = tt.RetryWithBackOff(func() error {
  1074  		_, err = server.RetrieveAll()
  1075  		if err != nil {
  1076  			return err
  1077  		}
  1078  		_, err = alice.RetrieveAll()
  1079  		if err != nil {
  1080  			return err
  1081  		}
  1082  
  1083  		info, err := alice.pushNotificationClient.GetPushNotificationInfo(&bob1.identity.PublicKey, bobInstallationIDs)
  1084  		if err != nil {
  1085  			return err
  1086  		}
  1087  		for _, i := range info {
  1088  			infoMap[i.AccessToken] = i
  1089  		}
  1090  
  1091  		// Check we have replies for both bob1 and bob2
  1092  		if len(infoMap) != 2 {
  1093  			return errors.New("info not fetched")
  1094  		}
  1095  		return nil
  1096  
  1097  	})
  1098  
  1099  	s.Require().Len(infoMap, 2)
  1100  
  1101  	// Check we have replies for both bob1 and bob2
  1102  	var bob1Info, bob2Info *pushnotificationclient.PushNotificationInfo
  1103  
  1104  	bob1Info = infoMap[bob1Servers[0].AccessToken]
  1105  	bob2Info = infoMap[bob2Servers[0].AccessToken]
  1106  
  1107  	s.Require().NotNil(bob1Info)
  1108  	s.Require().Equal(bob1.installationID, bob1Info.InstallationID)
  1109  	s.Require().Equal(bob1Servers[0].AccessToken, bob1Info.AccessToken)
  1110  	s.Require().Equal(&bob1.identity.PublicKey, bob1Info.PublicKey)
  1111  
  1112  	s.Require().NotNil(bob2Info)
  1113  	s.Require().Equal(bob2.installationID, bob2Info.InstallationID)
  1114  	s.Require().Equal(bob2Servers[0].AccessToken, bob2Info.AccessToken)
  1115  	s.Require().Equal(&bob2.identity.PublicKey, bob2Info.PublicKey)
  1116  
  1117  	retrievedNotificationInfo, err := alice.pushNotificationClient.GetPushNotificationInfo(&bob1.identity.PublicKey, bobInstallationIDs)
  1118  
  1119  	s.Require().NoError(err)
  1120  	s.Require().NotNil(retrievedNotificationInfo)
  1121  	s.Require().Len(retrievedNotificationInfo, 2)
  1122  
  1123  	var sentNotification *pushnotificationclient.SentNotification
  1124  	err = tt.RetryWithBackOff(func() error {
  1125  		_, err = server.RetrieveAll()
  1126  		if err != nil {
  1127  			return err
  1128  		}
  1129  		_, err = alice.RetrieveAll()
  1130  		if err != nil {
  1131  			return err
  1132  		}
  1133  		sentNotification, err = alice.pushNotificationClient.GetSentNotification(common.HashPublicKey(&bob1.identity.PublicKey), bob1.installationID, messageID)
  1134  		if err != nil {
  1135  			return err
  1136  		}
  1137  		if sentNotification == nil {
  1138  			return errors.New("sent notification not found")
  1139  		}
  1140  		if !sentNotification.Success {
  1141  			return errors.New("sent notification not successul")
  1142  		}
  1143  		return nil
  1144  	})
  1145  	s.Require().NoError(err)
  1146  }
  1147  
  1148  func (s *MessengerPushNotificationSuite) TestReceivePushNotificationReply() {
  1149  
  1150  	bob := s.m
  1151  
  1152  	serverKey, err := crypto.GenerateKey()
  1153  	s.Require().NoError(err)
  1154  	server := s.newPushNotificationServer(s.shh, serverKey)
  1155  	defer TearDownMessenger(&s.Suite, server)
  1156  
  1157  	alice := s.newMessenger(s.shh)
  1158  	s.Require().NoError(err)
  1159  	defer TearDownMessenger(&s.Suite, alice)
  1160  	s.Require().NoError(alice.EnableSendingPushNotifications())
  1161  	bobInstallationIDs := []string{bob.installationID}
  1162  
  1163  	// Create public chat and join for both alice and bob
  1164  	chat := CreatePublicChat("status", s.m.transport)
  1165  	err = bob.SaveChat(chat)
  1166  	s.Require().NoError(err)
  1167  
  1168  	_, err = bob.Join(chat)
  1169  	s.Require().NoError(err)
  1170  
  1171  	err = alice.SaveChat(chat)
  1172  	s.Require().NoError(err)
  1173  
  1174  	_, err = alice.Join(chat)
  1175  	s.Require().NoError(err)
  1176  
  1177  	// Register bob
  1178  	err = bob.AddPushNotificationsServer(context.Background(), &server.identity.PublicKey, pushnotificationclient.ServerTypeCustom)
  1179  	s.Require().NoError(err)
  1180  
  1181  	err = bob.RegisterForPushNotifications(context.Background(), bob1DeviceToken, testAPNTopic, protobuf.PushNotificationRegistration_APN_TOKEN)
  1182  
  1183  	// Pull servers  and check we registered
  1184  	err = tt.RetryWithBackOff(func() error {
  1185  		_, err = server.RetrieveAll()
  1186  		if err != nil {
  1187  			return err
  1188  		}
  1189  		_, err = bob.RetrieveAll()
  1190  		if err != nil {
  1191  			return err
  1192  		}
  1193  		registered, err := bob.RegisteredForPushNotifications()
  1194  		if err != nil {
  1195  			return err
  1196  		}
  1197  		if !registered {
  1198  			return errors.New("not registered")
  1199  		}
  1200  
  1201  		bobServers, err := bob.GetPushNotificationsServers()
  1202  		if err != nil {
  1203  			return err
  1204  		}
  1205  
  1206  		if len(bobServers) == 0 {
  1207  			return errors.New("not registered")
  1208  		}
  1209  
  1210  		return nil
  1211  	})
  1212  	// Make sure we receive it
  1213  	s.Require().NoError(err)
  1214  	bobServers, err := bob.GetPushNotificationsServers()
  1215  	s.Require().NoError(err)
  1216  
  1217  	firstMessage := buildTestMessage(*chat)
  1218  	firstMessage.Text = "Hello!"
  1219  	response, err := bob.SendChatMessage(context.Background(), firstMessage)
  1220  	s.Require().NoError(err)
  1221  	messageIDString := response.Messages()[0].ID
  1222  
  1223  	_, err = WaitOnMessengerResponse(
  1224  		alice,
  1225  		func(r *MessengerResponse) bool {
  1226  			for _, message := range r.Messages() {
  1227  				if message.ID == messageIDString {
  1228  					return true
  1229  				}
  1230  			}
  1231  			return false
  1232  
  1233  		},
  1234  		"no messages",
  1235  	)
  1236  
  1237  	replyMessage := buildTestMessage(*chat)
  1238  	replyMessage.Text = "Hello reply"
  1239  	replyMessage.ResponseTo = messageIDString
  1240  	response, err = alice.SendChatMessage(context.Background(), replyMessage)
  1241  	s.Require().NoError(err)
  1242  	messageIDString = response.Messages()[0].ID
  1243  	messageID, err := hex.DecodeString(messageIDString[2:])
  1244  	s.Require().NoError(err)
  1245  
  1246  	var bobInfo []*pushnotificationclient.PushNotificationInfo
  1247  	err = tt.RetryWithBackOff(func() error {
  1248  		_, err = server.RetrieveAll()
  1249  		if err != nil {
  1250  			return err
  1251  		}
  1252  		_, err = alice.RetrieveAll()
  1253  		if err != nil {
  1254  			return err
  1255  		}
  1256  
  1257  		bobInfo, err = alice.pushNotificationClient.GetPushNotificationInfo(&bob.identity.PublicKey, bobInstallationIDs)
  1258  		if err != nil {
  1259  			return err
  1260  		}
  1261  		// Check we have replies for bob
  1262  		if len(bobInfo) != 1 {
  1263  			return errors.New("info not fetched")
  1264  		}
  1265  		return nil
  1266  
  1267  	})
  1268  
  1269  	s.Require().NoError(err)
  1270  
  1271  	s.Require().NotEmpty(bobInfo)
  1272  	s.Require().Equal(bob.installationID, bobInfo[0].InstallationID)
  1273  	s.Require().Equal(bobServers[0].AccessToken, bobInfo[0].AccessToken)
  1274  	s.Require().Equal(&bob.identity.PublicKey, bobInfo[0].PublicKey)
  1275  
  1276  	retrievedNotificationInfo, err := alice.pushNotificationClient.GetPushNotificationInfo(&bob.identity.PublicKey, bobInstallationIDs)
  1277  
  1278  	s.Require().NoError(err)
  1279  	s.Require().NotNil(retrievedNotificationInfo)
  1280  	s.Require().Len(retrievedNotificationInfo, 1)
  1281  
  1282  	var sentNotification *pushnotificationclient.SentNotification
  1283  	err = tt.RetryWithBackOff(func() error {
  1284  		_, err = server.RetrieveAll()
  1285  		if err != nil {
  1286  			return err
  1287  		}
  1288  		_, err = alice.RetrieveAll()
  1289  		if err != nil {
  1290  			return err
  1291  		}
  1292  		sentNotification, err = alice.pushNotificationClient.GetSentNotification(common.HashPublicKey(&bob.identity.PublicKey), bob.installationID, messageID)
  1293  		if err != nil {
  1294  			return err
  1295  		}
  1296  		if sentNotification == nil {
  1297  			return errors.New("sent notification not found")
  1298  		}
  1299  		if !sentNotification.Success {
  1300  			return errors.New("sent notification not successul")
  1301  		}
  1302  		return nil
  1303  	})
  1304  	s.Require().NoError(err)
  1305  }