github.com/NpoolPlatform/chain-middleware@v0.0.0-20240228100535-eb1bcf896eb9/pkg/currency/coingecko/coingecko.go (about)

     1  package coingecko
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"os"
     7  	"strings"
     8  	"time"
     9  
    10  	"github.com/NpoolPlatform/go-service-framework/pkg/logger"
    11  
    12  	"github.com/shopspring/decimal"
    13  
    14  	"github.com/go-resty/resty/v2"
    15  )
    16  
    17  const (
    18  	coinAPI = "https://api.coingecko.com/api/v3"
    19  	timeout = 5
    20  )
    21  
    22  func CoinGeckoPrices(coinNames, fiatNames []string) (map[string]map[string]decimal.Decimal, error) {
    23  	if len(coinNames) == 0 {
    24  		return nil, fmt.Errorf("invalid coinnames")
    25  	}
    26  
    27  	coins := strings.Join(coinNames, ",")
    28  	fiats := strings.Join(fiatNames, ",")
    29  
    30  	socksProxy := os.Getenv("ENV_CURRENCY_REQUEST_PROXY")
    31  	url := fmt.Sprintf("%v%v?ids=%v&vs_currencies=%v", coinAPI, "/simple/price", coins, fiats)
    32  	cli := resty.New()
    33  	cli = cli.SetTimeout(timeout * time.Second)
    34  	if socksProxy != "" {
    35  		cli = cli.SetProxy(socksProxy)
    36  	}
    37  
    38  	logger.Sugar().Errorw(
    39  		"CoinGeckoPrices",
    40  		"URL", url,
    41  		"Proxy", socksProxy,
    42  		"Timeout", timeout,
    43  	)
    44  
    45  	resp, err := cli.R().Get(url)
    46  	if err != nil {
    47  		logger.Sugar().Errorw(
    48  			"CoinGeckoPrices",
    49  			"URL", url,
    50  			"Proxy", socksProxy,
    51  			"Error", err,
    52  		)
    53  		return nil, err
    54  	}
    55  	respMap := map[string]map[string]float64{}
    56  	err = json.Unmarshal(resp.Body(), &respMap)
    57  	if err != nil {
    58  		logger.Sugar().Errorw(
    59  			"CoinGeckoPrices",
    60  			"URL", url,
    61  			"Proxy", socksProxy,
    62  			"Resp", string(resp.Body()),
    63  			"Error", err,
    64  		)
    65  		return nil, err
    66  	}
    67  
    68  	infoMap := map[string]map[string]decimal.Decimal{}
    69  	for key, val := range respMap {
    70  		_infoMap, ok := infoMap[key]
    71  		if !ok {
    72  			_infoMap = map[string]decimal.Decimal{}
    73  		}
    74  		for _key, _val := range val {
    75  			_infoMap[_key] = decimal.NewFromFloat(_val)
    76  		}
    77  		infoMap[key] = _infoMap
    78  	}
    79  
    80  	return infoMap, nil
    81  }
    82  
    83  func CoinGeckoUSDPrices(coinNames []string) (map[string]decimal.Decimal, error) {
    84  	prices, err := CoinGeckoPrices(coinNames, []string{"usd"})
    85  	if err != nil {
    86  		return map[string]decimal.Decimal{}, err
    87  	}
    88  
    89  	_prices := map[string]decimal.Decimal{}
    90  	for key, val := range prices {
    91  		_prices[key] = val["usd"]
    92  	}
    93  
    94  	return _prices, nil
    95  }
    96  
    97  func CoinGeckoFiatPrices(fiatNames []string) (map[string]decimal.Decimal, error) {
    98  	socksProxy := os.Getenv("ENV_CURRENCY_REQUEST_PROXY")
    99  	fiats := strings.Join(fiatNames, ",")
   100  	url := fmt.Sprintf("%v%v?ids=usd&vs_currencies=%v", coinAPI, "/simple/price", fiats)
   101  	cli := resty.New()
   102  	cli = cli.SetTimeout(timeout * time.Second)
   103  	if socksProxy != "" {
   104  		cli = cli.SetProxy(socksProxy)
   105  	}
   106  	resp, err := cli.R().Get(url)
   107  	if err != nil {
   108  		logger.Sugar().Errorw(
   109  			"CoinGeckoFiatPrices",
   110  			"URL", url,
   111  			"Proxy", socksProxy,
   112  			"Error", err,
   113  		)
   114  		return nil, err
   115  	}
   116  
   117  	respMap := map[string]map[string]float64{}
   118  	err = json.Unmarshal(resp.Body(), &respMap)
   119  	if err != nil {
   120  		logger.Sugar().Errorw(
   121  			"CoinGeckoFiatPrices",
   122  			"URL", url,
   123  			"Proxy", socksProxy,
   124  			"Resp", resp.Body(),
   125  			"Error", err,
   126  		)
   127  		return nil, err
   128  	}
   129  
   130  	respMap1 := map[string]decimal.Decimal{}
   131  	if _, ok := respMap["usd"]; ok {
   132  		for key, val := range respMap["usd"] {
   133  			c := decimal.NewFromFloat(val)
   134  			respMap1[strings.ToLower(key)] = c
   135  		}
   136  	}
   137  	return respMap1, nil
   138  }