diff --git a/README.md b/README.md index 02a4df1..c958415 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # CoinGecko API [![Go Version](https://img.shields.io/badge/go-v1.21.1-green.svg)](https://golang.org/dl/) -[![Code Lint](https://github.com/bufdata/coingecko-api/actions/workflows/code-lint.yml/badge.svg)](https://github.com/bufdata/coingecko-api/actions/workflows/code-lint.yml) -[![Unit Test](https://github.com/bufdata/coingecko-api/actions/workflows/unit-test.yml/badge.svg)](https://github.com/bufdata/coingecko-api/actions/workflows/unit-test.yml) -[![GoDoc](https://pkg.go.dev/github.com/bufdata/coingecko-api?status.svg)](https://pkg.go.dev/github.com/bufdata/coingecko-api) -[![goreports](https://goreportcard.com/badge/github.com/bufdata/coingecko-api)](https://goreportcard.com/report/github.com/bufdata/coingecko-api) +[![PkgGoDev](https://pkg.go.dev/badge/github.com/bufdata/coingecko-api)](https://pkg.go.dev/github.com/bufdata/coingecko-api) +[![Go Report Card](https://goreportcard.com/badge/github.com/bufdata/coingecko-api)](https://goreportcard.com/report/github.com/bufdata/coingecko-api) [![Codecov](https://codecov.io/gh/bufdata/coingecko-api/branch/master/graph/badge.svg)](https://codecov.io/gh/bufdata/coingecko-api) [![license](https://img.shields.io/badge/license-MIT-blue)](https://github.com/bufdata/coingecko-api/blob/main/LICENSE) +[![Code Lint](https://github.com/bufdata/coingecko-api/actions/workflows/code-lint.yml/badge.svg)](https://github.com/bufdata/coingecko-api/actions/workflows/code-lint.yml) +[![Unit Test](https://github.com/bufdata/coingecko-api/actions/workflows/unit-test.yml/badge.svg)](https://github.com/bufdata/coingecko-api/actions/workflows/unit-test.yml) [![Build Status](https://travis-ci.com/bufdata/coingecko-api.svg?branch=main)](https://travis-ci.com/bufdata/coingecko-api) [![](https://static.coingecko.com/s/coingecko-logo-d13d6bcceddbb003f146b33c2f7e8193d72b93bb343d38e392897c3df3e78bdd.png)](https://coingecko.com) diff --git a/coingecko/methods.go b/coingecko/methods.go index 29f0303..6a2fb4d 100644 --- a/coingecko/methods.go +++ b/coingecko/methods.go @@ -250,7 +250,7 @@ func (c *Client) ListCoinsInfo(ctx context.Context, includePlatform bool) (*[]Li // // page(optional): page through results. Default value: 1. // -// sparkline(optional): include sparkline 7 days data (eg. true, false). Default value: false. +// sparkline(optional): include sparkline 7 days data (e.g. true, false). Default value: false. // // price_change_percentage(optional): include price change percentage in 1h, 24h, 7d, 14d, 30d, 200d, 1y // (eg. '1h,24h,7d' comma-separated, invalid values will be discarded). @@ -262,7 +262,7 @@ func (c *Client) ListCoinsInfo(ctx context.Context, includePlatform bool) (*[]Li func (c *Client) ListCoinsMarketsData(ctx context.Context, vsCurrency string, ids []string, category, order string, perPage, page uint, sparkline bool, priceChangePercentage []string, locale, precision string) (*[]ListCoinsMarketsDataResponse, error) { if vsCurrency == "" { - return nil, fmt.Errorf("vs currencies should not be empty") + return nil, fmt.Errorf("vsCurrency should not be empty") } params := url.Values{} diff --git a/coingecko/methods_test.go b/coingecko/methods_test.go index 4e1557f..6a9f46e 100644 --- a/coingecko/methods_test.go +++ b/coingecko/methods_test.go @@ -373,53 +373,161 @@ func TestClient_ListCoinsInfo(t *testing.T) { } } -// func TestClient_ListCoinsMarketsData(t *testing.T) { -// cases := []struct { -// name string -// server *httptest.Server -// wantedIsErr bool -// wantedResult *[]ListCoinsMarketsDataResponse -// wantedErrStr string -// }{ -// { -// name: "success", -// server: nil, -// wantedIsErr: false, -// wantedResult: nil, -// wantedErrStr: "", -// }, -// { -// name: "failed to call api", -// server: mockErrorHTTPServer(t, ""), -// wantedIsErr: true, -// wantedResult: nil, -// wantedErrStr: statusCode400ErrStr, -// }, -// { -// name: "failed to unmarshal json", -// server: mockHTTPServer(t, "", invalidJSONString), -// wantedIsErr: true, -// wantedResult: nil, -// wantedErrStr: invalidCharacterJSONErrStr, -// }, -// } -// for _, tt := range cases { -// t.Run(tt.name, func(t *testing.T) { -// client := setup(t) -// client.apiURL = tt.server.URL -// result, err := client.ListCoinsMarketsData(context.TODO(), false) -// if tt.wantedIsErr { -// if !strings.Contains(err.Error(), tt.wantedErrStr) { -// t.Fatalf("incorrect error, wanted error: %v, got error: %v", tt.wantedErrStr, err) -// } -// } else { -// if err != nil { -// t.Fatalf("error should be nil, got: %v", err) -// } -// } -// if !reflect.DeepEqual(result, tt.wantedResult) { -// t.Fatalf("incorrect response, wanted result: %+v, got result: %+v", tt.wantedResult, result) -// } -// }) -// } -// } +func TestClient_ListCoinsMarketsData(t *testing.T) { + var maxSupply = 1000000000.0 + cases := []struct { + name string + vsCurrency string + server *httptest.Server + wantedIsErr bool + wantedResult *[]ListCoinsMarketsDataResponse + wantedErrStr string + }{ + { + name: "success", + vsCurrency: "usd", + server: mockHTTPServer(t, "", `[{"id": "uniswap","symbol": "uni","name": "Uniswap","image": "https://assets.coingecko.com/coins/images/12504/large/uni.jpg?1696512319","current_price": 6.13,"market_cap": 4621266016,"market_cap_rank": 21,"fully_diluted_valuation": 6130897290,"total_volume": 477396644,"high_24h": 6.27,"low_24h": 5.18,"price_change_24h": 0.918302,"price_change_percentage_24h": 17.61082,"market_cap_change_24h": 681728375,"market_cap_change_percentage_24h": 17.30478,"circulating_supply": 753766667.0,"total_supply": 1000000000.0,"max_supply": 1000000000.0,"ath": 44.92,"ath_change_percentage": -86.35145,"ath_date": "2021-05-03T05:25:04.822Z","atl": 1.03,"atl_change_percentage": 495.11135,"atl_date": "2020-09-17T01:20:38.214Z","roi": null,"last_updated": "2023-11-23T03:07:17.295Z"}]`), + wantedIsErr: false, + wantedResult: &[]ListCoinsMarketsDataResponse{ + { + coinsStruct: coinsStruct{ + ID: "uniswap", + Symbol: "uni", + Name: "Uniswap", + }, + Image: "https://assets.coingecko.com/coins/images/12504/large/uni.jpg?1696512319", + CurrentPrice: 6.13, + MarketCap: 4621266016, + MarketCapRank: 21, + FullyDilutedValuation: 6130897290, + TotalVolume: 477396644, + High24h: 6.27, + Low24h: 5.18, + PriceChange24h: 0.918302, + PriceChangePercentage24h: 17.61082, + MarketCapChange24h: 681728375, + MarketCapChangePercentage24h: 17.30478, + CirculatingSupply: 753766667.0, + TotalSupply: 1000000000.0, + MaxSupply: &maxSupply, + Ath: 44.92, + AthChangePercentage: -86.35145, + AthDate: "2021-05-03T05:25:04.822Z", + Atl: 1.03, + AtlChangePercentage: 495.11135, + AtlDate: "2020-09-17T01:20:38.214Z", + ROI: nil, + LastUpdated: "2023-11-23T03:07:17.295Z", + }, + }, + wantedErrStr: "", + }, + { + name: "empty vsCurrency query param", + vsCurrency: "", + server: mockHTTPServer(t, "", ""), + wantedIsErr: true, + wantedResult: nil, + wantedErrStr: "vsCurrency should not be empty", + }, + { + name: "failed to call api", + vsCurrency: "usd", + server: mockErrorHTTPServer(t, ""), + wantedIsErr: true, + wantedResult: nil, + wantedErrStr: statusCode400ErrStr, + }, + { + name: "failed to unmarshal json", + vsCurrency: "usd", + server: mockHTTPServer(t, "", invalidJSONString), + wantedIsErr: true, + wantedResult: nil, + wantedErrStr: invalidCharacterJSONErrStr, + }, + } + for _, tt := range cases { + t.Run(tt.name, func(t *testing.T) { + client := setup(t) + client.apiURL = tt.server.URL + result, err := client.ListCoinsMarketsData(context.TODO(), tt.vsCurrency, []string{"ethereum"}, "decentralized-exchange", + "market_cap_desc", 100, 1, false, []string{"1h"}, "en", "full") + if tt.wantedIsErr { + if !strings.Contains(err.Error(), tt.wantedErrStr) { + t.Fatalf("incorrect error, wanted error: %v, got error: %v", tt.wantedErrStr, err) + } + } else { + if err != nil { + t.Fatalf("error should be nil, got: %v", err) + } + } + if !reflect.DeepEqual(result, tt.wantedResult) { + t.Fatalf("incorrect response, wanted result: %+v, got result: %+v", tt.wantedResult, result) + } + }) + } +} + +func TestClient_GetCoinDataByCoinID(t *testing.T) { + cases := []struct { + name string + id string + server *httptest.Server + wantedIsErr bool + wantedResult *CoinDataResponse + wantedErrStr string + }{ + // { + // name: "success", + // id: "ethereum", + // server: mockHTTPServer(t, "", ""), + // wantedIsErr: false, + // wantedResult: nil, + // wantedErrStr: "", + // }, + { + name: "empty coin id path param", + id: "", + server: mockHTTPServer(t, "", ""), + wantedIsErr: true, + wantedResult: nil, + wantedErrStr: "coin id should not be empty", + }, + { + name: "failed to call api", + id: "ethereum", + server: mockErrorHTTPServer(t, ""), + wantedIsErr: true, + wantedResult: nil, + wantedErrStr: statusCode400ErrStr, + }, + { + name: "failed to unmarshal json", + id: "ethereum", + server: mockHTTPServer(t, "", invalidJSONString), + wantedIsErr: true, + wantedResult: nil, + wantedErrStr: invalidCharacterJSONErrStr, + }, + } + for _, tt := range cases { + t.Run(tt.name, func(t *testing.T) { + client := setup(t) + client.apiURL = tt.server.URL + result, err := client.GetCoinDataByCoinID(context.TODO(), tt.id, true, true, true, true, true, true) + if tt.wantedIsErr { + if !strings.Contains(err.Error(), tt.wantedErrStr) { + t.Fatalf("incorrect error, wanted error: %v, got error: %v", tt.wantedErrStr, err) + } + } else { + if err != nil { + t.Fatalf("error should be nil, got: %v", err) + } + } + if !reflect.DeepEqual(result, tt.wantedResult) { + t.Fatalf("incorrect response, wanted result: %+v, got result: %+v", tt.wantedResult, result) + } + }) + } +} diff --git a/coingecko/model.go b/coingecko/model.go index 3a7ad93..9c90eee 100644 --- a/coingecko/model.go +++ b/coingecko/model.go @@ -39,12 +39,12 @@ type ListCoinsMarketsDataResponse struct { MaxSupply *float64 `json:"max_supply"` Ath float64 `json:"ath"` AthChangePercentage float64 `json:"ath_change_percentage"` - AthDate time.Time `json:"ath_date"` + AthDate string `json:"ath_date"` Atl float64 `json:"atl"` AtlChangePercentage float64 `json:"atl_change_percentage"` - AtlDate time.Time `json:"atl_date"` + AtlDate string `json:"atl_date"` ROI *ROIItem `json:"roi"` - LastUpdated time.Time `json:"last_updated"` + LastUpdated string `json:"last_updated"` SparklineIn7d *SparklineItem `json:"sparkline_in_7d,omitempty"` PriceChangePercentage1hInCurrency float64 `json:"price_change_percentage_1h_in_currency,omitempty"` PriceChangePercentage24hInCurrency float64 `json:"price_change_percentage_24h_in_currency,omitempty"`