From 4b63b483e4a061c9ab1621affdfee25e4f0152ae Mon Sep 17 00:00:00 2001 From: Vladyslav Burzakovskyy Date: Wed, 22 Jan 2020 14:25:03 +0100 Subject: [PATCH] fiatRates: always return rates as a map, even if the ticker is unavailable --- api/worker.go | 52 ++++++++++++++++++++----------------------- db/rocksdb.go | 3 +-- docs/api.md | 16 ++++++++----- server/public_test.go | 36 +++++++++++++++--------------- 4 files changed, 53 insertions(+), 54 deletions(-) diff --git a/api/worker.go b/api/worker.go index 3c1fa0c2..3757ca89 100644 --- a/api/worker.go +++ b/api/worker.go @@ -1176,34 +1176,20 @@ func (w *Worker) getFiatRatesResult(currencies []string, ticker *db.CurrencyRate Rates: ticker.Rates, }, nil } - if len(currencies) == 1 { - // Return one specific rate - var currency = strings.ToLower(currencies[0]) - timestamp := ticker.Timestamp.UTC().Unix() - if rate, found := ticker.Rates[currency]; !found { - return nil, NewAPIError(fmt.Sprintf("Currency %q is not available for timestamp %d.", currency, timestamp), true) + // Check if currencies from the list are available in the ticker rates + rates := make(map[string]float64) + for _, currency := range currencies { + currency = strings.ToLower(currency) + if rate, found := ticker.Rates[currency]; found { + rates[currency] = rate } else { - return &db.ResultTickerAsString{ - Timestamp: timestamp, - Rate: rate, - }, nil + rates[currency] = -1 } - } else { - // Check if currencies from the list are available in the ticker rates - rates := make(map[string]float64) - for _, currency := range currencies { - currency = strings.ToLower(currency) - if rate, found := ticker.Rates[currency]; found { - rates[currency] = rate - } else { - rates[currency] = -1 - } - } - return &db.ResultTickerAsString{ - Timestamp: ticker.Timestamp.UTC().Unix(), - Rates: rates, - }, nil } + return &db.ResultTickerAsString{ + Timestamp: ticker.Timestamp.UTC().Unix(), + Rates: rates, + }, nil } // GetFiatRatesForBlockID returns fiat rates for block height or block hash @@ -1246,6 +1232,16 @@ func (w *Worker) GetCurrentFiatRates(currencies []string) (*db.ResultTickerAsStr return result, nil } +// makeErrorRates returns a map of currrencies, with each value equal to -1 +// used when there was an error finding ticker +func makeErrorRates(currencies []string) map[string]float64 { + rates := make(map[string]float64) + for _, currency := range currencies { + rates[strings.ToLower(currency)] = -1 + } + return rates +} + // GetFiatRatesForTimestamps returns fiat rates for each of the provided dates func (w *Worker) GetFiatRatesForTimestamps(timestamps []int64, currencies []string) (*db.ResultTickersAsString, error) { if len(timestamps) == 0 { @@ -1259,15 +1255,15 @@ func (w *Worker) GetFiatRatesForTimestamps(timestamps []int64, currencies []stri ticker, err := w.db.FiatRatesFindTicker(&date) if err != nil { glog.Errorf("Error finding ticker for date %v. Error: %v", date, err) - ret.Tickers = append(ret.Tickers, db.ResultTickerAsString{Timestamp: date.Unix(), Rate: -1}) + ret.Tickers = append(ret.Tickers, db.ResultTickerAsString{Timestamp: date.Unix(), Rates: makeErrorRates(currencies)}) continue } else if ticker == nil { - ret.Tickers = append(ret.Tickers, db.ResultTickerAsString{Timestamp: date.Unix(), Rate: -1}) + ret.Tickers = append(ret.Tickers, db.ResultTickerAsString{Timestamp: date.Unix(), Rates: makeErrorRates(currencies)}) continue } result, err := w.getFiatRatesResult(currencies, ticker) if err != nil { - ret.Tickers = append(ret.Tickers, db.ResultTickerAsString{Timestamp: date.Unix(), Rate: -1}) + ret.Tickers = append(ret.Tickers, db.ResultTickerAsString{Timestamp: date.Unix(), Rates: makeErrorRates(currencies)}) continue } ret.Tickers = append(ret.Tickers, *result) diff --git a/db/rocksdb.go b/db/rocksdb.go index c06068e1..1453c510 100644 --- a/db/rocksdb.go +++ b/db/rocksdb.go @@ -43,8 +43,7 @@ type CurrencyRatesTicker struct { // ResultTickerAsString contains formatted CurrencyRatesTicker data type ResultTickerAsString struct { Timestamp int64 `json:"ts,omitempty"` - Rates map[string]float64 `json:"rates,omitempty"` - Rate float64 `json:"rate,omitempty"` + Rates map[string]float64 `json:"rates"` Error string `json:"error,omitempty"` } diff --git a/docs/api.md b/docs/api.md index 4dffe567..80a2c5ed 100644 --- a/docs/api.md +++ b/docs/api.md @@ -618,10 +618,10 @@ Example response (no parameters): ```javascript { - "ts":1574346615, + "ts": 1574346615, "rates": { - "eur":7134.1, - "usd":7914.5 + "eur": 7134.1, + "usd": 7914.5 } } ``` @@ -630,8 +630,10 @@ Example response (currency=usd): ```javascript { - "ts":1574346615, - "rate":7914.5 + "ts": 1574346615, + "rates": { + "usd": 7914.5 + } } ``` @@ -639,7 +641,9 @@ Example error response (e.g. rate unavailable, incorrect currency...): ```javascript { "ts":7980386400, - "rate":-1 + "rates": { + "usd": -1 + } } ``` diff --git a/server/public_test.go b/server/public_test.go index c1f3c949..4cc0fce1 100644 --- a/server/public_test.go +++ b/server/public_test.go @@ -533,7 +533,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `{"ts":1574346615,"rate":7914.5}`, + `{"ts":1574346615,"rates":{"usd":7914.5}}`, }, }, { @@ -542,7 +542,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `{"ts":1574344800,"rate":7814.5}`, + `{"ts":1574344800,"rates":{"usd":7814.5}}`, }, }, { @@ -560,7 +560,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `{"ts":7980386400,"rate":-1}`, + `{"ts":7980386400,"rates":{"usd":-1}}`, }, }, { @@ -569,7 +569,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `{"ts":1574344800,"rate":7100}`, + `{"ts":1574344800,"rates":{"eur":7100}}`, }, }, { @@ -578,7 +578,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `{"ts":1521511200,"rate":2000}`, + `{"ts":1521511200,"rates":{"usd":2000}}`, }, }, { @@ -587,7 +587,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `{"ts":1521611721,"rate":2003}`, + `{"ts":1521611721,"rates":{"usd":2003}}`, }, }, { @@ -596,7 +596,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `{"ts":1574346615,"rate":7134.1}`, + `{"ts":1574346615,"rates":{"eur":7134.1}}`, }, }, { @@ -605,7 +605,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `{"ts":1574346615,"rate":-1}`, + `{"ts":1574346615,"rates":{"does_not_exist":-1}}`, }, }, { @@ -1212,7 +1212,7 @@ func websocketTestsBitcoinType(t *testing.T, ts *httptest.Server) { "currencies": []string{"usd"}, }, }, - want: `{"id":"18","data":{"ts":1574346615,"rate":7914.5}}`, + want: `{"id":"18","data":{"ts":1574346615,"rates":{"usd":7914.5}}}`, }, { name: "websocket getCurrentFiatRates eur", @@ -1222,7 +1222,7 @@ func websocketTestsBitcoinType(t *testing.T, ts *httptest.Server) { "currencies": []string{"eur"}, }, }, - want: `{"id":"19","data":{"ts":1574346615,"rate":7134.1}}`, + want: `{"id":"19","data":{"ts":1574346615,"rates":{"eur":7134.1}}}`, }, { name: "websocket getCurrentFiatRates incorrect currency", @@ -1232,7 +1232,7 @@ func websocketTestsBitcoinType(t *testing.T, ts *httptest.Server) { "currencies": []string{"does-not-exist"}, }, }, - want: `{"id":"20","data":{"error":{"message":"Currency \"does-not-exist\" is not available for timestamp 1574346615."}}}`, + want: `{"id":"20","data":{"ts":1574346615,"rates":{"does-not-exist":-1}}}`, }, { name: "websocket getFiatRatesForTimestamps missing date", @@ -1264,7 +1264,7 @@ func websocketTestsBitcoinType(t *testing.T, ts *httptest.Server) { "timestamps": []int64{7885693815}, }, }, - want: `{"id":"23","data":{"tickers":[{"ts":7885693815,"rate":-1}]}}`, + want: `{"id":"23","data":{"tickers":[{"ts":7885693815,"rates":{"usd":-1}}]}}`, }, { name: "websocket getFiatRatesForTimestamps exact date", @@ -1275,7 +1275,7 @@ func websocketTestsBitcoinType(t *testing.T, ts *httptest.Server) { "timestamps": []int64{1574346615}, }, }, - want: `{"id":"24","data":{"tickers":[{"ts":1574346615,"rate":7914.5}]}}`, + want: `{"id":"24","data":{"tickers":[{"ts":1574346615,"rates":{"usd":7914.5}}]}}`, }, { name: "websocket getFiatRatesForTimestamps closest date, eur", @@ -1286,7 +1286,7 @@ func websocketTestsBitcoinType(t *testing.T, ts *httptest.Server) { "timestamps": []int64{1521507600}, }, }, - want: `{"id":"25","data":{"tickers":[{"ts":1521511200,"rate":1300}]}}`, + want: `{"id":"25","data":{"tickers":[{"ts":1521511200,"rates":{"eur":1300}}]}}`, }, { name: "websocket getFiatRatesForTimestamps multiple timestamps usd", @@ -1297,7 +1297,7 @@ func websocketTestsBitcoinType(t *testing.T, ts *httptest.Server) { "timestamps": []int64{1570346615, 1574346615}, }, }, - want: `{"id":"26","data":{"tickers":[{"ts":1574344800,"rate":7814.5},{"ts":1574346615,"rate":7914.5}]}}`, + want: `{"id":"26","data":{"tickers":[{"ts":1574344800,"rates":{"usd":7814.5}},{"ts":1574346615,"rates":{"usd":7914.5}}]}}`, }, { name: "websocket getFiatRatesForTimestamps multiple timestamps eur", @@ -1308,7 +1308,7 @@ func websocketTestsBitcoinType(t *testing.T, ts *httptest.Server) { "timestamps": []int64{1570346615, 1574346615}, }, }, - want: `{"id":"27","data":{"tickers":[{"ts":1574344800,"rate":7100},{"ts":1574346615,"rate":7134.1}]}}`, + want: `{"id":"27","data":{"tickers":[{"ts":1574344800,"rates":{"eur":7100}},{"ts":1574346615,"rates":{"eur":7134.1}}]}}`, }, { name: "websocket getFiatRatesForTimestamps multiple timestamps with an error", @@ -1319,7 +1319,7 @@ func websocketTestsBitcoinType(t *testing.T, ts *httptest.Server) { "timestamps": []int64{1570346615, 1574346615, 2000000000}, }, }, - want: `{"id":"28","data":{"tickers":[{"ts":1574344800,"rate":7814.5},{"ts":1574346615,"rate":7914.5},{"ts":2000000000,"rate":-1}]}}`, + want: `{"id":"28","data":{"tickers":[{"ts":1574344800,"rates":{"usd":7814.5}},{"ts":1574346615,"rates":{"usd":7914.5}},{"ts":2000000000,"rates":{"usd":-1}}]}}`, }, { name: "websocket getFiatRatesForTimestamps multiple errors", @@ -1330,7 +1330,7 @@ func websocketTestsBitcoinType(t *testing.T, ts *httptest.Server) { "timestamps": []int64{7832854800, 2000000000}, }, }, - want: `{"id":"29","data":{"tickers":[{"ts":7832854800,"rate":-1},{"ts":2000000000,"rate":-1}]}}`, + want: `{"id":"29","data":{"tickers":[{"ts":7832854800,"rates":{"usd":-1}},{"ts":2000000000,"rates":{"usd":-1}}]}}`, }, { name: "websocket getTickersList",