diff options
author | terminaldweller <devi@terminaldweller.com> | 2024-05-28 23:02:34 +0000 |
---|---|---|
committer | terminaldweller <devi@terminaldweller.com> | 2024-05-28 23:02:34 +0000 |
commit | 87794892bf0e5c9c729f709777bb01e383d192de (patch) | |
tree | aa9d9b525f41b2b68410c5bac5157c4d88ca3589 | |
parent | replaces redis with keydb (diff) | |
download | hived-87794892bf0e5c9c729f709777bb01e383d192de.tar.gz hived-87794892bf0e5c9c729f709777bb01e383d192de.zip |
added cmc as a provider
-rw-r--r-- | docker-compose-test.yaml | 8 | ||||
-rw-r--r-- | hived/CMCTickerResponseType.go | 46 | ||||
-rw-r--r-- | hived/hived.go | 88 | ||||
-rw-r--r-- | hived/polygonTickerResponseType.go (renamed from hived/polygonTicerResponseType.go) | 0 |
4 files changed, 117 insertions, 25 deletions
diff --git a/docker-compose-test.yaml b/docker-compose-test.yaml index 965bef9..8d8481f 100644 --- a/docker-compose-test.yaml +++ b/docker-compose-test.yaml @@ -11,7 +11,7 @@ services: ports: - "10008:8008" depends_on: - - redis + - keydb - telebot entrypoint: ["/hived/docker-entrypoint.sh"] cap_drop: @@ -19,6 +19,8 @@ services: environment: - SERVER_DEPLOYMENT_TYPE=test - POLYGON_API_KEY= + - HIVED_PRICE_SOURCE=cmc + - CMC_API_KEY=d941be62-d4da-426c-8dc3-7311b04dfa5f telebot: image: telebot build: @@ -56,7 +58,7 @@ services: environment: - ALLOW_EMPTY_PASSWORD=yes # volumes: - # - redis-data:/data/ + # - keydb-data:/data/ networks: mainnet: driver: bridge @@ -66,4 +68,4 @@ secrets: tg_bot_token: file: ./tgtoken volumes: - redis-data: + keydb-data: diff --git a/hived/CMCTickerResponseType.go b/hived/CMCTickerResponseType.go new file mode 100644 index 0000000..c7fcf84 --- /dev/null +++ b/hived/CMCTickerResponseType.go @@ -0,0 +1,46 @@ +package main + +type CMCTickerStatus struct { + Timestamp string `json:"timestamp"` + ErrorCode int `json:"error_code"` + ErrorMessage string `json:"error_message"` + Elapsed int `json:"elapsed"` + CreditCount int `json:"credit_count"` + Notice string `json:"notice"` +} + +type CMCTickerQuoteData struct { + Price float64 `json:"price"` + Volume24H float64 `json:"volume_24h"` + VolumeChnage24H float64 `json:"volume_change_24h"` + PercentChange1H float64 `json:"percent_change_1h"` + PercentChange24h float64 `json:"percent_change_24h"` + PercentChange7d float64 `json:"percent_change_7d"` + PercentChange30d float64 `json:"percent_change_30d"` + MarketCap float64 `json:"market_cap"` + MarketCapDominance float64 `json:"market_cap_dominance"` + FullyDilutedMarketCap float64 `json:"fully_diluted_market_cap"` + LastUpdated string `json:"last_updated"` +} + +type CMCTickerData struct { + ID int `json:"id"` + Name string `json:"name"` + Symbol string `json:"symbol"` + Slug string `json:"slug"` + IsActive int `json:"is_active"` + IsFiat int `json:"is_fiat"` + CirculatingSupply float64 `json:"circulating_supply"` + TotalSupply float64 `json:"total_supply"` + MaxSupply float64 `json:"max_supply"` + DateAdded string `json:"date_added"` + NumMarketPairs int `json:"num_market_pairs"` + CMCRank int `json:"cmc_rank"` + LastUpdated string `json:"last_updated"` + Quote map[string]CMCTickerQuoteData `json:"quote"` +} + +type CMCTickerResponseType struct { + Data map[string]CMCTickerData `json:"data"` + Status CMCTickerStatus `json:"status"` +} diff --git a/hived/hived.go b/hived/hived.go index 4ed81cf..6d3cdfb 100644 --- a/hived/hived.go +++ b/hived/hived.go @@ -28,6 +28,7 @@ import ( const ( cryptocomparePriceURL = "https://min-api.cryptocompare.com/data/price?" polygonCryptoTickerURL = "https://api.polygon.io/v2/snapshot/locale/global/markets/crypto/tickers" + cmcCryptoTickerURL = "https://pro-api.coinmarketcap.com/v2/cryptocurrency/quotes/latest" telegramBotTokenEnvVar = "TELEGRAM_BOT_TOKEN" //nolint: gosec serverDeploymentType = "SERVER_DEPLOYMENT_TYPE" httpClientTimeout = 5 @@ -121,21 +122,6 @@ type errorChanStruct struct { err error } -// type APISource int - -const ( - CryptoCompareSource = iota - PolygonSource - // CoinGeckoSource - // CoinCapSource -) - -// TODO-add more sources. -// TODO-do a round robin. -func chooseGetPriceSource() int { - return PolygonSource -} - func getPrice(ctx context.Context, name, unit string, waitGroup *sync.WaitGroup, @@ -145,21 +131,20 @@ func getPrice(ctx context.Context, val, err := rdb.Get(ctx, name+"_price").Float64() if err != nil { - source := chooseGetPriceSource() + source := os.Getenv("HIVED_PRICE_SOURCE") switch source { - case CryptoCompareSource: - fmt.Println("one") + case "cryptocompare": getPriceFromCryptoCompare(ctx, name, unit, waitGroup, priceChan, errChan) - case PolygonSource: - fmt.Println("two") + case "polygon": getPriceFromPolygon(ctx, name, unit, waitGroup, priceChan, errChan) - default: - + case "cmc": + getPriceFromCMC(ctx, name, unit, waitGroup, priceChan, errChan) } } else { priceChan <- priceChanStruct{name: name, price: val} errChan <- errorChanStruct{hasError: false, err: nil} + waitGroup.Done() } } @@ -280,6 +265,65 @@ func getPriceFromPolygon( errChan <- errorChanStruct{hasError: false, err: nil} } +func getPriceFromCMC( + ctx context.Context, + name, unit string, + wg *sync.WaitGroup, + priceChan chan<- priceChanStruct, + errChan chan<- errorChanStruct, +) { + defer wg.Done() + + apiKey := os.Getenv("CMC_API_KEY") + + params := "?slug=" + name + path := cmcCryptoTickerURL + params + + log.Print(path) + + client := GetProxiedClient() + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, path, nil) + if err != nil { + getPriceFromCryptoCompareErrorHandler(err, name, priceChan, errChan) + + return + } + + req.Header.Set("X-CMC_PRO_API_KEY", apiKey) + + resp, err := client.Do(req) + if err != nil { + getPriceFromCryptoCompareErrorHandler(err, name, priceChan, errChan) + + return + } + defer resp.Body.Close() + + var jsonBody CMCTickerResponseType + + err = json.NewDecoder(resp.Body).Decode(&jsonBody) + if err != nil { + getPriceFromCryptoCompareErrorHandler(err, name, priceChan, errChan) + } + + log.Print(jsonBody) + + var price float64 + for _, v := range jsonBody.Data { + price = v.Quote["USD"].Price + } + + err = rdb.Set(ctx, name+"_price", price, time.Duration(*cacheDuration*redisCacheDurationMultiplier)).Err() + + if err != nil { + log.Error().Err(err) + } + + priceChan <- priceChanStruct{name: name, price: price} + errChan <- errorChanStruct{hasError: false, err: nil} +} + func PriceHandler(writer http.ResponseWriter, request *http.Request) { writer.Header().Add("Content-Type", "application/json") diff --git a/hived/polygonTicerResponseType.go b/hived/polygonTickerResponseType.go index 6d8b323..6d8b323 100644 --- a/hived/polygonTicerResponseType.go +++ b/hived/polygonTickerResponseType.go |