From c041c990a987a01b58be39daf0fd5e7456389430 Mon Sep 17 00:00:00 2001 From: Adrian Gallagher Date: Fri, 6 Sep 2019 11:24:38 +1000 Subject: [PATCH] Improve ticker batching and websocket pair consistency --- currency/pair.go | 17 +- currency/pair_test.go | 24 +++ exchanges/binance/binance_types.go | 84 ++++---- exchanges/binance/binance_websocket.go | 32 +-- exchanges/binance/binance_wrapper.go | 5 +- exchanges/bitfinex/bitfinex_websocket.go | 3 +- exchanges/coinbasepro/coinbasepro_wrapper.go | 22 +- exchanges/exchange.go | 1 - exchanges/gateio/gateio_websocket.go | 6 +- exchanges/hitbtc/hitbtc_test.go | 17 ++ exchanges/hitbtc/hitbtc_types.go | 214 +++++++++---------- exchanges/hitbtc/hitbtc_websocket.go | 37 ++-- exchanges/hitbtc/hitbtc_wrapper.go | 16 +- exchanges/huobi/huobi_types.go | 153 ++++++------- exchanges/huobi/huobi_websocket.go | 28 +-- exchanges/huobi/huobi_wrapper.go | 11 +- exchanges/huobihadax/huobihadax_types.go | 140 ++++++------ exchanges/huobihadax/huobihadax_websocket.go | 28 +-- exchanges/huobihadax/huobihadax_wrapper.go | 8 +- exchanges/kraken/kraken_websocket.go | 3 +- exchanges/kraken/kraken_wrapper.go | 7 +- exchanges/lakebtc/lakebtc_test.go | 5 +- exchanges/lakebtc/lakebtc_websocket.go | 48 +++-- exchanges/zb/zb_wrapper.go | 9 +- 24 files changed, 519 insertions(+), 399 deletions(-) diff --git a/currency/pair.go b/currency/pair.go index 74e22195..e83ee8e2 100644 --- a/currency/pair.go +++ b/currency/pair.go @@ -73,6 +73,20 @@ func NewPairFromString(currencyPair string) Pair { return NewPairFromStrings(currencyPair[0:3], currencyPair[3:]) } +// NewPairFromFormattedPairs matches a supplied currency pair to a list of pairs +// with a specific format. This is helpful for exchanges which +// provide currency pairs with no delimiter so we can match it with a list and +// apply the same format +func NewPairFromFormattedPairs(currencyPair string, pairs Pairs, pairFmt PairFormat) Pair { + for x := range pairs { + if strings.EqualFold(pairs[x].Format(pairFmt.Delimiter, + pairFmt.Uppercase).String(), currencyPair) { + return pairs[x] + } + } + return NewPairFromString(currencyPair) +} + // Pair holds currency pair information type Pair struct { Delimiter string `json:"delimiter"` @@ -133,7 +147,8 @@ func (p Pair) Format(delimiter string, uppercase bool) Pair { // Equal compares two currency pairs and returns whether or not they are equal func (p Pair) Equal(cPair Pair) bool { - return p.Base.Item == cPair.Base.Item && p.Quote.Item == cPair.Quote.Item + return strings.EqualFold(p.Base.String(), cPair.Base.String()) && + strings.EqualFold(p.Quote.String(), cPair.Quote.String()) } // EqualIncludeReciprocal compares two currency pairs and returns whether or not diff --git a/currency/pair_test.go b/currency/pair_test.go index 8c46fd44..07e9f789 100644 --- a/currency/pair_test.go +++ b/currency/pair_test.go @@ -407,6 +407,30 @@ func TestNewPairFromString(t *testing.T) { } } +func TestNewPairFromFormattedPairs(t *testing.T) { + t.Parallel() + pairs := Pairs{ + NewPairDelimiter("BTC-USDT", "-"), + NewPairDelimiter("LTC-USD", "-"), + } + + p := NewPairFromFormattedPairs("BTCUSDT", pairs, PairFormat{Uppercase: true}) + if p.String() != "BTC-USDT" { + t.Error("Test failed. TestNewPairFromFormattedPairs: Expected currency was not found") + } + + p = NewPairFromFormattedPairs("btcusdt", pairs, PairFormat{Uppercase: false}) + if p.String() != "BTC-USDT" { + t.Error("Test failed. TestNewPairFromFormattedPairs: Expected currency was not found") + } + + // Now a wrong one, will default to NewPairFromString + p = NewPairFromFormattedPairs("ethusdt", pairs, PairFormat{}) + if p.String() != "ethusdt" && p.Base.String() != "eth" { + t.Error("Test failed. TestNewPairFromFormattedPairs: Expected currency was not found") + } +} + func TestContainsCurrency(t *testing.T) { p := NewPair(BTC, USD) diff --git a/exchanges/binance/binance_types.go b/exchanges/binance/binance_types.go index 78bfc660..30718199 100644 --- a/exchanges/binance/binance_types.go +++ b/exchanges/binance/binance_types.go @@ -167,29 +167,29 @@ type KlineStream struct { // TickerStream holds the ticker stream data type TickerStream struct { - EventType string `json:"e"` - EventTime int64 `json:"E"` - Symbol currency.Pair `json:"s"` - PriceChange float64 `json:"p,string"` - PriceChangePercent float64 `json:"P,string"` - WeightedAvgPrice float64 `json:"w,string"` - ClosePrice float64 `json:"x,string"` - LastPrice float64 `json:"c,string"` - LastPriceQuantity float64 `json:"Q,string"` - BestBidPrice float64 `json:"b,string"` - BestBidQuantity float64 `json:"B,string"` - BestAskPrice float64 `json:"a,string"` - BestAskQuantity float64 `json:"A,string"` - OpenPrice float64 `json:"o,string"` - HighPrice float64 `json:"h,string"` - LowPrice float64 `json:"l,string"` - TotalTradedVolume float64 `json:"v,string"` - TotalTradedQuoteVolume float64 `json:"q,string"` - OpenTime int64 `json:"O"` - CloseTime int64 `json:"C"` - FirstTradeID int64 `json:"F"` - LastTradeID int64 `json:"L"` - NumberOfTrades int64 `json:"n"` + EventType string `json:"e"` + EventTime int64 `json:"E"` + Symbol string `json:"s"` + PriceChange float64 `json:"p,string"` + PriceChangePercent float64 `json:"P,string"` + WeightedAvgPrice float64 `json:"w,string"` + ClosePrice float64 `json:"x,string"` + LastPrice float64 `json:"c,string"` + LastPriceQuantity float64 `json:"Q,string"` + BestBidPrice float64 `json:"b,string"` + BestBidQuantity float64 `json:"B,string"` + BestAskPrice float64 `json:"a,string"` + BestAskQuantity float64 `json:"A,string"` + OpenPrice float64 `json:"o,string"` + HighPrice float64 `json:"h,string"` + LowPrice float64 `json:"l,string"` + TotalTradedVolume float64 `json:"v,string"` + TotalTradedQuoteVolume float64 `json:"q,string"` + OpenTime int64 `json:"O"` + CloseTime int64 `json:"C"` + FirstTradeID int64 `json:"F"` + LastTradeID int64 `json:"L"` + NumberOfTrades int64 `json:"n"` } // HistoricalTrade holds recent trade data @@ -239,25 +239,25 @@ type AveragePrice struct { // PriceChangeStats contains statistics for the last 24 hours trade type PriceChangeStats struct { - Symbol currency.Pair `json:"symbol"` - PriceChange float64 `json:"priceChange,string"` - PriceChangePercent float64 `json:"priceChangePercent,string"` - WeightedAvgPrice float64 `json:"weightedAvgPrice,string"` - PrevClosePrice float64 `json:"prevClosePrice,string"` - LastPrice float64 `json:"lastPrice,string"` - LastQty float64 `json:"lastQty,string"` - BidPrice float64 `json:"bidPrice,string"` - AskPrice float64 `json:"askPrice,string"` - OpenPrice float64 `json:"openPrice,string"` - HighPrice float64 `json:"highPrice,string"` - LowPrice float64 `json:"lowPrice,string"` - Volume float64 `json:"volume,string"` - QuoteVolume float64 `json:"quoteVolume,string"` - OpenTime int64 `json:"openTime"` - CloseTime int64 `json:"closeTime"` - FirstID int64 `json:"fristId"` - LastID int64 `json:"lastId"` - Count int64 `json:"count"` + Symbol string `json:"symbol"` + PriceChange float64 `json:"priceChange,string"` + PriceChangePercent float64 `json:"priceChangePercent,string"` + WeightedAvgPrice float64 `json:"weightedAvgPrice,string"` + PrevClosePrice float64 `json:"prevClosePrice,string"` + LastPrice float64 `json:"lastPrice,string"` + LastQty float64 `json:"lastQty,string"` + BidPrice float64 `json:"bidPrice,string"` + AskPrice float64 `json:"askPrice,string"` + OpenPrice float64 `json:"openPrice,string"` + HighPrice float64 `json:"highPrice,string"` + LowPrice float64 `json:"lowPrice,string"` + Volume float64 `json:"volume,string"` + QuoteVolume float64 `json:"quoteVolume,string"` + OpenTime int64 `json:"openTime"` + CloseTime int64 `json:"closeTime"` + FirstID int64 `json:"fristId"` + LastID int64 `json:"lastId"` + Count int64 `json:"count"` } // SymbolPrice holds basic symbol price diff --git a/exchanges/binance/binance_websocket.go b/exchanges/binance/binance_websocket.go index 32108435..e8b24c3b 100644 --- a/exchanges/binance/binance_websocket.go +++ b/exchanges/binance/binance_websocket.go @@ -128,13 +128,14 @@ func (b *Binance) WsHandleData() { } b.Websocket.DataHandler <- wshandler.TradeData{ - CurrencyPair: currency.NewPairFromString(trade.Symbol), - Timestamp: time.Unix(0, trade.TimeStamp), - Price: price, - Amount: amount, - Exchange: b.GetName(), - AssetType: asset.Spot, - Side: trade.EventType, + CurrencyPair: currency.NewPairFromFormattedPairs(trade.Symbol, b.GetEnabledPairs(asset.Spot), + b.GetPairFormat(asset.Spot, true)), + Timestamp: time.Unix(0, trade.TimeStamp), + Price: price, + Amount: amount, + Exchange: b.GetName(), + AssetType: asset.Spot, + Side: trade.EventType, } continue case "ticker": @@ -160,7 +161,8 @@ func (b *Binance) WsHandleData() { Last: t.LastPrice, Timestamp: time.Unix(0, t.EventTime), AssetType: asset.Spot, - Pair: t.Symbol, + Pair: currency.NewPairFromFormattedPairs(t.Symbol, b.GetEnabledPairs(asset.Spot), + b.GetPairFormat(asset.Spot, true)), } continue @@ -176,7 +178,8 @@ func (b *Binance) WsHandleData() { var wsKline wshandler.KlineData wsKline.Timestamp = time.Unix(0, kline.EventTime) - wsKline.Pair = currency.NewPairFromString(kline.Symbol) + wsKline.Pair = currency.NewPairFromFormattedPairs(kline.Symbol, b.GetEnabledPairs(asset.Spot), + b.GetPairFormat(asset.Spot, true)) wsKline.AssetType = asset.Spot wsKline.Exchange = b.GetName() wsKline.StartTime = time.Unix(0, kline.Kline.StartTime) @@ -207,7 +210,8 @@ func (b *Binance) WsHandleData() { continue } - currencyPair := currency.NewPairFromString(depth.Pair) + currencyPair := currency.NewPairFromFormattedPairs(depth.Pair, b.GetEnabledPairs(asset.Spot), + b.GetPairFormat(asset.Spot, true)) b.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{ Pair: currencyPair, Asset: asset.Spot, @@ -222,10 +226,9 @@ func (b *Binance) WsHandleData() { // SeedLocalCache seeds depth data func (b *Binance) SeedLocalCache(p currency.Pair) error { var newOrderBook orderbook.Base - formattedPair := b.FormatExchangeCurrency(p, asset.Spot) orderbookNew, err := b.GetOrderBook( OrderBookDataRequestParams{ - Symbol: formattedPair.String(), + Symbol: b.FormatExchangeCurrency(p, asset.Spot).String(), Limit: 1000, }) if err != nil { @@ -242,7 +245,7 @@ func (b *Binance) SeedLocalCache(p currency.Pair) error { } newOrderBook.LastUpdated = time.Unix(orderbookNew.LastUpdateID, 0) - newOrderBook.Pair = currency.NewPairFromString(formattedPair.String()) + newOrderBook.Pair = p newOrderBook.AssetType = asset.Spot return b.Websocket.Orderbook.LoadSnapshot(&newOrderBook, false) @@ -276,7 +279,8 @@ func (b *Binance) UpdateLocalCache(wsdp *WebsocketDepthStream) error { } updateAsk = append(updateAsk, priceToBeUpdated) } - currencyPair := currency.NewPairFromString(wsdp.Pair) + currencyPair := currency.NewPairFromFormattedPairs(wsdp.Pair, b.GetEnabledPairs(asset.Spot), + b.GetPairFormat(asset.Spot, true)) return b.Websocket.Orderbook.Update(&wsorderbook.WebsocketOrderbookUpdate{ Bids: updateBid, diff --git a/exchanges/binance/binance_wrapper.go b/exchanges/binance/binance_wrapper.go index b046889d..707b9858 100644 --- a/exchanges/binance/binance_wrapper.go +++ b/exchanges/binance/binance_wrapper.go @@ -167,7 +167,7 @@ func (b *Binance) Run() { !common.StringDataContains(b.GetAvailablePairs(asset.Spot).Strings(), b.GetPairFormat(asset.Spot, false).Delimiter) { enabledPairs := currency.NewPairsFromStrings([]string{fmt.Sprintf("BTC%vUSDT", b.GetPairFormat(asset.Spot, false).Delimiter)}) log.Warn(log.ExchangeSys, - "Available pairs for Binance reset due to config upgrade, please enable the ones you would like again") + "Available pairs for Binance reset due to config upgrade, please enable the ones you would like to use again") forceUpdate = true err := b.UpdatePairs(enabledPairs, asset.Spot, true, true) @@ -227,7 +227,8 @@ func (b *Binance) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Pr pairs := b.GetEnabledPairs(assetType) for i := range pairs { for y := range tick { - if !tick[y].Symbol.Equal(pairs[i]) { + pairFmt := b.FormatExchangeCurrency(pairs[i], assetType).String() + if tick[y].Symbol != pairFmt { continue } tickerPrice := ticker.Price{ diff --git a/exchanges/bitfinex/bitfinex_websocket.go b/exchanges/bitfinex/bitfinex_websocket.go index 7503304f..557553e5 100644 --- a/exchanges/bitfinex/bitfinex_websocket.go +++ b/exchanges/bitfinex/bitfinex_websocket.go @@ -562,7 +562,8 @@ func (b *Bitfinex) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscr req["event"] = "subscribe" req["channel"] = channelToSubscribe.Channel if channelToSubscribe.Currency.String() != "" { - req["pair"] = channelToSubscribe.Currency.String() + req["pair"] = b.FormatExchangeCurrency(channelToSubscribe.Currency, + asset.Spot).String() } if len(channelToSubscribe.Params) > 0 { for k, v := range channelToSubscribe.Params { diff --git a/exchanges/coinbasepro/coinbasepro_wrapper.go b/exchanges/coinbasepro/coinbasepro_wrapper.go index 560211e0..40064905 100644 --- a/exchanges/coinbasepro/coinbasepro_wrapper.go +++ b/exchanges/coinbasepro/coinbasepro_wrapper.go @@ -62,6 +62,7 @@ func (c *CoinbasePro) SetDefaults() { Uppercase: true, }, ConfigFormat: ¤cy.PairFormat{ + Delimiter: "-", Uppercase: true, }, } @@ -162,11 +163,25 @@ func (c *CoinbasePro) Run() { c.PrintEnabledPairs() } - if !c.GetEnabledFeatures().AutoPairUpdates { + forceUpdate := false + if !common.StringDataContains(c.GetEnabledPairs(asset.Spot).Strings(), c.GetPairFormat(asset.Spot, false).Delimiter) || + !common.StringDataContains(c.GetAvailablePairs(asset.Spot).Strings(), c.GetPairFormat(asset.Spot, false).Delimiter) { + enabledPairs := currency.NewPairsFromStrings([]string{fmt.Sprintf("BTC%vUSD", c.GetPairFormat(asset.Spot, false).Delimiter)}) + log.Warn(log.ExchangeSys, + "Enabled pairs for CoinbasePro reset due to config upgrade, please enable the ones you would like to use again") + forceUpdate = true + + err := c.UpdatePairs(enabledPairs, asset.Spot, true, true) + if err != nil { + log.Errorf(log.ExchangeSys, "%s failed to update currencies. Err: %s\n", c.Name, err) + } + } + + if !c.GetEnabledFeatures().AutoPairUpdates && !forceUpdate { return } - err := c.UpdateTradablePairs(false) + err := c.UpdateTradablePairs(forceUpdate) if err != nil { log.Errorf(log.ExchangeSys, "%s failed to update tradable pairs. Err: %s", c.Name, err) } @@ -181,7 +196,8 @@ func (c *CoinbasePro) FetchTradablePairs(asset asset.Item) ([]string, error) { var products []string for x := range pairs { - products = append(products, pairs[x].BaseCurrency+pairs[x].QuoteCurrency) + products = append(products, fmt.Sprintf("%s%s%s", pairs[x].BaseCurrency, + c.GetPairFormat(asset, false).Delimiter, pairs[x].QuoteCurrency)) } return products, nil diff --git a/exchanges/exchange.go b/exchanges/exchange.go index f247b151..d3b8d9a8 100644 --- a/exchanges/exchange.go +++ b/exchanges/exchange.go @@ -262,7 +262,6 @@ func (e *Base) SetCurrencyPairFormat() { if e.Config.CurrencyPairs.RequestFormat == nil { e.Config.CurrencyPairs.RequestFormat = e.CurrencyPairs.RequestFormat } - return } diff --git a/exchanges/gateio/gateio_websocket.go b/exchanges/gateio/gateio_websocket.go index 0d8ad76e..15ebcdf0 100644 --- a/exchanges/gateio/gateio_websocket.go +++ b/exchanges/gateio/gateio_websocket.go @@ -338,7 +338,8 @@ func (g *Gateio) GenerateDefaultSubscriptions() { // Subscribe sends a websocket message to receive data from the channel func (g *Gateio) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error { - params := []interface{}{channelToSubscribe.Currency.String()} + params := []interface{}{g.FormatExchangeCurrency(channelToSubscribe.Currency, + asset.Spot).String()} for i := range channelToSubscribe.Params { params = append(params, channelToSubscribe.Params[i]) } @@ -370,7 +371,8 @@ func (g *Gateio) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscr subscribe := WebsocketRequest{ ID: g.WebsocketConn.GenerateMessageID(true), Method: unsbuscribeText, - Params: []interface{}{channelToSubscribe.Currency.String(), 1800}, + Params: []interface{}{g.FormatExchangeCurrency(channelToSubscribe.Currency, + asset.Spot).String(), 1800}, } resp, err := g.WebsocketConn.SendMessageReturnResponse(subscribe.ID, subscribe) if err != nil { diff --git a/exchanges/hitbtc/hitbtc_test.go b/exchanges/hitbtc/hitbtc_test.go index 71482667..eca699be 100644 --- a/exchanges/hitbtc/hitbtc_test.go +++ b/exchanges/hitbtc/hitbtc_test.go @@ -10,6 +10,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/config" "github.com/thrasher-corp/gocryptotrader/currency" exchange "github.com/thrasher-corp/gocryptotrader/exchanges" + "github.com/thrasher-corp/gocryptotrader/exchanges/asset" "github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues" "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler" ) @@ -97,6 +98,22 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) { } } +func TestUpdateTicker(t *testing.T) { + h.SetDefaults() + TestSetup(t) + + h.CurrencyPairs.StorePairs(asset.Spot, currency.NewPairsFromStrings([]string{"BTC-USD", "XRP-USD"}), true) + _, err := h.UpdateTicker(currency.NewPair(currency.BTC, currency.USD), asset.Spot) + if err != nil { + t.Error(err) + } + + _, err = h.FetchTicker(currency.NewPair(currency.XRP, currency.USD), asset.Spot) + if err != nil { + t.Error(err) + } +} + func TestGetAllTickers(t *testing.T) { _, err := h.GetTickers() if err != nil { diff --git a/exchanges/hitbtc/hitbtc_types.go b/exchanges/hitbtc/hitbtc_types.go index 131ee00f..1b38ac32 100644 --- a/exchanges/hitbtc/hitbtc_types.go +++ b/exchanges/hitbtc/hitbtc_types.go @@ -8,16 +8,16 @@ import ( // TickerResponse is the response type type TickerResponse struct { - Ask float64 `json:"ask,string"` - Bid float64 `json:"bid,string"` - High float64 `json:"high,string"` - Last float64 `json:"last,string"` - Low float64 `json:"low,string"` - Open float64 `json:"open,string"` - Volume float64 `json:"volume,string"` - VolumeQuote float64 `json:"volumeQuote,string"` - Symbol currency.Pair `json:"symbol"` - Timestamp time.Time `json:"timestamp"` + Ask float64 `json:"ask,string"` + Bid float64 `json:"bid,string"` + High float64 `json:"high,string"` + Last float64 `json:"last,string"` + Low float64 `json:"low,string"` + Open float64 `json:"open,string"` + Volume float64 `json:"volume,string"` + VolumeQuote float64 `json:"volumeQuote,string"` + Symbol string `json:"symbol"` + Timestamp time.Time `json:"timestamp"` } // Symbol holds symbol data @@ -322,16 +322,16 @@ type params struct { // WsTicker defines websocket ticker feed return params type WsTicker struct { Params struct { - Ask float64 `json:"ask,string"` - Bid float64 `json:"bid,string"` - Last float64 `json:"last,string"` - Open float64 `json:"open,string"` - Low float64 `json:"low,string"` - High float64 `json:"high,string"` - Volume float64 `json:"volume,string"` - VolumeQuote float64 `json:"volumeQuote,string"` - Timestamp string `json:"timestamp"` - Symbol currency.Pair `json:"symbol"` + Ask float64 `json:"ask,string"` + Bid float64 `json:"bid,string"` + Last float64 `json:"last,string"` + Open float64 `json:"open,string"` + Low float64 `json:"low,string"` + High float64 `json:"high,string"` + Volume float64 `json:"volume,string"` + VolumeQuote float64 `json:"volumeQuote,string"` + Timestamp string `json:"timestamp"` + Symbol string `json:"symbol"` } `json:"params"` } @@ -387,20 +387,20 @@ type WsActiveOrdersResponse struct { // WsActiveOrdersResponseData Active order data for WsActiveOrdersResponse type WsActiveOrdersResponseData struct { - ID string `json:"id"` - ClientOrderID string `json:"clientOrderId,omitempty"` - Symbol currency.Pair `json:"symbol"` - Side string `json:"side"` - Status string `json:"status"` - Type string `json:"type"` - TimeInForce string `json:"timeInForce"` - Quantity float64 `json:"quantity,string"` - Price float64 `json:"price,string"` - CumQuantity float64 `json:"cumQuantity,string"` - PostOnly bool `json:"postOnly"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - ReportType string `json:"reportType"` + ID string `json:"id"` + ClientOrderID string `json:"clientOrderId,omitempty"` + Symbol string `json:"symbol"` + Side string `json:"side"` + Status string `json:"status"` + Type string `json:"type"` + TimeInForce string `json:"timeInForce"` + Quantity float64 `json:"quantity,string"` + Price float64 `json:"price,string"` + CumQuantity float64 `json:"cumQuantity,string"` + PostOnly bool `json:"postOnly"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + ReportType string `json:"reportType"` } // WsReportResponse report response for auth subscription to reports @@ -411,24 +411,24 @@ type WsReportResponse struct { // WsReportResponseData Report data for WsReportResponse type WsReportResponseData struct { - ID string `json:"id"` - ClientOrderID string `json:"clientOrderId,omitempty"` - Symbol currency.Pair `json:"symbol"` - Side string `json:"side"` - Status string `json:"status"` - Type string `json:"type"` - TimeInForce string `json:"timeInForce"` - Quantity float64 `json:"quantity,string"` - Price float64 `json:"price,string"` - CumQuantity float64 `json:"cumQuantity,string"` - PostOnly bool `json:"postOnly"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - ReportType string `json:"reportType"` - TradeQuantity float64 `json:"tradeQuantity,string"` - TradePrice float64 `json:"tradePrice,string"` - TradeID int64 `json:"tradeId"` - TradeFee float64 `json:"tradeFee,string"` + ID string `json:"id"` + ClientOrderID string `json:"clientOrderId,omitempty"` + Symbol string `json:"symbol"` + Side string `json:"side"` + Status string `json:"status"` + Type string `json:"type"` + TimeInForce string `json:"timeInForce"` + Quantity float64 `json:"quantity,string"` + Price float64 `json:"price,string"` + CumQuantity float64 `json:"cumQuantity,string"` + PostOnly bool `json:"postOnly"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + ReportType string `json:"reportType"` + TradeQuantity float64 `json:"tradeQuantity,string"` + TradePrice float64 `json:"tradePrice,string"` + TradeID int64 `json:"tradeId"` + TradeFee float64 `json:"tradeFee,string"` } // WsSubmitOrderRequest WS request @@ -440,11 +440,11 @@ type WsSubmitOrderRequest struct { // WsSubmitOrderRequestData WS request data type WsSubmitOrderRequestData struct { - ClientOrderID int64 `json:"clientOrderId,string,omitempty"` - Symbol currency.Pair `json:"symbol"` - Side string `json:"side"` - Price float64 `json:"price,string"` - Quantity float64 `json:"quantity,string"` + ClientOrderID int64 `json:"clientOrderId,string,omitempty"` + Symbol string `json:"symbol"` + Side string `json:"side"` + Price float64 `json:"price,string"` + Quantity float64 `json:"quantity,string"` } // WsSubmitOrderSuccessResponse WS response @@ -494,20 +494,20 @@ type WsCancelOrderResponse struct { // WsCancelOrderResponseData WS response data type WsCancelOrderResponseData struct { - ID string `json:"id"` - ClientOrderID string `json:"clientOrderId,omitempty"` - Symbol currency.Pair `json:"symbol"` - Side string `json:"side"` - Status string `json:"status"` - Type string `json:"type"` - TimeInForce string `json:"timeInForce"` - Quantity float64 `json:"quantity,string"` - Price float64 `json:"price,string"` - CumQuantity float64 `json:"cumQuantity,string"` - PostOnly bool `json:"postOnly"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - ReportType string `json:"reportType"` + ID string `json:"id"` + ClientOrderID string `json:"clientOrderId,omitempty"` + Symbol string `json:"symbol"` + Side string `json:"side"` + Status string `json:"status"` + Type string `json:"type"` + TimeInForce string `json:"timeInForce"` + Quantity float64 `json:"quantity,string"` + Price float64 `json:"price,string"` + CumQuantity float64 `json:"cumQuantity,string"` + PostOnly bool `json:"postOnly"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + ReportType string `json:"reportType"` } // WsReplaceOrderResponse WS response @@ -519,21 +519,21 @@ type WsReplaceOrderResponse struct { // WsReplaceOrderResponseData WS response data type WsReplaceOrderResponseData struct { - ID string `json:"id"` - ClientOrderID string `json:"clientOrderId,omitempty"` - Symbol currency.Pair `json:"symbol"` - Side string `json:"side"` - Status string `json:"status"` - Type string `json:"type"` - TimeInForce string `json:"timeInForce"` - Quantity float64 `json:"quantity,string"` - Price float64 `json:"price,string"` - CumQuantity float64 `json:"cumQuantity,string"` - PostOnly bool `json:"postOnly"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - ReportType string `json:"reportType"` - OriginalRequestClientOrderID string `json:"originalRequestClientOrderId"` + ID string `json:"id"` + ClientOrderID string `json:"clientOrderId,omitempty"` + Symbol string `json:"symbol"` + Side string `json:"side"` + Status string `json:"status"` + Type string `json:"type"` + TimeInForce string `json:"timeInForce"` + Quantity float64 `json:"quantity,string"` + Price float64 `json:"price,string"` + CumQuantity float64 `json:"cumQuantity,string"` + PostOnly bool `json:"postOnly"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + ReportType string `json:"reportType"` + OriginalRequestClientOrderID string `json:"originalRequestClientOrderId"` } // WsGetActiveOrdersResponse WS response @@ -545,21 +545,21 @@ type WsGetActiveOrdersResponse struct { // WsGetActiveOrdersResponseData WS response data type WsGetActiveOrdersResponseData struct { - ID string `json:"id"` - ClientOrderID string `json:"clientOrderId,omitempty"` - Symbol currency.Pair `json:"symbol"` - Side string `json:"side"` - Status string `json:"status"` - Type string `json:"type"` - TimeInForce string `json:"timeInForce"` - Quantity float64 `json:"quantity,string"` - Price float64 `json:"price,string"` - CumQuantity float64 `json:"cumQuantity,string"` - PostOnly bool `json:"postOnly"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - ReportType string `json:"reportType"` - OriginalRequestClientOrderID string `json:"originalRequestClientOrderId"` + ID string `json:"id"` + ClientOrderID string `json:"clientOrderId,omitempty"` + Symbol string `json:"symbol"` + Side string `json:"side"` + Status string `json:"status"` + Type string `json:"type"` + TimeInForce string `json:"timeInForce"` + Quantity float64 `json:"quantity,string"` + Price float64 `json:"price,string"` + CumQuantity float64 `json:"cumQuantity,string"` + PostOnly bool `json:"postOnly"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + ReportType string `json:"reportType"` + OriginalRequestClientOrderID string `json:"originalRequestClientOrderId"` } // WsGetTradingBalanceResponse WS response @@ -646,7 +646,7 @@ type WsGetSymbolsRequest struct { // WsGetSymbolsRequestParameters request parameters type WsGetSymbolsRequestParameters struct { - Symbol currency.Pair `json:"symbol"` + Symbol string `json:"symbol"` } // WsGetSymbolsResponse symbol response @@ -658,7 +658,7 @@ type WsGetSymbolsResponse struct { // WsGetSymbolsResponseData symbol response data type WsGetSymbolsResponseData struct { - ID currency.Pair `json:"id"` + ID string `json:"id"` BaseCurrency currency.Code `json:"baseCurrency"` QuoteCurrency currency.Code `json:"quoteCurrency"` QuantityIncrement float64 `json:"quantityIncrement,string"` @@ -677,10 +677,10 @@ type WsGetTradesRequest struct { // WsGetTradesRequestParameters trade request params type WsGetTradesRequestParameters struct { - Symbol currency.Pair `json:"symbol"` - Limit int64 `json:"limit"` - Sort string `json:"sort"` - By string `json:"by"` + Symbol string `json:"symbol"` + Limit int64 `json:"limit"` + Sort string `json:"sort"` + By string `json:"by"` } // WsGetTradesResponse response diff --git a/exchanges/hitbtc/hitbtc_websocket.go b/exchanges/hitbtc/hitbtc_websocket.go index d979998e..4e058a05 100644 --- a/exchanges/hitbtc/hitbtc_websocket.go +++ b/exchanges/hitbtc/hitbtc_websocket.go @@ -127,7 +127,8 @@ func (h *HitBTC) handleSubscriptionUpdates(resp wshandler.WebsocketResponse, ini Last: ticker.Params.Last, Timestamp: ts, AssetType: asset.Spot, - Pair: ticker.Params.Symbol, + Pair: currency.NewPairFromFormattedPairs(ticker.Params.Symbol, + h.GetEnabledPairs(asset.Spot), h.GetPairFormat(asset.Spot, true)), } case "snapshotOrderbook": var obSnapshot WsOrderbook @@ -241,7 +242,8 @@ func (h *HitBTC) WsProcessOrderbookSnapshot(ob WsOrderbook) error { asks = append(asks, orderbook.Item{Amount: ob.Params.Ask[i].Size, Price: ob.Params.Ask[i].Price}) } - p := currency.NewPairFromString(ob.Params.Symbol) + p := currency.NewPairFromFormattedPairs(ob.Params.Symbol, + h.GetEnabledPairs(asset.Spot), h.GetPairFormat(asset.Spot, true)) var newOrderBook orderbook.Base newOrderBook.Asks = asks @@ -278,7 +280,8 @@ func (h *HitBTC) WsProcessOrderbookUpdate(update WsOrderbook) error { asks = append(asks, orderbook.Item{Price: update.Params.Ask[i].Price, Amount: update.Params.Ask[i].Size}) } - p := currency.NewPairFromString(update.Params.Symbol) + p := currency.NewPairFromFormattedPairs(update.Params.Symbol, + h.GetEnabledPairs(asset.Spot), h.GetPairFormat(asset.Spot, true)) err := h.Websocket.Orderbook.Update(&wsorderbook.WebsocketOrderbookUpdate{ Asks: asks, Bids: bids, @@ -327,17 +330,20 @@ func (h *HitBTC) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscrip } if channelToSubscribe.Currency.String() != "" { subscribe.Params = params{ - Symbol: channelToSubscribe.Currency.String(), + Symbol: h.FormatExchangeCurrency(channelToSubscribe.Currency, + asset.Spot).String(), } } if strings.EqualFold(channelToSubscribe.Channel, "subscribeTrades") { subscribe.Params = params{ - Symbol: channelToSubscribe.Currency.String(), - Limit: 100, + Symbol: h.FormatExchangeCurrency(channelToSubscribe.Currency, + asset.Spot).String(), + Limit: 100, } } else if strings.EqualFold(channelToSubscribe.Channel, "subscribeCandles") { subscribe.Params = params{ - Symbol: channelToSubscribe.Currency.String(), + Symbol: h.FormatExchangeCurrency(channelToSubscribe.Currency, + asset.Spot).String(), Period: "M30", Limit: 100, } @@ -353,17 +359,20 @@ func (h *HitBTC) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscr JSONRPCVersion: rpcVersion, Method: unsubscribeChannel, Params: params{ - Symbol: channelToSubscribe.Currency.String(), + Symbol: h.FormatExchangeCurrency(channelToSubscribe.Currency, + asset.Spot).String(), }, } if strings.EqualFold(unsubscribeChannel, "unsubscribeTrades") { subscribe.Params = params{ - Symbol: channelToSubscribe.Currency.String(), - Limit: 100, + Symbol: h.FormatExchangeCurrency(channelToSubscribe.Currency, + asset.Spot).String(), + Limit: 100, } } else if strings.EqualFold(unsubscribeChannel, "unsubscribeCandles") { subscribe.Params = params{ - Symbol: channelToSubscribe.Currency.String(), + Symbol: h.FormatExchangeCurrency(channelToSubscribe.Currency, + asset.Spot).String(), Period: "M30", Limit: 100, } @@ -408,7 +417,7 @@ func (h *HitBTC) wsPlaceOrder(pair currency.Pair, side string, price, quantity f Method: "newOrder", Params: WsSubmitOrderRequestData{ ClientOrderID: id, - Symbol: pair, + Symbol: h.FormatExchangeCurrency(pair, asset.Spot).String(), Side: strings.ToLower(side), Price: price, Quantity: quantity, @@ -566,7 +575,7 @@ func (h *HitBTC) wsGetSymbols(currencyItem currency.Pair) (*WsGetSymbolsResponse request := WsGetSymbolsRequest{ Method: "getSymbol", Params: WsGetSymbolsRequestParameters{ - Symbol: currencyItem, + Symbol: h.FormatExchangeCurrency(currencyItem, asset.Spot).String(), }, ID: h.WebsocketConn.GenerateMessageID(false), } @@ -590,7 +599,7 @@ func (h *HitBTC) wsGetTrades(currencyItem currency.Pair, limit int64, sort, by s request := WsGetTradesRequest{ Method: "getTrades", Params: WsGetTradesRequestParameters{ - Symbol: currencyItem, + Symbol: h.FormatExchangeCurrency(currencyItem, asset.Spot).String(), Limit: limit, Sort: sort, By: by, diff --git a/exchanges/hitbtc/hitbtc_wrapper.go b/exchanges/hitbtc/hitbtc_wrapper.go index 0a3ec744..a7cc2534 100644 --- a/exchanges/hitbtc/hitbtc_wrapper.go +++ b/exchanges/hitbtc/hitbtc_wrapper.go @@ -196,7 +196,8 @@ func (h *HitBTC) FetchTradablePairs(asset asset.Item) ([]string, error) { var pairs []string for x := range symbols { - pairs = append(pairs, fmt.Sprintf("%v%v%v", symbols[x].BaseCurrency, h.GetPairFormat(asset, false).Delimiter, symbols[x].QuoteCurrency)) + pairs = append(pairs, fmt.Sprintf("%v%v%v", symbols[x].BaseCurrency, + h.GetPairFormat(asset, false).Delimiter, symbols[x].QuoteCurrency)) } return pairs, nil } @@ -222,8 +223,17 @@ func (h *HitBTC) UpdateTicker(currencyPair currency.Pair, assetType asset.Item) pairs := h.GetEnabledPairs(assetType) for i := range pairs { for j := range tick { - if !tick[j].Symbol.Equal(pairs[i]) { - continue + pairFmt := h.FormatExchangeCurrency(pairs[i], assetType).String() + if tick[j].Symbol != pairFmt { + found := false + if strings.Contains(tick[j].Symbol, "USDT") { + if pairFmt == tick[j].Symbol[0:len(tick[j].Symbol)-1] { + found = true + } + } + if !found { + continue + } } tickerPrice := ticker.Price{ Last: tick[j].Last, diff --git a/exchanges/huobi/huobi_types.go b/exchanges/huobi/huobi_types.go index d40fe90e..7dd12b22 100644 --- a/exchanges/huobi/huobi_types.go +++ b/exchanges/huobi/huobi_types.go @@ -1,7 +1,5 @@ package huobi -import "github.com/thrasher-corp/gocryptotrader/currency" - // Response stores the Huobi response information type Response struct { Status string `json:"status"` @@ -49,14 +47,14 @@ type Tickers struct { // Ticker latest ticker data type Ticker struct { - Amount float64 `json:"amount"` - Close float64 `json:"close"` - Count int64 `json:"count"` - High float64 `json:"high"` - Low float64 `json:"low"` - Open float64 `json:"open"` - Symbol currency.Pair `json:"symbol"` - Volume float64 `json:"vol"` + Amount float64 `json:"amount"` + Close float64 `json:"close"` + Count int64 `json:"count"` + High float64 `json:"high"` + Low float64 `json:"low"` + Open float64 `json:"open"` + Symbol string `json:"symbol"` + Volume float64 `json:"vol"` } // OrderBookDataRequestParamsType var for request param types @@ -118,11 +116,17 @@ type Detail struct { // Symbol stores the symbol data type Symbol struct { - BaseCurrency string `json:"base-currency"` - QuoteCurrency string `json:"quote-currency"` - PricePrecision int `json:"price-precision"` - AmountPrecision int `json:"amount-precision"` - SymbolPartition string `json:"symbol-partition"` + BaseCurrency string `json:"base-currency"` + QuoteCurrency string `json:"quote-currency"` + PricePrecision int `json:"price-precision"` + AmountPrecision int `json:"amount-precision"` + SymbolPartition string `json:"symbol-partition"` + Innovation string `json:"innovation"` + State string `json:"state"` + ValuePrecision int `json:"value-precision"` + MinimumOrderAmount float64 `json:"min-order-amt"` + MaximumOrderAmount float64 `json:"max-order-amt"` + MinimumOrderValue float64 `json:"min-order-value"` } // Account stores the account data @@ -339,6 +343,7 @@ type WsKline struct { } } +// WsTick stores websocket ticker data type WsTick struct { Channel string `json:"ch"` Timestamp int64 `json:"ts"` @@ -403,15 +408,15 @@ type WsAuthenticatedSubscriptionRequest struct { // WsAuthenticatedAccountsListRequest request for account list authenticated connection type WsAuthenticatedAccountsListRequest struct { - Op string `json:"op"` - AccessKeyID string `json:"AccessKeyId"` - SignatureMethod string `json:"SignatureMethod"` - SignatureVersion string `json:"SignatureVersion"` - Timestamp string `json:"Timestamp"` - Signature string `json:"Signature"` - Topic string `json:"topic"` - Symbol currency.Pair `json:"symbol"` - ClientID int64 `json:"cid,string,omitempty"` + Op string `json:"op"` + AccessKeyID string `json:"AccessKeyId"` + SignatureMethod string `json:"SignatureMethod"` + SignatureVersion string `json:"SignatureVersion"` + Timestamp string `json:"Timestamp"` + Signature string `json:"Signature"` + Topic string `json:"topic"` + Symbol string `json:"symbol"` + ClientID int64 `json:"cid,string,omitempty"` } // WsAuthenticatedOrderDetailsRequest request for order details authenticated connection @@ -429,17 +434,17 @@ type WsAuthenticatedOrderDetailsRequest struct { // WsAuthenticatedOrdersListRequest request for orderslist authenticated connection type WsAuthenticatedOrdersListRequest struct { - Op string `json:"op"` - AccessKeyID string `json:"AccessKeyId"` - SignatureMethod string `json:"SignatureMethod"` - SignatureVersion string `json:"SignatureVersion"` - Timestamp string `json:"Timestamp"` - Signature string `json:"Signature"` - Topic string `json:"topic"` - States string `json:"states"` - AccountID int64 `json:"account-id"` - Symbol currency.Pair `json:"symbol"` - ClientID int64 `json:"cid,string,omitempty"` + Op string `json:"op"` + AccessKeyID string `json:"AccessKeyId"` + SignatureMethod string `json:"SignatureMethod"` + SignatureVersion string `json:"SignatureVersion"` + Timestamp string `json:"Timestamp"` + Signature string `json:"Signature"` + Topic string `json:"topic"` + States string `json:"states"` + AccountID int64 `json:"account-id"` + Symbol string `json:"symbol"` + ClientID int64 `json:"cid,string,omitempty"` } // WsAuthenticatedDataResponse response from authenticated connection @@ -481,15 +486,15 @@ type WsAuthenticatedOrdersUpdateResponse struct { // WsAuthenticatedOrdersUpdateResponseData order updatedata type WsAuthenticatedOrdersUpdateResponseData struct { - UnfilledAmount float64 `json:"unfilled-amount,string"` - FilledAmount float64 `json:"filled-amount,string"` - Price float64 `json:"price,string"` - OrderID int64 `json:"order-id"` - Symbol currency.Pair `json:"symbol"` - MatchID int64 `json:"match-id"` - FilledCashAmount float64 `json:"filled-cash-amount,string"` - Role string `json:"role"` - OrderState string `json:"order-state"` + UnfilledAmount float64 `json:"unfilled-amount,string"` + FilledAmount float64 `json:"filled-amount,string"` + Price float64 `json:"price,string"` + OrderID int64 `json:"order-id"` + Symbol string `json:"symbol"` + MatchID int64 `json:"match-id"` + FilledCashAmount float64 `json:"filled-cash-amount,string"` + Role string `json:"role"` + OrderState string `json:"order-state"` } // WsAuthenticatedOrdersResponse response from Orders authenticated subscription @@ -500,22 +505,22 @@ type WsAuthenticatedOrdersResponse struct { // WsAuthenticatedOrdersResponseData order data type WsAuthenticatedOrdersResponseData struct { - SeqID int64 `json:"seq-id"` - OrderID int64 `json:"order-id"` - Symbol currency.Pair `json:"symbol"` - AccountID int64 `json:"account-id"` - OrderAmount float64 `json:"order-amount,string"` - OrderPrice float64 `json:"order-price,string"` - CreatedAt int64 `json:"created-at"` - OrderType string `json:"order-type"` - OrderSource string `json:"order-source"` - OrderState string `json:"order-state"` - Role string `json:"role"` - Price float64 `json:"price,string"` - FilledAmount float64 `json:"filled-amount,string"` - UnfilledAmount float64 `json:"unfilled-amount,string"` - FilledCashAmount float64 `json:"filled-cash-amount,string"` - FilledFees float64 `json:"filled-fees,string"` + SeqID int64 `json:"seq-id"` + OrderID int64 `json:"order-id"` + Symbol string `json:"symbol"` + AccountID int64 `json:"account-id"` + OrderAmount float64 `json:"order-amount,string"` + OrderPrice float64 `json:"order-price,string"` + CreatedAt int64 `json:"created-at"` + OrderType string `json:"order-type"` + OrderSource string `json:"order-source"` + OrderState string `json:"order-state"` + Role string `json:"role"` + Price float64 `json:"price,string"` + FilledAmount float64 `json:"filled-amount,string"` + UnfilledAmount float64 `json:"unfilled-amount,string"` + FilledCashAmount float64 `json:"filled-cash-amount,string"` + FilledFees float64 `json:"filled-fees,string"` } // WsAuthenticatedAccountsListResponse response from AccountsList authenticated endpoint @@ -547,20 +552,20 @@ type WsAuthenticatedOrdersListResponse struct { // WsAuthenticatedOrdersListResponseData contains order details type WsAuthenticatedOrdersListResponseData struct { - ID int64 `json:"id"` - Symbol currency.Pair `json:"symbol"` - AccountID int64 `json:"account-id"` - Amount float64 `json:"amount,string"` - Price float64 `json:"price,string"` - CreatedAt int64 `json:"created-at"` - Type string `json:"type"` - FilledAmount float64 `json:"filled-amount,string"` - FilledCashAmount float64 `json:"filled-cash-amount,string"` - FilledFees float64 `json:"filled-fees,string"` - FinishedAt int64 `json:"finished-at"` - Source string `json:"source"` - State string `json:"state"` - CanceledAt int64 `json:"canceled-at"` + ID int64 `json:"id"` + Symbol string `json:"symbol"` + AccountID int64 `json:"account-id"` + Amount float64 `json:"amount,string"` + Price float64 `json:"price,string"` + CreatedAt int64 `json:"created-at"` + Type string `json:"type"` + FilledAmount float64 `json:"filled-amount,string"` + FilledCashAmount float64 `json:"filled-cash-amount,string"` + FilledFees float64 `json:"filled-fees,string"` + FinishedAt int64 `json:"finished-at"` + Source string `json:"source"` + State string `json:"state"` + CanceledAt int64 `json:"canceled-at"` } // WsAuthenticatedOrderDetailResponse response from OrderDetail authenticated endpoint diff --git a/exchanges/huobi/huobi_websocket.go b/exchanges/huobi/huobi_websocket.go index 3bbca6cc..ce063bd5 100644 --- a/exchanges/huobi/huobi_websocket.go +++ b/exchanges/huobi/huobi_websocket.go @@ -244,10 +244,11 @@ func (h *HUOBI) wsHandleMarketData(resp WsMessage) { } data := strings.Split(kline.Channel, ".") h.Websocket.DataHandler <- wshandler.KlineData{ - Timestamp: time.Unix(0, kline.Timestamp), - Exchange: h.GetName(), - AssetType: asset.Spot, - Pair: currency.NewPairFromString(data[1]), + Timestamp: time.Unix(0, kline.Timestamp), + Exchange: h.GetName(), + AssetType: asset.Spot, + Pair: currency.NewPairFromFormattedPairs(data[1], + h.GetEnabledPairs(asset.Spot), h.GetPairFormat(asset.Spot, true)), OpenPrice: kline.Tick.Open, ClosePrice: kline.Tick.Close, HighPrice: kline.Tick.High, @@ -263,10 +264,11 @@ func (h *HUOBI) wsHandleMarketData(resp WsMessage) { } data := strings.Split(trade.Channel, ".") h.Websocket.DataHandler <- wshandler.TradeData{ - Exchange: h.GetName(), - AssetType: asset.Spot, - CurrencyPair: currency.NewPairFromString(data[1]), - Timestamp: time.Unix(0, trade.Tick.Timestamp), + Exchange: h.GetName(), + AssetType: asset.Spot, + CurrencyPair: currency.NewPairFromFormattedPairs(data[1], + h.GetEnabledPairs(asset.Spot), h.GetPairFormat(asset.Spot, true)), + Timestamp: time.Unix(0, trade.Tick.Timestamp), } case strings.Contains(init.Channel, "detail"): var ticker WsTick @@ -286,14 +288,16 @@ func (h *HUOBI) wsHandleMarketData(resp WsMessage) { Low: ticker.Tick.Low, Timestamp: time.Unix(0, ticker.Timestamp), AssetType: asset.Spot, - Pair: currency.NewPairFromString(data[1]), + Pair: currency.NewPairFromFormattedPairs(data[1], + h.GetEnabledPairs(asset.Spot), h.GetPairFormat(asset.Spot, true)), } } } // WsProcessOrderbook processes new orderbook data func (h *HUOBI) WsProcessOrderbook(update *WsDepth, symbol string) error { - p := currency.NewPairFromString(symbol) + p := currency.NewPairFromFormattedPairs(symbol, + h.GetEnabledPairs(asset.Spot), h.GetPairFormat(asset.Spot, true)) var bids, asks []orderbook.Item for i := 0; i < len(update.Tick.Bids); i++ { bidLevel := update.Tick.Bids[i].([]interface{}) @@ -428,7 +432,7 @@ func (h *HUOBI) wsGetAccountsList(pair currency.Pair) (*WsAuthenticatedAccountsL SignatureVersion: signatureVersion, Timestamp: timestamp, Topic: wsAccountsList, - Symbol: pair, + Symbol: h.FormatExchangeCurrency(pair, asset.Spot).String(), } hmac := h.wsGenerateSignature(timestamp, wsAccountListEndpoint) request.Signature = crypto.Base64Encode(hmac) @@ -455,7 +459,7 @@ func (h *HUOBI) wsGetOrdersList(accountID int64, pair currency.Pair) (*WsAuthent Timestamp: timestamp, Topic: wsOrdersList, AccountID: accountID, - Symbol: pair.Lower(), + Symbol: h.FormatExchangeCurrency(pair, asset.Spot).String(), States: "submitted,partial-filled", } hmac := h.wsGenerateSignature(timestamp, wsOrdersListEndpoint) diff --git a/exchanges/huobi/huobi_wrapper.go b/exchanges/huobi/huobi_wrapper.go index db57407c..f2678e9e 100644 --- a/exchanges/huobi/huobi_wrapper.go +++ b/exchanges/huobi/huobi_wrapper.go @@ -228,7 +228,11 @@ func (h *HUOBI) FetchTradablePairs(asset asset.Item) ([]string, error) { var pairs []string for x := range symbols { - pairs = append(pairs, fmt.Sprintf("%v%v%v", symbols[x].BaseCurrency, h.GetPairFormat(asset, false).Delimiter, symbols[x].QuoteCurrency)) + if symbols[x].State != "online" { + continue + } + pairs = append(pairs, fmt.Sprintf("%v%v%v", symbols[x].BaseCurrency, + h.GetPairFormat(asset, false).Delimiter, symbols[x].QuoteCurrency)) } return pairs, nil @@ -255,7 +259,8 @@ func (h *HUOBI) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Pric pairs := h.GetEnabledPairs(assetType) for i := range pairs { for j := range tickers.Data { - if !pairs[i].Equal(tickers.Data[j].Symbol) { + pairFmt := h.FormatExchangeCurrency(pairs[i], assetType).String() + if pairFmt != tickers.Data[j].Symbol { continue } tickerPrice := ticker.Price{ @@ -264,7 +269,7 @@ func (h *HUOBI) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Pric Volume: tickers.Data[j].Volume, Open: tickers.Data[j].Open, Close: tickers.Data[j].Close, - Pair: tickers.Data[j].Symbol, + Pair: pairs[i], } err = ticker.ProcessTicker(h.GetName(), &tickerPrice, assetType) if err != nil { diff --git a/exchanges/huobihadax/huobihadax_types.go b/exchanges/huobihadax/huobihadax_types.go index 518ebd9d..40e3bf85 100644 --- a/exchanges/huobihadax/huobihadax_types.go +++ b/exchanges/huobihadax/huobihadax_types.go @@ -1,9 +1,5 @@ package huobihadax -import ( - "github.com/thrasher-corp/gocryptotrader/currency" -) - // Response stores the Huobi response information type Response struct { Status string `json:"status"` @@ -25,6 +21,7 @@ type KlineItem struct { Count int `json:"count"` } +// WsTick stores websocket ticker data type WsTick struct { Channel string `json:"ch"` Timestamp int64 `json:"ts"` @@ -48,14 +45,14 @@ type Tickers struct { // Ticker latest ticker data type Ticker struct { - Amount float64 `json:"amount"` - Close float64 `json:"close"` - Count int64 `json:"count"` - High float64 `json:"high"` - Low float64 `json:"low"` - Open float64 `json:"open"` - Symbol currency.Pair `json:"symbol"` - Volume float64 `json:"vol"` + Amount float64 `json:"amount"` + Close float64 `json:"close"` + Count int64 `json:"count"` + High float64 `json:"high"` + Low float64 `json:"low"` + Open float64 `json:"open"` + Symbol string `json:"symbol"` + Volume float64 `json:"vol"` } // DetailMerged stores the ticker detail merged data @@ -121,6 +118,7 @@ type Symbol struct { PricePrecision int `json:"price-precision"` AmountPrecision int `json:"amount-precision"` SymbolPartition string `json:"symbol-partition"` + Symbol string `json:"innovation"` } // Account stores the account data @@ -396,15 +394,15 @@ type WsAuthenticatedSubscriptionRequest struct { // WsAuthenticatedAccountsListRequest request for account list authenticated connection type WsAuthenticatedAccountsListRequest struct { - Op string `json:"op"` - AccessKeyID string `json:"AccessKeyId"` - SignatureMethod string `json:"SignatureMethod"` - SignatureVersion string `json:"SignatureVersion"` - Timestamp string `json:"Timestamp"` - Signature string `json:"Signature"` - Topic string `json:"topic"` - Symbol currency.Pair `json:"symbol"` - ClientID int64 `json:"cid,string,omitempty"` + Op string `json:"op"` + AccessKeyID string `json:"AccessKeyId"` + SignatureMethod string `json:"SignatureMethod"` + SignatureVersion string `json:"SignatureVersion"` + Timestamp string `json:"Timestamp"` + Signature string `json:"Signature"` + Topic string `json:"topic"` + Symbol string `json:"symbol"` + ClientID int64 `json:"cid,string,omitempty"` } // WsAuthenticatedOrderDetailsRequest request for order details authenticated connection @@ -422,17 +420,17 @@ type WsAuthenticatedOrderDetailsRequest struct { // WsAuthenticatedOrdersListRequest request for orderslist authenticated connection type WsAuthenticatedOrdersListRequest struct { - Op string `json:"op"` - AccessKeyID string `json:"AccessKeyId"` - SignatureMethod string `json:"SignatureMethod"` - SignatureVersion string `json:"SignatureVersion"` - Timestamp string `json:"Timestamp"` - Signature string `json:"Signature"` - Topic string `json:"topic"` - States string `json:"states"` - AccountID int64 `json:"account-id"` - Symbol currency.Pair `json:"symbol"` - ClientID int64 `json:"cid,string,omitempty"` + Op string `json:"op"` + AccessKeyID string `json:"AccessKeyId"` + SignatureMethod string `json:"SignatureMethod"` + SignatureVersion string `json:"SignatureVersion"` + Timestamp string `json:"Timestamp"` + Signature string `json:"Signature"` + Topic string `json:"topic"` + States string `json:"states"` + AccountID int64 `json:"account-id"` + Symbol string `json:"symbol"` + ClientID int64 `json:"cid,string,omitempty"` } // WsAuthenticatedDataResponse response from authenticated connection @@ -474,15 +472,15 @@ type WsAuthenticatedOrdersUpdateResponse struct { // WsAuthenticatedOrdersUpdateResponseData order updatedata type WsAuthenticatedOrdersUpdateResponseData struct { - UnfilledAmount float64 `json:"unfilled-amount,string"` - FilledAmount float64 `json:"filled-amount,string"` - Price float64 `json:"price,string"` - OrderID int64 `json:"order-id"` - Symbol currency.Pair `json:"symbol"` - MatchID int64 `json:"match-id"` - FilledCashAmount float64 `json:"filled-cash-amount,string"` - Role string `json:"role"` - OrderState string `json:"order-state"` + UnfilledAmount float64 `json:"unfilled-amount,string"` + FilledAmount float64 `json:"filled-amount,string"` + Price float64 `json:"price,string"` + OrderID int64 `json:"order-id"` + Symbol string `json:"symbol"` + MatchID int64 `json:"match-id"` + FilledCashAmount float64 `json:"filled-cash-amount,string"` + Role string `json:"role"` + OrderState string `json:"order-state"` } // WsAuthenticatedOrdersResponse response from Orders authenticated subscription @@ -493,22 +491,22 @@ type WsAuthenticatedOrdersResponse struct { // WsAuthenticatedOrdersResponseData order data type WsAuthenticatedOrdersResponseData struct { - SeqID int64 `json:"seq-id"` - OrderID int64 `json:"order-id"` - Symbol currency.Pair `json:"symbol"` - AccountID int64 `json:"account-id"` - OrderAmount float64 `json:"order-amount,string"` - OrderPrice float64 `json:"order-price,string"` - CreatedAt int64 `json:"created-at"` - OrderType string `json:"order-type"` - OrderSource string `json:"order-source"` - OrderState string `json:"order-state"` - Role string `json:"role"` - Price float64 `json:"price,string"` - FilledAmount float64 `json:"filled-amount,string"` - UnfilledAmount float64 `json:"unfilled-amount,string"` - FilledCashAmount float64 `json:"filled-cash-amount,string"` - FilledFees float64 `json:"filled-fees,string"` + SeqID int64 `json:"seq-id"` + OrderID int64 `json:"order-id"` + Symbol string `json:"symbol"` + AccountID int64 `json:"account-id"` + OrderAmount float64 `json:"order-amount,string"` + OrderPrice float64 `json:"order-price,string"` + CreatedAt int64 `json:"created-at"` + OrderType string `json:"order-type"` + OrderSource string `json:"order-source"` + OrderState string `json:"order-state"` + Role string `json:"role"` + Price float64 `json:"price,string"` + FilledAmount float64 `json:"filled-amount,string"` + UnfilledAmount float64 `json:"unfilled-amount,string"` + FilledCashAmount float64 `json:"filled-cash-amount,string"` + FilledFees float64 `json:"filled-fees,string"` } // WsAuthenticatedAccountsListResponse response from AccountsList authenticated endpoint @@ -540,20 +538,20 @@ type WsAuthenticatedOrdersListResponse struct { // WsAuthenticatedOrdersListResponseData contains order details type WsAuthenticatedOrdersListResponseData struct { - ID int64 `json:"id"` - Symbol currency.Pair `json:"symbol"` - AccountID int64 `json:"account-id"` - Amount float64 `json:"amount,string"` - Price float64 `json:"price,string"` - CreatedAt int64 `json:"created-at"` - Type string `json:"type"` - FilledAmount float64 `json:"filled-amount,string"` - FilledCashAmount float64 `json:"filled-cash-amount,string"` - FilledFees float64 `json:"filled-fees,string"` - FinishedAt int64 `json:"finished-at"` - Source string `json:"source"` - State string `json:"state"` - CanceledAt int64 `json:"canceled-at"` + ID int64 `json:"id"` + Symbol string `json:"symbol"` + AccountID int64 `json:"account-id"` + Amount float64 `json:"amount,string"` + Price float64 `json:"price,string"` + CreatedAt int64 `json:"created-at"` + Type string `json:"type"` + FilledAmount float64 `json:"filled-amount,string"` + FilledCashAmount float64 `json:"filled-cash-amount,string"` + FilledFees float64 `json:"filled-fees,string"` + FinishedAt int64 `json:"finished-at"` + Source string `json:"source"` + State string `json:"state"` + CanceledAt int64 `json:"canceled-at"` } // WsAuthenticatedOrderDetailResponse response from OrderDetail authenticated endpoint diff --git a/exchanges/huobihadax/huobihadax_websocket.go b/exchanges/huobihadax/huobihadax_websocket.go index bf1c803c..da9fef33 100644 --- a/exchanges/huobihadax/huobihadax_websocket.go +++ b/exchanges/huobihadax/huobihadax_websocket.go @@ -245,10 +245,11 @@ func (h *HUOBIHADAX) wsHandleMarketData(resp WsMessage) { } data := strings.Split(kline.Channel, ".") h.Websocket.DataHandler <- wshandler.KlineData{ - Timestamp: time.Unix(0, kline.Timestamp), - Exchange: h.GetName(), - AssetType: asset.Spot, - Pair: currency.NewPairFromString(data[1]), + Timestamp: time.Unix(0, kline.Timestamp), + Exchange: h.GetName(), + AssetType: asset.Spot, + Pair: currency.NewPairFromFormattedPairs(data[1], + h.GetEnabledPairs(asset.Spot), h.GetPairFormat(asset.Spot, true)), OpenPrice: kline.Tick.Open, ClosePrice: kline.Tick.Close, HighPrice: kline.Tick.High, @@ -264,10 +265,11 @@ func (h *HUOBIHADAX) wsHandleMarketData(resp WsMessage) { } data := strings.Split(trade.Channel, ".") h.Websocket.DataHandler <- wshandler.TradeData{ - Exchange: h.GetName(), - AssetType: asset.Spot, - CurrencyPair: currency.NewPairFromString(data[1]), - Timestamp: time.Unix(0, trade.Tick.Timestamp), + Exchange: h.GetName(), + AssetType: asset.Spot, + CurrencyPair: currency.NewPairFromFormattedPairs(data[1], + h.GetEnabledPairs(asset.Spot), h.GetPairFormat(asset.Spot, true)), + Timestamp: time.Unix(0, trade.Tick.Timestamp), } case strings.Contains(init.Channel, "detail"): var ticker WsTick @@ -287,14 +289,16 @@ func (h *HUOBIHADAX) wsHandleMarketData(resp WsMessage) { Low: ticker.Tick.Low, Timestamp: time.Unix(0, ticker.Timestamp), AssetType: asset.Spot, - Pair: currency.NewPairFromString(data[1]), + Pair: currency.NewPairFromFormattedPairs(data[1], + h.GetEnabledPairs(asset.Spot), h.GetPairFormat(asset.Spot, true)), } } } // WsProcessOrderbook processes new orderbook data func (h *HUOBIHADAX) WsProcessOrderbook(update *WsDepth, symbol string) error { - p := currency.NewPairFromString(symbol) + p := currency.NewPairFromFormattedPairs(symbol, + h.GetEnabledPairs(asset.Spot), h.GetPairFormat(asset.Spot, true)) var bids, asks []orderbook.Item for i := 0; i < len(update.Tick.Bids); i++ { bidLevel := update.Tick.Bids[i].([]interface{}) @@ -429,7 +433,7 @@ func (h *HUOBIHADAX) wsGetAccountsList(pair currency.Pair) (*WsAuthenticatedAcco SignatureVersion: signatureVersion, Timestamp: timestamp, Topic: wsAccountsList, - Symbol: pair, + Symbol: h.FormatExchangeCurrency(pair, asset.Spot).String(), } hmac := h.wsGenerateSignature(timestamp, wsAccountListEndpoint) request.Signature = crypto.Base64Encode(hmac) @@ -456,7 +460,7 @@ func (h *HUOBIHADAX) wsGetOrdersList(accountID int64, pair currency.Pair) (*WsAu Timestamp: timestamp, Topic: wsOrdersList, AccountID: accountID, - Symbol: pair.Lower(), + Symbol: h.FormatExchangeCurrency(pair, asset.Spot).String(), States: "submitted,partial-filled", } hmac := h.wsGenerateSignature(timestamp, wsOrdersListEndpoint) diff --git a/exchanges/huobihadax/huobihadax_wrapper.go b/exchanges/huobihadax/huobihadax_wrapper.go index 59a9f02f..5045b9ac 100644 --- a/exchanges/huobihadax/huobihadax_wrapper.go +++ b/exchanges/huobihadax/huobihadax_wrapper.go @@ -191,7 +191,8 @@ func (h *HUOBIHADAX) FetchTradablePairs(asset asset.Item) ([]string, error) { var pairs []string for x := range symbols { - pairs = append(pairs, fmt.Sprintf("%v%v%v", symbols[x].BaseCurrency, h.GetPairFormat(asset, false).Delimiter, symbols[x].QuoteCurrency)) + pairs = append(pairs, fmt.Sprintf("%v%v%v", symbols[x].BaseCurrency, + h.GetPairFormat(asset, false).Delimiter, symbols[x].QuoteCurrency)) } return pairs, nil @@ -218,7 +219,8 @@ func (h *HUOBIHADAX) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker pairs := h.GetEnabledPairs(assetType) for i := range pairs { for j := range tickers.Data { - if !pairs[i].Equal(tickers.Data[j].Symbol) { + pairFmt := h.FormatExchangeCurrency(pairs[i], assetType).String() + if pairFmt != tickers.Data[j].Symbol { continue } tickerPrice := ticker.Price{ @@ -227,7 +229,7 @@ func (h *HUOBIHADAX) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker Volume: tickers.Data[j].Volume, Open: tickers.Data[j].Open, Close: tickers.Data[j].Close, - Pair: tickers.Data[j].Symbol, + Pair: pairs[i], } err = ticker.ProcessTicker(h.GetName(), &tickerPrice, assetType) if err != nil { diff --git a/exchanges/kraken/kraken_websocket.go b/exchanges/kraken/kraken_websocket.go index ddb3c98c..7d855966 100644 --- a/exchanges/kraken/kraken_websocket.go +++ b/exchanges/kraken/kraken_websocket.go @@ -220,7 +220,8 @@ func (k *Kraken) WsHandleEventResponse(response *WebsocketEventResponse, rawResp // allowing correlation between subscriptions and returned data func addNewSubscriptionChannelData(response *WebsocketEventResponse) { // We change the / to - to maintain compatibility with REST/config - pair := currency.NewPairWithDelimiter(response.Pair.Base.String(), response.Pair.Quote.String(), "-") + pair := currency.NewPairWithDelimiter(response.Pair.Base.String(), + response.Pair.Quote.String(), "-") subscriptionChannelPair = append(subscriptionChannelPair, WebsocketChannelData{ Subscription: response.Subscription.Name, Pair: pair, diff --git a/exchanges/kraken/kraken_wrapper.go b/exchanges/kraken/kraken_wrapper.go index 1b5158ea..5d4912b6 100644 --- a/exchanges/kraken/kraken_wrapper.go +++ b/exchanges/kraken/kraken_wrapper.go @@ -170,7 +170,7 @@ func (k *Kraken) Run() { forceUpdate := false if !common.StringDataContains(k.GetEnabledPairs(asset.Spot).Strings(), k.GetPairFormat(asset.Spot, false).Delimiter) || !common.StringDataContains(k.GetAvailablePairs(asset.Spot).Strings(), k.GetPairFormat(asset.Spot, false).Delimiter) { - enabledPairs := currency.NewPairsFromStrings([]string{fmt.Sprintf("BTC%vUSD", k.GetPairFormat(asset.Spot, false).Delimiter)}) + enabledPairs := currency.NewPairsFromStrings([]string{fmt.Sprintf("XBT%vUSD", k.GetPairFormat(asset.Spot, false).Delimiter)}) log.Warn(log.ExchangeSys, "Available pairs for Kraken reset due to config upgrade, please enable the ones you would like again") forceUpdate = true @@ -242,13 +242,14 @@ func (k *Kraken) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Pri for i := range pairs { for curr, v := range tickers { - if !strings.EqualFold(pairs[i].String(), curr) { + pairFmt := k.FormatExchangeCurrency(pairs[i], assetType).String() + if !strings.EqualFold(pairFmt, curr) { var altCurrency string var ok bool if altCurrency, ok = assetPairMap[curr]; !ok { continue } - if !strings.EqualFold(pairs[i].String(), altCurrency) { + if !strings.EqualFold(pairFmt, altCurrency) { continue } } diff --git a/exchanges/lakebtc/lakebtc_test.go b/exchanges/lakebtc/lakebtc_test.go index 0eea8ece..0ddee837 100644 --- a/exchanges/lakebtc/lakebtc_test.go +++ b/exchanges/lakebtc/lakebtc_test.go @@ -491,8 +491,9 @@ func TestWsTradeProcessing(t *testing.T) { func TestWsTickerProcessing(t *testing.T) { TestSetDefaults(t) TestSetup(t) - l.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride() - l.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride() + const testChanSize = 26 + l.Websocket.DataHandler = make(chan interface{}, testChanSize) + l.Websocket.TrafficAlert = make(chan struct{}, testChanSize) json := `{"btcusd":{"low":"10990.05","high":"11966.24","last":"11903.29","volume":"1803.967079","sell":"11912.39","buy":"11902.2"},"btceur":{"low":"9886.87","high":"10732.72","last":"10691.44","volume":"87.994478","sell":"10711.62","buy":"10691.44"},"btchkd":{"low":null,"high":null,"last":"51776.98","volume":null,"sell":"93307.37","buy":"93177.56"},"btcjpy":{"low":"1176039.0","high":"1272246.0","last":"1265680.0","volume":"129.021421","sell":"1266764.0","buy":"1265680.0"},"btcgbp":{"low":"9157.12","high":"9953.43","last":"9941.28","volume":"10.4997","sell":"10007.89","buy":"9941.28"},"btcaud":{"low":"16102.57","high":"17594.22","last":"17548.16","volume":"7.338316","sell":"17616.67","buy":"17549.69"},"btccad":{"low":"14541.69","high":"15834.87","last":"15763.54","volume":"30.480309","sell":"15793.45","buy":"15756.13"},"btcsgd":{"low":"15133.82","high":"16501.62","last":"16455.53","volume":"4.044026","sell":"16484.37","buy":"16462.18"},"btcchf":{"low":"10800.58","high":"11526.24","last":"11526.24","volume":"0.1765","sell":"11675.34","buy":"11632.02"},"btcnzd":{"low":null,"high":null,"last":"8340.98","volume":null,"sell":"18315.49","buy":"18221.37"},"btcngn":{"low":null,"high":null,"last":"600000.0","volume":null,"sell":null,"buy":null},"eurusd":{"low":"1.1088","high":"1.1138","last":"1.1125","volume":"2680.105249","sell":"1.1142","buy":"1.1121"},"gbpusd":{"low":"1.1934","high":"1.1958","last":"1.1934","volume":"1493.923823","sell":"1.1979","buy":"1.1903"},"usdjpy":{"low":"105.26","high":"107.25","last":"106.33","volume":"114490.2179","sell":"106.34","buy":"106.27"},"usdhkd":{"low":null,"high":null,"last":"7.851","volume":null,"sell":"7.8328","buy":"7.8286"},"usdcad":{"low":"1.3225","high":"1.3272","last":"1.3255","volume":"11033.9877","sell":"1.3258","buy":"1.3238"},"usdsgd":{"low":"1.3776","high":"1.3839","last":"1.3838","volume":"2523.75","sell":"1.3838","buy":"1.3819"},"audusd":{"low":"0.6764","high":"0.6853","last":"0.6771","volume":"5442.608321","sell":"0.6782","buy":"0.6762"},"nzdusd":{"low":null,"high":null,"last":"0.6758","volume":null,"sell":"0.6532","buy":"0.6504"},"usdchf":{"low":"0.9838","high":"0.9838","last":"0.9838","volume":"108.3352","sell":"0.9801","buy":"0.9773"},"usdngn":{"low":null,"high":null,"last":"200.0","volume":null,"sell":null,"buy":null},"ethbtc":{"low":"0.0205","high":"0.025","last":"0.0205","volume":null,"sell":"0.03","buy":"0.0194"},"ltcbtc":{"low":null,"high":null,"last":"0.0114","volume":null,"sell":"0.009","buy":"0.0073"},"bchbtc":{"low":null,"high":null,"last":"0.0544","volume":null,"sell":"0.0322","buy":"0.0274"},"xrpbtc":{"low":"0.000042","high":"0.000042","last":"0.000042","volume":null,"sell":"0.000037","buy":"0.000022"},"baceth":{"low":"0.000035","high":"0.000035","last":"0.000035","volume":null,"sell":"0.0015","buy":null}}` err := l.processTicker(json) if err != nil { diff --git a/exchanges/lakebtc/lakebtc_websocket.go b/exchanges/lakebtc/lakebtc_websocket.go index 162ebaf6..690e2f41 100644 --- a/exchanges/lakebtc/lakebtc_websocket.go +++ b/exchanges/lakebtc/lakebtc_websocket.go @@ -21,9 +21,12 @@ const ( marketGlobalEndpoint = "market-global" marketSubstring = "market-" globalSubstring = "-global" - volumeString = "volume" - highString = "high" - lowString = "low" + tickerBuyString = "buy" + tickerHighString = "high" + tickerLastString = "last" + tickerLowString = "low" + tickerSellString = "sell" + tickerVolumeString = "volume" wssSchem = "wss" ) @@ -220,29 +223,28 @@ func (l *LakeBTC) processTicker(ticker string) error { } for k, v := range tUpdate { tickerData := v.(map[string]interface{}) - if tickerData[highString] == nil || tickerData[lowString] == nil || tickerData[volumeString] == nil { - continue - } - high, err := strconv.ParseFloat(tickerData[highString].(string), 64) - if err != nil { - l.Websocket.DataHandler <- fmt.Errorf("%v error parsing ticker data 'high' %v", l.Name, tickerData) - continue - } - low, err := strconv.ParseFloat(tickerData[lowString].(string), 64) - if err != nil { - l.Websocket.DataHandler <- fmt.Errorf("%v error parsing ticker data 'low' %v", l.Name, tickerData) - continue - } - vol, err := strconv.ParseFloat(tickerData[volumeString].(string), 64) - if err != nil { - l.Websocket.DataHandler <- fmt.Errorf("%v error parsing ticker data 'volume' %v", l.Name, tickerData) - continue + processTickerItem := func(tick map[string]interface{}, item string) float64 { + if tick[item] == nil { + return 0 + } + + p, err := strconv.ParseFloat(tick[item].(string), 64) + if err != nil { + l.Websocket.DataHandler <- fmt.Errorf("%s error parsing ticker data '%s' %v", l.Name, item, tickerData) + return 0 + } + + return p } + l.Websocket.DataHandler <- wshandler.TickerData{ Exchange: l.Name, - Volume: vol, - High: high, - Low: low, + Bid: processTickerItem(tickerData, tickerBuyString), + High: processTickerItem(tickerData, tickerHighString), + Last: processTickerItem(tickerData, tickerLastString), + Low: processTickerItem(tickerData, tickerLowString), + Ask: processTickerItem(tickerData, tickerSellString), + Volume: processTickerItem(tickerData, tickerVolumeString), AssetType: asset.Spot, Pair: currency.NewPairFromString(k), } diff --git a/exchanges/zb/zb_wrapper.go b/exchanges/zb/zb_wrapper.go index 34b46ded..e415043d 100644 --- a/exchanges/zb/zb_wrapper.go +++ b/exchanges/zb/zb_wrapper.go @@ -4,7 +4,6 @@ import ( "errors" "fmt" "strconv" - "strings" "sync" "time" @@ -188,9 +187,8 @@ func (z *ZB) FetchTradablePairs(asset asset.Item) ([]string, error) { func (z *ZB) UpdateTradablePairs(forceUpdate bool) error { pairs, err := z.FetchTradablePairs(asset.Spot) if err != nil { - return nil + return err } - return z.UpdatePairs(currency.NewPairsFromStrings(pairs), asset.Spot, false, forceUpdate) } @@ -204,8 +202,9 @@ func (z *ZB) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Price, } for _, x := range z.GetEnabledPairs(assetType) { - currencySplit := strings.Split(z.FormatExchangeCurrency(x, assetType).String(), z.GetPairFormat(assetType, false).Delimiter) - curr := currencySplit[0] + currencySplit[1] + // We can't use either pair format here, so format it to lower- + // case and without any delimiter + curr := x.Format("", false).String() if _, ok := result[curr]; !ok { continue }