mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-06-09 07:26:48 +00:00
Engine: Protocol Features, coverage, types, BTC markets websocket (#368)
* Attempts to update orderbook so it doesn't need to sort * Reverts the ws ob stuff. Gets rid of sorting because it happens later. Adds some exchange features * update existing feature lists. Expands list definition to match my emotions * Adds bithumb bitmex and bitstamp. adds a couple more types * Features for you, features for me, features for bittrex, btcmarkets, btse, coinbasepro, coinut, exmo, gateio and gemini * Features for hitbtc, huobi, itbit, kraken, lakebtc, lbank, localbitcoins, okcoin, okex, poloniex, yobit, zb * Who can forget good old alphapoint? * Adds btcmarksets websocket :glitch_crab: fixes alphapoint features * Adds extra data not in the documentation :/ * Replaces websocket features by using protocol features. However, it breaks it due to import cycles. I'm not sure what I'll do just yet * Removes import cycle via duplicate structs. * Increases coverage of config with `TestCheckCurrencyConfigValues`. Moves all currency pair package types into their own files or places it at the bottom of files if necessary * Increase coverage in code.go * One way of determining a test has failed, is when to it fails. Removed redundant explanation * Increases code coverage of conversion * Lint fixes * Fixes orderbook tests * Re-adds sorting because its important to still have the internal pre-processed orderbook to be representative of a real orderbook * Secret lints that did not show up via Windows linting * Adds protocol package to contain exchange features * Fixes protocol implementation * Fixes ws tests * Addresses the following: Removes st-st-stutters in config types, changes GetAvailableForexProviders -> GetSupportedForexProviders, removes errors from tests where error is nil, removes orderbook setup when not necessary, removes import newlines, removes false bools from declaration, changes should of to should have * imports and casing * Fixes two more nil error checks
This commit is contained in:
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
@@ -46,6 +47,7 @@ const (
|
||||
// BTCMarkets is the overarching type across the BTCMarkets package
|
||||
type BTCMarkets struct {
|
||||
exchange.Base
|
||||
WebsocketConn *wshandler.WebsocketConnection
|
||||
}
|
||||
|
||||
// GetMarkets returns the BTCMarkets instruments
|
||||
|
||||
@@ -27,11 +27,11 @@ func TestSetup(t *testing.T) {
|
||||
cfg := config.GetConfig()
|
||||
err := cfg.LoadConfig("../../testdata/configtest.json", true)
|
||||
if err != nil {
|
||||
t.Fatal("Test Failed - BTC Markets load config error", err)
|
||||
t.Fatal("BTC Markets load config error", err)
|
||||
}
|
||||
bConfig, err := cfg.GetExchangeConfig("BTC Markets")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - BTC Markets Setup() init error")
|
||||
t.Error("BTC Markets Setup() init error")
|
||||
}
|
||||
bConfig.API.Credentials.Key = apiKey
|
||||
bConfig.API.Credentials.Secret = apiSecret
|
||||
@@ -39,7 +39,7 @@ func TestSetup(t *testing.T) {
|
||||
|
||||
err = b.Setup(bConfig)
|
||||
if err != nil {
|
||||
t.Fatal("Test Failed - BTC Markets setup error", err)
|
||||
t.Fatal("BTC Markets setup error", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ func TestGetMarkets(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetMarkets()
|
||||
if err != nil {
|
||||
t.Error("Test failed - GetMarkets() error", err)
|
||||
t.Error("GetMarkets() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ func TestGetTicker(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetTicker("BTC", "AUD")
|
||||
if err != nil {
|
||||
t.Error("Test failed - GetTicker() error", err)
|
||||
t.Error("GetTicker() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ func TestGetOrderbook(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetOrderbook("BTC", "AUD")
|
||||
if err != nil {
|
||||
t.Error("Test failed - GetOrderbook() error", err)
|
||||
t.Error("GetOrderbook() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,14 +71,14 @@ func TestGetTrades(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetTrades("BTC", "AUD", nil)
|
||||
if err != nil {
|
||||
t.Error("Test failed - GetTrades() error", err)
|
||||
t.Error("GetTrades() error", err)
|
||||
}
|
||||
|
||||
val := url.Values{}
|
||||
val.Set("since", "0")
|
||||
_, err = b.GetTrades("BTC", "AUD", val)
|
||||
if err != nil {
|
||||
t.Error("Test failed - GetTrades() error", err)
|
||||
t.Error("GetTrades() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ func TestNewOrder(t *testing.T) {
|
||||
_, err := b.NewOrder("AUD", "BTC", 0, 0, "Bid",
|
||||
exchange.LimitOrderType.ToLower().ToString(), "testTest")
|
||||
if err == nil {
|
||||
t.Error("Test failed - NewOrder() error", err)
|
||||
t.Error("NewOrder() Expected error")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ func TestCancelExistingOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.CancelExistingOrder([]int64{1337})
|
||||
if err == nil {
|
||||
t.Error("Test failed - CancelExistingOrder() error", err)
|
||||
t.Error("CancelExistingOrder() Expected error")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,11 +103,11 @@ func TestGetOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetOrders("AUD", "BTC", 10, 0, false)
|
||||
if err == nil {
|
||||
t.Error("Test failed - GetOrders() error", err)
|
||||
t.Error("GetOrders() Expected error")
|
||||
}
|
||||
_, err = b.GetOrders("AUD", "BTC", 10, 0, true)
|
||||
if err == nil {
|
||||
t.Error("Test failed - GetOrders() error", err)
|
||||
t.Error("GetOrders() Expected error")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ func TestGetOrderDetail(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetOrderDetail([]int64{1337})
|
||||
if err == nil {
|
||||
t.Error("Test failed - GetOrderDetail() error", err)
|
||||
t.Error("GetOrderDetail() Expected error")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ func TestGetAccountBalance(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetAccountBalance()
|
||||
if err == nil {
|
||||
t.Error("Test failed - GetAccountBalance() error", err)
|
||||
t.Error("GetAccountBalance() Expected error")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ func TestWithdrawCrypto(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.WithdrawCrypto(0, "BTC", "LOLOLOL")
|
||||
if err == nil {
|
||||
t.Error("Test failed - WithdrawCrypto() error", err)
|
||||
t.Error("WithdrawCrypto() Expected error")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,21 +139,21 @@ func TestWithdrawAUD(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.WithdrawAUD("BLA", "1337", "blawest", "1336", 10000000)
|
||||
if err == nil {
|
||||
t.Error("Test failed - WithdrawAUD() error", err)
|
||||
t.Error("WithdrawAUD() Expected error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
_, err := b.GetAccountInfo()
|
||||
if err == nil {
|
||||
t.Error("Test failed - GetAccountInfo() error", err)
|
||||
t.Error("GetAccountInfo() Expected error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetFundingHistory(t *testing.T) {
|
||||
_, err := b.GetFundingHistory()
|
||||
if err == nil {
|
||||
t.Error("Test failed - GetAccountInfo() error", err)
|
||||
t.Error("GetAccountInfo() Expected error")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,14 +161,14 @@ func TestCancelOrder(t *testing.T) {
|
||||
_, err := b.CancelExistingOrder([]int64{1337})
|
||||
|
||||
if err == nil {
|
||||
t.Error("Test failed - CancelgOrder() error", err)
|
||||
t.Error("CancelgOrder() Expected error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetOrderInfo(t *testing.T) {
|
||||
_, err := b.GetOrderInfo("1337")
|
||||
if err == nil {
|
||||
t.Error("Test failed - GetOrderInfo() error", err)
|
||||
t.Error("GetOrderInfo() Expected error")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,14 +208,14 @@ func TestGetFee(t *testing.T) {
|
||||
feeBuilder.Pair.Quote = currency.USD
|
||||
if resp, err := b.GetFee(feeBuilder); resp != float64(0.00849999) || err != nil {
|
||||
t.Error(err)
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0.00849999), resp)
|
||||
t.Errorf("GetFee() error. Expected: %f, Received: %f", float64(0.00849999), resp)
|
||||
}
|
||||
|
||||
// CryptocurrencyTradeFee Basic
|
||||
feeBuilder = setFeeBuilder()
|
||||
if resp, err := b.GetFee(feeBuilder); resp != float64(0.0022) || err != nil {
|
||||
t.Error(err)
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0.0022), resp)
|
||||
t.Errorf("GetFee() error. Expected: %f, Received: %f", float64(0.0022), resp)
|
||||
}
|
||||
|
||||
// CryptocurrencyTradeFee High quantity
|
||||
@@ -223,7 +223,7 @@ func TestGetFee(t *testing.T) {
|
||||
feeBuilder.Amount = 1000
|
||||
feeBuilder.PurchasePrice = 1000
|
||||
if resp, err := b.GetFee(feeBuilder); resp != float64(2200) || err != nil {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(22000), resp)
|
||||
t.Errorf("GetFee() error. Expected: %f, Received: %f", float64(22000), resp)
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
@@ -231,7 +231,7 @@ func TestGetFee(t *testing.T) {
|
||||
feeBuilder = setFeeBuilder()
|
||||
feeBuilder.IsMaker = true
|
||||
if resp, err := b.GetFee(feeBuilder); resp != float64(0.0022) || err != nil {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0.0022), resp)
|
||||
t.Errorf("GetFee() error. Expected: %f, Received: %f", float64(0.0022), resp)
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@ func TestGetFee(t *testing.T) {
|
||||
feeBuilder = setFeeBuilder()
|
||||
feeBuilder.PurchasePrice = -1000
|
||||
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0), resp)
|
||||
t.Errorf("GetFee() error. Expected: %f, Received: %f", float64(0), resp)
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -248,7 +248,7 @@ func TestGetFee(t *testing.T) {
|
||||
feeBuilder = setFeeBuilder()
|
||||
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
|
||||
if resp, err := b.GetFee(feeBuilder); resp != float64(0.001) || err != nil {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0.001), resp)
|
||||
t.Errorf("GetFee() error. Expected: %f, Received: %f", float64(0.001), resp)
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ func TestGetFee(t *testing.T) {
|
||||
feeBuilder = setFeeBuilder()
|
||||
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
|
||||
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0), resp)
|
||||
t.Errorf("GetFee() error. Expected: %f, Received: %f", float64(0), resp)
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
@@ -265,7 +265,7 @@ func TestGetFee(t *testing.T) {
|
||||
feeBuilder.FeeType = exchange.InternationalBankDepositFee
|
||||
feeBuilder.FiatCurrency = currency.AUD
|
||||
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0), resp)
|
||||
t.Errorf("GetFee() error. Expected: %f, Received: %f", float64(0), resp)
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
@@ -274,7 +274,7 @@ func TestGetFee(t *testing.T) {
|
||||
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
|
||||
feeBuilder.FiatCurrency = currency.AUD
|
||||
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0), resp)
|
||||
t.Errorf("GetFee() error. Expected: %f, Received: %f", float64(0), resp)
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -418,7 +418,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
func TestModifyOrder(t *testing.T) {
|
||||
_, err := b.ModifyOrder(&exchange.ModifyOrder{})
|
||||
if err == nil {
|
||||
t.Error("Test failed - ModifyOrder() error")
|
||||
t.Error("ModifyOrder() Expected error")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -500,6 +500,6 @@ func TestWithdrawInternationalBank(t *testing.T) {
|
||||
func TestGetDepositAddress(t *testing.T) {
|
||||
_, err := b.GetDepositAddress(currency.BTC, "")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetDepositAddress() error cannot be nil")
|
||||
t.Error("GetDepositAddress() error cannot be nil")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package btcmarkets
|
||||
|
||||
import "github.com/thrasher-corp/gocryptotrader/currency"
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
)
|
||||
|
||||
// Response is the genralized response type
|
||||
type Response struct {
|
||||
@@ -143,3 +147,54 @@ var WithdrawalFees = map[currency.Code]float64{
|
||||
currency.OMG: 0.15,
|
||||
currency.POWR: 5,
|
||||
}
|
||||
|
||||
// WsSubscribe message sent via ws to subscribe
|
||||
type WsSubscribe struct {
|
||||
MarketIDs []string `json:"marketIds,omitempty"`
|
||||
Channels []string `json:"channels"`
|
||||
MessageType string `json:"messageType"`
|
||||
}
|
||||
|
||||
// WsMessageType message sent via ws to determine type
|
||||
type WsMessageType struct {
|
||||
MessageType string `json:"messageType"`
|
||||
}
|
||||
|
||||
// WsTick message received for ticker data
|
||||
type WsTick struct {
|
||||
Currency string `json:"marketId"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Bid float64 `json:"bestBid,string"`
|
||||
Ask float64 `json:"bestAsk,string"`
|
||||
Last float64 `json:"lastPrice,string"`
|
||||
Volume float64 `json:"volume24h,string"`
|
||||
Price24h float64 `json:"price24h,string"`
|
||||
Low24h float64 `json:"low24h,string"`
|
||||
High24 float64 `json:"high24h,string"`
|
||||
MessageType string `json:"messageType"`
|
||||
}
|
||||
|
||||
// WsTrade message received for trade data
|
||||
type WsTrade struct {
|
||||
Currency string `json:"marketId"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
TradeID int64 `json:"tradeId"`
|
||||
Price float64 `json:"price,string"`
|
||||
Volume float64 `json:"volume,string"`
|
||||
MessageType string `json:"messageType"`
|
||||
}
|
||||
|
||||
// WsOrderbook message received for orderbook data
|
||||
type WsOrderbook struct {
|
||||
Currency string `json:"marketId"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Bids [][]string `json:"bids"`
|
||||
Asks [][]string `json:"asks"`
|
||||
MessageType string `json:"messageType"`
|
||||
}
|
||||
|
||||
type WsError struct {
|
||||
MessageType string `json:"messageType"`
|
||||
Code int64 `json:"code"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
207
exchanges/btcmarkets/btcmarkets_websocket.go
Normal file
207
exchanges/btcmarkets/btcmarkets_websocket.go
Normal file
@@ -0,0 +1,207 @@
|
||||
package btcmarkets
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
btcMarketsWSURL = "wss://socket.btcmarkets.net/v2"
|
||||
)
|
||||
|
||||
// WsConnect connects to a websocket feed
|
||||
func (b *BTCMarkets) WsConnect() error {
|
||||
if !b.Websocket.IsEnabled() || !b.IsEnabled() {
|
||||
return errors.New(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
var dialer websocket.Dialer
|
||||
err := b.WebsocketConn.Dial(&dialer, http.Header{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if b.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%s Connected to Websocket.\n", b.GetName())
|
||||
}
|
||||
|
||||
b.generateDefaultSubscriptions()
|
||||
go b.WsHandleData()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WsHandleData handles websocket data from WsReadData
|
||||
func (b *BTCMarkets) WsHandleData() {
|
||||
b.Websocket.Wg.Add(1)
|
||||
defer func() {
|
||||
b.Websocket.Wg.Done()
|
||||
}()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-b.Websocket.ShutdownC:
|
||||
return
|
||||
default:
|
||||
resp, err := b.WebsocketConn.ReadMessage()
|
||||
if err != nil {
|
||||
b.Websocket.ReadMessageErrors <- err
|
||||
return
|
||||
}
|
||||
b.Websocket.TrafficAlert <- struct{}{}
|
||||
var wsResponse WsMessageType
|
||||
err = common.JSONDecode(resp.Raw, &wsResponse)
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- err
|
||||
continue
|
||||
}
|
||||
switch wsResponse.MessageType {
|
||||
case "heartbeat":
|
||||
if b.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%v - Websocket heartbeat received %s", b.GetName(), resp.Raw)
|
||||
}
|
||||
case "orderbook":
|
||||
var ob WsOrderbook
|
||||
err := common.JSONDecode(resp.Raw, &ob)
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- err
|
||||
continue
|
||||
}
|
||||
|
||||
p := currency.NewPairFromString(ob.Currency)
|
||||
var bids, asks []orderbook.Item
|
||||
for x := range ob.Bids {
|
||||
var price, amount float64
|
||||
price, err = strconv.ParseFloat(ob.Bids[x][0], 64)
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- err
|
||||
continue
|
||||
}
|
||||
amount, err = strconv.ParseFloat(ob.Bids[x][1], 64)
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- err
|
||||
continue
|
||||
}
|
||||
bids = append(bids, orderbook.Item{
|
||||
Amount: amount,
|
||||
Price: price,
|
||||
})
|
||||
}
|
||||
for x := range ob.Asks {
|
||||
var price, amount float64
|
||||
price, err = strconv.ParseFloat(ob.Asks[x][0], 64)
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- err
|
||||
continue
|
||||
}
|
||||
amount, err = strconv.ParseFloat(ob.Asks[x][1], 64)
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- err
|
||||
continue
|
||||
}
|
||||
asks = append(asks, orderbook.Item{
|
||||
Amount: amount,
|
||||
Price: price,
|
||||
})
|
||||
}
|
||||
err = b.Websocket.Orderbook.LoadSnapshot(&orderbook.Base{
|
||||
Pair: p,
|
||||
Bids: bids,
|
||||
Asks: asks,
|
||||
LastUpdated: ob.Timestamp,
|
||||
AssetType: asset.Spot,
|
||||
ExchangeName: b.Name,
|
||||
})
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- err
|
||||
continue
|
||||
}
|
||||
b.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
|
||||
Pair: p,
|
||||
Asset: asset.Spot,
|
||||
Exchange: b.GetName(),
|
||||
}
|
||||
case "trade":
|
||||
var trade WsTrade
|
||||
err := common.JSONDecode(resp.Raw, &trade)
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- err
|
||||
continue
|
||||
}
|
||||
p := currency.NewPairFromString(trade.Currency)
|
||||
b.Websocket.DataHandler <- wshandler.TradeData{
|
||||
Timestamp: trade.Timestamp,
|
||||
CurrencyPair: p,
|
||||
AssetType: asset.Spot,
|
||||
Exchange: b.GetName(),
|
||||
Price: trade.Price,
|
||||
Amount: trade.Volume,
|
||||
}
|
||||
case "tick":
|
||||
var tick WsTick
|
||||
err := common.JSONDecode(resp.Raw, &tick)
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- err
|
||||
continue
|
||||
}
|
||||
|
||||
p := currency.NewPairFromString(tick.Currency)
|
||||
b.Websocket.DataHandler <- wshandler.TickerData{
|
||||
Exchange: b.GetName(),
|
||||
Volume: tick.Volume,
|
||||
High: tick.High24,
|
||||
Low: tick.Low24h,
|
||||
Bid: tick.Bid,
|
||||
Ask: tick.Ask,
|
||||
Last: tick.Last,
|
||||
Timestamp: tick.Timestamp,
|
||||
AssetType: asset.Spot,
|
||||
Pair: p,
|
||||
}
|
||||
case "error":
|
||||
var wsErr WsError
|
||||
err := common.JSONDecode(resp.Raw, &wsErr)
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- err
|
||||
continue
|
||||
}
|
||||
b.Websocket.DataHandler <- fmt.Errorf("%v websocket error. Code: %v Message: %v", b.Name, wsErr.Code, wsErr.Message)
|
||||
default:
|
||||
b.Websocket.DataHandler <- fmt.Errorf("%v Unhandled websocket message %s", b.Name, resp.Raw)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (b *BTCMarkets) generateDefaultSubscriptions() {
|
||||
var channels = []string{"tick", "trade", "orderbook"}
|
||||
enabledCurrencies := b.GetEnabledPairs(asset.Spot)
|
||||
var subscriptions []wshandler.WebsocketChannelSubscription
|
||||
for i := range channels {
|
||||
for j := range enabledCurrencies {
|
||||
subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
|
||||
Channel: channels[i],
|
||||
Currency: enabledCurrencies[j],
|
||||
})
|
||||
}
|
||||
}
|
||||
b.Websocket.SubscribeToChannels(subscriptions)
|
||||
}
|
||||
|
||||
// Subscribe sends a websocket message to receive data from the channel
|
||||
func (b *BTCMarkets) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
|
||||
req := WsSubscribe{
|
||||
MarketIDs: []string{channelToSubscribe.Currency.String()},
|
||||
Channels: []string{channelToSubscribe.Channel},
|
||||
MessageType: "subscribe",
|
||||
}
|
||||
return b.WebsocketConn.SendMessage(req)
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
|
||||
@@ -71,10 +72,31 @@ func (b *BTCMarkets) SetDefaults() {
|
||||
b.Features = exchange.Features{
|
||||
Supports: exchange.FeaturesSupported{
|
||||
REST: true,
|
||||
Websocket: false,
|
||||
RESTCapabilities: exchange.ProtocolFeatures{
|
||||
AutoPairUpdates: true,
|
||||
TickerBatching: false,
|
||||
Websocket: true,
|
||||
RESTCapabilities: protocol.Features{
|
||||
TickerFetching: true,
|
||||
TradeFetching: true,
|
||||
OrderbookFetching: true,
|
||||
AutoPairUpdates: true,
|
||||
AccountInfo: true,
|
||||
GetOrder: true,
|
||||
GetOrders: true,
|
||||
CancelOrder: true,
|
||||
SubmitOrder: true,
|
||||
UserTradeHistory: true,
|
||||
CryptoWithdrawal: true,
|
||||
FiatWithdraw: true,
|
||||
TradeFee: true,
|
||||
FiatWithdrawalFee: true,
|
||||
CryptoWithdrawalFee: true,
|
||||
},
|
||||
WebsocketCapabilities: protocol.Features{
|
||||
TickerFetching: true,
|
||||
TradeFetching: true,
|
||||
OrderbookFetching: true,
|
||||
AccountInfo: true,
|
||||
Subscribe: true,
|
||||
AuthenticatedEndpoints: true,
|
||||
},
|
||||
WithdrawPermissions: exchange.AutoWithdrawCrypto |
|
||||
exchange.AutoWithdrawFiat,
|
||||
@@ -88,6 +110,12 @@ func (b *BTCMarkets) SetDefaults() {
|
||||
request.NewRateLimit(time.Second*10, btcmarketsAuthLimit),
|
||||
request.NewRateLimit(time.Second*10, btcmarketsUnauthLimit),
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout))
|
||||
|
||||
b.API.Endpoints.WebsocketURL = btcMarketsWSURL
|
||||
b.Websocket = wshandler.New()
|
||||
b.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
|
||||
b.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
|
||||
b.WebsocketOrderbookBufferLimit = exchange.DefaultWebsocketOrderbookBufferLimit
|
||||
}
|
||||
|
||||
// Setup takes in an exchange configuration and sets all parameters
|
||||
@@ -97,7 +125,38 @@ func (b *BTCMarkets) Setup(exch *config.ExchangeConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
return b.SetupDefaults(exch)
|
||||
err := b.SetupDefaults(exch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = b.Websocket.Setup(
|
||||
&wshandler.WebsocketSetup{
|
||||
Enabled: exch.Features.Enabled.Websocket,
|
||||
Verbose: exch.Verbose,
|
||||
AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
|
||||
WebsocketTimeout: exch.WebsocketTrafficTimeout,
|
||||
DefaultURL: btcMarketsWSURL,
|
||||
ExchangeName: exch.Name,
|
||||
RunningURL: exch.API.Endpoints.WebsocketURL,
|
||||
Connector: b.WsConnect,
|
||||
Subscriber: b.Subscribe,
|
||||
Features: &b.Features.Supports.WebsocketCapabilities,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
b.WebsocketConn = &wshandler.WebsocketConnection{
|
||||
ExchangeName: b.Name,
|
||||
URL: b.Websocket.GetWebsocketURL(),
|
||||
ProxyURL: b.Websocket.GetProxyAddress(),
|
||||
Verbose: b.Verbose,
|
||||
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
|
||||
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Start starts the BTC Markets go routine
|
||||
@@ -440,7 +499,7 @@ func (b *BTCMarkets) WithdrawFiatFundsToInternationalBank(withdrawRequest *excha
|
||||
|
||||
// GetWebsocket returns a pointer to the exchange websocket
|
||||
func (b *BTCMarkets) GetWebsocket() (*wshandler.Websocket, error) {
|
||||
return nil, common.ErrNotYetImplemented
|
||||
return b.Websocket, nil
|
||||
}
|
||||
|
||||
// GetFeeByType returns an estimate of fee based on type of transaction
|
||||
|
||||
Reference in New Issue
Block a user