Feat: Profile showcase validate collectible ownership (#4737)
* feat: profile showcase checks then presenting collectibles * chore: more obvious CollectiblesManager configuration
This commit is contained in:
parent
01b3f8ace4
commit
eb5bad4868
|
@ -164,6 +164,7 @@ func (m *DefaultTokenManager) GetAllChainIDs() ([]uint64, error) {
|
|||
|
||||
type CollectiblesManager interface {
|
||||
FetchBalancesByOwnerAndContractAddress(ctx context.Context, chainID walletcommon.ChainID, ownerAddress gethcommon.Address, contractAddresses []gethcommon.Address) (thirdparty.TokenBalancesPerContractAddress, error)
|
||||
GetCollectibleOwnership(id thirdparty.CollectibleUniqueID) ([]thirdparty.AccountBalance, error)
|
||||
}
|
||||
|
||||
func (m *DefaultTokenManager) GetBalancesByChain(ctx context.Context, accounts, tokenAddresses []gethcommon.Address, chainIDs []uint64) (BalancesByChain, error) {
|
||||
|
@ -5162,6 +5163,11 @@ func (m *Manager) encryptCommunityDescriptionChannel(community *Community, chann
|
|||
return m.encryptCommunityDescriptionImpl([]byte(community.IDString()+channelID), d)
|
||||
}
|
||||
|
||||
// TODO: add collectiblesManager to messenger intance
|
||||
func (m *Manager) GetCollectiblesManager() CollectiblesManager {
|
||||
return m.collectiblesManager
|
||||
}
|
||||
|
||||
type DecryptCommunityResponse struct {
|
||||
Decrypted bool
|
||||
Description *protobuf.CommunityDescription
|
||||
|
|
|
@ -3,6 +3,7 @@ package communities
|
|||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"image"
|
||||
"image/png"
|
||||
"math"
|
||||
|
@ -114,6 +115,10 @@ func (m *testCollectiblesManager) FetchBalancesByOwnerAndContractAddress(ctx con
|
|||
return m.response[uint64(chainID)][ownerAddress], nil
|
||||
}
|
||||
|
||||
func (m *testCollectiblesManager) GetCollectibleOwnership(id thirdparty.CollectibleUniqueID) ([]thirdparty.AccountBalance, error) {
|
||||
return nil, errors.New("GetCollectibleOwnership is not implemented for testCollectiblesManager")
|
||||
}
|
||||
|
||||
type testTokenManager struct {
|
||||
response map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big
|
||||
}
|
||||
|
|
|
@ -3,8 +3,6 @@ package identity
|
|||
import "errors"
|
||||
|
||||
var ErrorNoAccountProvidedWithTokenOrCollectible = errors.New("no account provided with tokens or collectible")
|
||||
var ErrorDublicateAccountAddress = errors.New("duplicate account address")
|
||||
var ErrorAccountVisibilityLowerThanCollectible = errors.New("account visibility lower than collectible")
|
||||
|
||||
type ProfileShowcaseVisibility int
|
||||
|
||||
|
@ -122,25 +120,5 @@ func Validate(preferences *ProfileShowcasePreferences) error {
|
|||
return ErrorNoAccountProvidedWithTokenOrCollectible
|
||||
}
|
||||
|
||||
accountsMap := make(map[string]*ProfileShowcaseAccountPreference)
|
||||
for _, account := range preferences.Accounts {
|
||||
if _, ok := accountsMap[account.Address]; ok {
|
||||
return ErrorDublicateAccountAddress
|
||||
}
|
||||
accountsMap[account.Address] = account
|
||||
}
|
||||
|
||||
for _, collectible := range preferences.Collectibles {
|
||||
account, ok := accountsMap[collectible.AccountAddress]
|
||||
if !ok {
|
||||
return nil
|
||||
// NOTE: with current wallet collectible implementation we don't know account on this stage
|
||||
// return errorNoAccountAddressForCollectible
|
||||
}
|
||||
if account.ShowcaseVisibility < collectible.ShowcaseVisibility {
|
||||
return ErrorAccountVisibilityLowerThanCollectible
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -451,17 +451,16 @@ func NewMessenger(
|
|||
|
||||
ensVerifier := ens.New(node, logger, transp, database, c.verifyENSURL, c.verifyENSContractAddress)
|
||||
|
||||
var walletAPI *wallet.API
|
||||
if c.walletService != nil {
|
||||
walletAPI = wallet.NewAPI(c.walletService)
|
||||
}
|
||||
|
||||
managerOptions := []communities.ManagerOption{
|
||||
communities.WithAccountManager(c.accountsManager),
|
||||
}
|
||||
|
||||
if walletAPI != nil {
|
||||
var walletAPI *wallet.API
|
||||
if c.walletService != nil {
|
||||
walletAPI = wallet.NewAPI(c.walletService)
|
||||
managerOptions = append(managerOptions, communities.WithCollectiblesManager(walletAPI))
|
||||
} else if c.collectiblesManager != nil {
|
||||
managerOptions = append(managerOptions, communities.WithCollectiblesManager(c.collectiblesManager))
|
||||
}
|
||||
|
||||
if c.tokenManager != nil {
|
||||
|
|
|
@ -159,7 +159,7 @@ func (s *MessengerBackupSuite) TestBackupProfile() {
|
|||
})
|
||||
s.Require().NoError(err)
|
||||
|
||||
profileShowcasePreferences := DummyProfileShowcasePreferences()
|
||||
profileShowcasePreferences := DummyProfileShowcasePreferences(false)
|
||||
err = bob1.SetProfileShowcasePreferences(profileShowcasePreferences, false)
|
||||
s.Require().NoError(err)
|
||||
|
||||
|
|
|
@ -92,6 +92,7 @@ type config struct {
|
|||
httpServer *server.MediaServer
|
||||
rpcClient *rpc.Client
|
||||
tokenManager communities.TokenManager
|
||||
collectiblesManager communities.CollectiblesManager
|
||||
accountsManager account.Manager
|
||||
|
||||
verifyTransactionClient EthClient
|
||||
|
@ -394,6 +395,13 @@ func WithTokenManager(tokenManager communities.TokenManager) Option {
|
|||
}
|
||||
}
|
||||
|
||||
func WithCollectiblesManager(collectiblesManager communities.CollectiblesManager) Option {
|
||||
return func(c *config) error {
|
||||
c.collectiblesManager = collectiblesManager
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func WithAccountManager(accountManager account.Manager) Option {
|
||||
return func(c *config) error {
|
||||
c.accountsManager = accountManager
|
||||
|
|
|
@ -6,21 +6,98 @@ import (
|
|||
"crypto/ecdsa"
|
||||
crand "crypto/rand"
|
||||
"errors"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"sort"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"go.uber.org/zap"
|
||||
|
||||
eth_common "github.com/ethereum/go-ethereum/common"
|
||||
|
||||
"github.com/status-im/status-go/eth-node/crypto"
|
||||
"github.com/status-im/status-go/multiaccounts/accounts"
|
||||
"github.com/status-im/status-go/protocol/common"
|
||||
"github.com/status-im/status-go/protocol/communities"
|
||||
"github.com/status-im/status-go/protocol/identity"
|
||||
"github.com/status-im/status-go/protocol/protobuf"
|
||||
"github.com/status-im/status-go/services/wallet/bigint"
|
||||
w_common "github.com/status-im/status-go/services/wallet/common"
|
||||
"github.com/status-im/status-go/services/wallet/thirdparty"
|
||||
)
|
||||
|
||||
var errorDecryptingPayloadEncryptionKey = errors.New("decrypting the payload encryption key resulted in no error and a nil key")
|
||||
var errorConvertCollectibleTokenIDToInt = errors.New("failed to convert collectible token id to bigint")
|
||||
var errorNoAccountPresentedForCollectible = errors.New("account holding the collectible is not presented in the profile showcase")
|
||||
var errorDublicateAccountAddress = errors.New("duplicate account address")
|
||||
var errorAccountVisibilityLowerThanCollectible = errors.New("account visibility lower than collectible")
|
||||
|
||||
func toCollectibleUniqueID(contractAddress string, tokenID string, chainID uint64) (thirdparty.CollectibleUniqueID, error) {
|
||||
tokenIDInt := new(big.Int)
|
||||
tokenIDInt, isTokenIDOk := tokenIDInt.SetString(tokenID, 10)
|
||||
if !isTokenIDOk {
|
||||
return thirdparty.CollectibleUniqueID{}, errorConvertCollectibleTokenIDToInt
|
||||
}
|
||||
|
||||
return thirdparty.CollectibleUniqueID{
|
||||
ContractID: thirdparty.ContractID{
|
||||
ChainID: w_common.ChainID(chainID),
|
||||
Address: eth_common.HexToAddress(contractAddress),
|
||||
},
|
||||
TokenID: &bigint.BigInt{Int: tokenIDInt},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *Messenger) fetchCollectibleOwner(contractAddress string, tokenID string, chainID uint64) ([]thirdparty.AccountBalance, error) {
|
||||
collectibleID, err := toCollectibleUniqueID(contractAddress, tokenID, chainID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
balance, err := m.communitiesManager.GetCollectiblesManager().GetCollectibleOwnership(collectibleID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return balance, nil
|
||||
}
|
||||
|
||||
func (m *Messenger) validateCollectiblesOwnership(accounts []*identity.ProfileShowcaseAccountPreference,
|
||||
collectibles []*identity.ProfileShowcaseCollectiblePreference) error {
|
||||
accountsMap := make(map[string]identity.ProfileShowcaseVisibility)
|
||||
|
||||
for _, accountProfile := range accounts {
|
||||
if _, ok := accountsMap[accountProfile.Address]; ok {
|
||||
return errorDublicateAccountAddress
|
||||
}
|
||||
accountsMap[accountProfile.Address] = accountProfile.ShowcaseVisibility
|
||||
}
|
||||
|
||||
for _, collectibleProfile := range collectibles {
|
||||
balances, err := m.fetchCollectibleOwner(collectibleProfile.ContractAddress, collectibleProfile.TokenID,
|
||||
collectibleProfile.ChainID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// NOTE: ERC721 tokens can have only a single holder
|
||||
// but ERC1155 which can be supported later can have more than one holder and balances > 1
|
||||
found := false
|
||||
for _, balance := range balances {
|
||||
if accountShowcaseVisibility, ok := accountsMap[balance.Address.String()]; ok {
|
||||
if accountShowcaseVisibility < collectibleProfile.ShowcaseVisibility {
|
||||
return errorAccountVisibilityLowerThanCollectible
|
||||
}
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return errorNoAccountPresentedForCollectible
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Messenger) toProfileShowcaseCommunityProto(preferences []*identity.ProfileShowcaseCommunityPreference, visibility identity.ProfileShowcaseVisibility) []*protobuf.ProfileShowcaseCommunity {
|
||||
entries := []*protobuf.ProfileShowcaseCommunity{}
|
||||
|
@ -182,15 +259,16 @@ func (m *Messenger) fromProfileShowcaseAccountProto(messages []*protobuf.Profile
|
|||
|
||||
func (m *Messenger) fromProfileShowcaseCollectibleProto(messages []*protobuf.ProfileShowcaseCollectible) []*identity.ProfileShowcaseCollectible {
|
||||
entries := []*identity.ProfileShowcaseCollectible{}
|
||||
for _, entry := range messages {
|
||||
entries = append(entries, &identity.ProfileShowcaseCollectible{
|
||||
ContractAddress: entry.ContractAddress,
|
||||
ChainID: entry.ChainId,
|
||||
TokenID: entry.TokenId,
|
||||
CommunityID: entry.CommunityId,
|
||||
AccountAddress: entry.AccountAddress,
|
||||
Order: int(entry.Order),
|
||||
})
|
||||
for _, message := range messages {
|
||||
entry := &identity.ProfileShowcaseCollectible{
|
||||
ContractAddress: message.ContractAddress,
|
||||
ChainID: message.ChainId,
|
||||
TokenID: message.TokenId,
|
||||
CommunityID: message.CommunityId,
|
||||
AccountAddress: message.AccountAddress,
|
||||
Order: int(message.Order),
|
||||
}
|
||||
entries = append(entries, entry)
|
||||
}
|
||||
return entries
|
||||
}
|
||||
|
@ -230,6 +308,11 @@ func (m *Messenger) setProfileShowcasePreferences(preferences *identity.ProfileS
|
|||
return err
|
||||
}
|
||||
|
||||
err = m.validateCollectiblesOwnership(preferences.Accounts, preferences.Collectibles)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = m.persistence.SaveProfileShowcasePreferences(preferences)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -2,10 +2,17 @@ package protocol
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"errors"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
"go.uber.org/zap"
|
||||
|
||||
gethcommon "github.com/ethereum/go-ethereum/common"
|
||||
"github.com/status-im/status-go/appdatabase"
|
||||
gethbridge "github.com/status-im/status-go/eth-node/bridge/geth"
|
||||
"github.com/status-im/status-go/eth-node/crypto"
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"github.com/status-im/status-go/multiaccounts/accounts"
|
||||
|
@ -13,14 +20,97 @@ import (
|
|||
"github.com/status-im/status-go/protocol/identity"
|
||||
"github.com/status-im/status-go/protocol/protobuf"
|
||||
"github.com/status-im/status-go/protocol/requests"
|
||||
"github.com/status-im/status-go/protocol/sqlite"
|
||||
"github.com/status-im/status-go/protocol/tt"
|
||||
"github.com/status-im/status-go/services/wallet/bigint"
|
||||
walletCommon "github.com/status-im/status-go/services/wallet/common"
|
||||
"github.com/status-im/status-go/services/wallet/thirdparty"
|
||||
"github.com/status-im/status-go/t/helpers"
|
||||
"github.com/status-im/status-go/waku"
|
||||
)
|
||||
|
||||
type CollectiblesManagerMock struct {
|
||||
response map[thirdparty.CollectibleUniqueID][]thirdparty.AccountBalance
|
||||
}
|
||||
|
||||
func (m *CollectiblesManagerMock) FetchBalancesByOwnerAndContractAddress(ctx context.Context, chainID walletCommon.ChainID,
|
||||
ownerAddress gethcommon.Address, contractAddresses []gethcommon.Address) (thirdparty.TokenBalancesPerContractAddress, error) {
|
||||
return nil, errors.New("FetchBalancesByOwnerAndContractAddress is not implemented for testCollectiblesManager")
|
||||
}
|
||||
|
||||
func (m *CollectiblesManagerMock) GetCollectibleOwnership(requestedID thirdparty.CollectibleUniqueID) ([]thirdparty.AccountBalance, error) {
|
||||
// NOTE: TokenID inside of thirdparty.CollectibleUniqueID is a pointer so m.response[id] is now working
|
||||
for id, balances := range m.response {
|
||||
if id.ContractID.Address == requestedID.ContractID.Address &&
|
||||
id.ContractID.ChainID == requestedID.ContractID.ChainID {
|
||||
return balances, nil
|
||||
}
|
||||
}
|
||||
return []thirdparty.AccountBalance{}, nil
|
||||
}
|
||||
|
||||
func (m *CollectiblesManagerMock) SetResponse(id thirdparty.CollectibleUniqueID, balances []thirdparty.AccountBalance) {
|
||||
if m.response == nil {
|
||||
m.response = map[thirdparty.CollectibleUniqueID][]thirdparty.AccountBalance{}
|
||||
}
|
||||
m.response[id] = balances
|
||||
}
|
||||
|
||||
func TestMessengerProfileShowcaseSuite(t *testing.T) { // nolint: deadcode,unused
|
||||
suite.Run(t, new(TestMessengerProfileShowcase))
|
||||
}
|
||||
|
||||
type TestMessengerProfileShowcase struct {
|
||||
MessengerBaseTestSuite
|
||||
suite.Suite
|
||||
m *Messenger // main instance of 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
|
||||
collectiblesMock *CollectiblesManagerMock
|
||||
}
|
||||
|
||||
func (s *TestMessengerProfileShowcase) 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.m = s.newMessengerForProfileShowcase()
|
||||
s.privateKey = s.m.identity
|
||||
}
|
||||
|
||||
func (s *TestMessengerProfileShowcase) TearDownTest() {
|
||||
TearDownMessenger(&s.Suite, s.m)
|
||||
_ = s.logger.Sync()
|
||||
}
|
||||
|
||||
func (s *TestMessengerProfileShowcase) newMessengerForProfileShowcase() *Messenger {
|
||||
db, err := helpers.SetupTestMemorySQLDB(appdatabase.DbInitializer{})
|
||||
s.NoError(err, "creating sqlite db instance")
|
||||
err = sqlite.Migrate(db)
|
||||
s.NoError(err, "protocol migrate")
|
||||
|
||||
privateKey, err := crypto.GenerateKey()
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.collectiblesMock = &CollectiblesManagerMock{}
|
||||
|
||||
options := []Option{
|
||||
WithCollectiblesManager(s.collectiblesMock),
|
||||
}
|
||||
|
||||
m, err := newMessengerWithKey(s.shh, privateKey, s.logger, options)
|
||||
s.Require().NoError(err)
|
||||
|
||||
_, err = m.Start()
|
||||
s.Require().NoError(err)
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func (s *TestMessengerProfileShowcase) mutualContact(theirMessenger *Messenger) {
|
||||
|
@ -113,8 +203,22 @@ func (s *TestMessengerProfileShowcase) verifiedContact(theirMessenger *Messenger
|
|||
}
|
||||
|
||||
func (s *TestMessengerProfileShowcase) TestSaveAndGetProfileShowcasePreferences() {
|
||||
request := DummyProfileShowcasePreferences()
|
||||
err := s.m.SetProfileShowcasePreferences(request, false)
|
||||
request := DummyProfileShowcasePreferences(true)
|
||||
|
||||
// Provide collectible balances test response
|
||||
collectible := request.Collectibles[0]
|
||||
collectibleID, err := toCollectibleUniqueID(collectible.ContractAddress, collectible.TokenID, collectible.ChainID)
|
||||
s.Require().NoError(err)
|
||||
balances := []thirdparty.AccountBalance{
|
||||
thirdparty.AccountBalance{
|
||||
Address: gethcommon.HexToAddress(request.Accounts[0].Address),
|
||||
Balance: &bigint.BigInt{Int: big.NewInt(5)},
|
||||
TxTimestamp: 0,
|
||||
},
|
||||
}
|
||||
s.collectiblesMock.SetResponse(collectibleID, balances)
|
||||
|
||||
err = s.m.SetProfileShowcasePreferences(request, false)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Restored preferences shoulf be same as stored
|
||||
|
@ -149,7 +253,7 @@ func (s *TestMessengerProfileShowcase) TestSaveAndGetProfileShowcasePreferences(
|
|||
|
||||
func (s *TestMessengerProfileShowcase) TestFailToSaveProfileShowcasePreferencesWithWrongVisibility() {
|
||||
accountEntry := &identity.ProfileShowcaseAccountPreference{
|
||||
Address: "0x32433445133424",
|
||||
Address: "0x0000000000000000000000000032433445133424",
|
||||
Name: "Status Account",
|
||||
ColorID: "blue",
|
||||
Emoji: ">:-]",
|
||||
|
@ -159,10 +263,9 @@ func (s *TestMessengerProfileShowcase) TestFailToSaveProfileShowcasePreferencesW
|
|||
|
||||
collectibleEntry := &identity.ProfileShowcaseCollectiblePreference{
|
||||
ContractAddress: "0x12378534257568678487683576",
|
||||
ChainID: 8,
|
||||
TokenID: "0x12321389592999f903",
|
||||
ChainID: 11155111,
|
||||
TokenID: "12321389592999903",
|
||||
CommunityID: "0x01312357798976535",
|
||||
AccountAddress: "0x32433445133424",
|
||||
ShowcaseVisibility: identity.ProfileShowcaseVisibilityContacts,
|
||||
Order: 17,
|
||||
}
|
||||
|
@ -172,13 +275,26 @@ func (s *TestMessengerProfileShowcase) TestFailToSaveProfileShowcasePreferencesW
|
|||
Collectibles: []*identity.ProfileShowcaseCollectiblePreference{collectibleEntry},
|
||||
}
|
||||
|
||||
err := s.m.SetProfileShowcasePreferences(request, false)
|
||||
s.Require().Equal(identity.ErrorAccountVisibilityLowerThanCollectible, err)
|
||||
// Provide collectible balances test response
|
||||
collectible := request.Collectibles[0]
|
||||
collectibleID, err := toCollectibleUniqueID(collectible.ContractAddress, collectible.TokenID, collectible.ChainID)
|
||||
s.Require().NoError(err)
|
||||
balances := []thirdparty.AccountBalance{
|
||||
thirdparty.AccountBalance{
|
||||
Address: gethcommon.HexToAddress(request.Accounts[0].Address),
|
||||
Balance: &bigint.BigInt{Int: big.NewInt(5)},
|
||||
TxTimestamp: 0,
|
||||
},
|
||||
}
|
||||
s.collectiblesMock.SetResponse(collectibleID, balances)
|
||||
|
||||
err = s.m.SetProfileShowcasePreferences(request, false)
|
||||
s.Require().Equal(errorAccountVisibilityLowerThanCollectible, err)
|
||||
}
|
||||
|
||||
func (s *TestMessengerProfileShowcase) TestEncryptAndDecryptProfileShowcaseEntries() {
|
||||
// Add mutual contact
|
||||
theirMessenger := s.newMessenger()
|
||||
theirMessenger := s.newMessengerForProfileShowcase()
|
||||
_, err := theirMessenger.Start()
|
||||
s.Require().NoError(err)
|
||||
defer TearDownMessenger(&s.Suite, theirMessenger)
|
||||
|
@ -208,8 +324,8 @@ func (s *TestMessengerProfileShowcase) TestEncryptAndDecryptProfileShowcaseEntri
|
|||
Collectibles: []*protobuf.ProfileShowcaseCollectible{
|
||||
&protobuf.ProfileShowcaseCollectible{
|
||||
ContractAddress: "0x12378534257568678487683576",
|
||||
ChainId: 7,
|
||||
TokenId: "0x12321389592999f903",
|
||||
ChainId: 1,
|
||||
TokenId: "12321389592999903",
|
||||
AccountAddress: "0x32433445133424",
|
||||
CommunityId: "0x12378534257568678487683576",
|
||||
Order: 0,
|
||||
|
@ -232,12 +348,12 @@ func (s *TestMessengerProfileShowcase) TestEncryptAndDecryptProfileShowcaseEntri
|
|||
UnverifiedTokens: []*protobuf.ProfileShowcaseUnverifiedToken{
|
||||
&protobuf.ProfileShowcaseUnverifiedToken{
|
||||
ContractAddress: "0x454525452023452",
|
||||
ChainId: 3,
|
||||
ChainId: 11155111,
|
||||
Order: 0,
|
||||
},
|
||||
&protobuf.ProfileShowcaseUnverifiedToken{
|
||||
ContractAddress: "0x12312323323233",
|
||||
ChainId: 2,
|
||||
ChainId: 1,
|
||||
Order: 1,
|
||||
},
|
||||
},
|
||||
|
@ -302,7 +418,7 @@ func (s *TestMessengerProfileShowcase) TestShareShowcasePreferences() {
|
|||
s.Require().NoError(err)
|
||||
|
||||
// Add mutual contact
|
||||
mutualContact := s.newMessenger()
|
||||
mutualContact := s.newMessengerForProfileShowcase()
|
||||
_, err = mutualContact.Start()
|
||||
s.Require().NoError(err)
|
||||
defer TearDownMessenger(&s.Suite, mutualContact)
|
||||
|
@ -310,7 +426,7 @@ func (s *TestMessengerProfileShowcase) TestShareShowcasePreferences() {
|
|||
s.mutualContact(mutualContact)
|
||||
|
||||
// Add identity verified contact
|
||||
verifiedContact := s.newMessenger()
|
||||
verifiedContact := s.newMessengerForProfileShowcase()
|
||||
_, err = verifiedContact.Start()
|
||||
s.Require().NoError(err)
|
||||
defer TearDownMessenger(&s.Suite, verifiedContact)
|
||||
|
@ -319,7 +435,21 @@ func (s *TestMessengerProfileShowcase) TestShareShowcasePreferences() {
|
|||
s.verifiedContact(verifiedContact)
|
||||
|
||||
// Save preferences to dispatch changes
|
||||
request := DummyProfileShowcasePreferences()
|
||||
request := DummyProfileShowcasePreferences(true)
|
||||
|
||||
// Provide collectible balances test response
|
||||
collectible := request.Collectibles[0]
|
||||
collectibleID, err := toCollectibleUniqueID(collectible.ContractAddress, collectible.TokenID, collectible.ChainID)
|
||||
s.Require().NoError(err)
|
||||
balances := []thirdparty.AccountBalance{
|
||||
thirdparty.AccountBalance{
|
||||
Address: gethcommon.HexToAddress(request.Accounts[0].Address),
|
||||
Balance: &bigint.BigInt{Int: big.NewInt(1)},
|
||||
TxTimestamp: 32443424,
|
||||
},
|
||||
}
|
||||
s.collectiblesMock.SetResponse(collectibleID, balances)
|
||||
|
||||
err = s.m.SetProfileShowcasePreferences(request, false)
|
||||
s.Require().NoError(err)
|
||||
|
||||
|
@ -433,7 +563,7 @@ func (s *TestMessengerProfileShowcase) TestProfileShowcaseProofOfMembershipUnenc
|
|||
s.Require().NoError(err)
|
||||
|
||||
// Add bob as a mutual contact
|
||||
bob := s.newMessenger()
|
||||
bob := s.newMessengerForProfileShowcase()
|
||||
_, err = bob.Start()
|
||||
s.Require().NoError(err)
|
||||
defer TearDownMessenger(&s.Suite, bob)
|
||||
|
@ -500,7 +630,7 @@ func (s *TestMessengerProfileShowcase) TestProfileShowcaseProofOfMembershipEncry
|
|||
s.Require().NoError(err)
|
||||
|
||||
// Add bob as a mutual contact
|
||||
bob := s.newMessenger()
|
||||
bob := s.newMessengerForProfileShowcase()
|
||||
_, err = bob.Start()
|
||||
s.Require().NoError(err)
|
||||
defer TearDownMessenger(&s.Suite, bob)
|
||||
|
|
|
@ -414,12 +414,12 @@ func RandomBytes(length int) []byte {
|
|||
return out
|
||||
}
|
||||
|
||||
func DummyProfileShowcasePreferences() *identity.ProfileShowcasePreferences {
|
||||
return &identity.ProfileShowcasePreferences{
|
||||
func DummyProfileShowcasePreferences(withCollectibles bool) *identity.ProfileShowcasePreferences {
|
||||
preferences := &identity.ProfileShowcasePreferences{
|
||||
Communities: []*identity.ProfileShowcaseCommunityPreference{}, // empty to avoid fetching
|
||||
Accounts: []*identity.ProfileShowcaseAccountPreference{
|
||||
{
|
||||
Address: "0x32433445133424",
|
||||
Address: "0x0000000000000000000000000033433445133423",
|
||||
Name: "Status Account",
|
||||
ColorID: "blue",
|
||||
Emoji: "-_-",
|
||||
|
@ -427,7 +427,7 @@ func DummyProfileShowcasePreferences() *identity.ProfileShowcasePreferences {
|
|||
Order: 0,
|
||||
},
|
||||
{
|
||||
Address: "0x3845354643324",
|
||||
Address: "0x0000000000000000000000000032433445133424",
|
||||
Name: "Money Box",
|
||||
ColorID: "red",
|
||||
Emoji: ":o)",
|
||||
|
@ -435,17 +435,6 @@ func DummyProfileShowcasePreferences() *identity.ProfileShowcasePreferences {
|
|||
Order: 1,
|
||||
},
|
||||
},
|
||||
Collectibles: []*identity.ProfileShowcaseCollectiblePreference{
|
||||
{
|
||||
ContractAddress: "0x12378534257568678487683576",
|
||||
ChainID: 1,
|
||||
TokenID: "0x12321389592999f903",
|
||||
CommunityID: "0x01312357798976535",
|
||||
AccountAddress: "0x32433445133424",
|
||||
ShowcaseVisibility: identity.ProfileShowcaseVisibilityEveryone,
|
||||
Order: 0,
|
||||
},
|
||||
},
|
||||
VerifiedTokens: []*identity.ProfileShowcaseVerifiedTokenPreference{
|
||||
{
|
||||
Symbol: "ETH",
|
||||
|
@ -466,16 +455,34 @@ func DummyProfileShowcasePreferences() *identity.ProfileShowcasePreferences {
|
|||
UnverifiedTokens: []*identity.ProfileShowcaseUnverifiedTokenPreference{
|
||||
{
|
||||
ContractAddress: "0x454525452023452",
|
||||
ChainID: 3,
|
||||
ChainID: 11155111,
|
||||
ShowcaseVisibility: identity.ProfileShowcaseVisibilityEveryone,
|
||||
Order: 0,
|
||||
},
|
||||
{
|
||||
ContractAddress: "0x12312323323233",
|
||||
ChainID: 6,
|
||||
ChainID: 1,
|
||||
ShowcaseVisibility: identity.ProfileShowcaseVisibilityContacts,
|
||||
Order: 1,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if withCollectibles {
|
||||
preferences.Collectibles = []*identity.ProfileShowcaseCollectiblePreference{
|
||||
{
|
||||
ContractAddress: "0x12378534257568678487683576",
|
||||
ChainID: 1,
|
||||
TokenID: "12321389592999903",
|
||||
CommunityID: "0x01312357798976535",
|
||||
AccountAddress: "0x32433445133424",
|
||||
ShowcaseVisibility: identity.ProfileShowcaseVisibilityEveryone,
|
||||
Order: 0,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
preferences.Collectibles = []*identity.ProfileShowcaseCollectiblePreference{}
|
||||
}
|
||||
|
||||
return preferences
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ func (s *TestProfileShowcasePersistence) TestProfileShowcasePreferences() {
|
|||
},
|
||||
Accounts: []*identity.ProfileShowcaseAccountPreference{
|
||||
&identity.ProfileShowcaseAccountPreference{
|
||||
Address: "0x32433445133424",
|
||||
Address: "0x0000000000000000000000000032433445133422",
|
||||
Name: "Status Account",
|
||||
ColorID: "blue",
|
||||
Emoji: "-_-",
|
||||
|
@ -39,7 +39,7 @@ func (s *TestProfileShowcasePersistence) TestProfileShowcasePreferences() {
|
|||
Order: 0,
|
||||
},
|
||||
&identity.ProfileShowcaseAccountPreference{
|
||||
Address: "0x3845354643324",
|
||||
Address: "0x0000000000000000000000000032433445133424",
|
||||
Name: "Money Box",
|
||||
ColorID: "red",
|
||||
Emoji: ":o)",
|
||||
|
@ -50,8 +50,8 @@ func (s *TestProfileShowcasePersistence) TestProfileShowcasePreferences() {
|
|||
Collectibles: []*identity.ProfileShowcaseCollectiblePreference{
|
||||
&identity.ProfileShowcaseCollectiblePreference{
|
||||
ContractAddress: "0x12378534257568678487683576",
|
||||
ChainID: 3,
|
||||
TokenID: "0x12321389592999f903",
|
||||
ChainID: 11155111,
|
||||
TokenID: "123213895929994903",
|
||||
CommunityID: "0x01312357798976535",
|
||||
AccountAddress: "0x32433445133424",
|
||||
ShowcaseVisibility: identity.ProfileShowcaseVisibilityEveryone,
|
||||
|
@ -85,7 +85,7 @@ func (s *TestProfileShowcasePersistence) TestProfileShowcasePreferences() {
|
|||
},
|
||||
&identity.ProfileShowcaseUnverifiedTokenPreference{
|
||||
ContractAddress: "0x12312323323233",
|
||||
ChainID: 2,
|
||||
ChainID: 11155111,
|
||||
CommunityID: "",
|
||||
ShowcaseVisibility: identity.ProfileShowcaseVisibilityContacts,
|
||||
Order: 1,
|
||||
|
@ -153,7 +153,7 @@ func (s *TestProfileShowcasePersistence) TestProfileShowcaseContacts() {
|
|||
},
|
||||
&identity.ProfileShowcaseAccount{
|
||||
ContactID: "contact_1",
|
||||
Address: "0x3845354643324",
|
||||
Address: "0x0000000000000000000000000032433445133424",
|
||||
Name: "Money Box",
|
||||
ColorID: "red",
|
||||
Emoji: ":o)",
|
||||
|
@ -163,8 +163,8 @@ func (s *TestProfileShowcasePersistence) TestProfileShowcaseContacts() {
|
|||
Collectibles: []*identity.ProfileShowcaseCollectible{
|
||||
&identity.ProfileShowcaseCollectible{
|
||||
ContractAddress: "0x12378534257568678487683576",
|
||||
ChainID: 2,
|
||||
TokenID: "0x12321389592999f903",
|
||||
ChainID: 1,
|
||||
TokenID: "123213895929994903",
|
||||
CommunityID: "0x01312357798976535",
|
||||
Order: 0,
|
||||
},
|
||||
|
@ -192,7 +192,7 @@ func (s *TestProfileShowcasePersistence) TestProfileShowcaseContacts() {
|
|||
},
|
||||
&identity.ProfileShowcaseUnverifiedToken{
|
||||
ContractAddress: "0x12312323323233",
|
||||
ChainID: 2,
|
||||
ChainID: 11155111,
|
||||
CommunityID: "0x32433445133424",
|
||||
Order: 1,
|
||||
},
|
||||
|
@ -216,8 +216,8 @@ func (s *TestProfileShowcasePersistence) TestProfileShowcaseContacts() {
|
|||
Collectibles: []*identity.ProfileShowcaseCollectible{
|
||||
&identity.ProfileShowcaseCollectible{
|
||||
ContractAddress: "0x12378534257568678487683576",
|
||||
ChainID: 2,
|
||||
TokenID: "0x12321389592999f903",
|
||||
ChainID: 1,
|
||||
TokenID: "123213895929994903",
|
||||
CommunityID: "0x01312357798976535",
|
||||
Order: 1,
|
||||
},
|
||||
|
@ -382,8 +382,8 @@ func (s *TestProfileShowcasePersistence) TestUpdateProfileShowcaseAccountOnWalle
|
|||
s.Require().NoError(err)
|
||||
persistence := newSQLitePersistence(db)
|
||||
|
||||
deleteAccountAddress := "0x3243344513424"
|
||||
updateAccountAddress := "0x3845354643324"
|
||||
deleteAccountAddress := "0x0000000000000000000000000033433445133423"
|
||||
updateAccountAddress := "0x0000000000000000000000000032433445133424"
|
||||
|
||||
preferences := &identity.ProfileShowcasePreferences{
|
||||
Accounts: []*identity.ProfileShowcaseAccountPreference{
|
||||
|
|
|
@ -329,7 +329,7 @@ func (s *SyncDeviceSuite) TestPairingSyncDeviceClientAsSender() {
|
|||
err = clientBackend.StatusNode().EnsService().API().Add(ctx, ensChainID, ensUsername)
|
||||
require.NoError(s.T(), err)
|
||||
// generate profile showcase preferences
|
||||
profileShowcasePreferences := protocol.DummyProfileShowcasePreferences()
|
||||
profileShowcasePreferences := protocol.DummyProfileShowcasePreferences(false)
|
||||
err = clientBackend.Messenger().SetProfileShowcasePreferences(profileShowcasePreferences, false)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
|
|
|
@ -316,6 +316,10 @@ func (api *API) FetchBalancesByOwnerAndContractAddress(ctx context.Context, chai
|
|||
return api.s.collectiblesManager.FetchBalancesByOwnerAndContractAddress(ctx, chainID, ownerAddress, contractAddresses)
|
||||
}
|
||||
|
||||
func (api *API) GetCollectibleOwnership(id thirdparty.CollectibleUniqueID) ([]thirdparty.AccountBalance, error) {
|
||||
return api.s.collectiblesManager.GetCollectibleOwnership(id)
|
||||
}
|
||||
|
||||
func (api *API) RefetchOwnedCollectibles() error {
|
||||
log.Debug("wallet.api.RefetchOwnedCollectibles")
|
||||
|
||||
|
|
|
@ -417,6 +417,10 @@ func (o *Manager) FetchCollectionsDataByContractID(ctx context.Context, ids []th
|
|||
return mapToList(data), nil
|
||||
}
|
||||
|
||||
func (o *Manager) GetCollectibleOwnership(id thirdparty.CollectibleUniqueID) ([]thirdparty.AccountBalance, error) {
|
||||
return o.ownershipDB.GetOwnership(id)
|
||||
}
|
||||
|
||||
func (o *Manager) getContractOwnershipProviders(chainID walletCommon.ChainID) (mainProvider thirdparty.CollectibleContractOwnershipProvider, fallbackProvider thirdparty.CollectibleContractOwnershipProvider) {
|
||||
mainProvider = nil
|
||||
fallbackProvider = nil
|
||||
|
|
Loading…
Reference in New Issue