2022-09-14 10:46:11 +00:00
|
|
|
package protocol
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"crypto/ecdsa"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/suite"
|
|
|
|
"go.uber.org/zap"
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
|
|
gethbridge "github.com/status-im/status-go/eth-node/bridge/geth"
|
|
|
|
"github.com/status-im/status-go/eth-node/crypto"
|
|
|
|
"github.com/status-im/status-go/eth-node/types"
|
2023-03-06 13:26:46 +00:00
|
|
|
"github.com/status-im/status-go/multiaccounts/settings"
|
2022-09-14 10:46:11 +00:00
|
|
|
"github.com/status-im/status-go/protocol/encryption/multidevice"
|
|
|
|
"github.com/status-im/status-go/protocol/tt"
|
|
|
|
"github.com/status-im/status-go/services/wallet"
|
|
|
|
"github.com/status-im/status-go/waku"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestMessengerSyncSavedAddressesSuite(t *testing.T) {
|
|
|
|
suite.Run(t, new(MessengerSyncSavedAddressesSuite))
|
|
|
|
}
|
|
|
|
|
|
|
|
type MessengerSyncSavedAddressesSuite struct {
|
|
|
|
suite.Suite
|
|
|
|
main *Messenger // main instance of Messenger paired with `other`
|
|
|
|
other *Messenger
|
|
|
|
privateKey *ecdsa.PrivateKey // private key for the main instance of Messenger
|
|
|
|
|
|
|
|
// If one wants to send messages between different instances of Messenger,
|
|
|
|
// a single Waku service should be shared.
|
|
|
|
shh types.Waku
|
|
|
|
|
|
|
|
logger *zap.Logger
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MessengerSyncSavedAddressesSuite) SetupTest() {
|
|
|
|
s.logger = tt.MustCreateTestLogger()
|
|
|
|
|
|
|
|
config := waku.DefaultConfig
|
|
|
|
config.MinimumAcceptedPoW = 0
|
|
|
|
shh := waku.New(&config, s.logger)
|
|
|
|
s.shh = gethbridge.NewGethWakuWrapper(shh)
|
|
|
|
s.Require().NoError(shh.Start())
|
|
|
|
|
|
|
|
s.main = s.newMessenger(s.shh)
|
|
|
|
s.privateKey = s.main.identity
|
|
|
|
// Start the main messenger in order to receive installations
|
|
|
|
_, err := s.main.Start()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// Create new device and add main account to
|
|
|
|
s.other, err = newMessengerWithKey(s.shh, s.main.identity, s.logger, nil)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// Pair devices (main and other)
|
|
|
|
imOther := &multidevice.InstallationMetadata{
|
|
|
|
Name: "other-device",
|
|
|
|
DeviceType: "other-device-type",
|
|
|
|
}
|
|
|
|
err = s.other.SetInstallationMetadata(s.other.installationID, imOther)
|
|
|
|
s.Require().NoError(err)
|
2023-02-28 12:32:45 +00:00
|
|
|
response, err := s.other.SendPairInstallation(context.Background(), nil)
|
2022-09-14 10:46:11 +00:00
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(response)
|
|
|
|
|
|
|
|
// Wait for the message to reach its destination
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
s.main,
|
|
|
|
func(r *MessengerResponse) bool { return len(r.Installations) > 0 },
|
|
|
|
"installation not received",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
err = s.main.EnableInstallation(s.other.installationID)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MessengerSyncSavedAddressesSuite) TearDownTest() {
|
2023-11-27 17:01:13 +00:00
|
|
|
TearDownMessenger(&s.Suite, s.main)
|
2022-09-14 10:46:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MessengerSyncSavedAddressesSuite) newMessenger(shh types.Waku) *Messenger {
|
|
|
|
privateKey, err := crypto.GenerateKey()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
messenger, err := newMessengerWithKey(s.shh, privateKey, s.logger, nil)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
return messenger
|
|
|
|
}
|
|
|
|
|
|
|
|
// Helpers duplicate of wallet test. Could not import it from saved_addresses_test.go
|
|
|
|
|
|
|
|
func contains[T comparable](container []T, element T, isEqual func(T, T) bool) bool {
|
|
|
|
for _, e := range container {
|
|
|
|
if isEqual(e, element) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func haveSameElements[T comparable](a []T, b []T, isEqual func(T, T) bool) bool {
|
|
|
|
for _, v := range a {
|
|
|
|
if !contains(b, v, isEqual) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func savedAddressDataIsEqual(a, b wallet.SavedAddress) bool {
|
2023-03-06 13:26:46 +00:00
|
|
|
return a.Address == b.Address && a.IsTest == b.IsTest && a.Name == b.Name &&
|
2024-01-09 14:59:54 +00:00
|
|
|
a.ENSName == b.ENSName && a.ChainShortNames == b.ChainShortNames && a.ColorID == b.ColorID
|
2022-09-14 10:46:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MessengerSyncSavedAddressesSuite) TestSyncExistingSavedAddresses() {
|
2023-03-06 13:26:46 +00:00
|
|
|
var isTestChain1 bool = false
|
|
|
|
var isTestChain2 bool = true
|
2022-09-14 10:46:11 +00:00
|
|
|
var testAddress1 = common.Address{1}
|
|
|
|
|
|
|
|
// Add saved addresses to main device
|
|
|
|
sa1 := wallet.SavedAddress{
|
2024-01-09 14:59:54 +00:00
|
|
|
Address: testAddress1,
|
|
|
|
Name: "TestC1A1",
|
|
|
|
IsTest: isTestChain1,
|
2022-09-14 10:46:11 +00:00
|
|
|
}
|
|
|
|
sa2 := wallet.SavedAddress{
|
2024-01-09 14:59:54 +00:00
|
|
|
ENSName: "test.ens.eth",
|
|
|
|
Name: "TestC2A1",
|
|
|
|
IsTest: isTestChain2,
|
2022-09-14 10:46:11 +00:00
|
|
|
}
|
|
|
|
|
2023-08-11 11:28:45 +00:00
|
|
|
savedAddressesManager := s.main.savedAddressesManager
|
2022-09-14 10:46:11 +00:00
|
|
|
|
|
|
|
_, err := savedAddressesManager.UpdateMetadataAndUpsertSavedAddress(sa1)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
_, err = savedAddressesManager.UpdateMetadataAndUpsertSavedAddress(sa2)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// Trigger's a sync between devices
|
2023-01-06 12:21:14 +00:00
|
|
|
err = s.main.SyncDevices(context.Background(), "ens-name", "profile-image", nil)
|
2022-09-14 10:46:11 +00:00
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// Wait and check that saved addresses are synced
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
s.other,
|
|
|
|
func(r *MessengerResponse) bool {
|
2023-02-13 20:09:20 +00:00
|
|
|
if len(r.SavedAddresses()) == 2 {
|
|
|
|
sas := r.SavedAddresses()
|
|
|
|
s.Require().True(haveSameElements([]wallet.SavedAddress{sa1, sa2}, []wallet.SavedAddress{*sas[0], *sas[1]}, savedAddressDataIsEqual))
|
2022-09-14 10:46:11 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
},
|
|
|
|
"expected to receive two changes",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
savedAddresses, err := s.other.savedAddressesManager.GetSavedAddresses()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Equal(2, len(savedAddresses))
|
|
|
|
s.Require().True(haveSameElements([]wallet.SavedAddress{sa1, sa2}, savedAddresses, savedAddressDataIsEqual))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MessengerSyncSavedAddressesSuite) TestSyncSavedAddresses() {
|
2023-03-06 13:26:46 +00:00
|
|
|
var isTestChain1 bool = true
|
2022-09-14 10:46:11 +00:00
|
|
|
var testAddress1 = common.Address{1}
|
|
|
|
|
|
|
|
// Add saved addresses to main device
|
|
|
|
sa1 := wallet.SavedAddress{
|
2024-01-09 14:59:54 +00:00
|
|
|
Address: testAddress1,
|
|
|
|
Name: "TestC1A1",
|
|
|
|
IsTest: isTestChain1,
|
2022-09-14 10:46:11 +00:00
|
|
|
}
|
|
|
|
sa2 := wallet.SavedAddress{
|
2024-01-09 14:59:54 +00:00
|
|
|
ENSName: "test.ens.eth",
|
|
|
|
Name: "TestC1A2",
|
|
|
|
IsTest: isTestChain1,
|
2022-09-14 10:46:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
err := s.main.UpsertSavedAddress(context.Background(), sa1)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
err = s.main.UpsertSavedAddress(context.Background(), sa2)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// Wait and check that saved addresses are synced
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
s.other,
|
|
|
|
func(r *MessengerResponse) bool {
|
2023-02-13 20:09:20 +00:00
|
|
|
if len(r.SavedAddresses()) == 2 {
|
|
|
|
sas := r.SavedAddresses()
|
|
|
|
s.Require().True(haveSameElements([]wallet.SavedAddress{sa1, sa2}, []wallet.SavedAddress{*sas[0], *sas[1]}, savedAddressDataIsEqual))
|
2022-09-14 10:46:11 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
},
|
|
|
|
"expected to receive two changes",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
savedAddresses, err := s.other.savedAddressesManager.GetSavedAddresses()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Equal(2, len(savedAddresses))
|
|
|
|
s.Require().True(haveSameElements([]wallet.SavedAddress{sa1, sa2}, savedAddresses, savedAddressDataIsEqual))
|
|
|
|
}
|
|
|
|
|
2023-03-06 13:26:46 +00:00
|
|
|
func (s *MessengerSyncSavedAddressesSuite) testSyncDeletesOfSavedAddressesWithTestModes(testModeMain bool, testModeOther bool) {
|
|
|
|
var isTestChain1 bool = true
|
|
|
|
var isTestChain2 bool = false
|
2022-09-14 10:46:11 +00:00
|
|
|
var testAddress1 = common.Address{1}
|
2024-01-09 14:59:54 +00:00
|
|
|
var testAddress2 = common.Address{2}
|
2022-09-14 10:46:11 +00:00
|
|
|
|
|
|
|
// Add saved addresses to main device
|
|
|
|
sa1 := wallet.SavedAddress{
|
2024-01-09 14:59:54 +00:00
|
|
|
Address: testAddress1,
|
|
|
|
Name: "TestC1A1",
|
|
|
|
IsTest: isTestChain1,
|
2022-09-14 10:46:11 +00:00
|
|
|
}
|
|
|
|
sa2 := wallet.SavedAddress{
|
2024-01-09 14:59:54 +00:00
|
|
|
Address: testAddress2,
|
|
|
|
Name: "TestC1A2",
|
|
|
|
IsTest: isTestChain2,
|
2022-09-14 10:46:11 +00:00
|
|
|
}
|
|
|
|
|
2023-03-06 13:26:46 +00:00
|
|
|
err := s.main.settings.SaveSettingField(settings.TestNetworksEnabled, testModeMain)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
err = s.other.settings.SaveSettingField(settings.TestNetworksEnabled, testModeOther)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
s.Require().NoError(err)
|
|
|
|
err = s.main.UpsertSavedAddress(context.Background(), sa1)
|
2022-09-14 10:46:11 +00:00
|
|
|
s.Require().NoError(err)
|
|
|
|
err = s.main.UpsertSavedAddress(context.Background(), sa2)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// Wait and check that saved addresses are synced
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
s.other,
|
|
|
|
func(r *MessengerResponse) bool {
|
2023-02-13 20:09:20 +00:00
|
|
|
if len(r.SavedAddresses()) == 2 {
|
|
|
|
sas := r.SavedAddresses()
|
|
|
|
s.Require().True(haveSameElements([]wallet.SavedAddress{sa1, sa2}, []wallet.SavedAddress{*sas[0], *sas[1]}, savedAddressDataIsEqual))
|
2022-09-14 10:46:11 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
},
|
|
|
|
"expected to receive two changes",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
savedAddresses, err := s.other.savedAddressesManager.GetSavedAddresses()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Equal(2, len(savedAddresses))
|
|
|
|
|
2023-03-06 13:26:46 +00:00
|
|
|
// Delete saved addresses with test mode = true and sync with the other device
|
2024-01-09 14:59:54 +00:00
|
|
|
err = s.main.DeleteSavedAddress(context.Background(), sa1.Address, sa1.IsTest)
|
2022-09-14 10:46:11 +00:00
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// Wait and check that saved addresses are synced
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
s.other,
|
|
|
|
func(r *MessengerResponse) bool {
|
2023-02-13 20:09:20 +00:00
|
|
|
if len(r.SavedAddresses()) == 1 {
|
2023-03-06 13:26:46 +00:00
|
|
|
sa := r.SavedAddresses()[0]
|
|
|
|
// We expect the deleted event to report address, ens, isTest
|
|
|
|
s.Require().Equal(sa1.Address, sa.Address)
|
|
|
|
s.Require().Equal(sa1.IsTest, sa.IsTest)
|
|
|
|
s.Require().Equal("", sa.Name)
|
2022-09-14 10:46:11 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
},
|
|
|
|
"expected to receive one change",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
savedAddresses, err = s.other.savedAddressesManager.GetSavedAddresses()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Equal(1, len(savedAddresses))
|
|
|
|
s.Require().True(haveSameElements([]wallet.SavedAddress{sa2}, savedAddresses, savedAddressDataIsEqual))
|
2023-03-06 13:26:46 +00:00
|
|
|
|
|
|
|
// Delete saved addresses with test mode = false and sync with the other device
|
2024-01-09 14:59:54 +00:00
|
|
|
err = s.main.DeleteSavedAddress(context.Background(), sa2.Address, sa2.IsTest)
|
2023-03-06 13:26:46 +00:00
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// Wait and check that saved addresses are synced
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
s.other,
|
|
|
|
func(r *MessengerResponse) bool {
|
|
|
|
if len(r.SavedAddresses()) == 1 {
|
|
|
|
sa := r.SavedAddresses()[0]
|
|
|
|
// We expect the deleted event to report address, ens, isTest
|
|
|
|
s.Require().Equal(sa2.Address, sa.Address)
|
|
|
|
s.Require().Equal(sa2.IsTest, sa.IsTest)
|
|
|
|
s.Require().Equal("", sa.Name)
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
},
|
|
|
|
"expected to receive one change",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
savedAddresses, err = s.other.savedAddressesManager.GetSavedAddresses()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Equal(0, len(savedAddresses))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MessengerSyncSavedAddressesSuite) TestSyncDeletesOfSavedAddressesSameTestModeOnBothDevices() {
|
|
|
|
testModeMain := true
|
|
|
|
testModeOther := testModeMain
|
|
|
|
s.testSyncDeletesOfSavedAddressesWithTestModes(testModeMain, testModeOther)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MessengerSyncSavedAddressesSuite) TestSyncDeletesOfSavedAddressesDifferentTestModeOnDevices() {
|
|
|
|
testModeMain := true
|
|
|
|
testModeOther := !testModeMain
|
|
|
|
s.testSyncDeletesOfSavedAddressesWithTestModes(testModeMain, testModeOther)
|
2022-09-14 10:46:11 +00:00
|
|
|
}
|