diff --git a/api/worker.go b/api/worker.go index 7325ccaf..833864a5 100644 --- a/api/worker.go +++ b/api/worker.go @@ -13,7 +13,6 @@ import ( "os" "sort" "strconv" - "strings" "time" "github.com/golang/glog" @@ -1148,36 +1147,27 @@ func (w *Worker) GetBlocks(page int, blocksOnPage int) (*Blocks, error) { // getFiatRatesResult checks if CurrencyRatesTicker contains all necessary data and returns formatted result func (w *Worker) getFiatRatesResult(currency string, ticker *db.CurrencyRatesTicker) (*db.ResultTickerAsString, error) { - rates := make(map[string]json.Number, 2) - timeFormatted := ticker.Timestamp.Format(db.FiatRatesTimeFormat) + if currency == "" { + return &db.ResultTickerAsString{ + Timestamp: ticker.Timestamp.UTC().Unix(), + Rates: ticker.Rates, + }, nil + } + rates := make(map[string]json.Number, 1) + timestamp := ticker.Timestamp.UTC().Unix() if rate, found := ticker.Rates[currency]; !found { - availableCurrencies := make([]string, 0, len(ticker.Rates)) - for availableCurrency := range ticker.Rates { - availableCurrencies = append(availableCurrencies, availableCurrency) - } - sort.Strings(availableCurrencies) // sort to get deterministic results - return nil, NewAPIError(fmt.Sprintf("Currency %q is not available for timestamp %s. Available currencies are: %s", currency, timeFormatted, strings.Join(availableCurrencies, ",")), true) + return nil, NewAPIError(fmt.Sprintf("Currency %q is not available for timestamp %d.", currency, timestamp), true) } else { rates[currency] = rate } - // add default usd currency - if currency != "usd" { - if rate, found := ticker.Rates["usd"]; found { - rates["usd"] = rate - } - } - result := &db.ResultTickerAsString{ - Timestamp: timeFormatted, + return &db.ResultTickerAsString{ + Timestamp: timestamp, Rates: rates, - } - return result, nil + }, nil } // GetFiatRatesForBlockID returns fiat rates for block height or block hash func (w *Worker) GetFiatRatesForBlockID(bid string, currency string) (*db.ResultTickerAsString, error) { - if currency == "" { - return nil, NewAPIError("Missing or empty \"currency\" parameter", true) - } var ticker *db.CurrencyRatesTicker bi, err := w.getBlockInfoFromBlockID(bid) if err != nil { @@ -1186,7 +1176,7 @@ func (w *Worker) GetFiatRatesForBlockID(bid string, currency string) (*db.Result } return nil, NewAPIError(fmt.Sprintf("Block %v not found, error: %v", bid, err), false) } - dbi := &db.BlockInfo{Time: bi.Time} // get timestamp from block + dbi := &db.BlockInfo{Time: bi.Time} // get Unix timestamp from block tm := time.Unix(dbi.Time, 0) // convert it to Time object ticker, err = w.db.FiatRatesFindTicker(&tm) if err != nil { @@ -1203,9 +1193,6 @@ func (w *Worker) GetFiatRatesForBlockID(bid string, currency string) (*db.Result // GetCurrentFiatRates returns current fiat rates func (w *Worker) GetCurrentFiatRates(currency string) (*db.ResultTickerAsString, error) { - if currency == "" { - return nil, NewAPIError("Missing or empty \"currency\" parameter", true) - } ticker, err := w.db.FiatRatesFindLastTicker() if err != nil { return nil, NewAPIError(fmt.Sprintf("Error finding ticker: %v", err), false) @@ -1219,28 +1206,28 @@ func (w *Worker) GetCurrentFiatRates(currency string) (*db.ResultTickerAsString, return result, nil } -// GetFiatRatesForDates returns fiat rates for each of the provided dates -func (w *Worker) GetFiatRatesForDates(dateStrings []string, currency string) (*db.ResultTickersAsString, error) { +// GetFiatRatesForTimestamps returns fiat rates for each of the provided dates +func (w *Worker) GetFiatRatesForTimestamps(timestamps []string, currency string) (*db.ResultTickersAsString, error) { if currency == "" { - return nil, NewAPIError("Missing or empty \"currency\" parameter", true) - } else if len(dateStrings) == 0 { - return nil, NewAPIError("No dates provided", true) + return nil, NewAPIError("Missing or empty \"currency\" parameter.", true) + } else if len(timestamps) == 0 { + return nil, NewAPIError("No timestamps provided", true) } ret := &db.ResultTickersAsString{} - for _, dateString := range dateStrings { - date, err := db.FiatRatesConvertDate(dateString) + for _, timestamp := range timestamps { + date, err := db.FiatRatesTimestampToTime(timestamp) if err != nil { - ret.Tickers = append(ret.Tickers, db.ResultTickerAsString{Error: fmt.Sprintf("%v", err)}) + ret.Tickers = append(ret.Tickers, db.ResultTickerAsString{Error: fmt.Sprintf("%q is not a valid Unix timestamp.", timestamp)}) continue } ticker, err := w.db.FiatRatesFindTicker(date) if err != nil { - glog.Errorf("Error finding ticker by date %v. Error: %v", dateString, err) - ret.Tickers = append(ret.Tickers, db.ResultTickerAsString{Error: "Ticker not found."}) + glog.Errorf("Error finding ticker for date %v. Error: %v", date, err) + ret.Tickers = append(ret.Tickers, db.ResultTickerAsString{Timestamp: date.Unix(), Error: "Ticker not found."}) continue } else if ticker == nil { - ret.Tickers = append(ret.Tickers, db.ResultTickerAsString{Error: fmt.Sprintf("No tickers available for %s (%s)", date, currency)}) + ret.Tickers = append(ret.Tickers, db.ResultTickerAsString{Timestamp: date.Unix(), Error: fmt.Sprintf("No tickers available for currency %q", currency)}) continue } result, err := w.getFiatRatesResult(currency, ticker) @@ -1254,13 +1241,14 @@ func (w *Worker) GetFiatRatesForDates(dateStrings []string, currency string) (*d } // GetFiatRatesTickersList returns the list of available fiatRates tickers -func (w *Worker) GetFiatRatesTickersList(dateString string) (*db.ResultTickerListAsString, error) { - if dateString == "" { - return nil, NewAPIError("Missing or empty \"date\" parameter", true) +func (w *Worker) GetFiatRatesTickersList(timestampString string) (*db.ResultTickerListAsString, error) { + if timestampString == "" { + return nil, NewAPIError("Missing or empty \"timestamp\" parameter", true) } - date, err := db.FiatRatesConvertDate(dateString) + + date, err := db.FiatRatesTimestampToTime(timestampString) if err != nil { - return nil, err + return nil, NewAPIError(fmt.Sprintf("%v is not a valid Unix timestamp.", timestampString), false) } ticker, err := w.db.FiatRatesFindTicker(date) @@ -1275,10 +1263,10 @@ func (w *Worker) GetFiatRatesTickersList(dateString string) (*db.ResultTickerLis keys = append(keys, k) } sort.Strings(keys) // sort to get deterministic results - timeFormatted := ticker.Timestamp.Format(db.FiatRatesTimeFormat) + timestamp := ticker.Timestamp.UTC().Unix() return &db.ResultTickerListAsString{ - Timestamp: timeFormatted, + Timestamp: timestamp, Tickers: keys, }, nil } diff --git a/db/rocksdb.go b/db/rocksdb.go index 9cc84108..07841752 100644 --- a/db/rocksdb.go +++ b/db/rocksdb.go @@ -42,7 +42,7 @@ type CurrencyRatesTicker struct { // ResultTickerAsString contains formatted CurrencyRatesTicker data type ResultTickerAsString struct { - Timestamp string `json:"data_timestamp,omitempty"` + Timestamp int64 `json:"ts,omitempty"` Rates map[string]json.Number `json:"rates,omitempty"` Error string `json:"error,omitempty"` } @@ -54,7 +54,7 @@ type ResultTickersAsString struct { // ResultTickerListAsString contains formatted data about available currency tickers type ResultTickerListAsString struct { - Timestamp string `json:"data_timestamp,omitempty"` + Timestamp int64 `json:"data_timestamp,omitempty"` Tickers []string `json:"available_currencies"` Error string `json:"error,omitempty"` } @@ -190,6 +190,17 @@ func FiatRatesConvertDate(date string) (*time.Time, error) { return nil, errors.New(msg) } +// FiatRatesTimestampToTime converts the unix timestamp string to a Time object +func FiatRatesTimestampToTime(timestamp string) (*time.Time, error) { + i, err := strconv.ParseInt(timestamp, 10, 64) + if err != nil { + return nil, err + } + ts := time.Unix(i, 0) + ts = ts.UTC() + return &ts, nil +} + // FiatRatesStoreTicker stores ticker data at the specified time func (d *RocksDB) FiatRatesStoreTicker(ticker *CurrencyRatesTicker) error { if len(ticker.Rates) == 0 { diff --git a/server/public.go b/server/public.go index e817dc99..6e418e0d 100644 --- a/server/public.go +++ b/server/public.go @@ -1130,12 +1130,12 @@ func (s *PublicServer) apiSendTx(r *http.Request, apiVersion int) (interface{}, // apiTickersList returns a list of available FiatRates currencies func (s *PublicServer) apiTickersList(r *http.Request, apiVersion int) (interface{}, error) { s.metrics.ExplorerViews.With(common.Labels{"action": "api-tickers-list"}).Inc() - date := strings.ToLower(r.URL.Query().Get("date")) - result, err := s.api.GetFiatRatesTickersList(date) + timestamp := strings.ToLower(r.URL.Query().Get("timestamp")) + result, err := s.api.GetFiatRatesTickersList(timestamp) return result, err } -// apiTickers returns FiatRates ticker prices for the specified block or date. +// apiTickers returns FiatRates ticker prices for the specified block or timestamp. func (s *PublicServer) apiTickers(r *http.Request, apiVersion int) (interface{}, error) { var result *db.ResultTickerAsString var err error @@ -1145,10 +1145,10 @@ func (s *PublicServer) apiTickers(r *http.Request, apiVersion int) (interface{}, // Get tickers for specified block height or block hash s.metrics.ExplorerViews.With(common.Labels{"action": "api-tickers-block"}).Inc() result, err = s.api.GetFiatRatesForBlockID(block, currency) - } else if date := r.URL.Query().Get("date"); date != "" { - // Get tickers for specified date + } else if timestamp := r.URL.Query().Get("timestamp"); timestamp != "" { + // Get tickers for specified timestamp s.metrics.ExplorerViews.With(common.Labels{"action": "api-tickers-date"}).Inc() - resultTickers, err := s.api.GetFiatRatesForDates([]string{date}, currency) + resultTickers, err := s.api.GetFiatRatesForTimestamps([]string{timestamp}, currency) if err != nil { return nil, err } diff --git a/server/public_test.go b/server/public_test.go index 9e8e8164..e1fea751 100644 --- a/server/public_test.go +++ b/server/public_test.go @@ -521,10 +521,10 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { { name: "apiFiatRates missing currency", r: newGetRequest(ts.URL + "/api/v2/tickers"), - status: http.StatusBadRequest, + status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `{"error":"Missing or empty \"currency\" parameter"}`, + `{"ts":1574346615,"rates":{"eur":7134.1,"usd":7914.5}}`, }, }, { @@ -533,52 +533,52 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `{"data_timestamp":"20191121143015","rates":{"usd":7914.5}}`, + `{"ts":1574346615,"rates":{"usd":7914.5}}`, }, }, { - name: "apiFiatRates get rate by exact date", - r: newGetRequest(ts.URL + "/api/v2/tickers?currency=usd&date=20191121140000"), + name: "apiFiatRates get rate by exact timestamp", + r: newGetRequest(ts.URL + "/api/v2/tickers?currency=usd×tamp=1574344800"), status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `{"data_timestamp":"20191121140000","rates":{"usd":7814.5}}`, + `{"ts":1574344800,"rates":{"usd":7814.5}}`, }, }, { - name: "apiFiatRates incorrect date", - r: newGetRequest(ts.URL + "/api/v2/tickers?currency=usd&date=yesterday"), + name: "apiFiatRates incorrect timestamp", + r: newGetRequest(ts.URL + "/api/v2/tickers?currency=usd×tamp=yesterday"), status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `{"error":"Date \"yesterday\" does not match any of available formats. Possible formats are: YYYYMMDDhhmmss, YYYYMMDDhhmm, YYYYMMDDhh, YYYYMMDD"}`, + `{"error":"\"yesterday\" is not a valid Unix timestamp."}`, }, }, { - name: "apiFiatRates future date", - r: newGetRequest(ts.URL + "/api/v2/tickers?currency=usd&date=20200101000000"), + name: "apiFiatRates future timestamp", + r: newGetRequest(ts.URL + "/api/v2/tickers?currency=usd×tamp=7980386400"), status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `{"error":"No tickers available for 2020-01-01 00:00:00 +0000 UTC (usd)"}`, + `{"ts":7980386400,"error":"No tickers available for currency \"usd\""}`, }, }, { - name: "apiFiatRates get EUR rate (exact date)", - r: newGetRequest(ts.URL + "/api/v2/tickers?date=20191121140000¤cy=eur"), + name: "apiFiatRates get EUR rate (exact timestamp)", + r: newGetRequest(ts.URL + "/api/v2/tickers?timestamp=1574344800¤cy=eur"), status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `{"data_timestamp":"20191121140000","rates":{"eur":7100.0,"usd":7814.5}}`, + `{"ts":1574344800,"rates":{"eur":7100.0}}`, }, }, { name: "apiFiatRates get closest rate", - r: newGetRequest(ts.URL + "/api/v2/tickers?date=20191121130000¤cy=usd"), + r: newGetRequest(ts.URL + "/api/v2/tickers?timestamp=1357045200¤cy=usd"), status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `{"data_timestamp":"20191121140000","rates":{"usd":7814.5}}`, + `{"ts":1521511200,"rates":{"usd":2000.0}}`, }, }, { @@ -587,34 +587,34 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `{"data_timestamp":"20180321055521","rates":{"usd":2003.0}}`, + `{"ts":1521611721,"rates":{"usd":2003.0}}`, }, }, { name: "apiFiatRates get rate for EUR", - r: newGetRequest(ts.URL + "/api/v2/tickers?date=20191121140000¤cy=eur"), + r: newGetRequest(ts.URL + "/api/v2/tickers?timestamp=1574346615¤cy=eur"), status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `{"data_timestamp":"20191121140000","rates":{"eur":7100.0,"usd":7814.5}}`, + `{"ts":1574346615,"rates":{"eur":7134.1}}`, }, }, { name: "apiFiatRates get exact rate for an incorrect currency", - r: newGetRequest(ts.URL + "/api/v2/tickers?date=20191121140000¤cy=does_not_exist"), + r: newGetRequest(ts.URL + "/api/v2/tickers?timestamp=1574346615¤cy=does_not_exist"), status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `{"error":"Currency \"does_not_exist\" is not available for timestamp 20191121140000. Available currencies are: eur,usd"}`, + `{"error":"Currency \"does_not_exist\" is not available for timestamp 1574346615."}`, }, }, { name: "apiTickerList", - r: newGetRequest(ts.URL + "/api/v2/tickers-list?date=20191121140000"), + r: newGetRequest(ts.URL + "/api/v2/tickers-list?timestamp=1574346615"), status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `{"data_timestamp":"20191121140000","available_currencies":["eur","usd"]}`, + `{"data_timestamp":1574346615,"available_currencies":["eur","usd"]}`, }, }, { @@ -1202,7 +1202,7 @@ func websocketTestsBitcoinType(t *testing.T, ts *httptest.Server) { "": "", }, }, - want: `{"id":"17","data":{"error":{"message":"Missing or empty \"currency\" parameter"}}}`, + want: `{"id":"17","data":{"ts":1574346615,"rates":{"eur":7134.1,"usd":7914.5}}}`, }, { name: "websocket getCurrentFiatRates usd", @@ -1212,7 +1212,7 @@ func websocketTestsBitcoinType(t *testing.T, ts *httptest.Server) { "currency": "usd", }, }, - want: `{"id":"18","data":{"data_timestamp":"20191121143015","rates":{"usd":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) { "currency": "eur", }, }, - want: `{"id":"19","data":{"data_timestamp":"20191121143015","rates":{"eur":7134.1,"usd":7914.5}}}`, + want: `{"id":"19","data":{"ts":1574346615,"rates":{"eur":7134.1}}}`, }, { name: "websocket getCurrentFiatRates incorrect currency", @@ -1232,115 +1232,115 @@ func websocketTestsBitcoinType(t *testing.T, ts *httptest.Server) { "currency": "does-not-exist", }, }, - want: `{"id":"20","data":{"error":{"message":"Currency \"does-not-exist\" is not available for timestamp 20191121143015. Available currencies are: eur,usd"}}}`, + want: `{"id":"20","data":{"error":{"message":"Currency \"does-not-exist\" is not available for timestamp 1574346615."}}}`, }, { - name: "websocket getFiatRatesForDates missing date", + name: "websocket getFiatRatesForTimestamps missing date", req: websocketReq{ - Method: "getFiatRatesForDates", + Method: "getFiatRatesForTimestamps", Params: map[string]interface{}{ "currency": "usd", }, }, - want: `{"id":"21","data":{"error":{"message":"No dates provided"}}}`, + want: `{"id":"21","data":{"error":{"message":"No timestamps provided"}}}`, }, { - name: "websocket getFiatRatesForDates incorrect date", + name: "websocket getFiatRatesForTimestamps incorrect date", req: websocketReq{ - Method: "getFiatRatesForDates", + Method: "getFiatRatesForTimestamps", Params: map[string]interface{}{ - "currency": "usd", - "dates": []string{"yesterday"}, + "currency": "usd", + "timestamps": []string{"yesterday"}, }, }, - want: `{"id":"22","data":{"tickers":[{"error":"Date \"yesterday\" does not match any of available formats. Possible formats are: YYYYMMDDhhmmss, YYYYMMDDhhmm, YYYYMMDDhh, YYYYMMDD"}]}}`, + want: `{"id":"22","data":{"tickers":[{"error":"\"yesterday\" is not a valid Unix timestamp."}]}}`, }, { - name: "websocket getFiatRatesForDates incorrect (future) date", + name: "websocket getFiatRatesForTimestamps incorrect (future) date", req: websocketReq{ - Method: "getFiatRatesForDates", + Method: "getFiatRatesForTimestamps", Params: map[string]interface{}{ - "currency": "usd", - "dates": []string{"20200101000000"}, + "currency": "usd", + "timestamps": []string{"7885693815"}, }, }, - want: `{"id":"23","data":{"tickers":[{"error":"No tickers available for 2020-01-01 00:00:00 +0000 UTC (usd)"}]}}`, + want: `{"id":"23","data":{"tickers":[{"ts":7885693815,"error":"No tickers available for currency \"usd\""}]}}`, }, { - name: "websocket getFiatRatesForDates exact date", + name: "websocket getFiatRatesForTimestamps exact date", req: websocketReq{ - Method: "getFiatRatesForDates", + Method: "getFiatRatesForTimestamps", Params: map[string]interface{}{ - "currency": "usd", - "dates": []string{"20191121140000"}, + "currency": "usd", + "timestamps": []string{"1574346615"}, }, }, - want: `{"id":"24","data":{"tickers":[{"data_timestamp":"20191121140000","rates":{"usd":7814.5}}]}}`, + want: `{"id":"24","data":{"tickers":[{"ts":1574346615,"rates":{"usd":7914.5}}]}}`, }, { - name: "websocket getFiatRatesForDates closest date, eur", + name: "websocket getFiatRatesForTimestamps closest date, eur", req: websocketReq{ - Method: "getFiatRatesForDates", + Method: "getFiatRatesForTimestamps", Params: map[string]interface{}{ - "currency": "eur", - "dates": []string{"20191121130000"}, + "currency": "eur", + "timestamps": []string{"1521507600"}, }, }, - want: `{"id":"25","data":{"tickers":[{"data_timestamp":"20191121140000","rates":{"eur":7100.0,"usd":7814.5}}]}}`, + want: `{"id":"25","data":{"tickers":[{"ts":1521511200,"rates":{"eur":1300.0}}]}}`, }, { - name: "websocket getFiatRatesForDates multiple dates usd", + name: "websocket getFiatRatesForTimestamps multiple timestamps usd", req: websocketReq{ - Method: "getFiatRatesForDates", + Method: "getFiatRatesForTimestamps", Params: map[string]interface{}{ - "currency": "usd", - "dates": []string{"20191121140000", "20191121143015"}, + "currency": "usd", + "timestamps": []string{"1570346615", "1574346615"}, }, }, - want: `{"id":"26","data":{"tickers":[{"data_timestamp":"20191121140000","rates":{"usd":7814.5}},{"data_timestamp":"20191121143015","rates":{"usd":7914.5}}]}}`, + want: `{"id":"26","data":{"tickers":[{"ts":1574344800,"rates":{"usd":7814.5}},{"ts":1574346615,"rates":{"usd":7914.5}}]}}`, }, { - name: "websocket getFiatRatesForDates multiple dates eur", + name: "websocket getFiatRatesForTimestamps multiple timestamps eur", req: websocketReq{ - Method: "getFiatRatesForDates", + Method: "getFiatRatesForTimestamps", Params: map[string]interface{}{ - "currency": "eur", - "dates": []string{"20191121140000", "20191121143015"}, + "currency": "eur", + "timestamps": []string{"1570346615", "1574346615"}, }, }, - want: `{"id":"27","data":{"tickers":[{"data_timestamp":"20191121140000","rates":{"eur":7100.0,"usd":7814.5}},{"data_timestamp":"20191121143015","rates":{"eur":7134.1,"usd":7914.5}}]}}`, + want: `{"id":"27","data":{"tickers":[{"ts":1574344800,"rates":{"eur":7100.0}},{"ts":1574346615,"rates":{"eur":7134.1}}]}}`, }, { - name: "websocket getFiatRatesForDates multiple dates with an error", + name: "websocket getFiatRatesForTimestamps multiple timestamps with an error", req: websocketReq{ - Method: "getFiatRatesForDates", + Method: "getFiatRatesForTimestamps", Params: map[string]interface{}{ - "currency": "usd", - "dates": []string{"20191121140000", "20191121143015", "not-a-real-date"}, + "currency": "usd", + "timestamps": []string{"1570346615", "1574346615", "not-a-real-date"}, }, }, - want: `{"id":"28","data":{"tickers":[{"data_timestamp":"20191121140000","rates":{"usd":7814.5}},{"data_timestamp":"20191121143015","rates":{"usd":7914.5}},{"error":"Date \"not-a-real-date\" does not match any of available formats. Possible formats are: YYYYMMDDhhmmss, YYYYMMDDhhmm, YYYYMMDDhh, YYYYMMDD"}]}}`, + want: `{"id":"28","data":{"tickers":[{"ts":1574344800,"rates":{"usd":7814.5}},{"ts":1574346615,"rates":{"usd":7914.5}},{"error":"\"not-a-real-date\" is not a valid Unix timestamp."}]}}`, }, { - name: "websocket getFiatRatesForDates multiple errors", + name: "websocket getFiatRatesForTimestamps multiple errors", req: websocketReq{ - Method: "getFiatRatesForDates", + Method: "getFiatRatesForTimestamps", Params: map[string]interface{}{ - "currency": "usd", - "dates": []string{"20200101000000", "not-a-real-date"}, + "currency": "usd", + "timestamps": []string{"7832854800", "not-a-real-date"}, }, }, - want: `{"id":"29","data":{"tickers":[{"error":"No tickers available for 2020-01-01 00:00:00 +0000 UTC (usd)"},{"error":"Date \"not-a-real-date\" does not match any of available formats. Possible formats are: YYYYMMDDhhmmss, YYYYMMDDhhmm, YYYYMMDDhh, YYYYMMDD"}]}}`, + want: `{"id":"29","data":{"tickers":[{"ts":7832854800,"error":"No tickers available for currency \"usd\""},{"error":"\"not-a-real-date\" is not a valid Unix timestamp."}]}}`, }, { name: "websocket getTickersList", req: websocketReq{ Method: "getFiatRatesTickersList", Params: map[string]interface{}{ - "date": "20191121140000", + "date": "1570346615", }, }, - want: `{"id":"30","data":{"data_timestamp":"20191121140000","available_currencies":["eur","usd"]}}`, + want: `{"id":"30","data":{"data_timestamp":1574344800,"available_currencies":["eur","usd"]}}`, }, { name: "websocket getBalanceHistory Addr2", diff --git a/server/websocket.go b/server/websocket.go index a576926c..b7d17d88 100644 --- a/server/websocket.go +++ b/server/websocket.go @@ -359,14 +359,14 @@ var requestHandlers = map[string]func(*WebsocketServer, *websocketChannel, *webs } return }, - "getFiatRatesForDates": func(s *WebsocketServer, c *websocketChannel, req *websocketReq) (rv interface{}, err error) { + "getFiatRatesForTimestamps": func(s *WebsocketServer, c *websocketChannel, req *websocketReq) (rv interface{}, err error) { r := struct { - Dates []string `json:"dates"` - Currency string `json:"currency"` + Timestamps []string `json:"timestamps"` + Currency string `json:"currency"` }{} err = json.Unmarshal(req.Params, &r) if err == nil { - rv, err = s.getFiatRatesForDates(r.Dates, r.Currency) + rv, err = s.getFiatRatesForTimestamps(r.Timestamps, r.Currency) } return }, @@ -698,6 +698,9 @@ func (s *WebsocketServer) subscribeFiatRates(c *websocketChannel, currency strin s.fiatRatesSubscriptionsLock.Lock() defer s.fiatRatesSubscriptionsLock.Unlock() + if currency == "" { + currency = "!ALL!" + } as, ok := s.fiatRatesSubscriptions[currency] if !ok { as = make(map[*websocketChannel]string) @@ -788,18 +791,18 @@ func (s *WebsocketServer) OnNewTxAddr(tx *bchain.Tx, addrDesc bchain.AddressDesc } } -func (s *WebsocketServer) broadcastTicker(coin string, rate json.Number) { +func (s *WebsocketServer) broadcastTicker(currency string, rates map[string]json.Number) { s.fiatRatesSubscriptionsLock.Lock() defer s.fiatRatesSubscriptionsLock.Unlock() - as, ok := s.fiatRatesSubscriptions[coin] + as, ok := s.fiatRatesSubscriptions[currency] if ok && len(as) > 0 { data := struct { - Rate interface{} `json:"rate"` + Rates interface{} `json:"rates"` }{ - Rate: rate, + Rates: rates, } // get the list of subscriptions again, this time keep the lock - as, ok = s.fiatRatesSubscriptions[coin] + as, ok = s.fiatRatesSubscriptions[currency] if ok { for c, id := range as { if c.IsAlive() { @@ -809,7 +812,7 @@ func (s *WebsocketServer) broadcastTicker(coin string, rate json.Number) { } } } - glog.Info("broadcasting new rate ", rate, " for coin ", coin, " to ", len(as), " channels") + glog.Info("broadcasting new rates for currency ", currency, " to ", len(as), " channels") } } } @@ -817,8 +820,9 @@ func (s *WebsocketServer) broadcastTicker(coin string, rate json.Number) { // OnNewFiatRatesTicker is a callback that broadcasts info about fiat rates affecting subscribed currency func (s *WebsocketServer) OnNewFiatRatesTicker(ticker *db.CurrencyRatesTicker) { for currency, rate := range ticker.Rates { - s.broadcastTicker(currency, rate) + s.broadcastTicker(currency, map[string]json.Number{currency: rate}) } + s.broadcastTicker("!ALL!", ticker.Rates) } func (s *WebsocketServer) getCurrentFiatRates(currency string) (interface{}, error) { @@ -826,12 +830,12 @@ func (s *WebsocketServer) getCurrentFiatRates(currency string) (interface{}, err return ret, err } -func (s *WebsocketServer) getFiatRatesForDates(dates []string, currency string) (interface{}, error) { - ret, err := s.api.GetFiatRatesForDates(dates, currency) +func (s *WebsocketServer) getFiatRatesForTimestamps(timestamps []string, currency string) (interface{}, error) { + ret, err := s.api.GetFiatRatesForTimestamps(timestamps, currency) return ret, err } -func (s *WebsocketServer) getFiatRatesTickersList(date string) (interface{}, error) { - ret, err := s.api.GetFiatRatesTickersList(date) +func (s *WebsocketServer) getFiatRatesTickersList(timestamp string) (interface{}, error) { + ret, err := s.api.GetFiatRatesTickersList(timestamp) return ret, err } diff --git a/static/test-websocket.html b/static/test-websocket.html index a8f121a8..ef6a0639 100644 --- a/static/test-websocket.html +++ b/static/test-websocket.html @@ -297,17 +297,17 @@ }); } - function getFiatRatesForDates() { - const method = 'getFiatRatesForDates'; - var dates = document.getElementById('getFiatRatesForDatesList').value.split(","); - var currency = document.getElementById('getFiatRatesForDatesCurrency').value; - dates = dates.map(s => s.trim()); + function getFiatRatesForTimestamps() { + const method = 'getFiatRatesForTimestamps'; + var timestamps = document.getElementById('getFiatRatesForTimestampsList').value.split(","); + var currency = document.getElementById('getFiatRatesForTimestampsCurrency').value; + timestamps = timestamps.map(s => s.trim()); const params = { - dates, + timestamps, "currency": currency }; send(method, params, function (result) { - document.getElementById('getFiatRatesForDatesResult').innerText = JSON.stringify(result).replace(/,/g, ", "); + document.getElementById('getFiatRatesForTimestampsResult').innerText = JSON.stringify(result).replace(/,/g, ", "); }); } @@ -533,24 +533,24 @@
- +
- +
- +
-
+
- +
@@ -561,7 +561,7 @@
- +