-
Notifications
You must be signed in to change notification settings - Fork 10
/
util.go
149 lines (135 loc) · 4.54 KB
/
util.go
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package main
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
)
// ChainInfo simplified version of the chain information from the registry
type ChainInfo struct {
Schema string `json:"$schema"`
ChainName string `json:"chain_name"`
ChainID string `json:"chain_id"`
PrettyName string `json:"pretty_name"`
Status string `json:"status"`
NetworkType string `json:"network_type"`
Bech32Prefix string `json:"bech32_prefix"`
DaemonName string `json:"daemon_name"`
NodeHome string `json:"node_home"`
KeyAlgos []string `json:"key_algos"`
Slip44 int `json:"slip44"`
Fees Fees `json:"fees"`
}
type FeeTokens struct {
Denom string `json:"denom"`
FixedMinGasPrice int `json:"fixed_min_gas_price"`
}
type Fees struct {
FeeTokens []FeeTokens `json:"fee_tokens"`
}
// getDenom get the denom to be used in transaction fees
// This method first will try to retrieve the denom from the configuration '[[chains]] denom'
// if the deno m is not available in the configuration then it will try to retrieve it from
// the chain-registry (https://github.com/cosmos/chain-registry). But in order for the chain
// registry retrieval to work, the chain name in the configuration file has to match the
// chain_name property in the chain.json. For example
// https://github.com/cosmos/chain-registry/blob/5ebdb2cf8bf0a6a14d602d4e63fd046f66895cbb/cosmoshub/chain.json#L3
func getDenom(conf *Config, chainName string) (string, error) {
chain, found := conf.GetChain(chainName)
if !found {
return "", errors.New(fmt.Sprintf("chain %s not found in config", chainName))
} else {
if chain.Denom != "" {
return chain.Denom, nil
} else {
// Try chain registry
denom, err := getDenomFromRegistry(chainName)
if err != nil {
return "", errors.New(fmt.Sprintf("cannot find denom in the config or registry: %s", err))
} else {
return denom, nil
}
}
}
}
func getDenomFromRegistry(chainName string) (string, error) {
chain := ChainInfo{}
denom := ""
url := fmt.Sprintf("https://raw.githubusercontent.com/cosmos/chain-registry/master/%s/chain.json", chainName)
method := "GET"
client := &http.Client{}
req, err := http.NewRequest(method, url, nil)
if err != nil {
fmt.Println(err)
return denom, err
}
res, err := client.Do(req)
if (err != nil) || (res.StatusCode == 404) {
fmt.Println(err)
return denom, errors.New(fmt.Sprintf("cannot find denom in the chain registry, please ensure the chain name in the configuration file matches the folder name in the registry (https://github.com/cosmos/chain-registry)"))
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
fmt.Println(err)
return denom, err
}
err = json.Unmarshal(body, &chain)
if err != nil {
fmt.Println(err)
return denom, err
}
// Assumption that the first fee token is the one used for paying
// the fees and the fee information is in the registry
if chain.Fees.FeeTokens != nil {
if chain.Fees.FeeTokens[0].Denom != "" {
return chain.Fees.FeeTokens[0].Denom, nil
}
}
return "", errors.New(fmt.Sprintf("cannot find denom fee information for the %s chain in the registry", chainName))
}
// Quick way to parse the denom from the json
// without worrying on the different message types
// that the unsigned may have. In the future this
// might be improved parsing the right msg type
func parseDenomFromJson(tx []byte) (string, error) {
var anyJson map[string]interface{}
err := json.Unmarshal(tx, &anyJson)
if err != nil {
return "", fmt.Errorf("cannot parse tx json, error %s", err)
}
if anyJson["auth_info"] != nil {
auth, ok := anyJson["auth_info"].(map[string]interface{})
if ok {
if auth["fee"] != nil {
fee, ok := auth["fee"].(map[string]interface{})
if ok {
if fee["amount"] != nil {
value, ok := fee["amount"].([]interface{})
if ok {
if len(value) >= 1 {
firstValue, ok := value[0].(map[string]interface{})
if ok {
if firstValue["denom"] != nil {
return firstValue["denom"].(string), nil
}
}
}
}
}
}
}
}
}
// in case cannot find the denom value in the json, return an error
return "", fmt.Errorf("cannot parse json, cannot find denom value")
}
func parseSdkVersionFromJson(nodeInfo NodeInfo) (string, error) {
for _, dep := range nodeInfo.ApplicationVersion.BuildDeps {
if dep.Path == "github.com/cosmos/cosmos-sdk" {
return dep.Version, nil
}
}
return "", errors.New(fmt.Sprintf("cannot parse sdk version, cannot find sdk version value"))
}