github.com/status-im/status-go@v1.1.0/services/wallet/collectibles/filter.go (about)

     1  package collectibles
     2  
     3  import (
     4  	"context"
     5  	"database/sql"
     6  	"errors"
     7  
     8  	"github.com/ethereum/go-ethereum/common"
     9  
    10  	sq "github.com/Masterminds/squirrel"
    11  
    12  	"github.com/status-im/status-go/protocol/communities/token"
    13  	"github.com/status-im/status-go/services/wallet/bigint"
    14  	wcommon "github.com/status-im/status-go/services/wallet/common"
    15  	"github.com/status-im/status-go/services/wallet/thirdparty"
    16  )
    17  
    18  func allCollectibleIDsFilter() []thirdparty.CollectibleUniqueID {
    19  	return []thirdparty.CollectibleUniqueID{}
    20  }
    21  
    22  func allCommunityIDsFilter() []string {
    23  	return []string{}
    24  }
    25  
    26  func allCommunityPrivilegesLevelsFilter() []token.PrivilegesLevel {
    27  	return []token.PrivilegesLevel{}
    28  }
    29  
    30  func allFilter() Filter {
    31  	return Filter{
    32  		CollectibleIDs:            allCollectibleIDsFilter(),
    33  		CommunityIDs:              allCommunityIDsFilter(),
    34  		CommunityPrivilegesLevels: allCommunityPrivilegesLevelsFilter(),
    35  		FilterCommunity:           All,
    36  	}
    37  }
    38  
    39  type FilterCommunityType int
    40  
    41  const (
    42  	All FilterCommunityType = iota
    43  	OnlyNonCommunity
    44  	OnlyCommunity
    45  )
    46  
    47  type Filter struct {
    48  	CollectibleIDs            []thirdparty.CollectibleUniqueID `json:"collectible_ids"`
    49  	CommunityIDs              []string                         `json:"community_ids"`
    50  	CommunityPrivilegesLevels []token.PrivilegesLevel          `json:"community_privileges_levels"`
    51  
    52  	FilterCommunity FilterCommunityType `json:"filter_community"`
    53  }
    54  
    55  func filterOwnedCollectibles(ctx context.Context, db *sql.DB, chainIDs []wcommon.ChainID, addresses []common.Address, filter Filter, offset int, limit int) ([]thirdparty.CollectibleUniqueID, error) {
    56  	if len(addresses) == 0 {
    57  		return nil, errors.New("no addresses provided")
    58  	}
    59  	if len(chainIDs) == 0 {
    60  		return nil, errors.New("no chainIDs provided")
    61  	}
    62  
    63  	q := sq.Select("ownership.chain_id,ownership.contract_address,ownership.token_id").Distinct()
    64  	q = q.From("collectibles_ownership_cache ownership").
    65  		LeftJoin(`collectible_data_cache data ON 
    66  		ownership.chain_id = data.chain_id AND 
    67  		ownership.contract_address = data.contract_address AND 
    68  		ownership.token_id = data.token_id`)
    69  
    70  	qConditions := sq.And{}
    71  	qConditions = append(qConditions, sq.Eq{"ownership.chain_id": chainIDs})
    72  	qConditions = append(qConditions, sq.Eq{"ownership.owner_address": addresses})
    73  
    74  	if len(filter.CollectibleIDs) > 0 {
    75  		collectibleIDConditions := sq.Or{}
    76  		for _, collectibleID := range filter.CollectibleIDs {
    77  			collectibleIDConditions = append(collectibleIDConditions,
    78  				sq.And{
    79  					sq.Eq{"ownership.chain_id": collectibleID.ContractID.ChainID},
    80  					sq.Eq{"ownership.contract_address": collectibleID.ContractID.Address},
    81  					sq.Eq{"ownership.token_id": (*bigint.SQLBigIntBytes)(collectibleID.TokenID.Int)},
    82  				})
    83  		}
    84  		qConditions = append(qConditions, collectibleIDConditions)
    85  	}
    86  
    87  	switch filter.FilterCommunity {
    88  	case All:
    89  		// nothing to do
    90  	case OnlyNonCommunity:
    91  		qConditions = append(qConditions, sq.Eq{"data.community_id": ""})
    92  	case OnlyCommunity:
    93  		qConditions = append(qConditions, sq.NotEq{"data.community_id": ""})
    94  	}
    95  
    96  	if len(filter.CommunityIDs) > 0 {
    97  		qConditions = append(qConditions, sq.Eq{"data.community_id": filter.CommunityIDs})
    98  	}
    99  
   100  	if len(filter.CommunityPrivilegesLevels) > 0 {
   101  		qConditions = append(qConditions, sq.Eq{"data.community_privileges_level": filter.CommunityPrivilegesLevels})
   102  	}
   103  
   104  	q = q.Where(qConditions)
   105  
   106  	q = q.Limit(uint64(limit))
   107  	q = q.Offset(uint64(offset))
   108  
   109  	query, args, err := q.ToSql()
   110  	if err != nil {
   111  		return nil, err
   112  	}
   113  
   114  	stmt, err := db.Prepare(query)
   115  	if err != nil {
   116  		return nil, err
   117  	}
   118  	defer stmt.Close()
   119  
   120  	rows, err := stmt.Query(args...)
   121  	if err != nil {
   122  		return nil, err
   123  	}
   124  	defer rows.Close()
   125  
   126  	return thirdparty.RowsToCollectibles(rows)
   127  }