diff --git a/binance.go b/binance.go index 8b6b983..f840004 100644 --- a/binance.go +++ b/binance.go @@ -1,6 +1,7 @@ package binance import ( + "encoding/json" "fmt" "time" ) @@ -54,6 +55,8 @@ type Binance interface { DepositHistory(hr HistoryRequest) ([]*Deposit, error) // WithdrawHistory lists withdraw data. WithdrawHistory(hr HistoryRequest) ([]*Withdrawal, error) + // ExchangeInfo displays exchange metadata + ExchangeInfo() (*ExchangeInfo, error) // StartUserDataStream starts stream and returns Stream with ListenKey. StartUserDataStream() (*Stream, error) @@ -547,3 +550,69 @@ type UserDataWebsocketRequest struct { func (b *binance) UserDataWebsocket(udwr UserDataWebsocketRequest) (chan *AccountEvent, chan struct{}, error) { return b.Service.UserDataWebsocket(udwr) } + +type RateLimitType string + +var ( + RequestsWeight = RateLimitType("REQUESTS_WEIGHT") + Orders = RateLimitType("ORDERS") + RawRequests = RateLimitType("RAW_REQUESTS") +) + +type RateLimit struct { + RateLimitType RateLimitType + Interval Interval + IntervalNum int + Limit int +} + +type PairStatus string + +var ( + PreTrading = PairStatus("PRE_TRADING") + Trading = PairStatus("TRADING") + PostTrading = PairStatus("POST_TRADING") + EndOfDay = PairStatus("END_OF_DAY") + Halt = PairStatus("HALT") + AuctionMatch = PairStatus("AUCTION_MATCH") + Break = PairStatus("BREAK") +) + +type Pair struct { + Symbol string + Status PairStatus + BaseAsset string + BaseAssetPrecision int + QuoteAsset string + QuotePrecision int + OrderTypes []OrderType + IcebergAllowed bool +} + +type ExchangeInfo struct { + Timezone string + ServerTime time.Time + RateLimits []*RateLimit + Symbols []*Pair +} + +func (ex *ExchangeInfo) UnmarshalJSON(b []byte) error { + info := &struct { + Timezone string + ServerTime int64 + RateLimits []*RateLimit + Symbols []*Pair + }{} + if err := json.Unmarshal(b, info); err != nil { + return err + } + ex.Timezone = info.Timezone + ex.ServerTime = time.Unix(info.ServerTime/1000, info.ServerTime%1000) + ex.RateLimits = info.RateLimits + ex.Symbols = info.Symbols + return nil +} + +func (b *binance) ExchangeInfo() (*ExchangeInfo, error) { + return b.Service.ExchangeInfo() +} diff --git a/mock_test.go b/mock_test.go index cada9b3..5c4d55a 100644 --- a/mock_test.go +++ b/mock_test.go @@ -218,3 +218,6 @@ func (m *ServiceMock) UserDataWebsocket(udwr binance.UserDataWebsocketRequest) ( } return aech, sch, args.Error(2) } +func (m *ServiceMock) ExchangeInfo() (*binance.ExchangeInfo, error) { + return nil, nil +} diff --git a/service_def.go b/service_def.go index e380f98..39d7075 100644 --- a/service_def.go +++ b/service_def.go @@ -37,6 +37,7 @@ type Service interface { Withdraw(wr WithdrawRequest) (*WithdrawResult, error) DepositHistory(hr HistoryRequest) ([]*Deposit, error) WithdrawHistory(hr HistoryRequest) ([]*Withdrawal, error) + ExchangeInfo() (*ExchangeInfo, error) StartUserDataStream() (*Stream, error) KeepAliveUserDataStream(s *Stream) error diff --git a/service_market.go b/service_market.go index ee7e1a5..bec4240 100644 --- a/service_market.go +++ b/service_market.go @@ -480,3 +480,27 @@ func (as *apiService) TickerAllBooks() ([]*BookTicker, error) { } return btc, nil } + +func (as *apiService) ExchangeInfo() (*ExchangeInfo, error) { + info := new(ExchangeInfo) + + res, err := as.request("GET", "api/v1/exchangeInfo", nil, false, false) + if err != nil { + return nil, err + } + textRes, err := ioutil.ReadAll(res.Body) + if err != nil { + return nil, errors.Wrap(err, "unable to read response from exchangeInfo") + } + defer res.Body.Close() + + if res.StatusCode != 200 { + return nil, as.handleError(textRes) + } + + if err := json.Unmarshal(textRes, info); err != nil { + return nil, errors.Wrap(err, "exchangeInfo unmarshal failed") + } + + return info, nil +}