-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathmethods_metadata.go
More file actions
131 lines (109 loc) · 4.44 KB
/
methods_metadata.go
File metadata and controls
131 lines (109 loc) · 4.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package sourcify
import (
"encoding/json"
"fmt"
"io"
"net/http"
"github.com/ethereum/go-ethereum/common"
)
// GetContractMetadata fetches the metadata of a contract from a given client,
// chain ID, contract address, and match type. It returns a Metadata object and
// an error, if any. This function is primarily used to fetch and parse metadata
// from smart contracts.
func GetContractMetadata(client *Client, chainId int, contract common.Address, matchType MethodMatchType) (*Metadata, error) {
var method Method
switch matchType {
case MethodMatchTypeFull:
method = MethodGetFileFromRepositoryFullMatch
case MethodMatchTypePartial:
method = MethodGetFileFromRepositoryPartialMatch
case MethodMatchTypeAny:
return nil, fmt.Errorf("type: %s is not implemented", matchType)
default:
return nil, fmt.Errorf("invalid match type: %s", matchType)
}
method.SetParams(
MethodParam{Key: ":chain", Value: chainId},
MethodParam{Key: ":address", Value: contract.Hex()},
MethodParam{Key: ":filePath", Value: "metadata.json"},
)
if err := method.Verify(); err != nil {
return nil, err
}
response, statusCode, err := client.CallMethod(method)
if err != nil {
return nil, err
}
// Close the io.ReadCloser interface.
// This is important as CallMethod is NOT closing the response body!
// You'll have memory leaks if you don't do this!
defer response.Close()
if statusCode != http.StatusOK {
if rErr := ToErrorResponse(response); rErr != nil {
return nil, rErr
}
return nil, fmt.Errorf("unexpected status code: %d", statusCode)
}
var toReturn Metadata
if err := json.NewDecoder(response).Decode(&toReturn); err != nil {
return nil, err
}
return &toReturn, nil
}
// GetContractMetadataAsBytes retrieves the metadata of a smart contract as a byte slice.
// The client parameter is a pointer to a Client instance used to make the API call.
// The chainId parameter is the ID of the blockchain network where the smart contract resides.
// The contract parameter is the address of the smart contract.
// The matchType parameter determines the type of method matching to use when retrieving the contract metadata.
// It returns a byte slice containing the contract metadata, or an error if there was an issue sending the request, decoding the response, or if an invalid matchType was provided.
//
// The MethodMatchType enum is used to determine the type of method matching to use:
// - MethodMatchTypeFull: Use full method matching. This will only return a match if the entire method signature matches.
// - MethodMatchTypePartial: Use partial method matching. This will return a match if any part of the method signature matches.
// - MethodMatchTypeAny: This match type is not implemented and will return an error.
//
// This function will send a request to the API endpoint specified in the client parameter, using the method determined by the matchType parameter.
// The method will be set with the chainId, contract address, and file path parameters.
// If the method fails verification, an error will be returned.
// If the API call is successful, the response body will be read and returned as a byte slice.
// If the status code of the response is not 200 OK, an error will be returned.
func GetContractMetadataAsBytes(client *Client, chainId int, contract common.Address, matchType MethodMatchType) ([]byte, error) {
var method Method
switch matchType {
case MethodMatchTypeFull:
method = MethodGetFileFromRepositoryFullMatch
case MethodMatchTypePartial:
method = MethodGetFileFromRepositoryPartialMatch
case MethodMatchTypeAny:
return nil, fmt.Errorf("type: %s is not implemented", matchType)
default:
return nil, fmt.Errorf("invalid match type: %s", matchType)
}
method.SetParams(
MethodParam{Key: ":chain", Value: chainId},
MethodParam{Key: ":address", Value: contract.Hex()},
MethodParam{Key: ":filePath", Value: "metadata.json"},
)
if err := method.Verify(); err != nil {
return nil, err
}
response, statusCode, err := client.CallMethod(method)
if err != nil {
return nil, err
}
// Close the io.ReadCloser interface.
// This is important as CallMethod is NOT closing the response body!
// You'll have memory leaks if you don't do this!
defer response.Close()
if statusCode != http.StatusOK {
if rErr := ToErrorResponse(response); rErr != nil {
return nil, rErr
}
return nil, fmt.Errorf("unexpected status code: %d", statusCode)
}
body, err := io.ReadAll(response)
if err != nil {
return nil, err
}
return body, nil
}