2022-08-23 08:46:15 +00:00
|
|
|
package wallet
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"net/http"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2022-10-10 19:02:04 +00:00
|
|
|
const cryptocompareURL = "https://min-api.cryptocompare.com"
|
|
|
|
|
2022-10-24 08:41:36 +00:00
|
|
|
var renameMapping = map[string]string{
|
|
|
|
"STT": "SNT",
|
|
|
|
}
|
|
|
|
|
2022-08-23 08:46:15 +00:00
|
|
|
type Coin struct {
|
|
|
|
ID string `json:"Id"`
|
|
|
|
Name string `json:"Name"`
|
|
|
|
Symbol string `json:"Symbol"`
|
|
|
|
Description string `json:"Description"`
|
|
|
|
TotalCoinsMined float64 `json:"TotalCoinsMined"`
|
|
|
|
AssetLaunchDate string `json:"AssetLaunchDate"`
|
|
|
|
AssetWhitepaperURL string `json:"AssetWhitepaperUrl"`
|
|
|
|
AssetWebsiteURL string `json:"AssetWebsiteUrl"`
|
|
|
|
BuiltOn string `json:"BuiltOn"`
|
|
|
|
SmartContractAddress string `json:"SmartContractAddress"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type MarketCoinValues struct {
|
2023-01-03 13:24:55 +00:00
|
|
|
MKTCAP float64 `json:"MKTCAP"`
|
|
|
|
HIGHDAY float64 `json:"HIGHDAY"`
|
|
|
|
LOWDAY float64 `json:"LOWDAY"`
|
|
|
|
CHANGEPCTHOUR float64 `json:"CHANGEPCTHOUR"`
|
|
|
|
CHANGEPCTDAY float64 `json:"CHANGEPCTDAY"`
|
|
|
|
CHANGEPCT24HOUR float64 `json:"CHANGEPCT24HOUR"`
|
|
|
|
CHANGE24HOUR float64 `json:"CHANGE24HOUR"`
|
2022-08-23 08:46:15 +00:00
|
|
|
}
|
|
|
|
|
2022-10-10 19:02:04 +00:00
|
|
|
type TokenHistoricalPairs struct {
|
|
|
|
Timestamp int64 `json:"time"`
|
|
|
|
Value float64 `json:"close"`
|
|
|
|
Volumefrom float64 `json:"volumefrom"`
|
|
|
|
Volumeto float64 `json:"volumeto"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type HistoricalValuesContainer struct {
|
|
|
|
Aggregated bool `json:"Aggregated"`
|
|
|
|
TimeFrom int64 `json:"TimeFrom"`
|
|
|
|
TimeTo int64 `json:"TimeTo"`
|
|
|
|
HistoricalData []TokenHistoricalPairs `json:"Data"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type HistoricalValuesData struct {
|
|
|
|
Data HistoricalValuesContainer `json:"Data"`
|
|
|
|
}
|
|
|
|
|
2022-08-23 08:46:15 +00:00
|
|
|
type CoinsContainer struct {
|
|
|
|
Data map[string]Coin `json:"Data"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type MarketValuesContainer struct {
|
2023-01-03 13:24:55 +00:00
|
|
|
Raw map[string]map[string]MarketCoinValues `json:"Raw"`
|
2022-08-23 08:46:15 +00:00
|
|
|
}
|
|
|
|
|
2022-10-24 08:41:36 +00:00
|
|
|
func renameSymbols(symbols []string) (renames []string) {
|
|
|
|
for _, symbol := range symbols {
|
|
|
|
renames = append(renames, getRealSymbol(symbol))
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func getRealSymbol(symbol string) string {
|
|
|
|
if val, ok := renameMapping[strings.ToUpper(symbol)]; ok {
|
|
|
|
return val
|
|
|
|
}
|
|
|
|
return strings.ToUpper(symbol)
|
|
|
|
}
|
|
|
|
|
2022-10-27 07:38:05 +00:00
|
|
|
func chunkSymbols(symbols []string) [][]string {
|
|
|
|
var chunks [][]string
|
|
|
|
chunkSize := 20
|
|
|
|
for i := 0; i < len(symbols); i += chunkSize {
|
|
|
|
end := i + chunkSize
|
2022-08-23 08:46:15 +00:00
|
|
|
|
2022-10-27 07:38:05 +00:00
|
|
|
if end > len(symbols) {
|
|
|
|
end = len(symbols)
|
|
|
|
}
|
2022-08-23 08:46:15 +00:00
|
|
|
|
2022-10-27 07:38:05 +00:00
|
|
|
chunks = append(chunks, symbols[i:end])
|
2022-08-23 08:46:15 +00:00
|
|
|
}
|
|
|
|
|
2022-10-27 07:38:05 +00:00
|
|
|
return chunks
|
|
|
|
}
|
2022-08-23 08:46:15 +00:00
|
|
|
|
2023-01-03 13:24:55 +00:00
|
|
|
func fetchCryptoComparePrices(symbols []string, currencies []string) (map[string]map[string]float64, error) {
|
2022-10-27 07:38:05 +00:00
|
|
|
chunks := chunkSymbols(symbols)
|
2023-01-03 13:24:55 +00:00
|
|
|
result := make(map[string]map[string]float64)
|
|
|
|
realCurrencies := renameSymbols(currencies)
|
2022-10-27 07:38:05 +00:00
|
|
|
for _, smbls := range chunks {
|
|
|
|
realSymbols := renameSymbols(smbls)
|
|
|
|
httpClient := http.Client{Timeout: time.Minute}
|
2023-01-03 13:24:55 +00:00
|
|
|
url := fmt.Sprintf("%s/data/pricemulti?fsyms=%s&tsyms=%s&extraParams=Status.im", cryptocompareURL, strings.Join(realSymbols, ","), strings.Join(realCurrencies, ","))
|
2022-10-27 07:38:05 +00:00
|
|
|
resp, err := httpClient.Get(url)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
|
|
|
|
body, err := ioutil.ReadAll(resp.Body)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
prices := make(map[string]map[string]float64)
|
|
|
|
err = json.Unmarshal(body, &prices)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, symbol := range smbls {
|
2023-01-03 13:24:55 +00:00
|
|
|
result[symbol] = map[string]float64{}
|
|
|
|
for _, currency := range currencies {
|
|
|
|
result[symbol][currency] = prices[getRealSymbol(symbol)][getRealSymbol(currency)]
|
|
|
|
}
|
2022-10-27 07:38:05 +00:00
|
|
|
}
|
2022-08-23 08:46:15 +00:00
|
|
|
}
|
|
|
|
return result, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func fetchCryptoCompareTokenDetails(symbols []string) (map[string]Coin, error) {
|
|
|
|
httpClient := http.Client{Timeout: time.Minute}
|
|
|
|
|
2022-10-10 19:02:04 +00:00
|
|
|
url := fmt.Sprintf("%s/data/all/coinlist", cryptocompareURL)
|
2022-08-23 08:46:15 +00:00
|
|
|
resp, err := httpClient.Get(url)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
|
|
|
|
body, err := ioutil.ReadAll(resp.Body)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
container := CoinsContainer{}
|
|
|
|
err = json.Unmarshal(body, &container)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
coins := make(map[string]Coin)
|
|
|
|
|
|
|
|
for _, symbol := range symbols {
|
2022-10-24 08:41:36 +00:00
|
|
|
coins[symbol] = container.Data[getRealSymbol(symbol)]
|
2022-08-23 08:46:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return coins, nil
|
|
|
|
}
|
|
|
|
|
2023-01-03 13:24:55 +00:00
|
|
|
func fetchTokenMarketValues(symbols []string, currencies []string) (map[string]map[string]MarketCoinValues, error) {
|
|
|
|
realCurrencies := renameSymbols(currencies)
|
2022-10-24 08:41:36 +00:00
|
|
|
realSymbols := renameSymbols(symbols)
|
2023-01-03 13:24:55 +00:00
|
|
|
item := map[string]map[string]MarketCoinValues{}
|
2022-08-23 08:46:15 +00:00
|
|
|
httpClient := http.Client{Timeout: time.Minute}
|
|
|
|
|
2023-01-03 13:24:55 +00:00
|
|
|
url := fmt.Sprintf("%s/data/pricemultifull?fsyms=%s&tsyms=%s&extraParams=Status.im", cryptocompareURL, strings.Join(realSymbols, ","), strings.Join(realCurrencies, ","))
|
2022-08-23 08:46:15 +00:00
|
|
|
resp, err := httpClient.Get(url)
|
|
|
|
if err != nil {
|
|
|
|
return item, err
|
|
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
|
|
|
|
body, err := ioutil.ReadAll(resp.Body)
|
|
|
|
if err != nil {
|
|
|
|
return item, err
|
|
|
|
}
|
|
|
|
|
|
|
|
container := MarketValuesContainer{}
|
|
|
|
err = json.Unmarshal(body, &container)
|
|
|
|
if err != nil {
|
|
|
|
return item, err
|
|
|
|
}
|
|
|
|
|
2022-10-24 08:41:36 +00:00
|
|
|
for _, symbol := range symbols {
|
2023-01-03 13:24:55 +00:00
|
|
|
item[symbol] = map[string]MarketCoinValues{}
|
|
|
|
for _, currency := range currencies {
|
|
|
|
item[symbol][currency] = container.Raw[getRealSymbol(symbol)][getRealSymbol(currency)]
|
|
|
|
}
|
2022-08-23 08:46:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return item, nil
|
|
|
|
}
|
2022-10-10 19:02:04 +00:00
|
|
|
|
|
|
|
func fetchHourlyMarketValues(symbol string, currency string, limit int, aggregate int) ([]TokenHistoricalPairs, error) {
|
|
|
|
item := []TokenHistoricalPairs{}
|
|
|
|
httpClient := http.Client{Timeout: time.Minute}
|
|
|
|
|
2022-10-24 08:41:36 +00:00
|
|
|
url := fmt.Sprintf("%s/data/v2/histohour?fsym=%s&tsym=%s&aggregate=%d&limit=%d&extraParams=Status.im", cryptocompareURL, getRealSymbol(symbol), currency, aggregate, limit)
|
2022-10-10 19:02:04 +00:00
|
|
|
resp, err := httpClient.Get(url)
|
|
|
|
if err != nil {
|
|
|
|
return item, err
|
|
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
|
|
|
|
body, err := ioutil.ReadAll(resp.Body)
|
|
|
|
if err != nil {
|
|
|
|
return item, err
|
|
|
|
}
|
|
|
|
|
|
|
|
container := HistoricalValuesData{}
|
|
|
|
err = json.Unmarshal(body, &container)
|
|
|
|
if err != nil {
|
|
|
|
return item, err
|
|
|
|
}
|
|
|
|
|
|
|
|
item = container.Data.HistoricalData
|
|
|
|
|
|
|
|
return item, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func fetchDailyMarketValues(symbol string, currency string, limit int, allData bool, aggregate int) ([]TokenHistoricalPairs, error) {
|
|
|
|
item := []TokenHistoricalPairs{}
|
|
|
|
httpClient := http.Client{Timeout: time.Minute}
|
|
|
|
|
2022-10-24 08:41:36 +00:00
|
|
|
url := fmt.Sprintf("%s/data/v2/histoday?fsym=%s&tsym=%s&aggregate=%d&limit=%d&allData=%v&extraParams=Status.im", cryptocompareURL, getRealSymbol(symbol), currency, aggregate, limit, allData)
|
2022-10-10 19:02:04 +00:00
|
|
|
resp, err := httpClient.Get(url)
|
|
|
|
if err != nil {
|
|
|
|
return item, err
|
|
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
|
|
|
|
body, err := ioutil.ReadAll(resp.Body)
|
|
|
|
if err != nil {
|
|
|
|
return item, err
|
|
|
|
}
|
|
|
|
|
|
|
|
container := HistoricalValuesData{}
|
|
|
|
err = json.Unmarshal(body, &container)
|
|
|
|
if err != nil {
|
|
|
|
return item, err
|
|
|
|
}
|
|
|
|
|
|
|
|
item = container.Data.HistoricalData
|
|
|
|
|
|
|
|
return item, nil
|
|
|
|
}
|