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

     1  package protocol
     2  
     3  import (
     4  	"context"
     5  	"encoding/hex"
     6  	"encoding/json"
     7  	"errors"
     8  	"fmt"
     9  	"io"
    10  	"math/big"
    11  	"os"
    12  	"strings"
    13  	"testing"
    14  	"time"
    15  
    16  	_ "github.com/mutecomm/go-sqlcipher/v4" // require go-sqlcipher that overrides default implementation
    17  	"github.com/stretchr/testify/suite"
    18  	"go.uber.org/zap"
    19  
    20  	"github.com/status-im/status-go/deprecation"
    21  	coretypes "github.com/status-im/status-go/eth-node/core/types"
    22  	"github.com/status-im/status-go/eth-node/crypto"
    23  	"github.com/status-im/status-go/eth-node/types"
    24  	enstypes "github.com/status-im/status-go/eth-node/types/ens"
    25  	"github.com/status-im/status-go/images"
    26  	"github.com/status-im/status-go/multiaccounts/settings"
    27  	"github.com/status-im/status-go/protocol/common"
    28  	"github.com/status-im/status-go/protocol/protobuf"
    29  	"github.com/status-im/status-go/protocol/requests"
    30  	"github.com/status-im/status-go/protocol/tt"
    31  	v1protocol "github.com/status-im/status-go/protocol/v1"
    32  	"github.com/status-im/status-go/server"
    33  )
    34  
    35  const (
    36  	testPK              = "0x0424a68f89ba5fcd5e0640c1e1f591d561fa4125ca4e2a43592bc4123eca10ce064e522c254bb83079ba404327f6eafc01ec90a1444331fe769d3f3a7f90b0dde1"
    37  	testPublicChatID    = "super-chat"
    38  	testContract        = "0x314159265dd8dbb310642f98f50c066173c1259b"
    39  	testValue           = "2000"
    40  	testTransactionHash = "0x412a851ac2ae51cad34a56c8a9cfee55d577ac5e1ac71cf488a2f2093a373799"
    41  	newEnsName          = "new-name"
    42  )
    43  
    44  func TestMessengerSuite(t *testing.T) {
    45  	suite.Run(t, new(MessengerSuite))
    46  }
    47  
    48  type MessengerSuite struct {
    49  	MessengerBaseTestSuite
    50  }
    51  
    52  type testNode struct {
    53  	shh types.Waku
    54  }
    55  
    56  func (n *testNode) NewENSVerifier(_ *zap.Logger) enstypes.ENSVerifier {
    57  	panic("not implemented")
    58  }
    59  
    60  func (n *testNode) AddPeer(_ string) error {
    61  	panic("not implemented")
    62  }
    63  
    64  func (n *testNode) RemovePeer(_ string) error {
    65  	panic("not implemented")
    66  }
    67  
    68  func (n *testNode) GetWaku(_ interface{}) (types.Waku, error) {
    69  	return n.shh, nil
    70  }
    71  
    72  func (n *testNode) GetWakuV2(_ interface{}) (types.Waku, error) {
    73  	return nil, errors.New("No waku v2 support")
    74  }
    75  
    76  func (n *testNode) GetWhisper(_ interface{}) (types.Whisper, error) {
    77  	return nil, nil
    78  }
    79  
    80  func (n *testNode) PeersCount() int {
    81  	return 1
    82  }
    83  
    84  func (s *MessengerSuite) TestInitFilters() {
    85  	testCases := []struct {
    86  		Name         string
    87  		Prep         func()
    88  		AddedFilters int
    89  	}{
    90  		{
    91  			Name:         "no chats and contacts",
    92  			Prep:         func() {},
    93  			AddedFilters: 3,
    94  		},
    95  		{
    96  			Name: "active public chat",
    97  			Prep: func() {
    98  				publicChat := Chat{
    99  					ChatType: ChatTypePublic,
   100  					ID:       "some-public-chat",
   101  					Active:   true,
   102  				}
   103  				err := s.m.SaveChat(&publicChat)
   104  				s.Require().NoError(err)
   105  			},
   106  			AddedFilters: 1,
   107  		},
   108  		{
   109  			Name: "active one-to-one chat",
   110  			Prep: func() {
   111  				key, err := crypto.GenerateKey()
   112  				s.Require().NoError(err)
   113  				privateChat := Chat{
   114  					ID:       types.EncodeHex(crypto.FromECDSAPub(&key.PublicKey)),
   115  					ChatType: ChatTypeOneToOne,
   116  					Active:   true,
   117  				}
   118  				err = s.m.SaveChat(&privateChat)
   119  				s.Require().NoError(err)
   120  			},
   121  			AddedFilters: 1,
   122  		},
   123  		{
   124  			Name: "active group chat",
   125  			Prep: func() {
   126  				key1, err := crypto.GenerateKey()
   127  				s.Require().NoError(err)
   128  				key2, err := crypto.GenerateKey()
   129  				s.Require().NoError(err)
   130  				groupChat := Chat{
   131  					ID:       "some-id",
   132  					ChatType: ChatTypePrivateGroupChat,
   133  					Active:   true,
   134  					Members: []ChatMember{
   135  						{
   136  							ID: types.EncodeHex(crypto.FromECDSAPub(&key1.PublicKey)),
   137  						},
   138  						{
   139  							ID: types.EncodeHex(crypto.FromECDSAPub(&key2.PublicKey)),
   140  						},
   141  					},
   142  				}
   143  				err = s.m.SaveChat(&groupChat)
   144  				s.Require().NoError(err)
   145  			},
   146  			AddedFilters: 2,
   147  		},
   148  		{
   149  			Name: "inactive chat",
   150  			Prep: func() {
   151  				publicChat := Chat{
   152  					ChatType: ChatTypePublic,
   153  					ID:       "some-public-chat-2",
   154  					Active:   false,
   155  				}
   156  				err := s.m.SaveChat(&publicChat)
   157  				s.Require().NoError(err)
   158  			},
   159  			AddedFilters: 0,
   160  		},
   161  		{
   162  			Name: "added contact",
   163  			Prep: func() {
   164  				key, err := crypto.GenerateKey()
   165  				s.Require().NoError(err)
   166  				_, err = s.m.AddContact(context.Background(), &requests.AddContact{ID: types.EncodeHex(crypto.FromECDSAPub(&key.PublicKey))})
   167  				s.Require().NoError(err)
   168  			},
   169  			AddedFilters: deprecation.AddProfileFiltersCount(1),
   170  		},
   171  	}
   172  
   173  	expectedFilters := 0
   174  	for _, tc := range testCases {
   175  		s.Run(tc.Name, func() {
   176  			tc.Prep()
   177  			err := s.m.InitFilters()
   178  			s.Require().NoError(err)
   179  			filters := s.m.transport.Filters()
   180  			expectedFilters += tc.AddedFilters
   181  			s.Equal(deprecation.AddTimelineFiltersCount(expectedFilters), len(filters))
   182  		})
   183  	}
   184  }
   185  
   186  func buildAudioMessage(s *MessengerSuite, chat Chat) *common.Message {
   187  	clock, timestamp := chat.NextClockAndTimestamp(&testTimeSource{})
   188  	message := common.NewMessage()
   189  	message.Text = "text-input-message"
   190  	message.ChatId = chat.ID
   191  	message.Clock = clock
   192  	message.Timestamp = timestamp
   193  	message.WhisperTimestamp = clock
   194  	message.LocalChatID = chat.ID
   195  	message.MessageType = protobuf.MessageType_PUBLIC_GROUP
   196  	message.ContentType = protobuf.ChatMessage_AUDIO
   197  	message.Payload = &protobuf.ChatMessage_Audio{
   198  		Audio: &protobuf.AudioMessage{
   199  			Type:    1,
   200  			Payload: []byte("some-payload"),
   201  		},
   202  	}
   203  
   204  	return message
   205  }
   206  
   207  func buildTestMessage(chat Chat) *common.Message {
   208  	clock, timestamp := chat.NextClockAndTimestamp(&testTimeSource{})
   209  	message := common.NewMessage()
   210  	message.Text = "text-input-message"
   211  	message.ChatId = chat.ID
   212  	message.Clock = clock
   213  	message.Timestamp = timestamp
   214  	message.WhisperTimestamp = clock
   215  	message.LocalChatID = chat.ID
   216  	message.ContentType = protobuf.ChatMessage_TEXT_PLAIN
   217  	switch chat.ChatType {
   218  	case ChatTypePublic, ChatTypeProfile:
   219  		message.MessageType = protobuf.MessageType_PUBLIC_GROUP
   220  	case ChatTypeOneToOne:
   221  		message.MessageType = protobuf.MessageType_ONE_TO_ONE
   222  	case ChatTypePrivateGroupChat:
   223  		message.MessageType = protobuf.MessageType_PRIVATE_GROUP
   224  	}
   225  
   226  	return message
   227  }
   228  
   229  func buildTestGapMessage(chat Chat) *common.Message {
   230  	clock, timestamp := chat.NextClockAndTimestamp(&testTimeSource{})
   231  	message := common.NewMessage()
   232  	message.ChatId = chat.ID
   233  	message.Clock = clock
   234  	message.Timestamp = timestamp
   235  	message.WhisperTimestamp = clock
   236  	message.LocalChatID = chat.ID
   237  	message.ContentType = protobuf.ChatMessage_SYSTEM_MESSAGE_GAP
   238  	switch chat.ChatType {
   239  	case ChatTypePublic, ChatTypeProfile:
   240  		message.MessageType = protobuf.MessageType_PUBLIC_GROUP
   241  	case ChatTypeOneToOne:
   242  		message.MessageType = protobuf.MessageType_ONE_TO_ONE
   243  	case ChatTypePrivateGroupChat:
   244  		message.MessageType = protobuf.MessageType_PRIVATE_GROUP
   245  	}
   246  
   247  	return message
   248  }
   249  
   250  func (s *MessengerSuite) TestMarkMessagesSeen() {
   251  	chat := CreatePublicChat("test-chat", s.m.transport)
   252  	chat.UnviewedMessagesCount = 2
   253  	chat.UnviewedMentionsCount = 3
   254  	chat.Highlight = true
   255  	err := s.m.SaveChat(chat)
   256  	s.Require().NoError(err)
   257  	inputMessage1 := buildTestMessage(*chat)
   258  	inputMessage1.ID = "1"
   259  	inputMessage1.Seen = false
   260  	inputMessage1.Text = "hey @" + common.PubkeyToHex(&s.m.identity.PublicKey)
   261  	inputMessage1.Mentioned = true
   262  	inputMessage2 := buildTestMessage(*chat)
   263  	inputMessage2.ID = "2"
   264  	inputMessage2.Text = "hey @" + common.PubkeyToHex(&s.m.identity.PublicKey)
   265  	inputMessage2.Mentioned = true
   266  	inputMessage2.Seen = false
   267  
   268  	err = s.m.SaveMessages([]*common.Message{inputMessage1, inputMessage2})
   269  	s.Require().NoError(err)
   270  
   271  	response, err := s.m.MarkMessagesRead(chat.ID, []string{inputMessage1.ID})
   272  	s.Require().NoError(err)
   273  
   274  	s.Require().Len(response.GetSeenAndUnseenMessages(), 1)
   275  	s.Require().Equal(chat.ID, response.GetSeenAndUnseenMessages()[0].ChatID)
   276  	s.Require().Equal(uint64(1), response.GetSeenAndUnseenMessages()[0].Count)
   277  	s.Require().Equal(uint64(1), response.GetSeenAndUnseenMessages()[0].CountWithMentions)
   278  	s.Require().Equal(true, response.GetSeenAndUnseenMessages()[0].Seen)
   279  	s.Require().Len(response.ActivityCenterNotifications(), 0)
   280  
   281  	// Make sure that if it's not seen, it does not return a count of 1
   282  	response, err = s.m.MarkMessagesRead(chat.ID, []string{inputMessage1.ID})
   283  	s.Require().NoError(err)
   284  	s.Require().Len(response.GetSeenAndUnseenMessages(), 1)
   285  	s.Require().Equal(chat.ID, response.GetSeenAndUnseenMessages()[0].ChatID)
   286  	s.Require().Equal(uint64(0), response.GetSeenAndUnseenMessages()[0].Count)
   287  	s.Require().Equal(uint64(0), response.GetSeenAndUnseenMessages()[0].CountWithMentions)
   288  	s.Require().Equal(true, response.GetSeenAndUnseenMessages()[0].Seen)
   289  	s.Require().Len(response.ActivityCenterNotifications(), 0)
   290  
   291  	chats := s.m.Chats()
   292  	for _, c := range chats {
   293  		if c.ID == chat.ID {
   294  			s.Require().Equal(uint(1), c.UnviewedMessagesCount)
   295  			s.Require().Equal(uint(1), c.UnviewedMentionsCount)
   296  			s.Require().Equal(false, c.Highlight)
   297  		}
   298  	}
   299  }
   300  
   301  func (s *MessengerSuite) TestMarkAllRead() {
   302  	chat := CreatePublicChat("test-chat", s.m.transport)
   303  	chat.UnviewedMessagesCount = 2
   304  	chat.Highlight = true
   305  	err := s.m.SaveChat(chat)
   306  	s.Require().NoError(err)
   307  	inputMessage1 := buildTestMessage(*chat)
   308  	inputMessage1.ID = "1"
   309  	inputMessage1.Seen = false
   310  	inputMessage2 := buildTestMessage(*chat)
   311  	inputMessage2.ID = "2"
   312  	inputMessage2.Seen = false
   313  
   314  	err = s.m.SaveMessages([]*common.Message{inputMessage1, inputMessage2})
   315  	s.Require().NoError(err)
   316  
   317  	_, err = s.m.MarkAllRead(context.Background(), chat.ID)
   318  	s.Require().NoError(err)
   319  
   320  	chats := s.m.Chats()
   321  	s.Require().Len(chats, deprecation.AddChatsCount(1))
   322  	for idx := range chats {
   323  		if chats[idx].ID == chat.ID {
   324  			s.Require().Equal(uint(0), chats[idx].UnviewedMessagesCount)
   325  			s.Require().Equal(false, chats[idx].Highlight)
   326  		}
   327  	}
   328  }
   329  
   330  func (s *MessengerSuite) TestSendPublic() {
   331  	chat := CreatePublicChat("test-chat", s.m.transport)
   332  	chat.LastClockValue = uint64(100000000000000)
   333  	err := s.m.SaveChat(chat)
   334  	s.NoError(err)
   335  	inputMessage := buildTestMessage(*chat)
   336  	response, err := s.m.SendChatMessage(context.Background(), inputMessage)
   337  	s.NoError(err)
   338  
   339  	s.Require().Equal(1, len(response.Messages()), "it returns the message")
   340  	outputMessage := response.Messages()[0]
   341  
   342  	s.Require().Equal(uint64(100000000000001), outputMessage.Clock, "it correctly sets the clock")
   343  	s.Require().Equal(uint64(100000000000001), chat.LastClockValue, "it correctly sets the last-clock-value")
   344  	s.Require().NotEqual(uint64(0), chat.Timestamp, "it sets the timestamp")
   345  	s.Require().Equal("0x"+hex.EncodeToString(crypto.FromECDSAPub(&s.privateKey.PublicKey)), outputMessage.From, "it sets the From field")
   346  	s.Require().True(outputMessage.Seen, "it marks the message as seen")
   347  	s.Require().Equal(outputMessage.OutgoingStatus, common.OutgoingStatusSending, "it marks the message as sending")
   348  	s.Require().NotEmpty(outputMessage.ID, "it sets the ID field")
   349  	s.Require().Equal(protobuf.MessageType_PUBLIC_GROUP, outputMessage.MessageType)
   350  
   351  	savedMessages, _, err := s.m.MessageByChatID(chat.ID, "", 10)
   352  	s.Require().NoError(err)
   353  	s.Require().Equal(1, len(savedMessages), "it saves the message")
   354  }
   355  
   356  func (s *MessengerSuite) TestSendProfile() {
   357  	// Early exit to skip testing deprecated code
   358  	if deprecation.ChatProfileDeprecated {
   359  		return
   360  	}
   361  
   362  	chat := CreateProfileChat("0x"+hex.EncodeToString(crypto.FromECDSAPub(&s.privateKey.PublicKey)), s.m.transport)
   363  	chat.LastClockValue = uint64(100000000000000)
   364  	err := s.m.SaveChat(chat)
   365  	s.NoError(err)
   366  	inputMessage := buildTestMessage(*chat)
   367  	response, err := s.m.SendChatMessage(context.Background(), inputMessage)
   368  	s.NoError(err)
   369  
   370  	s.Require().Equal(1, len(response.Messages()), "it returns the message")
   371  	outputMessage := response.Messages()[0]
   372  
   373  	s.Require().Equal(uint64(100000000000001), outputMessage.Clock, "it correctly sets the clock")
   374  	s.Require().Equal(uint64(100000000000001), chat.LastClockValue, "it correctly sets the last-clock-value")
   375  	s.Require().NotEqual(uint64(0), chat.Timestamp, "it sets the timestamp")
   376  	s.Require().Equal("0x"+hex.EncodeToString(crypto.FromECDSAPub(&s.privateKey.PublicKey)), outputMessage.From, "it sets the From field")
   377  	s.Require().Equal(chat.Profile, outputMessage.From, "From equal to chat Profile")
   378  	s.Require().True(outputMessage.Seen, "it marks the message as seen")
   379  	s.Require().Equal(outputMessage.OutgoingStatus, common.OutgoingStatusSending, "it marks the message as sending")
   380  	s.Require().NotEmpty(outputMessage.ID, "it sets the ID field")
   381  	s.Require().Equal(protobuf.MessageType_PUBLIC_GROUP, outputMessage.MessageType)
   382  
   383  	savedMessages, _, err := s.m.MessageByChatID(chat.ID, "", 10)
   384  	s.Require().NoError(err)
   385  	s.Require().Equal(1, len(savedMessages), "it saves the message")
   386  }
   387  
   388  func (s *MessengerSuite) TestSendPrivateOneToOne() {
   389  	recipientKey, err := crypto.GenerateKey()
   390  	s.NoError(err)
   391  	pkString := hex.EncodeToString(crypto.FromECDSAPub(&recipientKey.PublicKey))
   392  	chat := CreateOneToOneChat(pkString, &recipientKey.PublicKey, s.m.transport)
   393  
   394  	inputMessage := common.NewMessage()
   395  	inputMessage.ChatId = chat.ID
   396  	chat.LastClockValue = uint64(100000000000000)
   397  	err = s.m.SaveChat(chat)
   398  	s.NoError(err)
   399  	response, err := s.m.SendChatMessage(context.Background(), inputMessage)
   400  	s.NoError(err)
   401  	s.Require().Equal(1, len(response.Messages()), "it returns the message")
   402  	outputMessage := response.Messages()[0]
   403  
   404  	s.Require().Equal(uint64(100000000000001), outputMessage.Clock, "it correctly sets the clock")
   405  	s.Require().Equal(uint64(100000000000001), chat.LastClockValue, "it correctly sets the last-clock-value")
   406  
   407  	s.Require().NotEqual(uint64(0), chat.Timestamp, "it sets the timestamp")
   408  	s.Require().Equal("0x"+hex.EncodeToString(crypto.FromECDSAPub(&s.privateKey.PublicKey)), outputMessage.From, "it sets the From field")
   409  	s.Require().True(outputMessage.Seen, "it marks the message as seen")
   410  	s.Require().Equal(outputMessage.OutgoingStatus, common.OutgoingStatusSending, "it marks the message as sending")
   411  	s.Require().NotEmpty(outputMessage.ID, "it sets the ID field")
   412  	s.Require().Equal(protobuf.MessageType_ONE_TO_ONE, outputMessage.MessageType)
   413  }
   414  
   415  func (s *MessengerSuite) TestSendPrivateGroup() {
   416  	response, err := s.m.CreateGroupChatWithMembers(context.Background(), "test", []string{})
   417  	s.NoError(err)
   418  	s.Require().Len(response.Chats(), 1)
   419  
   420  	chat := response.Chats()[0]
   421  	key, err := crypto.GenerateKey()
   422  	s.NoError(err)
   423  
   424  	s.Require().NoError(makeMutualContact(s.m, &key.PublicKey))
   425  
   426  	members := []string{"0x" + hex.EncodeToString(crypto.FromECDSAPub(&key.PublicKey))}
   427  	_, err = s.m.AddMembersToGroupChat(context.Background(), chat.ID, members)
   428  	s.NoError(err)
   429  
   430  	inputMessage := common.NewMessage()
   431  	inputMessage.ChatId = chat.ID
   432  	chat.LastClockValue = uint64(100000000000000)
   433  	err = s.m.SaveChat(chat)
   434  	s.NoError(err)
   435  	response, err = s.m.SendChatMessage(context.Background(), inputMessage)
   436  	s.Require().NoError(err)
   437  	s.Require().Equal(1, len(response.Messages()), "it returns the message")
   438  	outputMessage := response.Messages()[0]
   439  
   440  	s.Require().Equal(uint64(100000000000001), outputMessage.Clock, "it correctly sets the clock")
   441  	s.Require().Equal(uint64(100000000000001), chat.LastClockValue, "it correctly sets the last-clock-value")
   442  
   443  	s.Require().NotEqual(uint64(0), chat.Timestamp, "it sets the timestamp")
   444  	s.Require().Equal("0x"+hex.EncodeToString(crypto.FromECDSAPub(&s.privateKey.PublicKey)), outputMessage.From, "it sets the From field")
   445  	s.Require().True(outputMessage.Seen, "it marks the message as seen")
   446  	s.Require().Equal(outputMessage.OutgoingStatus, common.OutgoingStatusSending, "it marks the message as sending")
   447  	s.Require().NotEmpty(outputMessage.ID, "it sets the ID field")
   448  	s.Require().Equal(protobuf.MessageType_PRIVATE_GROUP, outputMessage.MessageType)
   449  }
   450  
   451  func (s *MessengerSuite) TestSendPrivateEmptyGroup() {
   452  	response, err := s.m.CreateGroupChatWithMembers(context.Background(), "test", []string{})
   453  	s.NoError(err)
   454  	s.Require().Len(response.Chats(), 1)
   455  
   456  	chat := response.Chats()[0]
   457  
   458  	inputMessage := common.NewMessage()
   459  	inputMessage.ChatId = chat.ID
   460  	chat.LastClockValue = uint64(100000000000000)
   461  	err = s.m.SaveChat(chat)
   462  	s.NoError(err)
   463  	response, err = s.m.SendChatMessage(context.Background(), inputMessage)
   464  	s.NoError(err)
   465  	s.Require().Equal(1, len(response.Messages()), "it returns the message")
   466  	outputMessage := response.Messages()[0]
   467  
   468  	s.Require().Equal(uint64(100000000000001), outputMessage.Clock, "it correctly sets the clock")
   469  	s.Require().Equal(uint64(100000000000001), chat.LastClockValue, "it correctly sets the last-clock-value")
   470  
   471  	s.Require().NotEqual(uint64(0), chat.Timestamp, "it sets the timestamp")
   472  	s.Require().Equal("0x"+hex.EncodeToString(crypto.FromECDSAPub(&s.privateKey.PublicKey)), outputMessage.From, "it sets the From field")
   473  	s.Require().True(outputMessage.Seen, "it marks the message as seen")
   474  	s.Require().Equal(outputMessage.OutgoingStatus, common.OutgoingStatusSent, "it marks the message as sent")
   475  	s.Require().NotEmpty(outputMessage.ID, "it sets the ID field")
   476  	s.Require().Equal(protobuf.MessageType_PRIVATE_GROUP, outputMessage.MessageType)
   477  }
   478  
   479  // Make sure public messages sent by us are not
   480  func (s *MessengerSuite) TestRetrieveOwnPublic() {
   481  	chat := CreatePublicChat("status", s.m.transport)
   482  	err := s.m.SaveChat(chat)
   483  	s.NoError(err)
   484  	// Right-to-left text
   485  	text := "پيل اندر خانه يي تاريک بود عرضه را آورده بودندش هنود  i\nاز براي ديدنش مردم بسي اندر آن ظلمت همي شد هر کسي"
   486  
   487  	inputMessage := buildTestMessage(*chat)
   488  	inputMessage.ChatId = chat.ID
   489  	inputMessage.Text = text
   490  
   491  	response, err := s.m.SendChatMessage(context.Background(), inputMessage)
   492  	s.NoError(err)
   493  
   494  	s.Require().Len(response.Messages(), 1)
   495  
   496  	textMessage := response.Messages()[0]
   497  
   498  	s.Equal(textMessage.Text, text)
   499  	s.NotNil(textMessage.ParsedText)
   500  	s.True(textMessage.RTL)
   501  	s.Equal(1, textMessage.LineCount)
   502  
   503  	s.Require().Len(response.Chats(), 1)
   504  	actualChat := response.Chats()[0]
   505  	// It does not set the unviewed messages count
   506  	s.Require().Equal(uint(0), actualChat.UnviewedMessagesCount)
   507  	// It updates the last message clock value
   508  	s.Require().Equal(textMessage.Clock, actualChat.LastClockValue)
   509  	// It sets the last message
   510  	s.Require().NotNil(actualChat.LastMessage)
   511  }
   512  
   513  // Retrieve their public message
   514  func (s *MessengerSuite) TestRetrieveTheirPublic() {
   515  	theirMessenger := s.newMessenger()
   516  	defer TearDownMessenger(&s.Suite, theirMessenger)
   517  	theirChat := CreatePublicChat("status", s.m.transport)
   518  	err := theirMessenger.SaveChat(theirChat)
   519  	s.Require().NoError(err)
   520  
   521  	chat := CreatePublicChat("status", s.m.transport)
   522  	err = s.m.SaveChat(chat)
   523  	s.Require().NoError(err)
   524  
   525  	_, err = s.m.Join(chat)
   526  	s.Require().NoError(err)
   527  
   528  	inputMessage := buildTestMessage(*chat)
   529  
   530  	sendResponse, err := theirMessenger.SendChatMessage(context.Background(), inputMessage)
   531  	s.NoError(err)
   532  
   533  	sentMessage := sendResponse.Messages()[0]
   534  
   535  	// Wait for the message to reach its destination
   536  	response, err := WaitOnMessengerResponse(
   537  		s.m,
   538  		func(r *MessengerResponse) bool { return len(r.Messages()) > 0 },
   539  		"no messages",
   540  	)
   541  
   542  	s.Require().NoError(err)
   543  
   544  	s.Require().Len(response.Messages(), 1)
   545  	s.Require().Len(response.Chats(), 1)
   546  	actualChat := response.Chats()[0]
   547  	// It sets the unviewed messages count
   548  	s.Require().Equal(uint(1), actualChat.UnviewedMessagesCount)
   549  	// It updates the last message clock value
   550  	s.Require().Equal(sentMessage.Clock, actualChat.LastClockValue)
   551  	// It sets the last message
   552  	s.Require().NotNil(actualChat.LastMessage)
   553  }
   554  
   555  // Drop audio message in public group
   556  func (s *MessengerSuite) TestDropAudioMessageInPublicGroup() {
   557  	theirMessenger := s.newMessenger()
   558  	defer TearDownMessenger(&s.Suite, theirMessenger)
   559  	theirChat := CreatePublicChat("status", s.m.transport)
   560  	err := theirMessenger.SaveChat(theirChat)
   561  	s.Require().NoError(err)
   562  
   563  	chat := CreatePublicChat("status", s.m.transport)
   564  	err = s.m.SaveChat(chat)
   565  	s.Require().NoError(err)
   566  
   567  	_, err = s.m.Join(chat)
   568  	s.Require().NoError(err)
   569  
   570  	inputMessage := buildAudioMessage(s, *chat)
   571  
   572  	_, err = theirMessenger.SendChatMessage(context.Background(), inputMessage)
   573  	s.NoError(err)
   574  
   575  	time.Sleep(100 * time.Millisecond)
   576  	response, err := s.m.RetrieveAll()
   577  	s.Require().NoError(err)
   578  	s.Require().Len(response.Messages(), 0)
   579  }
   580  
   581  func (s *MessengerSuite) TestDeletedAtClockValue() {
   582  	theirMessenger := s.newMessenger()
   583  	defer TearDownMessenger(&s.Suite, theirMessenger)
   584  	theirChat := CreatePublicChat("status", s.m.transport)
   585  	err := theirMessenger.SaveChat(theirChat)
   586  	s.Require().NoError(err)
   587  
   588  	chat := CreatePublicChat("status", s.m.transport)
   589  	err = s.m.SaveChat(chat)
   590  	s.Require().NoError(err)
   591  
   592  	_, err = s.m.Join(chat)
   593  	s.Require().NoError(err)
   594  
   595  	inputMessage := buildTestMessage(*chat)
   596  
   597  	sentResponse, err := theirMessenger.SendChatMessage(context.Background(), inputMessage)
   598  	s.NoError(err)
   599  
   600  	chat.DeletedAtClockValue = sentResponse.Messages()[0].Clock
   601  	err = s.m.SaveChat(chat)
   602  	s.Require().NoError(err)
   603  
   604  	// Wait for the message to reach its destination
   605  	time.Sleep(100 * time.Millisecond)
   606  	response, err := s.m.RetrieveAll()
   607  	s.Require().NoError(err)
   608  	s.Require().Len(response.Messages(), 0)
   609  }
   610  
   611  func (s *MessengerSuite) TestRetrieveBlockedContact() {
   612  	theirMessenger := s.newMessenger()
   613  	defer TearDownMessenger(&s.Suite, theirMessenger)
   614  
   615  	theirChat := CreatePublicChat("status", s.m.transport)
   616  	err := theirMessenger.SaveChat(theirChat)
   617  	s.Require().NoError(err)
   618  	_, err = theirMessenger.Join(theirChat)
   619  	s.Require().NoError(err)
   620  
   621  	chat := CreatePublicChat("status", s.m.transport)
   622  	err = s.m.SaveChat(chat)
   623  	s.Require().NoError(err)
   624  	_, err = s.m.Join(chat)
   625  	s.Require().NoError(err)
   626  
   627  	publicKeyHex := "0x" + hex.EncodeToString(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
   628  	blockedContact := Contact{
   629  		ID:          publicKeyHex,
   630  		EnsName:     "contact-name",
   631  		LastUpdated: 20,
   632  		Blocked:     false,
   633  	}
   634  
   635  	requireMessageArrival := func(receiver *Messenger, require bool) {
   636  		// Wait for the message to reach its destination
   637  		time.Sleep(100 * time.Millisecond)
   638  		response, err := receiver.RetrieveAll()
   639  		s.Require().NoError(err)
   640  		if require {
   641  			containTextMsg := false
   642  			for _, msg := range response.Messages() {
   643  				if msg.ContentType == protobuf.ChatMessage_TEXT_PLAIN && msg.Text == "text-input-message" {
   644  					containTextMsg = true
   645  					break
   646  				}
   647  			}
   648  			s.Require().True(containTextMsg)
   649  		} else {
   650  			s.Require().Len(response.Messages(), 0)
   651  		}
   652  	}
   653  
   654  	// Block contact
   655  	_, err = s.m.BlockContact(context.Background(), blockedContact.ID, false)
   656  	s.Require().NoError(err)
   657  
   658  	// Blocked contact sends message, we should not receive it
   659  	theirMessage := buildTestMessage(*theirChat)
   660  	_, err = theirMessenger.SendChatMessage(context.Background(), theirMessage)
   661  	s.NoError(err)
   662  	requireMessageArrival(s.m, false)
   663  
   664  	// We send a message, blocked contact should still receive it
   665  	ourMessage := buildTestMessage(*chat)
   666  	_, err = s.m.SendChatMessage(context.Background(), ourMessage)
   667  	s.NoError(err)
   668  	requireMessageArrival(theirMessenger, true)
   669  
   670  	// Unblock contact
   671  	response, err := s.m.UnblockContact(blockedContact.ID)
   672  	s.Require().NoError(err)
   673  	s.Require().NotNil(response)
   674  	s.Require().Equal(false, response.Contacts[0].Blocked)
   675  	s.Require().Equal(true, response.Contacts[0].Removed)
   676  
   677  	// Unblocked contact sends message, we should receive it
   678  	_, err = theirMessenger.SendChatMessage(context.Background(), theirMessage)
   679  	s.Require().NoError(err)
   680  	requireMessageArrival(s.m, true)
   681  
   682  	// We send a message, unblocked contact should receive it
   683  	_, err = s.m.SendChatMessage(context.Background(), ourMessage)
   684  	s.NoError(err)
   685  	requireMessageArrival(theirMessenger, true)
   686  }
   687  
   688  // Resend their public message, receive only once
   689  func (s *MessengerSuite) TestResendPublicMessage() {
   690  	theirMessenger := s.newMessenger()
   691  	defer TearDownMessenger(&s.Suite, theirMessenger)
   692  	theirChat := CreatePublicChat("status", s.m.transport)
   693  	err := theirMessenger.SaveChat(theirChat)
   694  	s.Require().NoError(err)
   695  
   696  	chat := CreatePublicChat("status", s.m.transport)
   697  	err = s.m.SaveChat(chat)
   698  	s.Require().NoError(err)
   699  
   700  	_, err = s.m.Join(chat)
   701  	s.Require().NoError(err)
   702  
   703  	inputMessage := buildTestMessage(*chat)
   704  
   705  	sendResponse1, err := theirMessenger.SendChatMessage(context.Background(), inputMessage)
   706  	s.Require().NoError(err)
   707  
   708  	sentMessage := sendResponse1.Messages()[0]
   709  
   710  	err = theirMessenger.ReSendChatMessage(context.Background(), sentMessage.ID)
   711  	s.Require().NoError(err)
   712  
   713  	// Wait for the message to reach its destination
   714  	response, err := WaitOnMessengerResponse(
   715  		s.m,
   716  		func(r *MessengerResponse) bool { return len(r.Messages()) > 0 },
   717  		"no messages",
   718  	)
   719  	s.Require().NoError(err)
   720  
   721  	s.Require().Len(response.Messages(), 1)
   722  	s.Require().Len(response.Chats(), 1)
   723  	actualChat := response.Chats()[0]
   724  	// It sets the unviewed messages count
   725  	s.Require().Equal(uint(1), actualChat.UnviewedMessagesCount)
   726  	// It updates the last message clock value
   727  	s.Require().Equal(sentMessage.Clock, actualChat.LastClockValue)
   728  	// It sets the last message
   729  	s.Require().NotNil(actualChat.LastMessage)
   730  
   731  	// We send the messag again
   732  	err = theirMessenger.ReSendChatMessage(context.Background(), sentMessage.ID)
   733  	s.Require().NoError(err)
   734  
   735  	// It should not be retrieved anymore
   736  	time.Sleep(100 * time.Millisecond)
   737  	response, err = s.m.RetrieveAll()
   738  	s.Require().NoError(err)
   739  	s.Require().Len(response.Messages(), 0)
   740  }
   741  
   742  // Test receiving a message on an existing private chat
   743  func (s *MessengerSuite) TestRetrieveTheirPrivateChatExisting() {
   744  	theirMessenger := s.newMessenger()
   745  	defer TearDownMessenger(&s.Suite, theirMessenger)
   746  	theirChat := CreateOneToOneChat("XXX", &s.privateKey.PublicKey, s.m.transport)
   747  	err := theirMessenger.SaveChat(theirChat)
   748  	s.Require().NoError(err)
   749  
   750  	ourChat := CreateOneToOneChat("our-chat", &theirMessenger.identity.PublicKey, s.m.transport)
   751  	ourChat.UnviewedMessagesCount = 1
   752  	// Make chat inactive
   753  	ourChat.Active = false
   754  	err = s.m.SaveChat(ourChat)
   755  	s.Require().NoError(err)
   756  
   757  	inputMessage := buildTestMessage(*theirChat)
   758  
   759  	sendResponse, err := theirMessenger.SendChatMessage(context.Background(), inputMessage)
   760  	s.NoError(err)
   761  	s.Require().Len(sendResponse.Messages(), 1)
   762  
   763  	sentMessage := sendResponse.Messages()[0]
   764  
   765  	response, err := WaitOnMessengerResponse(
   766  		s.m,
   767  		func(r *MessengerResponse) bool { return len(r.Messages()) > 0 },
   768  		"no messages",
   769  	)
   770  	s.Require().NoError(err)
   771  
   772  	s.Require().Len(response.Chats(), 1)
   773  	actualChat := response.Chats()[0]
   774  	// It updates the unviewed messages count
   775  	s.Require().Equal(uint(2), actualChat.UnviewedMessagesCount)
   776  	// It updates the last message clock value
   777  	s.Require().Equal(sentMessage.Clock, actualChat.LastClockValue)
   778  	// It sets the last message
   779  	s.Require().NotNil(actualChat.LastMessage)
   780  	s.Require().False(actualChat.Active)
   781  }
   782  
   783  // Test receiving a message on an non-existing private chat
   784  func (s *MessengerSuite) TestRetrieveTheirPrivateChatNonExisting() {
   785  	theirMessenger := s.newMessenger()
   786  	defer TearDownMessenger(&s.Suite, theirMessenger)
   787  	chat := CreateOneToOneChat("XXX", &s.privateKey.PublicKey, s.m.transport)
   788  	err := theirMessenger.SaveChat(chat)
   789  	s.NoError(err)
   790  
   791  	inputMessage := buildTestMessage(*chat)
   792  
   793  	sendResponse, err := theirMessenger.SendChatMessage(context.Background(), inputMessage)
   794  	s.NoError(err)
   795  	s.Require().Len(sendResponse.Messages(), 1)
   796  
   797  	sentMessage := sendResponse.Messages()[0]
   798  
   799  	// Wait for the message to reach its destination
   800  	response, err := WaitOnMessengerResponse(
   801  		s.m,
   802  		func(r *MessengerResponse) bool { return len(r.Messages()) > 0 },
   803  		"no messages",
   804  	)
   805  
   806  	s.Require().NoError(err)
   807  
   808  	s.Require().Len(response.Chats(), 1)
   809  	actualChat := response.Chats()[0]
   810  	// It updates the unviewed messages count
   811  	s.Require().Equal(uint(1), actualChat.UnviewedMessagesCount)
   812  	// It updates the last message clock value
   813  	s.Require().Equal(sentMessage.Clock, actualChat.LastClockValue)
   814  	// It sets the last message
   815  	s.Require().NotNil(actualChat.LastMessage)
   816  	// It does not set the chat as active
   817  	s.Require().False(actualChat.Active)
   818  }
   819  
   820  // Test receiving a message on an non-existing public chat
   821  func (s *MessengerSuite) TestRetrieveTheirPublicChatNonExisting() {
   822  	theirMessenger := s.newMessenger()
   823  	defer TearDownMessenger(&s.Suite, theirMessenger)
   824  	chat := CreatePublicChat("test-chat", s.m.transport)
   825  	err := theirMessenger.SaveChat(chat)
   826  	s.NoError(err)
   827  
   828  	inputMessage := buildTestMessage(*chat)
   829  
   830  	sendResponse, err := theirMessenger.SendChatMessage(context.Background(), inputMessage)
   831  	s.NoError(err)
   832  	s.Require().Len(sendResponse.Messages(), 1)
   833  
   834  	// Wait for the message to reach its destination
   835  	time.Sleep(100 * time.Millisecond)
   836  	response, err := s.m.RetrieveAll()
   837  	s.NoError(err)
   838  
   839  	s.Require().Equal(len(response.Messages()), 0)
   840  	s.Require().Equal(len(response.Chats()), 0)
   841  }
   842  
   843  // Test receiving a message on an existing private group chat
   844  func (s *MessengerSuite) TestRetrieveTheirPrivateGroupChat() {
   845  	var response *MessengerResponse
   846  	theirMessenger := s.newMessenger()
   847  	defer TearDownMessenger(&s.Suite, theirMessenger)
   848  	response, err := s.m.CreateGroupChatWithMembers(context.Background(), "id", []string{})
   849  	s.NoError(err)
   850  	s.Require().Len(response.Chats(), 1)
   851  
   852  	ourChat := response.Chats()[0]
   853  
   854  	err = s.m.SaveChat(ourChat)
   855  	s.NoError(err)
   856  
   857  	s.Require().NoError(makeMutualContact(s.m, &theirMessenger.identity.PublicKey))
   858  
   859  	members := []string{"0x" + hex.EncodeToString(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))}
   860  	_, err = s.m.AddMembersToGroupChat(context.Background(), ourChat.ID, members)
   861  	s.NoError(err)
   862  
   863  	// Retrieve their messages so that the chat is created
   864  	response, err = WaitOnMessengerResponse(
   865  		theirMessenger,
   866  		func(r *MessengerResponse) bool { return len(r.Chats()) > 0 },
   867  		"chat invitation not received",
   868  	)
   869  	s.Require().NoError(err)
   870  	s.Require().Len(response.Chats(), 1)
   871  	s.Require().Len(response.ActivityCenterNotifications(), 1)
   872  	s.Require().False(response.Chats()[0].Active)
   873  
   874  	_, err = theirMessenger.ConfirmJoiningGroup(context.Background(), ourChat.ID)
   875  	s.NoError(err)
   876  
   877  	// Wait for the message to reach its destination
   878  	_, err = WaitOnMessengerResponse(
   879  		s.m,
   880  		func(r *MessengerResponse) bool { return len(r.Chats()) > 0 },
   881  		"no joining group event received",
   882  	)
   883  	s.Require().NoError(err)
   884  
   885  	inputMessage := buildTestMessage(*ourChat)
   886  
   887  	sendResponse, err := theirMessenger.SendChatMessage(context.Background(), inputMessage)
   888  	s.NoError(err)
   889  	s.Require().Len(sendResponse.Messages(), 1)
   890  
   891  	sentMessage := sendResponse.Messages()[0]
   892  
   893  	response, err = WaitOnMessengerResponse(
   894  		s.m,
   895  		func(r *MessengerResponse) bool { return len(r.Messages()) > 0 },
   896  		"no messages",
   897  	)
   898  	s.Require().NoError(err)
   899  
   900  	s.Require().Len(response.Chats(), 1)
   901  	actualChat := response.Chats()[0]
   902  	// It updates the unviewed messages count
   903  	s.Require().Equal(uint(1), actualChat.UnviewedMessagesCount)
   904  	// It updates the last message clock value
   905  	s.Require().Equal(sentMessage.Clock, actualChat.LastClockValue)
   906  	// It sets the last message
   907  	s.Require().NotNil(actualChat.LastMessage)
   908  }
   909  
   910  // Test receiving a message on an existing private group chat
   911  func (s *MessengerSuite) TestChangeNameGroupChat() {
   912  	var response *MessengerResponse
   913  	theirMessenger := s.newMessenger()
   914  	defer TearDownMessenger(&s.Suite, theirMessenger)
   915  	response, err := s.m.CreateGroupChatWithMembers(context.Background(), "old-name", []string{})
   916  	s.NoError(err)
   917  	s.Require().Len(response.Chats(), 1)
   918  
   919  	ourChat := response.Chats()[0]
   920  
   921  	err = s.m.SaveChat(ourChat)
   922  	s.NoError(err)
   923  
   924  	s.Require().NoError(makeMutualContact(s.m, &theirMessenger.identity.PublicKey))
   925  
   926  	members := []string{"0x" + hex.EncodeToString(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))}
   927  	_, err = s.m.AddMembersToGroupChat(context.Background(), ourChat.ID, members)
   928  	s.NoError(err)
   929  
   930  	// Retrieve their messages so that the chat is created
   931  	_, err = WaitOnMessengerResponse(
   932  		theirMessenger,
   933  		func(r *MessengerResponse) bool { return len(r.Chats()) > 0 },
   934  		"chat invitation not received",
   935  	)
   936  	s.Require().NoError(err)
   937  
   938  	_, err = theirMessenger.ConfirmJoiningGroup(context.Background(), ourChat.ID)
   939  	s.NoError(err)
   940  
   941  	// Wait for join group event
   942  	_, err = WaitOnMessengerResponse(
   943  		s.m,
   944  		func(r *MessengerResponse) bool { return len(r.Chats()) > 0 },
   945  		"no joining group event received",
   946  	)
   947  	s.Require().NoError(err)
   948  
   949  	_, err = s.m.ChangeGroupChatName(context.Background(), ourChat.ID, newEnsName)
   950  	s.NoError(err)
   951  
   952  	// Retrieve their messages so that the chat is created
   953  	response, err = WaitOnMessengerResponse(
   954  		theirMessenger,
   955  		func(r *MessengerResponse) bool { return len(r.Chats()) > 0 },
   956  		"chat invitation not received",
   957  	)
   958  	s.Require().NoError(err)
   959  
   960  	s.Require().Len(response.Chats(), 1)
   961  	actualChat := response.Chats()[0]
   962  	s.Require().Equal(newEnsName, actualChat.Name)
   963  }
   964  
   965  // Test being re-invited to a group chat
   966  func (s *MessengerSuite) TestReInvitedToGroupChat() {
   967  	var response *MessengerResponse
   968  	theirMessenger := s.newMessenger()
   969  	defer TearDownMessenger(&s.Suite, theirMessenger)
   970  	response, err := s.m.CreateGroupChatWithMembers(context.Background(), "old-name", []string{})
   971  	s.NoError(err)
   972  	s.Require().Len(response.Chats(), 1)
   973  
   974  	ourChat := response.Chats()[0]
   975  
   976  	err = s.m.SaveChat(ourChat)
   977  	s.NoError(err)
   978  
   979  	s.Require().NoError(makeMutualContact(s.m, &theirMessenger.identity.PublicKey))
   980  
   981  	members := []string{"0x" + hex.EncodeToString(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))}
   982  	_, err = s.m.AddMembersToGroupChat(context.Background(), ourChat.ID, members)
   983  	s.NoError(err)
   984  
   985  	// Retrieve their messages so that the chat is created
   986  	response, err = WaitOnMessengerResponse(
   987  		theirMessenger,
   988  		func(r *MessengerResponse) bool { return len(r.Chats()) > 0 },
   989  		"chat invitation not received",
   990  	)
   991  	s.Require().NoError(err)
   992  	s.Require().Len(response.ActivityCenterNotifications(), 1)
   993  	s.Require().False(response.Chats()[0].Active)
   994  
   995  	_, err = theirMessenger.ConfirmJoiningGroup(context.Background(), ourChat.ID)
   996  	s.NoError(err)
   997  
   998  	// Wait for join group event
   999  	_, err = WaitOnMessengerResponse(
  1000  		s.m,
  1001  		func(r *MessengerResponse) bool { return len(r.Chats()) > 0 },
  1002  		"no joining group event received",
  1003  	)
  1004  	s.Require().NoError(err)
  1005  
  1006  	response, err = theirMessenger.LeaveGroupChat(context.Background(), ourChat.ID, true)
  1007  	s.NoError(err)
  1008  
  1009  	s.Require().Len(response.Chats(), 1)
  1010  	s.Require().False(response.Chats()[0].Active)
  1011  
  1012  	// Retrieve messages so user is removed
  1013  	_, err = WaitOnMessengerResponse(
  1014  		s.m,
  1015  		func(r *MessengerResponse) bool { return len(r.Chats()) > 0 && len(r.Chats()[0].Members) == 1 },
  1016  		"leave group chat not received",
  1017  	)
  1018  
  1019  	s.Require().NoError(err)
  1020  
  1021  	// And we get re-invited
  1022  	_, err = s.m.AddMembersToGroupChat(context.Background(), ourChat.ID, members)
  1023  	s.NoError(err)
  1024  
  1025  	// Retrieve their messages so that the chat is created
  1026  	response, err = WaitOnMessengerResponse(
  1027  		theirMessenger,
  1028  		func(r *MessengerResponse) bool { return len(r.Chats()) > 0 },
  1029  		"chat invitation not received",
  1030  	)
  1031  
  1032  	s.Require().NoError(err)
  1033  
  1034  	s.Require().Len(response.Chats(), 1)
  1035  	s.Require().False(response.Chats()[0].Active)
  1036  }
  1037  
  1038  func (s *MessengerSuite) TestChatPersistencePublic() {
  1039  	chat := &Chat{
  1040  		ID:                    "chat-name",
  1041  		Name:                  "chat-name",
  1042  		Color:                 "#fffff",
  1043  		Active:                true,
  1044  		ChatType:              ChatTypePublic,
  1045  		Timestamp:             10,
  1046  		LastClockValue:        20,
  1047  		DeletedAtClockValue:   30,
  1048  		UnviewedMessagesCount: 40,
  1049  		LastMessage:           common.NewMessage(),
  1050  		Highlight:             false,
  1051  	}
  1052  
  1053  	s.Require().NoError(s.m.SaveChat(chat))
  1054  	savedChats := s.m.Chats()
  1055  	s.Require().Equal(deprecation.AddChatsCount(1), len(savedChats))
  1056  }
  1057  
  1058  func (s *MessengerSuite) TestDeleteChat() {
  1059  	chatID := "chatid"
  1060  	chat := &Chat{
  1061  		ID:                    chatID,
  1062  		Name:                  "chat-name",
  1063  		Color:                 "#fffff",
  1064  		Active:                true,
  1065  		ChatType:              ChatTypePublic,
  1066  		Timestamp:             10,
  1067  		LastClockValue:        20,
  1068  		DeletedAtClockValue:   30,
  1069  		UnviewedMessagesCount: 40,
  1070  		LastMessage:           common.NewMessage(),
  1071  		Highlight:             false,
  1072  	}
  1073  
  1074  	s.Require().NoError(s.m.SaveChat(chat))
  1075  	savedChats := s.m.Chats()
  1076  	s.Require().Equal(deprecation.AddChatsCount(1), len(savedChats))
  1077  
  1078  	s.Require().NoError(s.m.DeleteChat(chatID))
  1079  	savedChats = s.m.Chats()
  1080  	s.Require().Equal(deprecation.AddChatsCount(0), len(savedChats))
  1081  }
  1082  
  1083  func (s *MessengerSuite) TestChatPersistenceUpdate() {
  1084  	chat := &Chat{
  1085  		ID:                    "chat-name",
  1086  		Name:                  "chat-name",
  1087  		Color:                 "#fffff",
  1088  		Active:                true,
  1089  		ChatType:              ChatTypePublic,
  1090  		Timestamp:             10,
  1091  		LastClockValue:        20,
  1092  		DeletedAtClockValue:   30,
  1093  		UnviewedMessagesCount: 40,
  1094  		LastMessage:           common.NewMessage(),
  1095  		Highlight:             false,
  1096  	}
  1097  
  1098  	s.Require().NoError(s.m.SaveChat(chat))
  1099  	savedChats := s.m.Chats()
  1100  	s.Require().Equal(deprecation.AddChatsCount(1), len(savedChats))
  1101  
  1102  	var actualChat *Chat
  1103  	for idx := range savedChats {
  1104  		if savedChats[idx].ID == chat.ID {
  1105  			actualChat = chat
  1106  		}
  1107  	}
  1108  
  1109  	s.Require().NotNil(actualChat)
  1110  	s.Require().Equal(chat, actualChat)
  1111  
  1112  	chat.Name = "updated-name-1"
  1113  	s.Require().NoError(s.m.SaveChat(chat))
  1114  
  1115  	var actualUpdatedChat *Chat
  1116  	updatedChats := s.m.Chats()
  1117  
  1118  	for idx := range updatedChats {
  1119  		if updatedChats[idx].ID == chat.ID {
  1120  			actualUpdatedChat = chat
  1121  		}
  1122  	}
  1123  
  1124  	s.Require().Equal(chat, actualUpdatedChat)
  1125  }
  1126  
  1127  func (s *MessengerSuite) TestChatPersistenceOneToOne() {
  1128  	chat := &Chat{
  1129  		ID:                    testPK,
  1130  		Name:                  testPK,
  1131  		Color:                 "#fffff",
  1132  		Active:                true,
  1133  		ChatType:              ChatTypeOneToOne,
  1134  		Timestamp:             10,
  1135  		LastClockValue:        20,
  1136  		DeletedAtClockValue:   30,
  1137  		UnviewedMessagesCount: 40,
  1138  		LastMessage:           common.NewMessage(),
  1139  		Highlight:             false,
  1140  	}
  1141  
  1142  	publicKeyBytes, err := hex.DecodeString(testPK[2:])
  1143  	s.Require().NoError(err)
  1144  
  1145  	pk, err := crypto.UnmarshalPubkey(publicKeyBytes)
  1146  	s.Require().NoError(err)
  1147  
  1148  	s.Require().NoError(s.m.SaveChat(chat))
  1149  	savedChats := s.m.Chats()
  1150  	s.Require().Equal(deprecation.AddChatsCount(1), len(savedChats))
  1151  
  1152  	var actualChat *Chat
  1153  	for idx := range savedChats {
  1154  		if chat.ID == savedChats[idx].ID {
  1155  			actualChat = savedChats[idx]
  1156  		}
  1157  
  1158  	}
  1159  
  1160  	actualPk, err := actualChat.PublicKey()
  1161  	s.Require().NoError(err)
  1162  
  1163  	s.Require().Equal(pk, actualPk)
  1164  
  1165  	s.Require().Equal(chat, actualChat)
  1166  	s.Require().NotEmpty(actualChat.Identicon)
  1167  	s.Require().NotEmpty(actualChat.Alias)
  1168  }
  1169  
  1170  func (s *MessengerSuite) TestChatPersistencePrivateGroupChat() {
  1171  
  1172  	member1Key, err := crypto.GenerateKey()
  1173  	s.Require().NoError(err)
  1174  	member1ID := types.EncodeHex(crypto.FromECDSAPub(&member1Key.PublicKey))
  1175  
  1176  	member2Key, err := crypto.GenerateKey()
  1177  	s.Require().NoError(err)
  1178  	member2ID := types.EncodeHex(crypto.FromECDSAPub(&member2Key.PublicKey))
  1179  
  1180  	member3Key, err := crypto.GenerateKey()
  1181  	s.Require().NoError(err)
  1182  	member3ID := types.EncodeHex(crypto.FromECDSAPub(&member3Key.PublicKey))
  1183  
  1184  	chat := &Chat{
  1185  		ID:        "chat-id",
  1186  		Name:      "chat-id",
  1187  		Color:     "#fffff",
  1188  		Active:    true,
  1189  		ChatType:  ChatTypePrivateGroupChat,
  1190  		Timestamp: 10,
  1191  		Members: []ChatMember{
  1192  			{
  1193  				ID:    member1ID,
  1194  				Admin: false,
  1195  			},
  1196  			{
  1197  				ID:    member2ID,
  1198  				Admin: true,
  1199  			},
  1200  			{
  1201  				ID:    member3ID,
  1202  				Admin: true,
  1203  			},
  1204  		},
  1205  		MembershipUpdates: []v1protocol.MembershipUpdateEvent{
  1206  			{
  1207  				Type:       protobuf.MembershipUpdateEvent_CHAT_CREATED,
  1208  				Name:       "name-1",
  1209  				ClockValue: 1,
  1210  				Signature:  []byte("signature-1"),
  1211  				From:       "from-1",
  1212  				Members:    []string{"member-1", "member-2"},
  1213  			},
  1214  			{
  1215  				Type:       protobuf.MembershipUpdateEvent_MEMBERS_ADDED,
  1216  				Name:       "name-2",
  1217  				ClockValue: 2,
  1218  				Signature:  []byte("signature-2"),
  1219  				From:       "from-2",
  1220  				Members:    []string{"member-2", "member-3"},
  1221  			},
  1222  		},
  1223  		LastClockValue:        20,
  1224  		DeletedAtClockValue:   30,
  1225  		UnviewedMessagesCount: 40,
  1226  		LastMessage:           common.NewMessage(),
  1227  		Highlight:             false,
  1228  	}
  1229  	s.Require().NoError(s.m.SaveChat(chat))
  1230  	savedChats := s.m.Chats()
  1231  	s.Require().Equal(deprecation.AddChatsCount(1), len(savedChats))
  1232  
  1233  	var actualChat *Chat
  1234  	for idx := range savedChats {
  1235  		if savedChats[idx].ID == chat.ID {
  1236  			actualChat = savedChats[idx]
  1237  		}
  1238  
  1239  	}
  1240  
  1241  	s.Require().Equal(chat, actualChat)
  1242  }
  1243  
  1244  func (s *MessengerSuite) TestBlockContact() {
  1245  	contact := Contact{
  1246  		ID:                       testPK,
  1247  		EnsName:                  "contact-name",
  1248  		LastUpdated:              20,
  1249  		ContactRequestLocalState: ContactRequestStateSent,
  1250  	}
  1251  
  1252  	key2, err := crypto.GenerateKey()
  1253  	s.Require().NoError(err)
  1254  
  1255  	contact2 := Contact{
  1256  		ID:                       common.PubkeyToHex(&key2.PublicKey),
  1257  		EnsName:                  "contact-name",
  1258  		LastUpdated:              20,
  1259  		ContactRequestLocalState: ContactRequestStateSent,
  1260  	}
  1261  
  1262  	chat1 := &Chat{
  1263  		ID:                    contact.ID,
  1264  		Name:                  "chat-name",
  1265  		Color:                 "#fffff",
  1266  		Active:                true,
  1267  		ChatType:              ChatTypeOneToOne,
  1268  		Timestamp:             1,
  1269  		LastClockValue:        20,
  1270  		DeletedAtClockValue:   30,
  1271  		UnviewedMessagesCount: 40,
  1272  		Highlight:             false,
  1273  	}
  1274  
  1275  	chat2 := &Chat{
  1276  		ID:                    "chat-2",
  1277  		Name:                  "chat-name",
  1278  		Color:                 "#fffff",
  1279  		Active:                true,
  1280  		ChatType:              ChatTypePublic,
  1281  		Timestamp:             2,
  1282  		LastClockValue:        20,
  1283  		DeletedAtClockValue:   30,
  1284  		UnviewedMessagesCount: 40,
  1285  		Highlight:             false,
  1286  	}
  1287  
  1288  	chat3 := &Chat{
  1289  		ID:                    "chat-3",
  1290  		Name:                  "chat-name",
  1291  		Color:                 "#fffff",
  1292  		Active:                true,
  1293  		ChatType:              ChatTypePublic,
  1294  		Timestamp:             3,
  1295  		LastClockValue:        20,
  1296  		DeletedAtClockValue:   30,
  1297  		UnviewedMessagesCount: 40,
  1298  		Highlight:             false,
  1299  	}
  1300  
  1301  	s.Require().NoError(s.m.SaveChat(chat1))
  1302  	s.Require().NoError(s.m.SaveChat(chat2))
  1303  	s.Require().NoError(s.m.SaveChat(chat3))
  1304  
  1305  	_, err = s.m.AddContact(context.Background(), &requests.AddContact{ID: contact.ID})
  1306  	s.Require().NoError(err)
  1307  
  1308  	messages := []*common.Message{
  1309  		{
  1310  			ID:          "test-1",
  1311  			LocalChatID: chat2.ID,
  1312  			ChatMessage: &protobuf.ChatMessage{
  1313  				ContentType: 1,
  1314  				Text:        "test-1",
  1315  				Clock:       1,
  1316  			},
  1317  			From: contact.ID,
  1318  		},
  1319  		{
  1320  			ID:          "test-2",
  1321  			LocalChatID: chat2.ID,
  1322  			ChatMessage: &protobuf.ChatMessage{
  1323  				ContentType: 2,
  1324  				Text:        "test-2",
  1325  				Clock:       2,
  1326  			},
  1327  			From: contact.ID,
  1328  		},
  1329  		{
  1330  			ID:          "test-3",
  1331  			LocalChatID: chat2.ID,
  1332  			ChatMessage: &protobuf.ChatMessage{
  1333  				ContentType: 3,
  1334  				Text:        "test-3",
  1335  				Clock:       3,
  1336  			},
  1337  			Seen: false,
  1338  			From: contact2.ID,
  1339  		},
  1340  		{
  1341  			ID:          "test-4",
  1342  			LocalChatID: chat2.ID,
  1343  			ChatMessage: &protobuf.ChatMessage{
  1344  				ContentType: 4,
  1345  				Text:        "test-4",
  1346  				Clock:       4,
  1347  			},
  1348  			Seen: false,
  1349  			From: contact2.ID,
  1350  		},
  1351  		{
  1352  			ID:          "test-5",
  1353  			LocalChatID: chat2.ID,
  1354  			ChatMessage: &protobuf.ChatMessage{
  1355  				ContentType: 5,
  1356  				Text:        "test-5",
  1357  				Clock:       5,
  1358  			},
  1359  			Seen: true,
  1360  			From: contact2.ID,
  1361  		},
  1362  		{
  1363  			ID:          "test-6",
  1364  			LocalChatID: chat3.ID,
  1365  			ChatMessage: &protobuf.ChatMessage{
  1366  				ContentType: 6,
  1367  				Text:        "test-6",
  1368  				Clock:       6,
  1369  			},
  1370  			Seen: false,
  1371  			From: contact.ID,
  1372  		},
  1373  		{
  1374  			ID:          "test-7",
  1375  			LocalChatID: chat3.ID,
  1376  			ChatMessage: &protobuf.ChatMessage{
  1377  				ContentType: 7,
  1378  				Text:        "test-7",
  1379  				Clock:       7,
  1380  			},
  1381  			Seen: false,
  1382  			From: contact2.ID,
  1383  		},
  1384  	}
  1385  
  1386  	err = s.m.SaveMessages(messages)
  1387  	s.Require().NoError(err)
  1388  
  1389  	response, err := s.m.BlockContact(context.Background(), contact.ID, false)
  1390  	s.Require().NoError(err)
  1391  
  1392  	blockedContacts := s.m.BlockedContacts()
  1393  	s.Require().True(blockedContacts[0].Removed)
  1394  
  1395  	chats := response.Chats()
  1396  
  1397  	var actualChat2, actualChat3 *Chat
  1398  	for idx := range chats {
  1399  		if chats[idx].ID == chat2.ID {
  1400  			actualChat2 = chats[idx]
  1401  		} else if chats[idx].ID == chat3.ID {
  1402  			actualChat3 = chats[idx]
  1403  		}
  1404  	}
  1405  	// The new unviewed count is updated
  1406  	s.Require().Equal(uint(1), actualChat3.UnviewedMessagesCount)
  1407  	s.Require().Equal(uint(2), actualChat2.UnviewedMessagesCount)
  1408  
  1409  	// The new message content is updated
  1410  	s.Require().NotNil(actualChat3.LastMessage)
  1411  
  1412  	s.Require().Equal("test-7", actualChat3.LastMessage.ID)
  1413  
  1414  	s.Require().NotNil(actualChat2.LastMessage)
  1415  	s.Require().Equal("test-5", actualChat2.LastMessage.ID)
  1416  
  1417  	// The contact is updated
  1418  	savedContacts := s.m.Contacts()
  1419  	s.Require().Equal(1, len(savedContacts))
  1420  
  1421  	// The chat is deleted
  1422  	actualChats := s.m.Chats()
  1423  	s.Require().Equal(deprecation.AddChatsCount(3), len(actualChats))
  1424  
  1425  	// The messages have been deleted
  1426  	chat2Messages, _, err := s.m.MessageByChatID(chat2.ID, "", 20)
  1427  	s.Require().NoError(err)
  1428  	s.Require().Equal(3, len(chat2Messages))
  1429  
  1430  	chat3Messages, _, err := s.m.MessageByChatID(chat3.ID, "", 20)
  1431  	s.Require().NoError(err)
  1432  	s.Require().Equal(1, len(chat3Messages))
  1433  
  1434  }
  1435  
  1436  func (s *MessengerSuite) TestContactPersistence() {
  1437  	_, err := s.m.AddContact(context.Background(), &requests.AddContact{ID: testPK})
  1438  	s.Require().NoError(err)
  1439  	savedContacts := s.m.Contacts()
  1440  
  1441  	s.Require().Equal(1, len(savedContacts))
  1442  
  1443  	s.Require().True(savedContacts[0].added())
  1444  }
  1445  
  1446  func (s *MessengerSuite) TestSharedSecretHandler() {
  1447  	err := s.m.handleSharedSecrets(nil)
  1448  	s.NoError(err)
  1449  }
  1450  
  1451  func (s *MessengerSuite) TestCreateGroupChatWithMembers() {
  1452  	members := []string{testPK}
  1453  
  1454  	pubKey, err := common.HexToPubkey(testPK)
  1455  	s.Require().NoError(err)
  1456  	s.Require().NoError(makeMutualContact(s.m, pubKey))
  1457  
  1458  	response, err := s.m.CreateGroupChatWithMembers(context.Background(), "test", members)
  1459  	s.NoError(err)
  1460  	s.Require().Len(response.Chats(), 1)
  1461  
  1462  	chat := response.Chats()[0]
  1463  
  1464  	s.Require().Equal("test", chat.Name)
  1465  	publicKeyHex := "0x" + hex.EncodeToString(crypto.FromECDSAPub(&s.m.identity.PublicKey))
  1466  	s.Require().Contains(chat.ID, publicKeyHex)
  1467  	s.EqualValues([]string{publicKeyHex}, []string{chat.Members[0].ID})
  1468  	s.Equal(members[0], chat.Members[1].ID)
  1469  }
  1470  
  1471  func (s *MessengerSuite) TestAddMembersToChat() {
  1472  	response, err := s.m.CreateGroupChatWithMembers(context.Background(), "test", []string{})
  1473  	s.Require().NoError(err)
  1474  	s.Require().Len(response.Chats(), 1)
  1475  
  1476  	chat := response.Chats()[0]
  1477  
  1478  	key, err := crypto.GenerateKey()
  1479  	s.Require().NoError(err)
  1480  	members := []string{"0x" + hex.EncodeToString(crypto.FromECDSAPub(&key.PublicKey))}
  1481  
  1482  	s.Require().NoError(makeMutualContact(s.m, &key.PublicKey))
  1483  
  1484  	response, err = s.m.AddMembersToGroupChat(context.Background(), chat.ID, members)
  1485  	s.Require().NoError(err)
  1486  	s.Require().Len(response.Chats(), 1)
  1487  	s.Require().Len(response.Messages(), 1)
  1488  
  1489  	chat = response.Chats()[0]
  1490  
  1491  	publicKeyHex := "0x" + hex.EncodeToString(crypto.FromECDSAPub(&s.m.identity.PublicKey))
  1492  	keyHex := "0x" + hex.EncodeToString(crypto.FromECDSAPub(&key.PublicKey))
  1493  	s.EqualValues([]string{publicKeyHex, keyHex}, []string{chat.Members[0].ID, chat.Members[1].ID})
  1494  }
  1495  
  1496  func (s *MessengerSuite) TestDeclineRequestAddressForTransaction() {
  1497  	value := testValue
  1498  	contract := testContract
  1499  	theirMessenger := s.newMessenger()
  1500  	defer TearDownMessenger(&s.Suite, theirMessenger)
  1501  	theirPkString := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
  1502  	myPkString := types.EncodeHex(crypto.FromECDSAPub(&s.m.identity.PublicKey))
  1503  
  1504  	chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey, s.m.transport)
  1505  	err := s.m.SaveChat(chat)
  1506  	s.Require().NoError(err)
  1507  
  1508  	myAddress := crypto.PubkeyToAddress(s.m.identity.PublicKey)
  1509  
  1510  	response, err := s.m.RequestAddressForTransaction(context.Background(), theirPkString, myAddress.Hex(), value, contract)
  1511  	s.Require().NoError(err)
  1512  	s.Require().NotNil(response)
  1513  	s.Require().Len(response.Chats(), 1)
  1514  	s.Require().Len(response.Messages(), 1)
  1515  
  1516  	senderMessage := response.Messages()[0]
  1517  	s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, senderMessage.ContentType)
  1518  	initialCommandID := senderMessage.ID
  1519  
  1520  	s.Require().Equal("Request address for transaction", senderMessage.Text)
  1521  	s.Require().NotNil(senderMessage.CommandParameters)
  1522  	s.Require().Equal(value, senderMessage.CommandParameters.Value)
  1523  	s.Require().Equal(contract, senderMessage.CommandParameters.Contract)
  1524  	s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID)
  1525  	s.Require().Equal(common.CommandStateRequestAddressForTransaction, senderMessage.CommandParameters.CommandState)
  1526  
  1527  	// Wait for the message to reach its destination
  1528  	response, err = WaitOnMessengerResponse(
  1529  		theirMessenger,
  1530  		func(r *MessengerResponse) bool { return len(r.Messages()) > 0 },
  1531  		"no messages",
  1532  	)
  1533  	s.Require().NoError(err)
  1534  
  1535  	s.Require().NotNil(response)
  1536  	s.Require().Len(response.Chats(), 1)
  1537  	s.Require().Len(response.Messages(), 1)
  1538  
  1539  	receiverMessage := response.Messages()[0]
  1540  	s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, receiverMessage.ContentType)
  1541  	s.Require().Equal("Request address for transaction", receiverMessage.Text)
  1542  	s.Require().NotNil(receiverMessage.CommandParameters)
  1543  	s.Require().Equal(value, receiverMessage.CommandParameters.Value)
  1544  	s.Require().Equal(contract, receiverMessage.CommandParameters.Contract)
  1545  	s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID)
  1546  	s.Require().Equal(theirPkString, receiverMessage.ChatId)
  1547  	s.Require().Equal(common.CommandStateRequestAddressForTransaction, receiverMessage.CommandParameters.CommandState)
  1548  
  1549  	// We decline the request
  1550  	response, err = theirMessenger.DeclineRequestAddressForTransaction(context.Background(), receiverMessage.ID)
  1551  	s.Require().NoError(err)
  1552  	s.Require().Len(response.Chats(), 1)
  1553  	s.Require().Len(response.Messages(), 1)
  1554  
  1555  	senderMessage = response.Messages()[0]
  1556  	s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, senderMessage.ContentType)
  1557  	s.Require().Equal("Request address for transaction declined", senderMessage.Text)
  1558  	s.Require().NotNil(senderMessage.CommandParameters)
  1559  	s.Require().Equal(value, senderMessage.CommandParameters.Value)
  1560  	s.Require().Equal(contract, senderMessage.CommandParameters.Contract)
  1561  	s.Require().Equal(common.CommandStateRequestAddressForTransactionDeclined, senderMessage.CommandParameters.CommandState)
  1562  	s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID)
  1563  	s.Require().Equal(receiverMessage.ID, senderMessage.Replace)
  1564  
  1565  	// Wait for the message to reach its destination
  1566  	response, err = WaitOnMessengerResponse(
  1567  		s.m,
  1568  		func(r *MessengerResponse) bool { return len(r.Messages()) > 0 },
  1569  		"no messages",
  1570  	)
  1571  	s.Require().NoError(err)
  1572  
  1573  	s.Require().Len(response.Chats(), 1)
  1574  	s.Require().Len(response.Messages(), 1)
  1575  
  1576  	receiverMessage = response.Messages()[0]
  1577  	s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, receiverMessage.ContentType)
  1578  	s.Require().Equal("Request address for transaction declined", receiverMessage.Text)
  1579  	s.Require().NotNil(receiverMessage.CommandParameters)
  1580  	s.Require().Equal(value, receiverMessage.CommandParameters.Value)
  1581  	s.Require().Equal(contract, receiverMessage.CommandParameters.Contract)
  1582  	s.Require().Equal(common.CommandStateRequestAddressForTransactionDeclined, receiverMessage.CommandParameters.CommandState)
  1583  	s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID)
  1584  	s.Require().Equal(myPkString, receiverMessage.ChatId)
  1585  	s.Require().Equal(initialCommandID, receiverMessage.Replace)
  1586  }
  1587  
  1588  func (s *MessengerSuite) TestSendEthTransaction() {
  1589  	value := testValue
  1590  	contract := testContract
  1591  
  1592  	theirMessenger := s.newMessenger()
  1593  	defer TearDownMessenger(&s.Suite, theirMessenger)
  1594  	theirPkString := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
  1595  
  1596  	receiverAddress := crypto.PubkeyToAddress(theirMessenger.identity.PublicKey)
  1597  	receiverAddressString := strings.ToLower(receiverAddress.Hex())
  1598  
  1599  	chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey, s.m.transport)
  1600  	err := s.m.SaveChat(chat)
  1601  	s.Require().NoError(err)
  1602  
  1603  	transactionHash := testTransactionHash
  1604  	signature, err := buildSignature(s.m.identity, &s.m.identity.PublicKey, transactionHash)
  1605  	s.Require().NoError(err)
  1606  
  1607  	response, err := s.m.SendTransaction(context.Background(), theirPkString, value, contract, transactionHash, signature)
  1608  	s.Require().NoError(err)
  1609  	s.Require().NotNil(response)
  1610  	s.Require().Len(response.Chats(), 1)
  1611  	s.Require().Len(response.Messages(), 1)
  1612  
  1613  	senderMessage := response.Messages()[0]
  1614  	s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, senderMessage.ContentType)
  1615  	s.Require().Equal("Transaction sent", senderMessage.Text)
  1616  	s.Require().NotNil(senderMessage.CommandParameters)
  1617  	s.Require().Equal(transactionHash, senderMessage.CommandParameters.TransactionHash)
  1618  	s.Require().Equal(contract, senderMessage.CommandParameters.Contract)
  1619  	s.Require().Equal(value, senderMessage.CommandParameters.Value)
  1620  	s.Require().Equal(signature, senderMessage.CommandParameters.Signature)
  1621  	s.Require().Equal(common.CommandStateTransactionSent, senderMessage.CommandParameters.CommandState)
  1622  	s.Require().NotEmpty(senderMessage.ID)
  1623  	s.Require().Equal("", senderMessage.Replace)
  1624  
  1625  	var transactions []*TransactionToValidate
  1626  	// Wait for the message to reach its destination
  1627  	err = tt.RetryWithBackOff(func() error {
  1628  		var err error
  1629  
  1630  		_, err = theirMessenger.RetrieveAll()
  1631  		if err != nil {
  1632  			return err
  1633  		}
  1634  		transactions, err = theirMessenger.persistence.TransactionsToValidate()
  1635  		if err == nil && len(transactions) == 0 {
  1636  			err = errors.New("no transactions")
  1637  		}
  1638  		return err
  1639  	})
  1640  	s.Require().NoError(err)
  1641  
  1642  	actualTransaction := transactions[0]
  1643  
  1644  	s.Require().Equal(&s.m.identity.PublicKey, actualTransaction.From)
  1645  	s.Require().Equal(transactionHash, actualTransaction.TransactionHash)
  1646  	s.Require().True(actualTransaction.Validate)
  1647  
  1648  	senderAddress := crypto.PubkeyToAddress(s.m.identity.PublicKey)
  1649  
  1650  	client := MockEthClient{}
  1651  	valueBig, ok := big.NewInt(0).SetString(value, 10)
  1652  	s.Require().True(ok)
  1653  	client.messages = make(map[string]MockTransaction)
  1654  	client.messages[transactionHash] = MockTransaction{
  1655  		Status: coretypes.TransactionStatusSuccess,
  1656  		Message: coretypes.NewMessage(
  1657  			senderAddress,
  1658  			&receiverAddress,
  1659  			1,
  1660  			valueBig,
  1661  			0,
  1662  			nil,
  1663  			nil,
  1664  			false,
  1665  		),
  1666  	}
  1667  	theirMessenger.verifyTransactionClient = client
  1668  	response, err = theirMessenger.ValidateTransactions(context.Background(), []types.Address{receiverAddress})
  1669  	s.Require().NoError(err)
  1670  
  1671  	s.Require().NotNil(response)
  1672  	s.Require().Len(response.Chats(), 1)
  1673  	s.Require().Len(response.Messages(), 1)
  1674  
  1675  	receiverMessage := response.Messages()[0]
  1676  	s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, receiverMessage.ContentType)
  1677  
  1678  	s.Require().Equal("Transaction received", receiverMessage.Text)
  1679  	s.Require().NotNil(receiverMessage.CommandParameters)
  1680  	s.Require().Equal(value, receiverMessage.CommandParameters.Value)
  1681  	s.Require().Equal(strings.ToLower(receiverAddress.Hex()), receiverMessage.CommandParameters.Address)
  1682  	s.Require().Equal(transactionHash, receiverMessage.CommandParameters.TransactionHash)
  1683  	s.Require().Equal(receiverAddressString, receiverMessage.CommandParameters.Address)
  1684  	s.Require().Equal("", receiverMessage.CommandParameters.ID)
  1685  	s.Require().Equal(common.CommandStateTransactionSent, receiverMessage.CommandParameters.CommandState)
  1686  	s.Require().Equal(senderMessage.ID, receiverMessage.ID)
  1687  	s.Require().Equal("", receiverMessage.Replace)
  1688  }
  1689  
  1690  func (s *MessengerSuite) TestSendTokenTransaction() {
  1691  	value := testValue
  1692  	contract := testContract
  1693  
  1694  	theirMessenger := s.newMessenger()
  1695  	defer TearDownMessenger(&s.Suite, theirMessenger)
  1696  	theirPkString := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
  1697  
  1698  	receiverAddress := crypto.PubkeyToAddress(theirMessenger.identity.PublicKey)
  1699  	receiverAddressString := strings.ToLower(receiverAddress.Hex())
  1700  
  1701  	chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey, s.m.transport)
  1702  	err := s.m.SaveChat(chat)
  1703  	s.Require().NoError(err)
  1704  
  1705  	transactionHash := testTransactionHash
  1706  	signature, err := buildSignature(s.m.identity, &s.m.identity.PublicKey, transactionHash)
  1707  	s.Require().NoError(err)
  1708  
  1709  	response, err := s.m.SendTransaction(context.Background(), theirPkString, value, contract, transactionHash, signature)
  1710  	s.Require().NoError(err)
  1711  	s.Require().NotNil(response)
  1712  	s.Require().Len(response.Chats(), 1)
  1713  	s.Require().Len(response.Messages(), 1)
  1714  
  1715  	senderMessage := response.Messages()[0]
  1716  	s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, senderMessage.ContentType)
  1717  	s.Require().Equal("Transaction sent", senderMessage.Text)
  1718  	s.Require().NotNil(senderMessage.CommandParameters)
  1719  	s.Require().Equal(transactionHash, senderMessage.CommandParameters.TransactionHash)
  1720  	s.Require().Equal(value, senderMessage.CommandParameters.Value)
  1721  	s.Require().Equal(contract, senderMessage.CommandParameters.Contract)
  1722  	s.Require().Equal(signature, senderMessage.CommandParameters.Signature)
  1723  	s.Require().Equal(common.CommandStateTransactionSent, senderMessage.CommandParameters.CommandState)
  1724  	s.Require().NotEmpty(senderMessage.ID)
  1725  
  1726  	var transactions []*TransactionToValidate
  1727  	// Wait for the message to reach its destination
  1728  	err = tt.RetryWithBackOff(func() error {
  1729  		var err error
  1730  
  1731  		_, err = theirMessenger.RetrieveAll()
  1732  		if err != nil {
  1733  			return err
  1734  		}
  1735  		transactions, err = theirMessenger.persistence.TransactionsToValidate()
  1736  		if err == nil && len(transactions) == 0 {
  1737  			err = errors.New("no transactions")
  1738  		}
  1739  		return err
  1740  	})
  1741  	s.Require().NoError(err)
  1742  
  1743  	actualTransaction := transactions[0]
  1744  
  1745  	s.Require().Equal(&s.m.identity.PublicKey, actualTransaction.From)
  1746  	s.Require().Equal(transactionHash, actualTransaction.TransactionHash)
  1747  	s.Require().True(actualTransaction.Validate)
  1748  
  1749  	senderAddress := crypto.PubkeyToAddress(s.m.identity.PublicKey)
  1750  
  1751  	contractAddress := types.HexToAddress(contract)
  1752  	client := MockEthClient{}
  1753  	valueBig, ok := big.NewInt(0).SetString(value, 10)
  1754  	s.Require().True(ok)
  1755  	client.messages = make(map[string]MockTransaction)
  1756  	client.messages[transactionHash] = MockTransaction{
  1757  		Status: coretypes.TransactionStatusSuccess,
  1758  		Message: coretypes.NewMessage(
  1759  			senderAddress,
  1760  			&contractAddress,
  1761  			1,
  1762  			nil,
  1763  			0,
  1764  			nil,
  1765  			buildData(transferFunction, receiverAddress, valueBig),
  1766  			false,
  1767  		),
  1768  	}
  1769  	theirMessenger.verifyTransactionClient = client
  1770  	response, err = theirMessenger.ValidateTransactions(context.Background(), []types.Address{receiverAddress})
  1771  	s.Require().NoError(err)
  1772  
  1773  	s.Require().NotNil(response)
  1774  	s.Require().Len(response.Chats(), 1)
  1775  	s.Require().Len(response.Messages(), 1)
  1776  
  1777  	receiverMessage := response.Messages()[0]
  1778  	s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, receiverMessage.ContentType)
  1779  
  1780  	s.Require().Equal("Transaction received", receiverMessage.Text)
  1781  	s.Require().NotNil(receiverMessage.CommandParameters)
  1782  	s.Require().Equal(value, receiverMessage.CommandParameters.Value)
  1783  	s.Require().Equal(contract, receiverMessage.CommandParameters.Contract)
  1784  	s.Require().Equal(transactionHash, receiverMessage.CommandParameters.TransactionHash)
  1785  	s.Require().Equal(receiverAddressString, receiverMessage.CommandParameters.Address)
  1786  	s.Require().Equal("", receiverMessage.CommandParameters.ID)
  1787  	s.Require().Equal(common.CommandStateTransactionSent, receiverMessage.CommandParameters.CommandState)
  1788  	s.Require().Equal(senderMessage.ID, receiverMessage.ID)
  1789  	s.Require().Equal(senderMessage.Replace, senderMessage.Replace)
  1790  }
  1791  
  1792  func (s *MessengerSuite) TestAcceptRequestAddressForTransaction() {
  1793  	value := testValue
  1794  	contract := testContract
  1795  	theirMessenger := s.newMessenger()
  1796  	defer TearDownMessenger(&s.Suite, theirMessenger)
  1797  	theirPkString := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
  1798  	myPkString := types.EncodeHex(crypto.FromECDSAPub(&s.m.identity.PublicKey))
  1799  
  1800  	myAddress := crypto.PubkeyToAddress(s.m.identity.PublicKey)
  1801  
  1802  	chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey, s.m.transport)
  1803  	err := s.m.SaveChat(chat)
  1804  	s.Require().NoError(err)
  1805  
  1806  	response, err := s.m.RequestAddressForTransaction(context.Background(), theirPkString, myAddress.Hex(), value, contract)
  1807  	s.Require().NoError(err)
  1808  	s.Require().NotNil(response)
  1809  	s.Require().Len(response.Chats(), 1)
  1810  	s.Require().Len(response.Messages(), 1)
  1811  
  1812  	senderMessage := response.Messages()[0]
  1813  	s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, senderMessage.ContentType)
  1814  	initialCommandID := senderMessage.ID
  1815  
  1816  	s.Require().Equal("Request address for transaction", senderMessage.Text)
  1817  	s.Require().NotNil(senderMessage.CommandParameters)
  1818  	s.Require().Equal(value, senderMessage.CommandParameters.Value)
  1819  	s.Require().Equal(contract, senderMessage.CommandParameters.Contract)
  1820  	s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID)
  1821  	s.Require().Equal(common.CommandStateRequestAddressForTransaction, senderMessage.CommandParameters.CommandState)
  1822  
  1823  	// Wait for the message to reach its destination
  1824  	response, err = WaitOnMessengerResponse(
  1825  		theirMessenger,
  1826  		func(r *MessengerResponse) bool { return len(r.Messages()) > 0 },
  1827  		"no messages",
  1828  	)
  1829  	s.Require().NoError(err)
  1830  
  1831  	s.Require().NotNil(response)
  1832  	s.Require().Len(response.Chats(), 1)
  1833  	s.Require().Len(response.Messages(), 1)
  1834  
  1835  	receiverMessage := response.Messages()[0]
  1836  	s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, receiverMessage.ContentType)
  1837  	s.Require().Equal("Request address for transaction", receiverMessage.Text)
  1838  	s.Require().NotNil(receiverMessage.CommandParameters)
  1839  	s.Require().Equal(value, receiverMessage.CommandParameters.Value)
  1840  	s.Require().Equal(contract, receiverMessage.CommandParameters.Contract)
  1841  	s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID)
  1842  	s.Require().Equal(common.CommandStateRequestAddressForTransaction, receiverMessage.CommandParameters.CommandState)
  1843  	s.Require().Equal(theirPkString, receiverMessage.ChatId)
  1844  
  1845  	// We accept the request
  1846  	response, err = theirMessenger.AcceptRequestAddressForTransaction(context.Background(), receiverMessage.ID, "some-address")
  1847  	s.Require().NoError(err)
  1848  	s.Require().Len(response.Chats(), 1)
  1849  	s.Require().Len(response.Messages(), 1)
  1850  
  1851  	senderMessage = response.Messages()[0]
  1852  	s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, senderMessage.ContentType)
  1853  	s.Require().Equal("Request address for transaction accepted", senderMessage.Text)
  1854  	s.Require().NotNil(senderMessage.CommandParameters)
  1855  	s.Require().Equal(value, senderMessage.CommandParameters.Value)
  1856  	s.Require().Equal(contract, senderMessage.CommandParameters.Contract)
  1857  	s.Require().Equal(common.CommandStateRequestAddressForTransactionAccepted, senderMessage.CommandParameters.CommandState)
  1858  	s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID)
  1859  	s.Require().Equal("some-address", senderMessage.CommandParameters.Address)
  1860  	s.Require().Equal(receiverMessage.ID, senderMessage.Replace)
  1861  
  1862  	// Wait for the message to reach its destination
  1863  	response, err = WaitOnMessengerResponse(
  1864  		s.m,
  1865  		func(r *MessengerResponse) bool { return len(r.Messages()) > 0 },
  1866  		"no messages",
  1867  	)
  1868  	s.Require().NoError(err)
  1869  
  1870  	s.Require().Len(response.Chats(), 1)
  1871  	s.Require().Len(response.Messages(), 1)
  1872  
  1873  	receiverMessage = response.Messages()[0]
  1874  	s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, receiverMessage.ContentType)
  1875  	s.Require().Equal("Request address for transaction accepted", receiverMessage.Text)
  1876  	s.Require().NotNil(receiverMessage.CommandParameters)
  1877  	s.Require().Equal(value, receiverMessage.CommandParameters.Value)
  1878  	s.Require().Equal(contract, receiverMessage.CommandParameters.Contract)
  1879  	s.Require().Equal(common.CommandStateRequestAddressForTransactionAccepted, receiverMessage.CommandParameters.CommandState)
  1880  	s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID)
  1881  	s.Require().Equal("some-address", receiverMessage.CommandParameters.Address)
  1882  	s.Require().Equal(initialCommandID, receiverMessage.Replace)
  1883  	s.Require().Equal(myPkString, receiverMessage.ChatId)
  1884  }
  1885  
  1886  func (s *MessengerSuite) TestDeclineRequestTransaction() {
  1887  	value := testValue
  1888  	contract := testContract
  1889  	receiverAddress := crypto.PubkeyToAddress(s.m.identity.PublicKey)
  1890  	receiverAddressString := strings.ToLower(receiverAddress.Hex())
  1891  	theirMessenger := s.newMessenger()
  1892  	defer TearDownMessenger(&s.Suite, theirMessenger)
  1893  	theirPkString := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
  1894  
  1895  	chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey, s.m.transport)
  1896  	err := s.m.SaveChat(chat)
  1897  	s.Require().NoError(err)
  1898  
  1899  	response, err := s.m.RequestTransaction(context.Background(), theirPkString, value, contract, receiverAddressString)
  1900  	s.Require().NoError(err)
  1901  	s.Require().NotNil(response)
  1902  	s.Require().Len(response.Chats(), 1)
  1903  	s.Require().Len(response.Messages(), 1)
  1904  
  1905  	senderMessage := response.Messages()[0]
  1906  	s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, senderMessage.ContentType)
  1907  	initialCommandID := senderMessage.ID
  1908  
  1909  	s.Require().Equal("Request transaction", senderMessage.Text)
  1910  	s.Require().NotNil(senderMessage.CommandParameters)
  1911  	s.Require().Equal(value, senderMessage.CommandParameters.Value)
  1912  	s.Require().Equal(contract, senderMessage.CommandParameters.Contract)
  1913  	s.Require().Equal(receiverAddressString, senderMessage.CommandParameters.Address)
  1914  	s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID)
  1915  	s.Require().Equal(common.CommandStateRequestTransaction, senderMessage.CommandParameters.CommandState)
  1916  
  1917  	// Wait for the message to reach its destination
  1918  	response, err = WaitOnMessengerResponse(
  1919  		theirMessenger,
  1920  		func(r *MessengerResponse) bool { return len(r.Messages()) > 0 },
  1921  		"no messages",
  1922  	)
  1923  	s.Require().NoError(err)
  1924  
  1925  	s.Require().NotNil(response)
  1926  	s.Require().Len(response.Chats(), 1)
  1927  	s.Require().Len(response.Messages(), 1)
  1928  
  1929  	receiverMessage := response.Messages()[0]
  1930  	s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, receiverMessage.ContentType)
  1931  	s.Require().Equal("Request transaction", receiverMessage.Text)
  1932  	s.Require().NotNil(receiverMessage.CommandParameters)
  1933  	s.Require().Equal(value, receiverMessage.CommandParameters.Value)
  1934  	s.Require().Equal(contract, receiverMessage.CommandParameters.Contract)
  1935  	s.Require().Equal(receiverAddressString, receiverMessage.CommandParameters.Address)
  1936  	s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID)
  1937  	s.Require().Equal(common.CommandStateRequestTransaction, receiverMessage.CommandParameters.CommandState)
  1938  
  1939  	response, err = theirMessenger.DeclineRequestTransaction(context.Background(), initialCommandID)
  1940  	s.Require().NoError(err)
  1941  	s.Require().NotNil(response)
  1942  	s.Require().Len(response.Chats(), 1)
  1943  	s.Require().Len(response.Messages(), 1)
  1944  
  1945  	senderMessage = response.Messages()[0]
  1946  	s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, senderMessage.ContentType)
  1947  
  1948  	s.Require().Equal("Transaction request declined", senderMessage.Text)
  1949  	s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID)
  1950  	s.Require().Equal(receiverMessage.ID, senderMessage.Replace)
  1951  	s.Require().Equal(common.CommandStateRequestTransactionDeclined, senderMessage.CommandParameters.CommandState)
  1952  
  1953  	// Wait for the message to reach its destination
  1954  	response, err = WaitOnMessengerResponse(
  1955  		s.m,
  1956  		func(r *MessengerResponse) bool { return len(r.Messages()) > 0 },
  1957  		"no messages",
  1958  	)
  1959  	s.Require().NoError(err)
  1960  
  1961  	s.Require().NotNil(response)
  1962  	s.Require().Len(response.Chats(), 1)
  1963  	s.Require().Len(response.Messages(), 1)
  1964  
  1965  	receiverMessage = response.Messages()[0]
  1966  	s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, receiverMessage.ContentType)
  1967  
  1968  	s.Require().Equal("Transaction request declined", receiverMessage.Text)
  1969  	s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID)
  1970  	s.Require().Equal(initialCommandID, receiverMessage.Replace)
  1971  	s.Require().Equal(common.CommandStateRequestTransactionDeclined, receiverMessage.CommandParameters.CommandState)
  1972  }
  1973  
  1974  func (s *MessengerSuite) TestRequestTransaction() {
  1975  	value := testValue
  1976  	contract := testContract
  1977  	receiverAddress := crypto.PubkeyToAddress(s.m.identity.PublicKey)
  1978  	receiverAddressString := strings.ToLower(receiverAddress.Hex())
  1979  	theirMessenger := s.newMessenger()
  1980  	defer TearDownMessenger(&s.Suite, theirMessenger)
  1981  	theirPkString := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
  1982  
  1983  	chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey, s.m.transport)
  1984  	err := s.m.SaveChat(chat)
  1985  	s.Require().NoError(err)
  1986  
  1987  	response, err := s.m.RequestTransaction(context.Background(), theirPkString, value, contract, receiverAddressString)
  1988  	s.Require().NoError(err)
  1989  	s.Require().NotNil(response)
  1990  	s.Require().Len(response.Chats(), 1)
  1991  	s.Require().Len(response.Messages(), 1)
  1992  
  1993  	senderMessage := response.Messages()[0]
  1994  	s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, senderMessage.ContentType)
  1995  	initialCommandID := senderMessage.ID
  1996  
  1997  	s.Require().Equal("Request transaction", senderMessage.Text)
  1998  	s.Require().NotNil(senderMessage.CommandParameters)
  1999  	s.Require().Equal(value, senderMessage.CommandParameters.Value)
  2000  	s.Require().Equal(contract, senderMessage.CommandParameters.Contract)
  2001  	s.Require().Equal(receiverAddressString, senderMessage.CommandParameters.Address)
  2002  	s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID)
  2003  	s.Require().Equal(common.CommandStateRequestTransaction, senderMessage.CommandParameters.CommandState)
  2004  
  2005  	// Wait for the message to reach its destination
  2006  	response, err = WaitOnMessengerResponse(
  2007  		theirMessenger,
  2008  		func(r *MessengerResponse) bool { return len(r.Messages()) > 0 },
  2009  		"no messages",
  2010  	)
  2011  	s.Require().NoError(err)
  2012  
  2013  	s.Require().NotNil(response)
  2014  	s.Require().Len(response.Chats(), 1)
  2015  	s.Require().Len(response.Messages(), 1)
  2016  
  2017  	receiverMessage := response.Messages()[0]
  2018  	s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, receiverMessage.ContentType)
  2019  	s.Require().Equal("Request transaction", receiverMessage.Text)
  2020  	s.Require().NotNil(receiverMessage.CommandParameters)
  2021  	s.Require().Equal(value, receiverMessage.CommandParameters.Value)
  2022  	s.Require().Equal(contract, receiverMessage.CommandParameters.Contract)
  2023  	s.Require().Equal(receiverAddressString, receiverMessage.CommandParameters.Address)
  2024  	s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID)
  2025  	s.Require().Equal(common.CommandStateRequestTransaction, receiverMessage.CommandParameters.CommandState)
  2026  
  2027  	transactionHash := "0x412a851ac2ae51cad34a56c8a9cfee55d577ac5e1ac71cf488a2f2093a373799"
  2028  	signature, err := buildSignature(theirMessenger.identity, &theirMessenger.identity.PublicKey, transactionHash)
  2029  	s.Require().NoError(err)
  2030  	response, err = theirMessenger.AcceptRequestTransaction(context.Background(), transactionHash, initialCommandID, signature)
  2031  	s.Require().NoError(err)
  2032  	s.Require().NotNil(response)
  2033  	s.Require().Len(response.Chats(), 1)
  2034  	s.Require().Len(response.Messages(), 1)
  2035  
  2036  	senderMessage = response.Messages()[0]
  2037  	s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, senderMessage.ContentType)
  2038  
  2039  	s.Require().Equal("Transaction sent", senderMessage.Text)
  2040  	s.Require().NotNil(senderMessage.CommandParameters)
  2041  	s.Require().Equal(value, senderMessage.CommandParameters.Value)
  2042  	s.Require().Equal(contract, senderMessage.CommandParameters.Contract)
  2043  	s.Require().Equal(transactionHash, senderMessage.CommandParameters.TransactionHash)
  2044  	s.Require().Equal(receiverAddressString, senderMessage.CommandParameters.Address)
  2045  	s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID)
  2046  	s.Require().Equal(signature, senderMessage.CommandParameters.Signature)
  2047  	s.Require().NotEmpty(senderMessage.ID)
  2048  	s.Require().Equal(receiverMessage.ID, senderMessage.Replace)
  2049  	s.Require().Equal(common.CommandStateTransactionSent, senderMessage.CommandParameters.CommandState)
  2050  
  2051  	var transactions []*TransactionToValidate
  2052  	// Wait for the message to reach its destination
  2053  	err = tt.RetryWithBackOff(func() error {
  2054  		var err error
  2055  
  2056  		_, err = s.m.RetrieveAll()
  2057  		if err != nil {
  2058  			return err
  2059  		}
  2060  		transactions, err = s.m.persistence.TransactionsToValidate()
  2061  		if err == nil && len(transactions) == 0 {
  2062  			err = errors.New("no transactions")
  2063  		}
  2064  		return err
  2065  	})
  2066  	s.Require().NoError(err)
  2067  
  2068  	actualTransaction := transactions[0]
  2069  
  2070  	s.Require().Equal(&theirMessenger.identity.PublicKey, actualTransaction.From)
  2071  	s.Require().Equal(transactionHash, actualTransaction.TransactionHash)
  2072  	s.Require().True(actualTransaction.Validate)
  2073  	s.Require().Equal(initialCommandID, actualTransaction.CommandID)
  2074  
  2075  	senderAddress := crypto.PubkeyToAddress(theirMessenger.identity.PublicKey)
  2076  
  2077  	contractAddress := types.HexToAddress(contract)
  2078  	client := MockEthClient{}
  2079  	valueBig, ok := big.NewInt(0).SetString(value, 10)
  2080  	s.Require().True(ok)
  2081  	client.messages = make(map[string]MockTransaction)
  2082  	client.messages[transactionHash] = MockTransaction{
  2083  		Status: coretypes.TransactionStatusSuccess,
  2084  		Message: coretypes.NewMessage(
  2085  			senderAddress,
  2086  			&contractAddress,
  2087  			1,
  2088  			nil,
  2089  			0,
  2090  			nil,
  2091  			buildData(transferFunction, receiverAddress, valueBig),
  2092  			false,
  2093  		),
  2094  	}
  2095  	s.m.verifyTransactionClient = client
  2096  	response, err = s.m.ValidateTransactions(context.Background(), []types.Address{receiverAddress})
  2097  	s.Require().NoError(err)
  2098  
  2099  	s.Require().NotNil(response)
  2100  	s.Require().Len(response.Chats(), 1)
  2101  	s.Require().Len(response.Messages(), 1)
  2102  
  2103  	receiverMessage = response.Messages()[0]
  2104  	s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, receiverMessage.ContentType)
  2105  
  2106  	s.Require().Equal("Transaction received", receiverMessage.Text)
  2107  	s.Require().NotNil(receiverMessage.CommandParameters)
  2108  	s.Require().Equal(value, receiverMessage.CommandParameters.Value)
  2109  	s.Require().Equal(contract, receiverMessage.CommandParameters.Contract)
  2110  	s.Require().Equal(transactionHash, receiverMessage.CommandParameters.TransactionHash)
  2111  	s.Require().Equal(receiverAddressString, receiverMessage.CommandParameters.Address)
  2112  	s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID)
  2113  	s.Require().Equal(signature, receiverMessage.CommandParameters.Signature)
  2114  	s.Require().Equal(common.CommandStateTransactionSent, receiverMessage.CommandParameters.CommandState)
  2115  	s.Require().Equal(senderMessage.ID, receiverMessage.ID)
  2116  	s.Require().Equal(senderMessage.Replace, senderMessage.Replace)
  2117  }
  2118  
  2119  type MockTransaction struct {
  2120  	Status  coretypes.TransactionStatus
  2121  	Message coretypes.Message
  2122  }
  2123  
  2124  type MockEthClient struct {
  2125  	messages map[string]MockTransaction
  2126  }
  2127  
  2128  func (m MockEthClient) TransactionByHash(ctx context.Context, hash types.Hash) (coretypes.Message, coretypes.TransactionStatus, error) {
  2129  	mockTransaction, ok := m.messages[hash.Hex()]
  2130  	if !ok {
  2131  		return coretypes.Message{}, coretypes.TransactionStatusFailed, nil
  2132  	}
  2133  	return mockTransaction.Message, mockTransaction.Status, nil
  2134  }
  2135  
  2136  func (s *MessengerSuite) TestMessageJSON() {
  2137  	message := &common.Message{
  2138  		ID:          "test-1",
  2139  		LocalChatID: "local-chat-id",
  2140  		Alias:       "alias",
  2141  		ChatMessage: &protobuf.ChatMessage{
  2142  			ChatId:      "remote-chat-id",
  2143  			ContentType: 0,
  2144  			Text:        "test-1",
  2145  			Clock:       1,
  2146  		},
  2147  		From: testPK,
  2148  	}
  2149  
  2150  	_, err := json.Marshal(message)
  2151  	s.Require().NoError(err)
  2152  }
  2153  
  2154  func (s *MessengerSuite) TestSentEventTracking() {
  2155  
  2156  	//when message sent, its sent field should be "false" until we got confirmation
  2157  	chat := CreatePublicChat("test-chat", s.m.transport)
  2158  	err := s.m.SaveChat(chat)
  2159  	s.NoError(err)
  2160  	inputMessage := buildTestMessage(*chat)
  2161  
  2162  	_, err = s.m.SendChatMessage(context.Background(), inputMessage)
  2163  	s.NoError(err)
  2164  
  2165  	rawMessage, err := s.m.persistence.RawMessageByID(inputMessage.ID)
  2166  	s.NoError(err)
  2167  	s.False(rawMessage.Sent)
  2168  
  2169  	//when message sent, its sent field should be true after we got confirmation
  2170  	err = s.m.processSentMessage(inputMessage.ID)
  2171  	s.NoError(err)
  2172  
  2173  	rawMessage, err = s.m.persistence.RawMessageByID(inputMessage.ID)
  2174  	s.NoError(err)
  2175  	s.True(rawMessage.Sent)
  2176  }
  2177  
  2178  func (s *MessengerSuite) TestLastSentField() {
  2179  	//send message
  2180  	chat := CreatePublicChat("test-chat", s.m.transport)
  2181  	err := s.m.SaveChat(chat)
  2182  	s.NoError(err)
  2183  	inputMessage := buildTestMessage(*chat)
  2184  
  2185  	_, err = s.m.SendChatMessage(context.Background(), inputMessage)
  2186  	s.NoError(err)
  2187  
  2188  	rawMessage, err := s.m.persistence.RawMessageByID(inputMessage.ID)
  2189  	s.NoError(err)
  2190  	s.Equal(1, rawMessage.SendCount)
  2191  
  2192  	//make sure LastSent is set
  2193  	s.NotEqual(uint64(0), rawMessage.LastSent, "rawMessage.LastSent should be non-zero after sending")
  2194  }
  2195  
  2196  // TODO rewrite test to use persistence calls, as shouldResendMessage does not contain
  2197  // relevant logic now
  2198  // func (s *MessengerSuite) TestShouldResendEmoji() {
  2199  // 	// shouldn't try to resend non-emoji messages.
  2200  // 	ok, err := s.m.shouldResendMessage(&common.RawMessage{
  2201  // 		MessageType: protobuf.ApplicationMetadataMessage_CONTACT_UPDATE,
  2202  // 		Sent:        false,
  2203  // 		SendCount:   2,
  2204  // 	}, s.m.getTimesource())
  2205  // 	s.Error(err)
  2206  // 	s.False(ok)
  2207  
  2208  // 	// shouldn't try to resend already sent message
  2209  // 	ok, err = s.m.shouldResendMessage(&common.RawMessage{
  2210  // 		MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION,
  2211  // 		Sent:        true,
  2212  // 		SendCount:   1,
  2213  // 	}, s.m.getTimesource())
  2214  // 	s.Error(err)
  2215  // 	s.False(ok)
  2216  
  2217  // 	// messages that already sent to many times shouldn't be resend
  2218  // 	ok, err = s.m.shouldResendMessage(&common.RawMessage{
  2219  // 		MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION,
  2220  // 		Sent:        false,
  2221  // 		SendCount:   s.m.config.messageResendMaxCount + 1,
  2222  // 	}, s.m.getTimesource())
  2223  // 	s.NoError(err)
  2224  // 	s.False(ok)
  2225  
  2226  // 	// message sent one time CAN'T be resend in 15 seconds (only after 30)
  2227  // 	ok, err = s.m.shouldResendMessage(&common.RawMessage{
  2228  // 		MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION,
  2229  // 		Sent:        false,
  2230  // 		SendCount:   1,
  2231  // 		LastSent:    s.m.getTimesource().GetCurrentTime() - 15*uint64(time.Second.Milliseconds()),
  2232  // 	}, s.m.getTimesource())
  2233  // 	s.NoError(err)
  2234  // 	s.False(ok)
  2235  
  2236  // 	// message sent one time CAN be resend in 35 seconds
  2237  // 	ok, err = s.m.shouldResendMessage(&common.RawMessage{
  2238  // 		MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION,
  2239  // 		Sent:        false,
  2240  // 		SendCount:   1,
  2241  // 		LastSent:    s.m.getTimesource().GetCurrentTime() - 35*uint64(time.Second.Milliseconds()),
  2242  // 	}, s.m.getTimesource())
  2243  // 	s.NoError(err)
  2244  // 	s.True(ok)
  2245  
  2246  // 	// message sent three times CAN'T be resend in 100 seconds (only after 120)
  2247  // 	ok, err = s.m.shouldResendMessage(&common.RawMessage{
  2248  // 		MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION,
  2249  // 		Sent:        false,
  2250  // 		SendCount:   3,
  2251  // 		LastSent:    s.m.getTimesource().GetCurrentTime() - 100*uint64(time.Second.Milliseconds()),
  2252  // 	}, s.m.getTimesource())
  2253  // 	s.NoError(err)
  2254  // 	s.False(ok)
  2255  
  2256  // 	// message sent tow times CAN be resend in 65 seconds
  2257  // 	ok, err = s.m.shouldResendMessage(&common.RawMessage{
  2258  // 		MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION,
  2259  // 		Sent:        false,
  2260  // 		SendCount:   3,
  2261  // 		LastSent:    s.m.getTimesource().GetCurrentTime() - 125*uint64(time.Second.Milliseconds()),
  2262  // 	}, s.m.getTimesource())
  2263  // 	s.NoError(err)
  2264  // 	s.True(ok)
  2265  // }
  2266  
  2267  func (s *MessengerSuite) TestSendMessageWithPreviews() {
  2268  	httpServer, err := server.NewMediaServer(s.m.database, nil, nil, nil)
  2269  	s.Require().NoError(err)
  2270  	err = httpServer.SetPort(9876)
  2271  	s.NoError(err)
  2272  	s.m.SetMediaServer(httpServer)
  2273  
  2274  	chat := CreatePublicChat("test-chat", s.m.transport)
  2275  	err = s.m.SaveChat(chat)
  2276  	s.NoError(err)
  2277  	inputMsg := buildTestMessage(*chat)
  2278  
  2279  	contactPublicKey, err := crypto.GenerateKey()
  2280  	s.Require().NoError(err)
  2281  	compressedContactPublicKey := crypto.CompressPubkey(&contactPublicKey.PublicKey)
  2282  	contactID := types.EncodeHex(crypto.FromECDSAPub(&contactPublicKey.PublicKey))
  2283  
  2284  	preview := common.LinkPreview{
  2285  		Type:        protobuf.UnfurledLink_LINK,
  2286  		URL:         "https://github.com",
  2287  		Title:       "Build software better, together",
  2288  		Description: "GitHub is where people build software.",
  2289  		Thumbnail: common.LinkPreviewThumbnail{
  2290  			DataURI: "data:image/png;base64,iVBORw0KGgoAAAANSUg=",
  2291  			Width:   100,
  2292  			Height:  200,
  2293  		},
  2294  		Favicon: common.LinkPreviewThumbnail{
  2295  			DataURI: "data:image/png;base64,iVBORw0KGgoAAAANSUg=",
  2296  		},
  2297  	}
  2298  	inputMsg.LinkPreviews = []common.LinkPreview{preview}
  2299  
  2300  	sentContactPreview := common.StatusLinkPreview{
  2301  		URL: "https://status.app/u/TestUrl",
  2302  		Contact: &common.StatusContactLinkPreview{
  2303  			PublicKey:   contactID,
  2304  			DisplayName: "TestDisplayName",
  2305  			Description: "Test description",
  2306  			Icon: common.LinkPreviewThumbnail{
  2307  				Width:   100,
  2308  				Height:  200,
  2309  				DataURI: "data:image/png;base64,iVBORw0KGgoAAAANSUg=",
  2310  			},
  2311  		},
  2312  	}
  2313  	inputMsg.StatusLinkPreviews = []common.StatusLinkPreview{sentContactPreview}
  2314  
  2315  	_, err = s.m.SendChatMessage(context.Background(), inputMsg)
  2316  	s.NoError(err)
  2317  
  2318  	savedMsgs, _, err := s.m.MessageByChatID(chat.ID, "", 10)
  2319  	s.Require().NoError(err)
  2320  	s.Require().Len(savedMsgs, 1)
  2321  	savedMsg := savedMsgs[0]
  2322  
  2323  	// Test unfurled links have been saved.
  2324  	s.Require().Len(savedMsg.UnfurledLinks, 1)
  2325  	savedLinkProto := savedMsg.UnfurledLinks[0]
  2326  	s.Require().Equal(preview.Type, savedLinkProto.Type)
  2327  	s.Require().Equal(preview.URL, savedLinkProto.Url)
  2328  	s.Require().Equal(preview.Title, savedLinkProto.Title)
  2329  	s.Require().Equal(preview.Description, savedLinkProto.Description)
  2330  
  2331  	// Test the saved link thumbnail can be encoded as a data URI.
  2332  	expectedDataURI, err := images.GetPayloadDataURI(savedLinkProto.ThumbnailPayload)
  2333  	s.Require().NoError(err)
  2334  	s.Require().Equal(preview.Thumbnail.DataURI, expectedDataURI)
  2335  
  2336  	s.Require().Equal(
  2337  		httpServer.MakeLinkPreviewThumbnailURL(inputMsg.ID, preview.URL),
  2338  		savedMsg.LinkPreviews[0].Thumbnail.URL,
  2339  	)
  2340  
  2341  	// Check saved message protobuf fields
  2342  	s.Require().NotNil(savedMsg.UnfurledStatusLinks)
  2343  	s.Require().Len(savedMsg.UnfurledStatusLinks.UnfurledStatusLinks, 1)
  2344  	savedStatusLinkProto := savedMsg.UnfurledStatusLinks.UnfurledStatusLinks[0]
  2345  	s.Require().Equal(sentContactPreview.URL, savedStatusLinkProto.Url)
  2346  	s.Require().NotNil(savedStatusLinkProto.GetContact())
  2347  	s.Require().Nil(savedStatusLinkProto.GetCommunity())
  2348  	s.Require().Nil(savedStatusLinkProto.GetChannel())
  2349  
  2350  	savedContactProto := savedStatusLinkProto.GetContact()
  2351  	s.Require().Equal(compressedContactPublicKey, savedContactProto.PublicKey)
  2352  	s.Require().Equal(sentContactPreview.Contact.DisplayName, savedContactProto.DisplayName)
  2353  	s.Require().Equal(sentContactPreview.Contact.Description, savedContactProto.Description)
  2354  	s.Require().NotNil(savedContactProto.Icon)
  2355  	s.Require().Equal(sentContactPreview.Contact.Icon.Width, int(savedContactProto.Icon.Width))
  2356  	s.Require().Equal(sentContactPreview.Contact.Icon.Height, int(savedContactProto.Icon.Height))
  2357  
  2358  	iconDataURI, err := images.GetPayloadDataURI(savedContactProto.Icon.Payload)
  2359  	s.Require().NoError(err)
  2360  	s.Require().Equal(sentContactPreview.Contact.Icon.DataURI, iconDataURI)
  2361  
  2362  	// Check message `StatusLinkPreviews` properties
  2363  	s.Require().Len(savedMsg.StatusLinkPreviews, 1)
  2364  	savedStatusLinkPreview := savedMsg.StatusLinkPreviews[0]
  2365  	s.Require().Equal(sentContactPreview.URL, savedStatusLinkPreview.URL)
  2366  	s.Require().NotNil(savedStatusLinkPreview.Contact)
  2367  
  2368  	savedContact := savedStatusLinkPreview.Contact
  2369  	s.Require().Equal(sentContactPreview.Contact.PublicKey, savedContact.PublicKey)
  2370  	s.Require().Equal(sentContactPreview.Contact.DisplayName, savedContact.DisplayName)
  2371  	s.Require().Equal(sentContactPreview.Contact.Description, savedContact.Description)
  2372  	s.Require().NotNil(savedContact.Icon)
  2373  	s.Require().Equal(sentContactPreview.Contact.Icon.Width, savedContact.Icon.Width)
  2374  	s.Require().Equal(sentContactPreview.Contact.Icon.Height, savedContact.Icon.Height)
  2375  	expectedIconURL := httpServer.MakeStatusLinkPreviewThumbnailURL(inputMsg.ID, sentContactPreview.URL, "contact-icon")
  2376  	s.Require().Equal(expectedIconURL, savedContact.Icon.URL)
  2377  }
  2378  
  2379  func (s *MessengerSuite) TestMessageSent() {
  2380  	//send message
  2381  	chat := CreatePublicChat("test-chat", s.m.transport)
  2382  	err := s.m.SaveChat(chat)
  2383  	s.NoError(err)
  2384  	inputMessage := buildTestMessage(*chat)
  2385  
  2386  	_, err = s.m.SendChatMessage(context.Background(), inputMessage)
  2387  	s.NoError(err)
  2388  
  2389  	rawMessage, err := s.m.persistence.RawMessageByID(inputMessage.ID)
  2390  	s.NoError(err)
  2391  	s.Equal(1, rawMessage.SendCount)
  2392  	s.False(rawMessage.Sent)
  2393  
  2394  	//imitate chat message sent
  2395  	err = s.m.processSentMessage(inputMessage.ID)
  2396  	s.NoError(err)
  2397  
  2398  	rawMessage, err = s.m.persistence.RawMessageByID(inputMessage.ID)
  2399  	s.NoError(err)
  2400  	s.Equal(1, rawMessage.SendCount)
  2401  	s.True(rawMessage.Sent)
  2402  }
  2403  
  2404  func (s *MessengerSuite) TestProcessSentMessages() {
  2405  	err := s.m.processSentMessage("a")
  2406  	s.Require().NoError(err)
  2407  }
  2408  
  2409  func (s *MessengerSuite) TestResendExpiredEmojis() {
  2410  	//send message
  2411  	chat := CreatePublicChat("test-chat", s.m.transport)
  2412  	err := s.m.SaveChat(chat)
  2413  	s.NoError(err)
  2414  	inputMessage := buildTestMessage(*chat)
  2415  
  2416  	_, err = s.m.SendChatMessage(context.Background(), inputMessage)
  2417  	s.NoError(err)
  2418  
  2419  	//create emoji
  2420  	_, err = s.m.SendEmojiReaction(context.Background(), chat.ID, inputMessage.ID, protobuf.EmojiReaction_SAD)
  2421  	s.Require().NoError(err)
  2422  
  2423  	ids, err := s.m.persistence.RawMessagesIDsByType(protobuf.ApplicationMetadataMessage_EMOJI_REACTION)
  2424  	s.Require().NoError(err)
  2425  	emojiID := ids[0]
  2426  
  2427  	//check that emoji was sent one time
  2428  	rawMessage, err := s.m.persistence.RawMessageByID(emojiID)
  2429  	s.NoError(err)
  2430  	s.False(rawMessage.Sent)
  2431  	s.Equal(1, rawMessage.SendCount)
  2432  
  2433  	//imitate that more than 30 seconds passed since message was sent
  2434  	rawMessage.LastSent = rawMessage.LastSent - 35*uint64(time.Second.Milliseconds())
  2435  	err = s.m.persistence.SaveRawMessage(rawMessage)
  2436  	s.NoError(err)
  2437  	time.Sleep(2 * time.Second)
  2438  
  2439  	//make sure it was resent and SendCount incremented
  2440  	rawMessage, err = s.m.persistence.RawMessageByID(emojiID)
  2441  	s.NoError(err)
  2442  	s.True(rawMessage.SendCount >= 2)
  2443  }
  2444  
  2445  func buildImageWithAlbumIDMessage(chat Chat, albumID string) (*common.Message, error) {
  2446  	file, err := os.Open("../_assets/tests/test.jpg")
  2447  	if err != err {
  2448  		return nil, err
  2449  	}
  2450  	defer file.Close()
  2451  
  2452  	payload, err := io.ReadAll(file)
  2453  	if err != err {
  2454  		return nil, err
  2455  	}
  2456  
  2457  	clock, timestamp := chat.NextClockAndTimestamp(&testTimeSource{})
  2458  	message := common.NewMessage()
  2459  	message.ChatId = chat.ID
  2460  	message.Clock = clock
  2461  	message.Timestamp = timestamp
  2462  	message.WhisperTimestamp = clock
  2463  	message.LocalChatID = chat.ID
  2464  	message.MessageType = protobuf.MessageType_ONE_TO_ONE
  2465  	message.ContentType = protobuf.ChatMessage_IMAGE
  2466  
  2467  	image := protobuf.ImageMessage{
  2468  		Payload: payload,
  2469  		Format:  protobuf.ImageFormat_JPEG,
  2470  		Width:   1200,
  2471  		Height:  1000,
  2472  		AlbumId: albumID,
  2473  	}
  2474  	message.Payload = &protobuf.ChatMessage_Image{Image: &image}
  2475  
  2476  	return message, nil
  2477  }
  2478  
  2479  func buildImageWithoutAlbumIDMessage(chat Chat) (*common.Message, error) {
  2480  	return buildImageWithAlbumIDMessage(chat, "")
  2481  }
  2482  
  2483  type testTimeSource struct{}
  2484  
  2485  func (t *testTimeSource) GetCurrentTime() uint64 {
  2486  	return uint64(time.Now().Unix())
  2487  }
  2488  
  2489  func (s *MessengerSuite) TestSendMessageMention() {
  2490  	// Initialize Alice and Bob's messengers
  2491  	alice, bob := s.m, s.newMessenger()
  2492  	defer TearDownMessenger(&s.Suite, bob)
  2493  
  2494  	// Set display names for Bob and Alice
  2495  	s.Require().NoError(bob.settings.SaveSettingField(settings.DisplayName, "bobby"))
  2496  	s.Require().NoError(alice.settings.SaveSettingField(settings.DisplayName, "Alice"))
  2497  	s.Require().NoError(alice.settings.SaveSettingField(settings.NotificationsEnabled, true))
  2498  
  2499  	// Create one-to-one chats
  2500  	chat, chat2 := CreateOneToOneChat(common.PubkeyToHex(&alice.identity.PublicKey), &alice.identity.PublicKey, bob.transport),
  2501  		CreateOneToOneChat(common.PubkeyToHex(&bob.identity.PublicKey), &bob.identity.PublicKey, alice.transport)
  2502  	s.Require().NoError(bob.SaveChat(chat))
  2503  	s.Require().NoError(alice.SaveChat(chat2))
  2504  
  2505  	// Prepare the message and Send the message from Bob to Alice
  2506  	inputMessage := common.NewMessage()
  2507  	inputMessage.ChatId = chat.ID
  2508  	inputMessage.Text = fmt.Sprintf("@%s talk to @%s", alice.myHexIdentity(), bob.myHexIdentity())
  2509  	inputMessage.ContentType = protobuf.ChatMessage_TEXT_PLAIN
  2510  	_, err := bob.SendChatMessage(context.Background(), inputMessage)
  2511  	s.Require().NoError(err)
  2512  
  2513  	// Wait for Alice to receive the message and make sure it's properly formatted
  2514  	response, err := WaitOnMessengerResponse(alice, func(r *MessengerResponse) bool { return len(r.Notifications()) >= 1 }, "no messages")
  2515  	s.Require().NoError(err)
  2516  	s.Require().Equal("Alice talk to bobby", response.Notifications()[0].Message)
  2517  }