@@ -2,6 +2,7 @@ package handlers
22
33import (
44 "fmt"
5+ "math/big"
56 "strings"
67
78 "github.com/gin-gonic/gin"
@@ -47,11 +48,13 @@ func GetTokenBalancesByType(c *gin.Context) {
4748 api .BadRequestErrorHandler (c , err )
4849 return
4950 }
50- tokenType := c .Param ("type" )
51- if tokenType != "erc20" && tokenType != "erc1155" && tokenType != "erc721" {
52- api .BadRequestErrorHandler (c , fmt .Errorf ("invalid token type '%s'" , tokenType ))
51+
52+ tokenTypes , err := getTokenTypesFromReq (c )
53+ if err != nil {
54+ api .BadRequestErrorHandler (c , err )
5355 return
5456 }
57+
5558 owner := strings .ToLower (c .Param ("owner" ))
5659 if ! strings .HasPrefix (owner , "0x" ) {
5760 api .BadRequestErrorHandler (c , fmt .Errorf ("invalid owner address '%s'" , owner ))
@@ -62,21 +65,29 @@ func GetTokenBalancesByType(c *gin.Context) {
6265 api .BadRequestErrorHandler (c , fmt .Errorf ("invalid token address '%s'" , tokenAddress ))
6366 return
6467 }
68+
69+ tokenIds , err := getTokenIdsFromReq (c )
70+ if err != nil {
71+ api .BadRequestErrorHandler (c , fmt .Errorf ("invalid token ids '%s'" , err ))
72+ return
73+ }
74+
6575 hideZeroBalances := c .Query ("hide_zero_balances" ) != "false"
6676
6777 columns := []string {"address" , "sum(balance) as balance" }
6878 groupBy := []string {"address" }
69- if tokenType != " erc20" {
79+ if ! strings . Contains ( strings . Join ( tokenTypes , "," ), " erc20") {
7080 columns = []string {"address" , "token_id" , "sum(balance) as balance" }
7181 groupBy = []string {"address" , "token_id" }
7282 }
7383
7484 qf := storage.BalancesQueryFilter {
7585 ChainId : chainId ,
7686 Owner : owner ,
77- TokenType : tokenType ,
87+ TokenTypes : tokenTypes ,
7888 TokenAddress : tokenAddress ,
7989 ZeroBalance : hideZeroBalances ,
90+ TokenIds : tokenIds ,
8091 GroupBy : groupBy ,
8192 SortBy : c .Query ("sort_by" ),
8293 SortOrder : c .Query ("sort_order" ),
@@ -131,6 +142,43 @@ func serializeBalance(balance common.TokenBalance) BalanceModel {
131142 }
132143}
133144
145+ func getTokenTypesFromReq (c * gin.Context ) ([]string , error ) {
146+ tokenTypeParam := c .Param ("type" )
147+ var tokenTypes []string
148+ if tokenTypeParam != "" {
149+ tokenTypes = []string {tokenTypeParam }
150+ } else {
151+ tokenTypes = c .QueryArray ("token_type" )
152+ }
153+
154+ for i , tokenType := range tokenTypes {
155+ tokenType = strings .ToLower (tokenType )
156+ if tokenType != "erc721" && tokenType != "erc1155" && tokenType != "erc20" {
157+ return []string {}, fmt .Errorf ("invalid token type: %s" , tokenType )
158+ }
159+ tokenTypes [i ] = tokenType
160+ }
161+ return tokenTypes , nil
162+ }
163+
164+ func getTokenIdsFromReq (c * gin.Context ) ([]* big.Int , error ) {
165+ tokenIds := c .QueryArray ("token_id" )
166+ tokenIdsBn := make ([]* big.Int , len (tokenIds ))
167+ for i , tokenId := range tokenIds {
168+ tokenId = strings .TrimSpace (tokenId ) // Remove potential whitespace
169+ if tokenId == "" {
170+ return nil , fmt .Errorf ("invalid token id: %s" , tokenId )
171+ }
172+ num := new (big.Int )
173+ _ , ok := num .SetString (tokenId , 10 ) // Base 10
174+ if ! ok {
175+ return nil , fmt .Errorf ("invalid token id: %s" , tokenId )
176+ }
177+ tokenIdsBn [i ] = num
178+ }
179+ return tokenIdsBn , nil
180+ }
181+
134182// @Summary Get holders of a token
135183// @Description Retrieve holders of a token
136184// @Tags holders
@@ -161,25 +209,32 @@ func GetTokenHoldersByType(c *gin.Context) {
161209 return
162210 }
163211
164- tokenType := c . Query ( "token_type" )
165- if tokenType != "" && tokenType != "erc20" && tokenType != "erc1155" && tokenType != "erc721" {
166- api .BadRequestErrorHandler (c , fmt . Errorf ( "invalid token type '%s'" , tokenType ) )
212+ tokenTypes , err := getTokenTypesFromReq ( c )
213+ if err != nil {
214+ api .BadRequestErrorHandler (c , err )
167215 return
168216 }
169217 hideZeroBalances := c .Query ("hide_zero_balances" ) != "false"
170218
171219 columns := []string {"owner" , "sum(balance) as balance" }
172220 groupBy := []string {"owner" }
173- if tokenType != "erc20" {
221+
222+ if ! strings .Contains (strings .Join (tokenTypes , "," ), "erc20" ) {
174223 columns = []string {"owner" , "token_id" , "sum(balance) as balance" }
175224 groupBy = []string {"owner" , "token_id" }
176225 }
177226
227+ tokenIds , err := getTokenIdsFromReq (c )
228+ if err != nil {
229+ api .BadRequestErrorHandler (c , fmt .Errorf ("invalid token ids '%s'" , err ))
230+ return
231+ }
178232 qf := storage.BalancesQueryFilter {
179233 ChainId : chainId ,
180- TokenType : tokenType ,
234+ TokenTypes : tokenTypes ,
181235 TokenAddress : address ,
182236 ZeroBalance : hideZeroBalances ,
237+ TokenIds : tokenIds ,
183238 GroupBy : groupBy ,
184239 SortBy : c .Query ("sort_by" ),
185240 SortOrder : c .Query ("sort_order" ),
0 commit comments