exchange/wrapper: add GetServerTime() for exchange analytics (#938)

* exchange/wrapper: add GetServerTime() for exchange analytics

* binance: fix linter issue

* glorious: nits

* glorious: nits rides again

* thrasher: nits implement huobi

* thrasher: nits add to exchange_wrapper_issues cmd
This commit is contained in:
Ryan O'Hara-Reid
2022-05-06 11:38:59 +10:00
committed by GitHub
parent c6ad429827
commit d735effc8e
24 changed files with 230 additions and 28 deletions

View File

@@ -480,6 +480,20 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config)
SentParams: jsonifyInterface([]interface{}{p, assetTypes[i], startTime, endTime, kline.OneDay}),
})
var getServerTimeResponse time.Time
getServerTimeResponse, err = e.GetServerTime(context.TODO(), assetTypes[i])
msg = ""
if err != nil {
msg = err.Error()
responseContainer.ErrorCount++
}
responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{
Function: "GetServerTime",
Error: msg,
Response: getServerTimeResponse,
SentParams: jsonifyInterface([]interface{}{assetTypes[i]}),
})
err = e.UpdateOrderExecutionLimits(context.TODO(), assetTypes[i])
msg = ""
if err != nil {

View File

@@ -70,6 +70,41 @@ func TestUServerTime(t *testing.T) {
}
}
func TestWrapperGetServerTime(t *testing.T) {
t.Parallel()
_, err := b.GetServerTime(context.Background(), asset.Empty)
if !errors.Is(err, asset.ErrNotSupported) {
t.Fatalf("received: '%v' but expected: '%v'", err, asset.ErrNotSupported)
}
st, err := b.GetServerTime(context.Background(), asset.Spot)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
if st.IsZero() {
t.Fatal("expected a time")
}
st, err = b.GetServerTime(context.Background(), asset.USDTMarginedFutures)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
if st.IsZero() {
t.Fatal("expected a time")
}
st, err = b.GetServerTime(context.Background(), asset.CoinMarginedFutures)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
if st.IsZero() {
t.Fatal("expected a time")
}
}
func TestParseSAPITime(t *testing.T) {
t.Parallel()
tm, err := time.Parse(binanceSAPITimeLayout, "2021-05-27 03:56:46")

View File

@@ -74,7 +74,7 @@ func (b *Binance) UServerTime(ctx context.Context) (time.Time, error) {
if err != nil {
return time.Time{}, err
}
return time.Unix(0, data.ServerTime*1000000), nil
return time.UnixMilli(data.ServerTime), nil
}
// UExchangeInfo stores usdt margined futures data

View File

@@ -1882,3 +1882,24 @@ func (b *Binance) formatUSDTMarginedFuturesPair(p currency.Pair, pairFmt currenc
}
return p.Format(currency.UnderscoreDelimiter, pairFmt.Uppercase)
}
// GetServerTime returns the current exchange server time.
func (b *Binance) GetServerTime(ctx context.Context, ai asset.Item) (time.Time, error) {
switch ai {
case asset.USDTMarginedFutures:
return b.UServerTime(ctx)
case asset.Spot:
info, err := b.GetExchangeInfo(ctx)
if err != nil {
return time.Time{}, err
}
return info.Servertime, nil
case asset.CoinMarginedFutures:
info, err := b.FuturesExchangeInfo(ctx)
if err != nil {
return time.Time{}, err
}
return time.UnixMilli(info.ServerTime), nil
}
return time.Time{}, fmt.Errorf("%s %w", ai, asset.ErrNotSupported)
}

View File

