diff --git a/selector/selector.go b/selector/selector.go index abb2703..9c495e5 100644 --- a/selector/selector.go +++ b/selector/selector.go @@ -139,7 +139,7 @@ func validateUriExtension(uri string) error { } func bytesToJsonString(b []byte, abiSourceUri string) string { - var data any // TODO: zeuslawyer refactor to handle array or map. Eg of array https://raw.githubusercontent.com/Cyfrin/ccip-contracts/main/contracts-ccip/abi/v0.8/Router.json + var data any if err := json.Unmarshal(b, &data); err != nil { panic(fmt.Errorf("error parsing JSON from file at %s : %s", abiSourceUri, err)) @@ -148,7 +148,7 @@ func bytesToJsonString(b []byte, abiSourceUri string) string { // Check if the data is a slice (array) or a map (object) var abiData any switch v := data.(type) { - case []interface{}: + case []any: fmt.Println("Data is an array") // You can work with v as a []interface{} abiData = v @@ -159,7 +159,7 @@ func bytesToJsonString(b []byte, abiSourceUri string) string { panic(fmt.Errorf("Property 'abi' not found in unmarshalled JSON data. Check the file at %s", abiSourceUri)) } - // check that the abi property is an array + // check that the "abi" property is an array _, ok = d.([]any) if !ok { fmt.Printf("Value of property 'abi' in supplied file is not an array") diff --git a/selector/selector_test.go b/selector/selector_test.go index 228fe97..f04a39b 100644 --- a/selector/selector_test.go +++ b/selector/selector_test.go @@ -1,6 +1,7 @@ package selector import ( + "fmt" "path" "strings" "testing" @@ -111,7 +112,7 @@ func TestFuncFromSelector(t *testing.T) { { name: "file - object missing abi property", selector: "0xa9059cbb", - path: path.Join("testdata", "erc20.bad-abi.json"), + path: path.Join("testdata", "bad-abi.json"), panics: true, want: "Property 'abi' not found", }, @@ -129,6 +130,13 @@ func TestFuncFromSelector(t *testing.T) { panics: true, want: "invalid file/url extension", }, + { + name: "URL - HTTP GET error", + selector: "0xa9059cbb", + url: "https://fake.json", + panics: true, + want: fmt.Sprintf("Get \"%s\"", "https://fake.json"), + }, { name: "non existent selector", selector: "0xa3063fba", @@ -178,7 +186,63 @@ func TestFuncFromSelector(t *testing.T) { } } -// TODO @zeuslawyer do TestErrorFromSelector() +func TestErrorSigFromSelector(t *testing.T) { + tests := []struct { + name string + selector string + path string + url string + panics bool + want string // Hex string + }{ + { + name: "Happy Path - error with single param", + selector: "0xae236d9c", + path: path.Join("testdata", "errors.abi.json"), + want: "UnsupportedDestinationChain(uint64)", + }, + { + name: "Happy Path - error with no param", + selector: "0xd0d25976", + path: path.Join("testdata", "errors.abi.json"), + want: "SenderNotAllowed(address)", + }, + { + name: "Error Not In Abi - Should Panic", + selector: "0x1841b4e1", + path: path.Join("testdata", "errors.abi.json"), + panics: true, + want: "no error with id", + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + if tc.panics { + defer func() { + if r := recover(); r != nil { + // Check if the panic value is as expected + errorString := r.(error).Error() + wantErrorSubString := tc.want + if strings.Contains(errorString, wantErrorSubString) == false { + t.Errorf("Expected panic message to contain: %s, got: %v", wantErrorSubString, errorString) + } + } else { + // The function did not panic as expected + t.Error("Expected the function to panic, but it did not") + } + }() + + ErrorSigFromSelector(tc.selector, tc.path, tc.url) + } else { + got := ErrorSigFromSelector(tc.selector, tc.path, tc.url) + if got != tc.want { + t.Errorf("ErrorSigFromSelector(%s) = %s, want %s", tc.selector, got, tc.want) + } + } + }) + } +} func TestEventFromTopicHash(t *testing.T) { tests := []struct { @@ -190,7 +254,7 @@ func TestEventFromTopicHash(t *testing.T) { want string // Hex string }{ // TODO @zeuslawyer do remaining test cases - // TODO should can the abi decoding function be reused to decode topic hash? + // TODO can the abiDecode() function be reused to decode topic hash? { name: "Event Signature from ABI file", topicHash: "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", // "0x8c5be1e5", diff --git a/selector/testdata/erc20.bad-abi.json b/selector/testdata/bad-abi.json similarity index 100% rename from selector/testdata/erc20.bad-abi.json rename to selector/testdata/bad-abi.json diff --git a/selector/testdata/errors.abi.json b/selector/testdata/errors.abi.json new file mode 100644 index 0000000..6faa067 --- /dev/null +++ b/selector/testdata/errors.abi.json @@ -0,0 +1,29 @@ +[ + { + "inputs": [], + "name": "InsufficientFeeTokenAmount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "destChainSelector", + "type": "uint64" + } + ], + "name": "UnsupportedDestinationChain", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "SenderNotAllowed", + "type": "error" + } +]