chore(communities)_: reevaluate permissions with pre-fetched owners
That's an optimisation. Instead of fetching collectibles owners for each member, it is fetched once, before members iteration. It should significantly reduce amount of queries to providers. closes: status-im/status-desktop#14914
This commit is contained in:
parent
b0213e6a41
commit
ec9e29ef92
|
@ -302,6 +302,7 @@ func (m *DefaultTokenManager) GetAllChainIDs() ([]uint64, error) {
|
||||||
type CollectiblesManager interface {
|
type CollectiblesManager interface {
|
||||||
FetchBalancesByOwnerAndContractAddress(ctx context.Context, chainID walletcommon.ChainID, ownerAddress gethcommon.Address, contractAddresses []gethcommon.Address) (thirdparty.TokenBalancesPerContractAddress, error)
|
FetchBalancesByOwnerAndContractAddress(ctx context.Context, chainID walletcommon.ChainID, ownerAddress gethcommon.Address, contractAddresses []gethcommon.Address) (thirdparty.TokenBalancesPerContractAddress, error)
|
||||||
GetCollectibleOwnership(id thirdparty.CollectibleUniqueID) ([]thirdparty.AccountBalance, error)
|
GetCollectibleOwnership(id thirdparty.CollectibleUniqueID) ([]thirdparty.AccountBalance, error)
|
||||||
|
FetchCollectibleOwnersByContractAddress(ctx context.Context, chainID walletcommon.ChainID, contractAddress gethcommon.Address) (*thirdparty.CollectibleContractOwnership, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *DefaultTokenManager) GetBalancesByChain(ctx context.Context, accounts, tokenAddresses []gethcommon.Address, chainIDs []uint64) (BalancesByChain, error) {
|
func (m *DefaultTokenManager) GetBalancesByChain(ctx context.Context, accounts, tokenAddresses []gethcommon.Address, chainIDs []uint64) (BalancesByChain, error) {
|
||||||
|
@ -984,6 +985,27 @@ func (rmr *reevaluateMembersResult) newPrivilegedRoles() (map[protobuf.Community
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetch all owners for all collectibles.
|
||||||
|
func (m *Manager) fetchCollectiblesOwners(collectibles map[walletcommon.ChainID]map[gethcommon.Address]struct{}) (CollectiblesOwners, error) {
|
||||||
|
if m.collectiblesManager == nil {
|
||||||
|
return nil, errors.New("no collectibles manager")
|
||||||
|
}
|
||||||
|
|
||||||
|
collectiblesOwners := make(CollectiblesOwners)
|
||||||
|
for chainID, contractAddresses := range collectibles {
|
||||||
|
collectiblesOwners[chainID] = make(map[gethcommon.Address]*thirdparty.CollectibleContractOwnership)
|
||||||
|
|
||||||
|
for contractAddress := range contractAddresses {
|
||||||
|
ownership, err := m.collectiblesManager.FetchCollectibleOwnersByContractAddress(context.Background(), chainID, contractAddress)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
collectiblesOwners[chainID][contractAddress] = ownership
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return collectiblesOwners, nil
|
||||||
|
}
|
||||||
|
|
||||||
// use it only for testing purposes
|
// use it only for testing purposes
|
||||||
func (m *Manager) ReevaluateMembers(communityID types.HexBytes) (*Community, map[protobuf.CommunityMember_Roles][]*ecdsa.PublicKey, error) {
|
func (m *Manager) ReevaluateMembers(communityID types.HexBytes) (*Community, map[protobuf.CommunityMember_Roles][]*ecdsa.PublicKey, error) {
|
||||||
return m.reevaluateMembers(communityID)
|
return m.reevaluateMembers(communityID)
|
||||||
|
@ -1009,6 +1031,12 @@ func (m *Manager) reevaluateMembers(communityID types.HexBytes) (*Community, map
|
||||||
|
|
||||||
communityPermissionsPreParsedData, channelPermissionsPreParsedData := PreParsePermissionsData(community.tokenPermissions())
|
communityPermissionsPreParsedData, channelPermissionsPreParsedData := PreParsePermissionsData(community.tokenPermissions())
|
||||||
|
|
||||||
|
// Optimization: Fetch all collectibles owners before members iteration to avoid asking providers for the same collectibles.
|
||||||
|
collectiblesOwners, err := m.fetchCollectiblesOwners(CollectibleAddressesFromPreParsedPermissionsData(communityPermissionsPreParsedData, channelPermissionsPreParsedData))
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
result := &reevaluateMembersResult{
|
result := &reevaluateMembersResult{
|
||||||
membersToRemove: map[string]struct{}{},
|
membersToRemove: map[string]struct{}{},
|
||||||
membersRoles: map[string]*reevaluateMemberRole{},
|
membersRoles: map[string]*reevaluateMemberRole{},
|
||||||
|
@ -1046,7 +1074,7 @@ func (m *Manager) reevaluateMembers(communityID types.HexBytes) (*Community, map
|
||||||
|
|
||||||
becomeTokenMasterPermissions := communityPermissionsPreParsedData[protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER]
|
becomeTokenMasterPermissions := communityPermissionsPreParsedData[protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER]
|
||||||
if becomeTokenMasterPermissions != nil {
|
if becomeTokenMasterPermissions != nil {
|
||||||
permissionResponse, err := m.PermissionChecker.CheckPermissions(becomeTokenMasterPermissions, accountsAndChainIDs, true)
|
permissionResponse, err := m.PermissionChecker.CheckPermissionsWithPreFetchedData(becomeTokenMasterPermissions, accountsAndChainIDs, true, collectiblesOwners)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -1060,7 +1088,7 @@ func (m *Manager) reevaluateMembers(communityID types.HexBytes) (*Community, map
|
||||||
|
|
||||||
becomeAdminPermissions := communityPermissionsPreParsedData[protobuf.CommunityTokenPermission_BECOME_ADMIN]
|
becomeAdminPermissions := communityPermissionsPreParsedData[protobuf.CommunityTokenPermission_BECOME_ADMIN]
|
||||||
if becomeAdminPermissions != nil {
|
if becomeAdminPermissions != nil {
|
||||||
permissionResponse, err := m.PermissionChecker.CheckPermissions(becomeAdminPermissions, accountsAndChainIDs, true)
|
permissionResponse, err := m.PermissionChecker.CheckPermissionsWithPreFetchedData(becomeAdminPermissions, accountsAndChainIDs, true, collectiblesOwners)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -1074,7 +1102,7 @@ func (m *Manager) reevaluateMembers(communityID types.HexBytes) (*Community, map
|
||||||
|
|
||||||
becomeMemberPermissions := communityPermissionsPreParsedData[protobuf.CommunityTokenPermission_BECOME_MEMBER]
|
becomeMemberPermissions := communityPermissionsPreParsedData[protobuf.CommunityTokenPermission_BECOME_MEMBER]
|
||||||
if becomeMemberPermissions != nil {
|
if becomeMemberPermissions != nil {
|
||||||
permissionResponse, err := m.PermissionChecker.CheckPermissions(becomeMemberPermissions, accountsAndChainIDs, true)
|
permissionResponse, err := m.PermissionChecker.CheckPermissionsWithPreFetchedData(becomeMemberPermissions, accountsAndChainIDs, true, collectiblesOwners)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -1086,7 +1114,7 @@ func (m *Manager) reevaluateMembers(communityID types.HexBytes) (*Community, map
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addToChannels, removeFromChannels, err := m.reevaluateMemberChannelsPermissions(community, memberPubKey, channelPermissionsPreParsedData, accountsAndChainIDs)
|
addToChannels, removeFromChannels, err := m.reevaluateMemberChannelsPermissions(community, memberPubKey, channelPermissionsPreParsedData, accountsAndChainIDs, collectiblesOwners)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -1199,13 +1227,13 @@ func (m *Manager) applyReevaluateMembersResult(communityID types.HexBytes, resul
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) reevaluateMemberChannelsPermissions(community *Community, memberPubKey *ecdsa.PublicKey,
|
func (m *Manager) reevaluateMemberChannelsPermissions(community *Community, memberPubKey *ecdsa.PublicKey,
|
||||||
channelPermissionsPreParsedData map[string]*PreParsedCommunityPermissionsData, accountsAndChainIDs []*AccountChainIDsCombination) (map[string]protobuf.CommunityMember_ChannelRole, map[string]struct{}, error) {
|
channelPermissionsPreParsedData map[string]*PreParsedCommunityPermissionsData, accountsAndChainIDs []*AccountChainIDsCombination, collectiblesOwners CollectiblesOwners) (map[string]protobuf.CommunityMember_ChannelRole, map[string]struct{}, error) {
|
||||||
|
|
||||||
addToChannels := map[string]protobuf.CommunityMember_ChannelRole{}
|
addToChannels := map[string]protobuf.CommunityMember_ChannelRole{}
|
||||||
removeFromChannels := map[string]struct{}{}
|
removeFromChannels := map[string]struct{}{}
|
||||||
|
|
||||||
// check which permissions we satisfy and which not
|
// check which permissions we satisfy and which not
|
||||||
channelPermissionsCheckResult, err := m.checkChannelsPermissions(channelPermissionsPreParsedData, accountsAndChainIDs, true)
|
channelPermissionsCheckResult, err := m.checkChannelsPermissionsWithPreFetchedData(channelPermissionsPreParsedData, accountsAndChainIDs, true, collectiblesOwners)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -1241,10 +1269,18 @@ func (m *Manager) reevaluateMemberChannelsPermissions(community *Community, memb
|
||||||
return addToChannels, removeFromChannels, nil
|
return addToChannels, removeFromChannels, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) checkChannelsPermissions(channelsPermissionsPreParsedData map[string]*PreParsedCommunityPermissionsData, accountsAndChainIDs []*AccountChainIDsCombination, shortcircuit bool) (map[string]map[protobuf.CommunityTokenPermission_Type]bool, error) {
|
func (m *Manager) checkChannelsPermissionsImpl(channelsPermissionsPreParsedData map[string]*PreParsedCommunityPermissionsData, accountsAndChainIDs []*AccountChainIDsCombination, shortcircuit bool, collectiblesOwners CollectiblesOwners) (map[string]map[protobuf.CommunityTokenPermission_Type]bool, error) {
|
||||||
|
checkPermissions := func(channelsPermissionPreParsedData *PreParsedCommunityPermissionsData) (*CheckPermissionsResponse, error) {
|
||||||
|
if collectiblesOwners != nil {
|
||||||
|
return m.PermissionChecker.CheckPermissionsWithPreFetchedData(channelsPermissionPreParsedData, accountsAndChainIDs, true, collectiblesOwners)
|
||||||
|
} else {
|
||||||
|
return m.PermissionChecker.CheckPermissions(channelsPermissionPreParsedData, accountsAndChainIDs, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
channelPermissionsCheckResult := make(map[string]map[protobuf.CommunityTokenPermission_Type]bool)
|
channelPermissionsCheckResult := make(map[string]map[protobuf.CommunityTokenPermission_Type]bool)
|
||||||
for _, channelsPermissionPreParsedData := range channelsPermissionsPreParsedData {
|
for _, channelsPermissionPreParsedData := range channelsPermissionsPreParsedData {
|
||||||
permissionResponse, err := m.PermissionChecker.CheckPermissions(channelsPermissionPreParsedData, accountsAndChainIDs, true)
|
permissionResponse, err := checkPermissions(channelsPermissionPreParsedData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return channelPermissionsCheckResult, err
|
return channelPermissionsCheckResult, err
|
||||||
}
|
}
|
||||||
|
@ -1264,6 +1300,14 @@ func (m *Manager) checkChannelsPermissions(channelsPermissionsPreParsedData map[
|
||||||
return channelPermissionsCheckResult, nil
|
return channelPermissionsCheckResult, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Manager) checkChannelsPermissionsWithPreFetchedData(channelsPermissionsPreParsedData map[string]*PreParsedCommunityPermissionsData, accountsAndChainIDs []*AccountChainIDsCombination, shortcircuit bool, collectiblesOwners CollectiblesOwners) (map[string]map[protobuf.CommunityTokenPermission_Type]bool, error) {
|
||||||
|
return m.checkChannelsPermissionsImpl(channelsPermissionsPreParsedData, accountsAndChainIDs, shortcircuit, collectiblesOwners)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) checkChannelsPermissions(channelsPermissionsPreParsedData map[string]*PreParsedCommunityPermissionsData, accountsAndChainIDs []*AccountChainIDsCombination, shortcircuit bool) (map[string]map[protobuf.CommunityTokenPermission_Type]bool, error) {
|
||||||
|
return m.checkChannelsPermissionsImpl(channelsPermissionsPreParsedData, accountsAndChainIDs, shortcircuit, nil)
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Manager) StartMembersReevaluationLoop(communityID types.HexBytes, reevaluateOnStart bool) {
|
func (m *Manager) StartMembersReevaluationLoop(communityID types.HexBytes, reevaluateOnStart bool) {
|
||||||
go m.reevaluateMembersLoop(communityID, reevaluateOnStart)
|
go m.reevaluateMembersLoop(communityID, reevaluateOnStart)
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,6 +137,32 @@ func (m *testCollectiblesManager) GetCollectibleOwnership(id thirdparty.Collecti
|
||||||
return nil, errors.New("GetCollectibleOwnership is not implemented for testCollectiblesManager")
|
return nil, errors.New("GetCollectibleOwnership is not implemented for testCollectiblesManager")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *testCollectiblesManager) FetchCollectibleOwnersByContractAddress(ctx context.Context, chainID walletCommon.ChainID, contractAddress gethcommon.Address) (*thirdparty.CollectibleContractOwnership, error) {
|
||||||
|
ret := &thirdparty.CollectibleContractOwnership{
|
||||||
|
ContractAddress: contractAddress,
|
||||||
|
Owners: []thirdparty.CollectibleOwner{},
|
||||||
|
}
|
||||||
|
|
||||||
|
balancesPerOwner, ok := m.response[uint64(chainID)]
|
||||||
|
if !ok {
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for ownerAddress, collectibles := range balancesPerOwner {
|
||||||
|
for collectibleAddress, balances := range collectibles {
|
||||||
|
if collectibleAddress == contractAddress {
|
||||||
|
ret.Owners = append(ret.Owners, thirdparty.CollectibleOwner{
|
||||||
|
OwnerAddress: ownerAddress,
|
||||||
|
TokenBalances: balances,
|
||||||
|
})
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
type testTokenManager struct {
|
type testTokenManager struct {
|
||||||
response map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big
|
response map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
type PermissionChecker interface {
|
type PermissionChecker interface {
|
||||||
CheckPermissionToJoin(*Community, []gethcommon.Address) (*CheckPermissionToJoinResponse, error)
|
CheckPermissionToJoin(*Community, []gethcommon.Address) (*CheckPermissionToJoinResponse, error)
|
||||||
CheckPermissions(permissionsParsedData *PreParsedCommunityPermissionsData, accountsAndChainIDs []*AccountChainIDsCombination, shortcircuit bool) (*CheckPermissionsResponse, error)
|
CheckPermissions(permissionsParsedData *PreParsedCommunityPermissionsData, accountsAndChainIDs []*AccountChainIDsCombination, shortcircuit bool) (*CheckPermissionsResponse, error)
|
||||||
|
CheckPermissionsWithPreFetchedData(permissionsParsedData *PreParsedCommunityPermissionsData, accountsAndChainIDs []*AccountChainIDsCombination, shortcircuit bool, collectiblesOwners CollectiblesOwners) (*CheckPermissionsResponse, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type DefaultPermissionChecker struct {
|
type DefaultPermissionChecker struct {
|
||||||
|
@ -62,7 +63,10 @@ func (p *DefaultPermissionChecker) getOwnedENS(addresses []gethcommon.Address) (
|
||||||
}
|
}
|
||||||
return ownedENS, nil
|
return ownedENS, nil
|
||||||
}
|
}
|
||||||
func (p *DefaultPermissionChecker) GetOwnedERC721Tokens(walletAddresses []gethcommon.Address, tokenRequirements map[uint64]map[string]*protobuf.TokenCriteria, chainIDs []uint64) (CollectiblesByChain, error) {
|
|
||||||
|
type collectiblesBalancesGetter = func(ctx context.Context, chainID walletcommon.ChainID, ownerAddress gethcommon.Address, contractAddresses []gethcommon.Address) (thirdparty.TokenBalancesPerContractAddress, error)
|
||||||
|
|
||||||
|
func (p *DefaultPermissionChecker) getOwnedERC721Tokens(walletAddresses []gethcommon.Address, tokenRequirements map[uint64]map[string]*protobuf.TokenCriteria, chainIDs []uint64, getCollectiblesBalances collectiblesBalancesGetter) (CollectiblesByChain, error) {
|
||||||
if p.collectiblesManager == nil {
|
if p.collectiblesManager == nil {
|
||||||
return nil, errors.New("no collectibles manager")
|
return nil, errors.New("no collectibles manager")
|
||||||
}
|
}
|
||||||
|
@ -94,7 +98,7 @@ func (p *DefaultPermissionChecker) GetOwnedERC721Tokens(walletAddresses []gethco
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, owner := range walletAddresses {
|
for _, owner := range walletAddresses {
|
||||||
balances, err := p.collectiblesManager.FetchBalancesByOwnerAndContractAddress(ctx, walletcommon.ChainID(chainID), owner, contractAddresses)
|
balances, err := getCollectiblesBalances(ctx, walletcommon.ChainID(chainID), owner, contractAddresses)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.logger.Info("couldn't fetch owner assets", zap.Error(err))
|
p.logger.Info("couldn't fetch owner assets", zap.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -208,10 +212,9 @@ func (p *DefaultPermissionChecker) checkPermissionsOrDefault(permissions []*Comm
|
||||||
return p.CheckPermissions(preParsedPermissions, accountsAndChainIDs, false)
|
return p.CheckPermissions(preParsedPermissions, accountsAndChainIDs, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckPermissions will retrieve balances and check whether the user has
|
type ownedERC721TokensGetter = func(walletAddresses []gethcommon.Address, tokenRequirements map[uint64]map[string]*protobuf.TokenCriteria, chainIDs []uint64) (CollectiblesByChain, error)
|
||||||
// permission to join the community, if shortcircuit is true, it will stop as soon
|
|
||||||
// as we know the answer
|
func (p *DefaultPermissionChecker) checkPermissions(permissionsParsedData *PreParsedCommunityPermissionsData, accountsAndChainIDs []*AccountChainIDsCombination, shortcircuit bool, getOwnedERC721Tokens ownedERC721TokensGetter) (*CheckPermissionsResponse, error) {
|
||||||
func (p *DefaultPermissionChecker) CheckPermissions(permissionsParsedData *PreParsedCommunityPermissionsData, accountsAndChainIDs []*AccountChainIDsCombination, shortcircuit bool) (*CheckPermissionsResponse, error) {
|
|
||||||
|
|
||||||
response := &CheckPermissionsResponse{
|
response := &CheckPermissionsResponse{
|
||||||
Satisfied: false,
|
Satisfied: false,
|
||||||
|
@ -260,7 +263,7 @@ func (p *DefaultPermissionChecker) CheckPermissions(permissionsParsedData *PrePa
|
||||||
|
|
||||||
ownedERC721Tokens := make(CollectiblesByChain)
|
ownedERC721Tokens := make(CollectiblesByChain)
|
||||||
if len(chainIDsForERC721) > 0 {
|
if len(chainIDsForERC721) > 0 {
|
||||||
collectibles, err := p.GetOwnedERC721Tokens(accounts, erc721TokenRequirements, chainIDsForERC721)
|
collectibles, err := getOwnedERC721Tokens(accounts, erc721TokenRequirements, chainIDsForERC721)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -445,6 +448,53 @@ func (p *DefaultPermissionChecker) CheckPermissions(permissionsParsedData *PrePa
|
||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CheckPermissions will retrieve balances and check whether the user has
|
||||||
|
// permission to join the community, if shortcircuit is true, it will stop as soon
|
||||||
|
// as we know the answer
|
||||||
|
func (p *DefaultPermissionChecker) CheckPermissions(permissionsParsedData *PreParsedCommunityPermissionsData, accountsAndChainIDs []*AccountChainIDsCombination, shortcircuit bool) (*CheckPermissionsResponse, error) {
|
||||||
|
var getOwnedERC721Tokens ownedERC721TokensGetter = func(walletAddresses []gethcommon.Address, tokenRequirements map[uint64]map[string]*protobuf.TokenCriteria, chainIDs []uint64) (CollectiblesByChain, error) {
|
||||||
|
return p.getOwnedERC721Tokens(walletAddresses, tokenRequirements, chainIDs, p.collectiblesManager.FetchBalancesByOwnerAndContractAddress)
|
||||||
|
}
|
||||||
|
|
||||||
|
return p.checkPermissions(permissionsParsedData, accountsAndChainIDs, shortcircuit, getOwnedERC721Tokens)
|
||||||
|
}
|
||||||
|
|
||||||
|
type CollectiblesOwners = map[walletcommon.ChainID]map[gethcommon.Address]*thirdparty.CollectibleContractOwnership
|
||||||
|
|
||||||
|
// Same as CheckPermissions but relies on already provided collectibles owners
|
||||||
|
func (p *DefaultPermissionChecker) CheckPermissionsWithPreFetchedData(permissionsParsedData *PreParsedCommunityPermissionsData, accountsAndChainIDs []*AccountChainIDsCombination, shortcircuit bool, collectiblesOwners CollectiblesOwners) (*CheckPermissionsResponse, error) {
|
||||||
|
var getCollectiblesBalances collectiblesBalancesGetter = func(ctx context.Context, chainID walletcommon.ChainID, ownerAddress gethcommon.Address, contractAddresses []gethcommon.Address) (thirdparty.TokenBalancesPerContractAddress, error) {
|
||||||
|
ret := make(thirdparty.TokenBalancesPerContractAddress)
|
||||||
|
|
||||||
|
collectiblesByChain, ok := collectiblesOwners[chainID]
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("no data available for chainID")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, contractAddress := range contractAddresses {
|
||||||
|
ownership, ok := collectiblesByChain[contractAddress]
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("no data available for collectible")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, nftOwner := range ownership.Owners {
|
||||||
|
if nftOwner.OwnerAddress == ownerAddress {
|
||||||
|
ret[contractAddress] = nftOwner.TokenBalances
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var getOwnedERC721Tokens ownedERC721TokensGetter = func(walletAddresses []gethcommon.Address, tokenRequirements map[uint64]map[string]*protobuf.TokenCriteria, chainIDs []uint64) (CollectiblesByChain, error) {
|
||||||
|
return p.getOwnedERC721Tokens(walletAddresses, tokenRequirements, chainIDs, getCollectiblesBalances)
|
||||||
|
}
|
||||||
|
|
||||||
|
return p.checkPermissions(permissionsParsedData, accountsAndChainIDs, shortcircuit, getOwnedERC721Tokens)
|
||||||
|
}
|
||||||
|
|
||||||
func preParsedPermissionsData(permissions []*CommunityTokenPermission) *PreParsedPermissionsData {
|
func preParsedPermissionsData(permissions []*CommunityTokenPermission) *PreParsedPermissionsData {
|
||||||
erc20TokenRequirements, erc721TokenRequirements, _ := ExtractTokenCriteria(permissions)
|
erc20TokenRequirements, erc721TokenRequirements, _ := ExtractTokenCriteria(permissions)
|
||||||
|
|
||||||
|
@ -505,3 +555,33 @@ func PreParsePermissionsData(permissions map[string]*CommunityTokenPermission) (
|
||||||
|
|
||||||
return communityPermissionsPreParsedData, channelPermissionsPreParsedData
|
return communityPermissionsPreParsedData, channelPermissionsPreParsedData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CollectibleAddressesFromPreParsedPermissionsData(communityPermissions map[protobuf.CommunityTokenPermission_Type]*PreParsedCommunityPermissionsData, channelPermissions map[string]*PreParsedCommunityPermissionsData) map[walletcommon.ChainID]map[gethcommon.Address]struct{} {
|
||||||
|
ret := make(map[walletcommon.ChainID]map[gethcommon.Address]struct{})
|
||||||
|
|
||||||
|
allPermissionsData := []*PreParsedCommunityPermissionsData{}
|
||||||
|
for _, permissionsData := range communityPermissions {
|
||||||
|
if permissionsData != nil {
|
||||||
|
allPermissionsData = append(allPermissionsData, permissionsData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, permissionsData := range channelPermissions {
|
||||||
|
if permissionsData != nil {
|
||||||
|
allPermissionsData = append(allPermissionsData, permissionsData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, data := range allPermissionsData {
|
||||||
|
for chainID, contractAddresses := range data.Erc721TokenRequirements {
|
||||||
|
if ret[walletcommon.ChainID(chainID)] == nil {
|
||||||
|
ret[walletcommon.ChainID(chainID)] = make(map[gethcommon.Address]struct{})
|
||||||
|
}
|
||||||
|
|
||||||
|
for contractAddress := range contractAddresses {
|
||||||
|
ret[walletcommon.ChainID(chainID)][gethcommon.HexToAddress(contractAddress)] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
|
@ -24,6 +24,8 @@ import (
|
||||||
"github.com/status-im/status-go/protocol/communities/token"
|
"github.com/status-im/status-go/protocol/communities/token"
|
||||||
"github.com/status-im/status-go/protocol/protobuf"
|
"github.com/status-im/status-go/protocol/protobuf"
|
||||||
"github.com/status-im/status-go/protocol/requests"
|
"github.com/status-im/status-go/protocol/requests"
|
||||||
|
walletCommon "github.com/status-im/status-go/services/wallet/common"
|
||||||
|
"github.com/status-im/status-go/services/wallet/thirdparty"
|
||||||
walletToken "github.com/status-im/status-go/services/wallet/token"
|
walletToken "github.com/status-im/status-go/services/wallet/token"
|
||||||
"github.com/status-im/status-go/transactions"
|
"github.com/status-im/status-go/transactions"
|
||||||
)
|
)
|
||||||
|
@ -72,6 +74,37 @@ func (m *TokenManagerMock) FindOrCreateTokenByAddress(ctx context.Context, chain
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 (m *CollectiblesManagerMock) FetchCollectibleOwnersByContractAddress(ctx context.Context, chainID walletCommon.ChainID, contractAddress gethcommon.Address) (*thirdparty.CollectibleContractOwnership, error) {
|
||||||
|
return nil, errors.New("FetchCollectibleOwnersByContractAddress is not implemented for CollectiblesManagerMock")
|
||||||
|
}
|
||||||
|
|
||||||
type CollectiblesServiceMock struct {
|
type CollectiblesServiceMock struct {
|
||||||
Collectibles map[uint64]map[string]*communities.CollectibleContractData
|
Collectibles map[uint64]map[string]*communities.CollectibleContractData
|
||||||
Assets map[uint64]map[string]*communities.AssetContractData
|
Assets map[uint64]map[string]*communities.AssetContractData
|
||||||
|
@ -227,9 +260,12 @@ func newTestCommunitiesMessenger(s *suite.Suite, waku types.Waku, config testCom
|
||||||
Balances: config.mockedBalances,
|
Balances: config.mockedBalances,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
collectiblesManagerMock := &CollectiblesManagerMock{}
|
||||||
|
|
||||||
options := []Option{
|
options := []Option{
|
||||||
WithAccountManager(accountsManagerMock),
|
WithAccountManager(accountsManagerMock),
|
||||||
WithTokenManager(tokenManagerMock),
|
WithTokenManager(tokenManagerMock),
|
||||||
|
WithCollectiblesManager(collectiblesManagerMock),
|
||||||
WithCommunityTokensService(config.collectiblesService),
|
WithCommunityTokensService(config.collectiblesService),
|
||||||
WithAppSettings(*config.appSettings, *config.nodeConfig),
|
WithAppSettings(*config.appSettings, *config.nodeConfig),
|
||||||
}
|
}
|
||||||
|
|
|
@ -3624,6 +3624,10 @@ func (t *testPermissionChecker) CheckPermissions(permissionsParsedData *communit
|
||||||
return &communities.CheckPermissionsResponse{Satisfied: true}, nil
|
return &communities.CheckPermissionsResponse{Satisfied: true}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *testPermissionChecker) CheckPermissionsWithPreFetchedData(permissionsParsedData *communities.PreParsedCommunityPermissionsData, accountsAndChainIDs []*communities.AccountChainIDsCombination, shortcircuit bool, collectiblesOwners communities.CollectiblesOwners) (*communities.CheckPermissionsResponse, error) {
|
||||||
|
return &communities.CheckPermissionsResponse{Satisfied: true}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *MessengerCommunitiesSuite) TestStartCommunityRekeyLoop() {
|
func (s *MessengerCommunitiesSuite) TestStartCommunityRekeyLoop() {
|
||||||
community, chat := createEncryptedCommunity(&s.Suite, s.owner)
|
community, chat := createEncryptedCommunity(&s.Suite, s.owner)
|
||||||
s.Require().True(community.Encrypted())
|
s.Require().True(community.Encrypted())
|
||||||
|
|
|
@ -25,39 +25,11 @@ import (
|
||||||
"github.com/status-im/status-go/protocol/sqlite"
|
"github.com/status-im/status-go/protocol/sqlite"
|
||||||
"github.com/status-im/status-go/protocol/tt"
|
"github.com/status-im/status-go/protocol/tt"
|
||||||
"github.com/status-im/status-go/services/wallet/bigint"
|
"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/services/wallet/thirdparty"
|
||||||
"github.com/status-im/status-go/t/helpers"
|
"github.com/status-im/status-go/t/helpers"
|
||||||
"github.com/status-im/status-go/waku"
|
"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
|
func TestMessengerProfileShowcaseSuite(t *testing.T) { // nolint: deadcode,unused
|
||||||
suite.Run(t, new(TestMessengerProfileShowcase))
|
suite.Run(t, new(TestMessengerProfileShowcase))
|
||||||
}
|
}
|
||||||
|
|
|
@ -326,6 +326,11 @@ func (api *API) GetCollectibleOwnersByContractAddress(ctx context.Context, chain
|
||||||
return api.s.collectiblesManager.FetchCollectibleOwnersByContractAddress(ctx, chainID, contractAddress)
|
return api.s.collectiblesManager.FetchCollectibleOwnersByContractAddress(ctx, chainID, contractAddress)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (api *API) FetchCollectibleOwnersByContractAddress(ctx context.Context, chainID wcommon.ChainID, contractAddress common.Address) (*thirdparty.CollectibleContractOwnership, error) {
|
||||||
|
log.Debug("call to FetchCollectibleOwnersByContractAddress")
|
||||||
|
return api.s.collectiblesManager.FetchCollectibleOwnersByContractAddress(ctx, chainID, contractAddress)
|
||||||
|
}
|
||||||
|
|
||||||
func (api *API) SearchCollectibles(ctx context.Context, chainID wcommon.ChainID, text string, cursor string, limit int, providerID string) (*thirdparty.FullCollectibleDataContainer, error) {
|
func (api *API) SearchCollectibles(ctx context.Context, chainID wcommon.ChainID, text string, cursor string, limit int, providerID string) (*thirdparty.FullCollectibleDataContainer, error) {
|
||||||
log.Debug("call to SearchCollectibles")
|
log.Debug("call to SearchCollectibles")
|
||||||
return api.s.collectiblesManager.SearchCollectibles(ctx, chainID, text, cursor, limit, providerID)
|
return api.s.collectiblesManager.SearchCollectibles(ctx, chainID, text, cursor, limit, providerID)
|
||||||
|
|
Loading…
Reference in New Issue