Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 154 additions & 1 deletion internal/common/utils.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package common

import "math/big"
import (
"fmt"
"math/big"
"strings"
"unicode"
)

func BigIntSliceToChunks(values []*big.Int, chunkSize int) [][]*big.Int {
if chunkSize >= len(values) || chunkSize <= 0 {
Expand All @@ -16,3 +21,151 @@ func BigIntSliceToChunks(values []*big.Int, chunkSize int) [][]*big.Int {
}
return chunks
}

// StripPayload removes parameter names, 'indexed' keywords,
// and extra whitespaces from a Solidity function or event signature.
func StripPayload(signature string) string {
// Find the index of the first '(' and last ')'
start := strings.Index(signature, "(")
end := strings.LastIndex(signature, ")")
if start == -1 || end == -1 || end <= start {
// Return the original signature if it doesn't match the expected pattern
return signature
}

functionName := strings.TrimSpace(signature[:start])
paramsStr := signature[start+1 : end]

// Parse parameters
strippedParams := parseParameters(paramsStr)

// Reconstruct the cleaned-up signature
strippedSignature := fmt.Sprintf("%s(%s)", functionName, strings.Join(strippedParams, ","))
return strippedSignature
}

// parseParameters parses the parameter string and returns a slice of cleaned-up parameter types
func parseParameters(paramsStr string) []string {
var params []string
var currentParam strings.Builder
bracketDepth := 0
var inType bool // Indicates if we are currently parsing a type

runes := []rune(paramsStr)
i := 0
for i < len(runes) {
char := runes[i]
switch char {
case '(', '[', '{':
bracketDepth++
inType = true
currentParam.WriteRune(char)
i++
case ')', ']', '}':
bracketDepth--
currentParam.WriteRune(char)
i++
case ',':
if bracketDepth == 0 {
// End of current parameter
paramType := cleanType(currentParam.String())
if paramType != "" {
params = append(params, paramType)
}
currentParam.Reset()
inType = false
i++
} else {
currentParam.WriteRune(char)
i++
}
case ' ':
if inType {
currentParam.WriteRune(char)
}
i++
default:
// Check if the word is a keyword to ignore
if unicode.IsLetter(char) {
wordStart := i
for i < len(runes) && (unicode.IsLetter(runes[i]) || unicode.IsDigit(runes[i])) {
i++
}
word := string(runes[wordStart:i])

// Ignore 'indexed' and parameter names
if isType(word) {
inType = true
currentParam.WriteString(word)
} else if word == "indexed" {
// Skip 'indexed'
inType = false
} else {
// Ignore parameter names
if inType {
// If we are in the middle of parsing a type and encounter a parameter name, skip it
inType = false
}
}
} else {
if inType {
currentParam.WriteRune(char)
}
i++
}
}
}

// Add the last parameter
if currentParam.Len() > 0 {
paramType := cleanType(currentParam.String())
if paramType != "" {
params = append(params, paramType)
}
}

return params
}

// cleanType cleans up a parameter type string by removing extra spaces and 'tuple' keyword
func cleanType(param string) string {
// Remove 'tuple' keyword
param = strings.ReplaceAll(param, "tuple", "")
// Remove 'indexed' keyword
param = strings.ReplaceAll(param, "indexed", "")
// Remove any parameter names (already handled in parsing)
param = strings.TrimSpace(param)
// Remove extra whitespaces
param = strings.Join(strings.Fields(param), "")
return param
}

// isType checks if a word is a Solidity type
func isType(word string) bool {
types := map[string]bool{
"uint": true,
"int": true,
"uint8": true,
"int8": true,
"uint16": true,
"int16": true,
"uint32": true,
"int32": true,
"uint64": true,
"int64": true,
"uint128": true,
"int128": true,
"uint256": true,
"int256": true,
"address": true,
"bool": true,
"string": true,
"bytes": true,
"fixed": true,
"ufixed": true,
"function": true,
// Add other types as needed
}

return types[word]
}
4 changes: 3 additions & 1 deletion internal/handlers/logs_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/rs/zerolog/log"
"github.com/thirdweb-dev/indexer/api"
config "github.com/thirdweb-dev/indexer/configs"
"github.com/thirdweb-dev/indexer/internal/common"
"github.com/thirdweb-dev/indexer/internal/storage"
)

Expand Down Expand Up @@ -105,7 +106,8 @@ func GetLogsByContract(c *gin.Context) {
func GetLogsByContractAndSignature(c *gin.Context) {
contractAddress := c.Param("contract")
eventSignature := c.Param("signature")
handleLogsRequest(c, contractAddress, eventSignature)
strippedSignature := common.StripPayload(eventSignature)
handleLogsRequest(c, contractAddress, strippedSignature)
}

func handleLogsRequest(c *gin.Context, contractAddress, signature string) {
Expand Down
4 changes: 3 additions & 1 deletion internal/handlers/transactions_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/gin-gonic/gin"
"github.com/rs/zerolog/log"
"github.com/thirdweb-dev/indexer/api"
"github.com/thirdweb-dev/indexer/internal/common"
"github.com/thirdweb-dev/indexer/internal/rpc"
"github.com/thirdweb-dev/indexer/internal/storage"
)
Expand Down Expand Up @@ -107,7 +108,8 @@ func GetTransactionsByContract(c *gin.Context) {
func GetTransactionsByContractAndSignature(c *gin.Context) {
to := c.Param("to")
signature := c.Param("signature")
handleTransactionsRequest(c, to, signature)
strippedSignature := common.StripPayload(signature)
handleTransactionsRequest(c, to, strippedSignature)
}

func handleTransactionsRequest(c *gin.Context, contractAddress, signature string) {
Expand Down
Loading