Skip to content

Commit

Permalink
feat: strip signature params
Browse files Browse the repository at this point in the history
  • Loading branch information
catalyst17 committed Oct 28, 2024
1 parent 2bdd298 commit 86d4285
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 3 deletions.
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

0 comments on commit 86d4285

Please sign in to comment.