Skip to content

Commit

Permalink
Fix: parse URL from ByteArray (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
aopoltorzhicky authored Sep 10, 2024
1 parent 03c1e76 commit 74f2c26
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 12 deletions.
75 changes: 63 additions & 12 deletions cmd/metadata/filler.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,11 +272,11 @@ func (f Filler) handleErc721(ctx context.Context, schema abi.JsonSchema, task *s
task.Metadata = make(map[string]any)
}

nameSelector, _, err := f.getSelectorByName(schema, entrypointName)
nameSelector, nameSchema, err := f.getSelectorByName(schema, entrypointName)
if err != nil {
return err
}
symbolSelector, _, err := f.getSelectorByName(schema, entrypointSymbol)
symbolSelector, symbolSchema, err := f.getSelectorByName(schema, entrypointSymbol)
if err != nil {
return err
}
Expand All @@ -286,7 +286,7 @@ func (f Filler) handleErc721(ctx context.Context, schema abi.JsonSchema, task *s
}

if f.multicall != "" {
if err := handlerFillerError(f.multicallErc721(ctx, address, nameSelector, symbolSelector, uriSelector, funcSchema, task)); err != nil {
if err := handlerFillerError(f.multicallErc721(ctx, address, nameSelector, symbolSelector, uriSelector, nameSchema, symbolSchema, funcSchema, task)); err != nil {
return err
}
} else {
Expand Down Expand Up @@ -482,7 +482,7 @@ func (f Filler) multicallErc20(ctx context.Context, address data.Felt, selectorN
return nil
}

func (f Filler) multicallErc721(ctx context.Context, address data.Felt, selectorName, selectorSymbol, selectorUri string, uriSchema abi.JsonSchemaFunction, task *storage.TokenMetadata) error {
func (f Filler) multicallErc721(ctx context.Context, address data.Felt, selectorName, selectorSymbol, selectorUri string, nameSchema, symbolSchema, uriSchema abi.JsonSchemaFunction, task *storage.TokenMetadata) error {
tokenId, err := data.NewUint256FromString(task.TokenId.String())
if err != nil {
return errors.Wrap(ErrInvalidTokenId, err.Error())
Expand Down Expand Up @@ -510,9 +510,27 @@ func (f Filler) multicallErc721(ctx context.Context, address data.Felt, selector
if len(response) < 4 {
return errors.Wrapf(ErrViewExecution, "invalid multicall response: %v", response)
}
task.Metadata[entrypointName] = response[1].ToAsciiString()
task.Metadata[entrypointSymbol] = response[2].ToAsciiString()
uri := parseUri(uriSchema, response[3:])

var offset = 1
name, nameOffset, err := parseString(nameSchema, response[offset:])
if err != nil {
return err
}
offset += nameOffset
task.Metadata[entrypointName] = name

symbol, symbolOffset, err := parseString(symbolSchema, response[offset:])
if err != nil {
return err
}
offset += symbolOffset
task.Metadata[entrypointSymbol] = symbol

uri, _, err := parseString(uriSchema, response[offset:])
if err != nil {
return err
}

if url, err := url.ParseRequestURI(uri); err != nil {
return errors.Wrap(ErrInvalidUri, uri)
} else if err := ValidateURL(url); err != nil {
Expand Down Expand Up @@ -613,7 +631,10 @@ func (f Filler) getTokenUri(ctx context.Context, address data.Felt, selector str
return nil, errors.Wrapf(ErrViewExecution, "invalid response for token uri: %v", response)
}

uri := parseUri(funcSchema, response)
uri, _, err := parseString(funcSchema, response)
if err != nil {
return nil, err
}
if url, err := url.ParseRequestURI(uri); err != nil {
return nil, errors.Wrap(ErrInvalidUri, uri)
} else if err := ValidateURL(url); err != nil {
Expand Down Expand Up @@ -652,26 +673,56 @@ func (f Filler) getImplementation(ctx context.Context, address data.Felt, name s
return item.Value().([]byte), nil
}

func parseUri(funcSchema abi.JsonSchemaFunction, response []data.Felt) string {
func parseString(funcSchema abi.JsonSchemaFunction, response []data.Felt) (string, int, error) {
var isArray bool
for name := range funcSchema.Output.Properties {
if strings.HasSuffix(name, "_len") || funcSchema.Output.Properties[name].Type == jsonschema.ItemTypeArray {
if funcSchema.Output.Properties[name].Type == jsonschema.ItemTypeArray || strings.HasSuffix(name, "_len") {
isArray = true
break
}
if funcSchema.Output.Properties[name].Title == "core::byte_array::ByteArray" {
return parseStringArray(response)
}
}

if isArray {
response = response[1:]
} else {
return response[0].ToAsciiString(), 1, nil
}

var uri string
var (
uri string
count int
)
for i := range response {
if response[i] == "0x0" {
count = i + 1
break
}
uri += response[i].ToAsciiString()
}

return uri
return uri, count, nil
}

func parseStringArray(response []data.Felt) (string, int, error) {
if len(response) == 0 {
return "", 0, nil
}
result := ""
fullWords, err := response[0].Uint64()
if err != nil {
return "", 0, err
}
if uint64(len(response)-1) < fullWords+2 {
return "", 0, errors.Errorf("full words count = %d | response length = %d", fullWords, len(response))
}

for i := uint64(1); i < fullWords+1; i++ {
result += response[i].ToAsciiString()
}

result += response[fullWords+1].ToAsciiString()
return result, int(fullWords + 3), nil
}
41 changes: 41 additions & 0 deletions cmd/metadata/filler_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package main

import (
"testing"

"github.com/dipdup-io/starknet-go-api/pkg/data"
"github.com/stretchr/testify/require"
)

func Test_parseStringArray(t *testing.T) {
tests := []struct {
name string
response []data.Felt
want string
wantOffset int
}{
{
name: "test 1",
response: []data.Felt{
"0x0", "0x537461726b6e65742e6964", "0xb",
},
want: "Starknet.id",
wantOffset: 3,
}, {
name: "test 2",
response: []data.Felt{
"0x1", "0x68747470733a2f2f6170692e737461726b6e65742e69642f7572693f69643d", "0x313937393433393730333538", "0xc",
},
want: "https://api.starknet.id/uri?id=197943970358",
wantOffset: 4,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, offset, err := parseStringArray(tt.response)
require.NoError(t, err)
require.Equal(t, tt.want, got)
require.Equal(t, tt.wantOffset, offset)
})
}
}

0 comments on commit 74f2c26

Please sign in to comment.