FiatRates: change input & output time values to Unix timestamps

make currency parameter optional, return all rates if it's empty

update tests
pull/345/head
Vladyslav Burzakovskyy 2019-12-19 17:11:54 +01:00 committed by Martin
parent f2ff7985b1
commit 14c64410f7
6 changed files with 156 additions and 153 deletions

View File

@ -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
}

View File

@ -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 {

View File

@ -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
}

View File

@ -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&timestamp=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&timestamp=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&timestamp=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&currency=eur"),
name: "apiFiatRates get EUR rate (exact timestamp)",
r: newGetRequest(ts.URL + "/api/v2/tickers?timestamp=1574344800&currency=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&currency=usd"),
r: newGetRequest(ts.URL + "/api/v2/tickers?timestamp=1357045200&currency=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&currency=eur"),
r: newGetRequest(ts.URL + "/api/v2/tickers?timestamp=1574346615&currency=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&currency=does_not_exist"),
r: newGetRequest(ts.URL + "/api/v2/tickers?timestamp=1574346615&currency=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",

View File

@ -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
}

View File

@ -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 @@
</div>
<div class="row">
<div class="col-2">
<input class="btn btn-secondary" type="button" value="get fiat rates for dates" onclick="getFiatRatesForDates()">
<input class="btn btn-secondary" type="button" value="get fiat rates for dates" onclick="getFiatRatesForTimestamps()">
</div>
<div class="col-1">
<input type="text" class="form-control" id="getFiatRatesForDatesCurrency" value="usd">
<input type="text" class="form-control" id="getFiatRatesForTimestampsCurrency" value="usd">
</div>
<div class="col-7">
<input type="text" class="form-control" id="getFiatRatesForDatesList" value="20191121140000,20191121143015">
<input type="text" class="form-control" id="getFiatRatesForTimestampsList" value="1575288000,1575550800">
</div>
</div>
<div class="row">
<div class="col" id="getFiatRatesForDatesResult"></div>
<div class="col" id="getFiatRatesForTimestampsResult"></div>
</div>
<div class="row">
<div class="col-2">
<input class="btn btn-secondary" type="button" value="get current fiat rates" onclick="getCurrentFiatRates()">
</div>
<div class="col-1">
<input type="text" class="form-control" id="getCurrentFiatRatesCurrency" value="usd">
<input type="text" class="form-control" id="getCurrentFiatRatesCurrency" placeholder="usd">
</div>
</div>
<div class="row">
@ -561,7 +561,7 @@
<input class="btn btn-secondary" type="button" value="get fiat rates tickers" onclick="getFiatRatesTickersList()">
</div>
<div class="col-8">
<input type="text" class="form-control" id="getFiatRatesTickersListDate" value="20191121140000">
<input type="text" class="form-control" id="getFiatRatesTickersListDate" value="1576591569" placeholder="Unix timestamp">
</div>
</div>
<div class="row">