-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implemented event_decoders_test.go #20
Closed
Closed
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
5b415f3
Added makefile for testing framework
DarkLord017 29c805d
Added core.go
DarkLord017 ff259fa
Delete Makefile
Sh0g0-1758 21f942d
Implemented event_decoders_test.go
x-senpai-x adac2a1
Improved code quality and removed unnecessary checks
DarkLord017 a64ef4b
Merge pull request #16 from DarkLord017/implemented_core
Sh0g0-1758 10bc5b7
Merge pull request #23 from BlocSoc-iitr/main
Sh0g0-1758 6ef21f1
Merge branch 'BlocSoc-iitr:v0.1' into v0.1
x-senpai-x File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
package athena_abi | ||
|
||
import ( | ||
"errors" | ||
"log" | ||
) | ||
|
||
type StarknetABI struct { | ||
ABIName *string | ||
ClassHash []byte | ||
Functions map[string]AbiFunction | ||
Events map[string]AbiEvent | ||
Constructor []AbiParameter | ||
L1Handler *AbiFunction | ||
ImplementedInterfaces map[string]AbiInterface | ||
} | ||
|
||
// Declare errors | ||
var ( | ||
errParseDefinedTypes = errors.New("unable to parse defined types") | ||
errParseInterfaces = errors.New("unable to parse interfaces") | ||
errParseFunctions = errors.New("unable to parse functions") | ||
errParseEvents = errors.New("unable to parse events") | ||
errParseConstructor = errors.New("unable to parse constructor") | ||
errParseL1Handler = errors.New("unable to parse L1 handler") | ||
errParseImplementedInterfaces = errors.New("unable to parse implemented interfaces") | ||
) | ||
|
||
// Parse Starknet ABI from JSON | ||
// @param abiJSON | ||
// @param abiname | ||
// @param classHash | ||
func StarknetAbiFromJSON(abiJson []map[string]interface{}, abiName string, classHash []byte) (*StarknetABI, error) { | ||
groupedAbi := GroupAbiByType(abiJson) | ||
|
||
// Parse defined types (structs and enums) | ||
definedTypes, err := ParseEnumsAndStructs(groupedAbi["type_def"]) | ||
if err != nil { | ||
sortedDefs, errDef := TopoSortTypeDefs(groupedAbi["type_def"]) | ||
if errDef == nil { | ||
defineTypes, errDtypes := ParseEnumsAndStructs(sortedDefs) | ||
definedTypes = defineTypes | ||
errDef = errDtypes | ||
} | ||
if errDef != nil { | ||
return nil, errParseDefinedTypes | ||
} | ||
log.Println("ABI Struct and Enum definitions out of order & required topological sorting") | ||
} | ||
|
||
// Parse interfaces | ||
var definedInterfaces []AbiInterface | ||
for _, iface := range groupedAbi["interface"] { | ||
functions := []AbiFunction{} | ||
for _, funcData := range iface["items"].([]interface{}) { | ||
parsedAbi, errWhileParsing := ParseAbiFunction(funcData.(map[string]interface{}), definedTypes) | ||
if errWhileParsing != nil { | ||
return nil, errParseInterfaces | ||
} | ||
functions = append(functions, *parsedAbi) | ||
} | ||
definedInterfaces = append(definedInterfaces, AbiInterface{ | ||
name: iface["name"].(string), | ||
functions: functions, | ||
}) | ||
} | ||
|
||
// Parse functions | ||
functions := make(map[string]AbiFunction) | ||
for _, functionData := range groupedAbi["function"] { | ||
funcName := functionData["name"].(string) | ||
abiFunc, errParsingFunctions := ParseAbiFunction(functionData, definedTypes) | ||
if errParsingFunctions != nil { | ||
return nil, errParseFunctions | ||
} | ||
functions[funcName] = *abiFunc | ||
} | ||
|
||
// Add functions from interfaces | ||
for _, iface := range definedInterfaces { | ||
for _, function := range iface.functions { | ||
functions[function.name] = function | ||
} | ||
} | ||
|
||
// Parse events | ||
parsedAbiEvents := []AbiEvent{} | ||
for _, eventData := range groupedAbi["event"] { | ||
parsedEvent, errParsingEvent := ParseAbiEvent(eventData, definedTypes) | ||
if errParsingEvent != nil { | ||
return nil, errParseEvents | ||
} | ||
parsedAbiEvents = append(parsedAbiEvents, *parsedEvent) | ||
} | ||
|
||
events := make(map[string]AbiEvent) | ||
for _, event := range parsedAbiEvents { | ||
if event.name != "" { | ||
events[event.name] = event | ||
} | ||
} | ||
|
||
// Parse constructor | ||
var constructor []AbiParameter | ||
if len(groupedAbi["constructor"]) == 1 { | ||
for _, paramData := range groupedAbi["constructor"][0]["inputs"].([]interface{}) { | ||
param := paramData.(map[string]interface{}) | ||
typed, errorParsingType := parseType(param["type"].(string), definedTypes) | ||
if errorParsingType != nil { | ||
return nil, errParseConstructor | ||
} | ||
constructor = append(constructor, AbiParameter{ | ||
Name: param["name"].(string), | ||
Type: typed, | ||
}) | ||
} | ||
} else { | ||
constructor = nil | ||
} | ||
|
||
// Parse L1 handler | ||
var l1Handler *AbiFunction | ||
if len(groupedAbi["l1_handler"]) == 1 { | ||
handler, errorParsingFunction := ParseAbiFunction(groupedAbi["l1_handler"][0], definedTypes) | ||
if errorParsingFunction != nil { | ||
return nil, errParseL1Handler | ||
} | ||
l1Handler = handler | ||
} else { | ||
l1Handler = nil | ||
} | ||
|
||
// Parse implemented interfaces | ||
implementedInterfaces := make(map[string]AbiInterface) | ||
implArray, ok := groupedAbi["impl"] | ||
if !ok { | ||
return nil, errParseImplementedInterfaces | ||
} | ||
for _, implData := range implArray { | ||
implMap := implData | ||
if ifaceName, ok := implMap["interface_name"].(string); ok { | ||
for _, iface := range definedInterfaces { | ||
if iface.name == ifaceName { | ||
implementedInterfaces[iface.name] = iface | ||
} | ||
} | ||
} | ||
} | ||
|
||
// Return the populated StarknetAbi struct | ||
return &StarknetABI{ | ||
ABIName: &abiName, | ||
ClassHash: classHash, | ||
Functions: functions, | ||
Events: events, | ||
Constructor: constructor, | ||
L1Handler: l1Handler, | ||
ImplementedInterfaces: implementedInterfaces, | ||
}, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package athena_abi | ||
|
||
import ( | ||
"math/big" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestEventDecode(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
abiEvent *AbiEvent | ||
eventData []*big.Int | ||
eventKeys []*big.Int | ||
expected map[string]interface{} | ||
}{ | ||
{ | ||
name: "Approval Event", | ||
abiEvent: NewAbiEvent( | ||
"Approval", | ||
[]string{"owner", "spender", "value"}, | ||
map[string]StarknetType{"value": U256}, | ||
map[string]StarknetType{"owner": U256, "spender": U256}, | ||
"erc20_key_events", | ||
), | ||
eventData: []*big.Int{ | ||
mustParseBigInt("C95E3D845779376FED50", 16), | ||
big.NewInt(0), | ||
}, | ||
eventKeys: []*big.Int{ | ||
mustParseBigInt("0134692B230B9E1FFA39098904722134159652B09C5BC41D88D6698779D228FF", 16), // Event ID | ||
mustParseBigInt("060CAFC0B0E66067B3A4978E93552DE54E0CAEEB82A352A202E0DC79A41459B6", 16), // Owner low | ||
big.NewInt(0), // Owner high | ||
mustParseBigInt("04270219D365D6B017231B52E92B3FB5D7C8378B05E9ABC97724537A80E93B0F", 16), // Spender low | ||
big.NewInt(0), // Spender high | ||
}, | ||
expected: map[string]interface{}{ | ||
"owner": mustParseBigInt("060CAFC0B0E66067B3A4978E93552DE54E0CAEEB82A352A202E0DC79A41459B6", 16), | ||
"spender": mustParseBigInt("04270219D365D6B017231B52E92B3FB5D7C8378B05E9ABC97724537A80E93B0F", 16), | ||
"value": mustParseBigInt("C95E3D845779376FED50", 16), //Doubt here needs review | ||
}, | ||
}, | ||
} | ||
|
||
for _, test := range tests { | ||
t.Run(test.name, func(t *testing.T) { | ||
decodedEvent, err := test.abiEvent.Decode(test.eventData, test.eventKeys) | ||
if err != nil { | ||
t.Fatalf("Error decoding event: %v\nEvent Data: %v\nEvent Keys: %v", err, test.eventData, test.eventKeys) | ||
} | ||
|
||
assert.Equal(t, test.abiEvent.abiName, decodedEvent.abiName) | ||
assert.Equal(t, test.abiEvent.name, decodedEvent.name) | ||
|
||
for key, expectedValue := range test.expected { | ||
actualValue, exists := decodedEvent.data[key] | ||
assert.True(t, exists, "Key %s not found in decoded event", key) | ||
if !exists { | ||
continue | ||
} | ||
|
||
switch expected := expectedValue.(type) { | ||
case string: | ||
actual, ok := actualValue.(*big.Int) | ||
assert.True(t, ok, "Expected *big.Int for key %s, got %T", key, actualValue) | ||
if ok { | ||
assert.Equal(t, expected, bigIntToAddress(actual)) | ||
} | ||
case *big.Int: | ||
actual, ok := actualValue.(*big.Int) | ||
assert.True(t, ok, "Expected *big.Int for key %s, got %T", key, actualValue) | ||
if ok { | ||
assert.Equal(t, 0, expected.Cmp(actual), "For key %s, expected %s, got %s", key, expected.String(), actual.String()) | ||
} | ||
default: | ||
t.Errorf("Unexpected type for key %s: %T", key, expectedValue) | ||
} | ||
} | ||
}) | ||
} | ||
} | ||
|
||
// Helper function to parse big integers | ||
func mustParseBigInt(s string, base int) *big.Int { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Move these helper functions to uitls.go |
||
n, ok := new(big.Int).SetString(s, base) | ||
if !ok { | ||
panic("Failed to parse big integer: " + s) | ||
} | ||
return n | ||
} | ||
|
||
// Helper function to convert big.Int to address string | ||
func bigIntToAddress(n *big.Int) string { | ||
return "0x" + n.Text(16) | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How did you get this ? In the original code, I saw that they have loaded an abi for the testing purpose.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, Lets wait for core.go to be implemented. Then you can use from_json function from it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Sh0g0-1758 Do I need to incorporate starknetabifromjson?