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 }