97 lines
2.1 KiB
Go
97 lines
2.1 KiB
Go
package coingecko
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/shopspring/decimal"
|
|
"github.com/wormhole-foundation/wormhole-explorer/common/domain"
|
|
)
|
|
|
|
// CoingeckoAPI is a client for the coingecko API
|
|
type CoingeckoAPI struct {
|
|
url string
|
|
chunkSize int
|
|
client *http.Client
|
|
}
|
|
|
|
// NewCoingeckoAPI creates a new coingecko client
|
|
func NewCoingeckoAPI(url string) *CoingeckoAPI {
|
|
return &CoingeckoAPI{
|
|
url: url,
|
|
chunkSize: 200,
|
|
client: http.DefaultClient,
|
|
}
|
|
}
|
|
|
|
// NotionalUSD is the response from the coingecko API.
|
|
type NotionalUSD struct {
|
|
Price *decimal.Decimal `json:"usd"`
|
|
}
|
|
|
|
// GetNotionalUSD returns the notional USD value for the given ids
|
|
// ids is a list of coingecko chain identifier.
|
|
func (c *CoingeckoAPI) GetNotionalUSD(ids []string) (map[string]NotionalUSD, error) {
|
|
response := map[string]NotionalUSD{}
|
|
chunksIds := chunkChainIds(ids, c.chunkSize)
|
|
|
|
// iterate over chunks of ids.
|
|
for _, chunk := range chunksIds {
|
|
notionalUrl := fmt.Sprintf("%s/simple/price?ids=%s&vs_currencies=usd", c.url, strings.Join(chunk, ","))
|
|
|
|
req, err := http.NewRequest(http.MethodGet, notionalUrl, nil)
|
|
if err != nil {
|
|
return response, err
|
|
}
|
|
res, err := c.client.Do(req)
|
|
if err != nil {
|
|
return response, err
|
|
}
|
|
defer res.Body.Close()
|
|
|
|
body, err := ioutil.ReadAll(res.Body)
|
|
if err != nil {
|
|
return response, err
|
|
}
|
|
|
|
chunkResponse := map[string]NotionalUSD{}
|
|
err = json.Unmarshal(body, &chunkResponse)
|
|
if err != nil {
|
|
return response, err
|
|
}
|
|
|
|
// merge chunk response with response.
|
|
for k, v := range chunkResponse {
|
|
response[k] = v
|
|
}
|
|
}
|
|
|
|
return response, nil
|
|
}
|
|
|
|
func chunkChainIds(slice []string, chunkSize int) [][]string {
|
|
var chunks [][]string
|
|
for i := 0; i < len(slice); i += chunkSize {
|
|
end := i + chunkSize
|
|
if end > len(slice) {
|
|
end = len(slice)
|
|
}
|
|
chunks = append(chunks, slice[i:end])
|
|
}
|
|
return chunks
|
|
}
|
|
|
|
// GetChainIDs returns the coingecko chain ids for the given p2p network.
|
|
func GetChainIDs(p2pNetwork string) []string {
|
|
|
|
if p2pNetwork == domain.P2pMainNet {
|
|
return domain.GetAllCoingeckoIDs()
|
|
}
|
|
|
|
// TODO: define chains ids for testnet.
|
|
return []string{}
|
|
}
|