@@ -270,8 +270,8 @@ func (b *BTCMarkets) GetMultipleOrderbooks(ctx context.Context, marketIDs []stri
return orderbooks, nil
}
// GetServerTime gets time from btcmarkets
func (b *BTCMarkets) GetServerTime(ctx context.Context) (time.Time, error) {
// GetCurrentServerTime gets time from btcmarkets
func (b *BTCMarkets) GetCurrentServerTime(ctx context.Context) (time.Time, error) {
var resp TimeResp
return resp.Time, b.SendHTTPRequest(ctx, btcMarketsAPIURL+btcMarketsAPIVersion+btcMarketsGetTime,
&resp)

View File

@@ -142,14 +142,26 @@ func TestGetMultipleOrderbooks(t *testing.T) {
}
}
func TestGetServerTime(t *testing.T) {
func TestGetCurrentServerTime(t *testing.T) {
t.Parallel()
_, err := b.GetServerTime(context.Background())
_, err := b.GetCurrentServerTime(context.Background())
if err != nil {
t.Error(err)
}
}
func TestWrapperGetServerTime(t *testing.T) {
t.Parallel()
st, err := b.GetServerTime(context.Background(), asset.Spot)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
if st.IsZero() {
t.Fatal("expected a time")
}
}
func TestGetAccountBalance(t *testing.T) {
t.Parallel()
if !areTestAPIKeysSet() {

View File

@@ -1086,3 +1086,8 @@ func (b *BTCMarkets) GetHistoricCandlesExtended(ctx context.Context, p currency.
ret.SortCandlesByTimestamp(false)
return ret, nil
}
// GetServerTime returns the current exchange server time.
func (b *BTCMarkets) GetServerTime(ctx context.Context, _ asset.Item) (time.Time, error) {
return b.GetCurrentServerTime(ctx)
}

View File

@@ -162,8 +162,8 @@ func (b *BTSE) GetPrice(ctx context.Context, symbol string) (Price, error) {
return p, b.SendHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, path, &p, true, queryFunc)
}
// GetServerTime returns the exchanges server time
func (b *BTSE) GetServerTime(ctx context.Context) (*ServerTime, error) {
// GetCurrentServerTime returns the exchanges server time
func (b *BTSE) GetCurrentServerTime(ctx context.Context) (*ServerTime, error) {
var s ServerTime
return &s, b.SendHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, btseTime, &s, true, queryFunc)
}

View File

@@ -291,14 +291,26 @@ func TestUpdateTickers(t *testing.T) {
}
}
func TestGetServerTime(t *testing.T) {
func TestGetCurrentServerTime(t *testing.T) {
t.Parallel()
_, err := b.GetServerTime(context.Background())
_, err := b.GetCurrentServerTime(context.Background())
if err != nil {
t.Error(err)
}
}
func TestWrapperGetServerTime(t *testing.T) {
t.Parallel()
st, err := b.GetServerTime(context.Background(), asset.Spot)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
if st.IsZero() {
t.Fatal("expected a time")
}
}
func TestGetWalletInformation(t *testing.T) {
t.Parallel()
if !areTestAPIKeysSet() {

View File

@@ -1106,3 +1106,12 @@ func OrderSizeLimits(pair string) (limits OrderSizeLimit, found bool) {
val, ok := resp.(OrderSizeLimit)
return val, ok
}
// GetServerTime returns the current exchange server time.
func (b *BTSE) GetServerTime(ctx context.Context, _ asset.Item) (time.Time, error) {
st, err := b.GetCurrentServerTime(ctx)
if err != nil {
return time.Time{}, err
}
return st.ISO, nil
}

View File

@@ -273,10 +273,9 @@ func (c *CoinbasePro) GetCurrencies(ctx context.Context) ([]Currency, error) {
return currencies, c.SendHTTPRequest(ctx, exchange.RestSpot, coinbaseproCurrencies, &currencies)
}
// GetServerTime returns the API server time
func (c *CoinbasePro) GetServerTime(ctx context.Context) (ServerTime, error) {
// GetCurrentServerTime returns the API server time
func (c *CoinbasePro) GetCurrentServerTime(ctx context.Context) (ServerTime, error) {
serverTime := ServerTime{}
return serverTime, c.SendHTTPRequest(ctx, exchange.RestSpot, coinbaseproTime, &serverTime)
}

View File

@@ -144,13 +144,25 @@ func TestGetCurrencies(t *testing.T) {
}
}
func TestGetServerTime(t *testing.T) {
_, err := c.GetServerTime(context.Background())
func TestGetCurrentServerTime(t *testing.T) {
_, err := c.GetCurrentServerTime(context.Background())
if err != nil {
t.Error("GetServerTime() error", err)
}
}
func TestWrapperGetServerTime(t *testing.T) {
t.Parallel()
st, err := c.GetServerTime(context.Background(), asset.Spot)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
if st.IsZero() {
t.Fatal("expected a time")
}
}
func TestAuthRequests(t *testing.T) {
if !areTestAPIKeysSet() {
t.Skip("API keys not set, skipping test")

View File

@@ -1019,3 +1019,12 @@ func (c *CoinbasePro) ValidateCredentials(ctx context.Context, assetType asset.I
_, err := c.UpdateAccountInfo(ctx, assetType)
return c.CheckTransientError(err)
}
// GetServerTime returns the current exchange server time.
func (c *CoinbasePro) GetServerTime(ctx context.Context, _ asset.Item) (time.Time, error) {
st, err := c.GetCurrentServerTime(ctx)
if err != nil {
return time.Time{}, err
}
return st.ISO, nil
}

View File

@@ -1306,3 +1306,8 @@ func (b *Base) GetFuturesPositions(context.Context, asset.Item, currency.Pair, t
func (b *Base) HasAssetTypeAccountSegregation() bool {
return b.Features.Supports.RESTCapabilities.HasAssetTypeAccountSegregation
}
// GetServerTime returns the current exchange server time.
func (b *Base) GetServerTime(_ context.Context, _ asset.Item) (time.Time, error) {
return time.Time{}, common.ErrNotYetImplemented
}

View File

@@ -2320,3 +2320,11 @@ func TestSetFillsFeedStatus(t *testing.T) {
t.Error("expected false")
}
}
func TestGetServerTime(t *testing.T) {
t.Parallel()
var b Base
if _, err := b.GetServerTime(context.Background(), asset.Spot); !errors.Is(err, common.ErrNotYetImplemented) {
t.Errorf("received: %v, expected: %v", err, common.ErrNotYetImplemented)
}
}

View File

@@ -324,20 +324,17 @@ func (h *HUOBI) GetCurrenciesIncludingChains(ctx context.Context, curr currency.
return resp.Data, nil
}
// GetTimestamp returns the Huobi server time
func (h *HUOBI) GetTimestamp(ctx context.Context) (int64, error) {
type response struct {
// GetCurrentServerTime returns the Huobi server time
func (h *HUOBI) GetCurrentServerTime(ctx context.Context) (time.Time, error) {
var result struct {
Response
Timestamp int64 `json:"data"`
}
var result response
err := h.SendHTTPRequest(ctx, exchange.RestSpot, "/v"+huobiAPIVersion+"/"+huobiTimestamp, &result)
if result.ErrorMessage != "" {
return 0, errors.New(result.ErrorMessage)
return time.Time{}, errors.New(result.ErrorMessage)
}
return result.Timestamp, err
return time.UnixMilli(result.Timestamp), err
}
// GetAccounts returns the Huobi user accounts

View File

@@ -1754,10 +1754,26 @@ func TestGetTicker(t *testing.T) {
func TestGetTimestamp(t *testing.T) {
t.Parallel()
_, err := h.GetTimestamp(context.Background())
st, err := h.GetCurrentServerTime(context.Background())
if err != nil {
t.Errorf("Huobi TestGetTimestamp: %s", err)
}
if st.IsZero() {
t.Fatal("expected a time")
}
}
func TestWrapperGetServerTime(t *testing.T) {
t.Parallel()
st, err := h.GetServerTime(context.Background(), asset.Spot)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
if st.IsZero() {
t.Fatal("expected a time")
}
}
func TestGetAccounts(t *testing.T) {

View File

@@ -1844,3 +1844,8 @@ func (h *HUOBI) GetAvailableTransferChains(ctx context.Context, cryptocurrency c
}
return availableChains, nil
}
// GetServerTime returns the current exchange server time.
func (h *HUOBI) GetServerTime(ctx context.Context, _ asset.Item) (time.Time, error) {
return h.GetCurrentServerTime(ctx)
}

View File

@@ -78,6 +78,7 @@ type IBotExchange interface {
GetHistoricCandlesExtended(ctx context.Context, p currency.Pair, a asset.Item, timeStart, timeEnd time.Time, interval kline.Interval) (kline.Item, error)
DisableRateLimiter() error
EnableRateLimiter() error
GetServerTime(ctx context.Context, ai asset.Item) (time.Time, error)
CurrencyStateManagement
order.PNLCalculation

View File

@@ -37,8 +37,8 @@ type Kraken struct {
wsRequestMtx sync.Mutex
}
// GetServerTime returns current server time
func (k *Kraken) GetServerTime(ctx context.Context) (TimeResponse, error) {
// GetCurrentServerTime returns current server time
func (k *Kraken) GetCurrentServerTime(ctx context.Context) (TimeResponse, error) {
path := fmt.Sprintf("/%s/public/%s", krakenAPIVersion, krakenServerTime)
var response struct {

View File

@@ -75,11 +75,23 @@ func TestStart(t *testing.T) {
testWg.Wait()
}
func TestGetServerTime(t *testing.T) {
func TestGetCurrentServerTime(t *testing.T) {
t.Parallel()
_, err := k.GetServerTime(context.Background())
_, err := k.GetCurrentServerTime(context.Background())
if err != nil {
t.Error("GetServerTime() error", err)
t.Error("GetCurrentServerTime() error", err)
}
}
func TestWrapperGetServerTime(t *testing.T) {
t.Parallel()
st, err := k.GetServerTime(context.Background(), asset.Spot)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
if st.IsZero() {
t.Fatal("expected a time")
}
}

View File

@@ -1565,3 +1565,12 @@ func (k *Kraken) GetAvailableTransferChains(ctx context.Context, cryptocurrency
}
return availableChains, nil
}
// GetServerTime returns the current exchange server time.
func (k *Kraken) GetServerTime(ctx context.Context, _ asset.Item) (time.Time, error) {
st, err := k.GetCurrentServerTime(ctx)
if err != nil {
return time.Time{}, err
}
return time.Parse("Mon, 02 Jan 06 15:04:05 -0700", st.Rfc1123)
}

View File

@@ -570,3 +570,15 @@ func TestUpdateTickers(t *testing.T) {
t.Error(err)
}
}
func TestWrapperGetServerTime(t *testing.T) {
t.Parallel()
st, err := y.GetServerTime(context.Background(), asset.Spot)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
if st.IsZero() {
t.Fatal("expected a time")
}
}

View File

@@ -698,3 +698,12 @@ func (y *Yobit) GetHistoricCandles(ctx context.Context, pair currency.Pair, a as
func (y *Yobit) GetHistoricCandlesExtended(ctx context.Context, pair currency.Pair, a asset.Item, start, end time.Time, interval kline.Interval) (kline.Item, error) {
return kline.Item{}, common.ErrFunctionNotSupported
}
// GetServerTime returns the current exchange server time.
func (y *Yobit) GetServerTime(ctx context.Context, _ asset.Item) (time.Time, error) {
info, err := y.GetInfo(ctx)
if err != nil {
return time.Time{}, err
}
return time.Unix(info.ServerTime, 0), nil
}