FiatRates: change input & output time values to Unix timestamps
make currency parameter optional, return all rates if it's empty update testspull/345/head
parent
f2ff7985b1
commit
14c64410f7
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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">
|
||||
|
|
Loading…
Reference in New Issue