mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-20 23:16:49 +00:00
Merge branch 'master' into engine
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
# GoCryptoTrader package Exchanges
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
|
||||
|
||||
[](https://travis-ci.org/thrasher-/gocryptotrader)
|
||||
[](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges)
|
||||
[](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
|
||||
[](https://travis-ci.org/thrasher-corp/gocryptotrader)
|
||||
[](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges)
|
||||
[](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-corp/gocryptotrader)
|
||||
|
||||
|
||||
This exchanges package is part of the GoCryptoTrader codebase.
|
||||
@@ -35,12 +35,12 @@ When submitting a PR, please abide by our coding guidelines:
|
||||
|
||||
+ Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)).
|
||||
+ Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines.
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-corp/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Pull requests need to be based on and opened against the `master` branch.
|
||||
|
||||
## Donations
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
|
||||
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# GoCryptoTrader package Alphapoint
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
|
||||
|
||||
[](https://travis-ci.org/thrasher-/gocryptotrader)
|
||||
[](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/alphapoint)
|
||||
[](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
|
||||
[](https://travis-ci.org/thrasher-corp/gocryptotrader)
|
||||
[](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/alphapoint)
|
||||
[](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-corp/gocryptotrader)
|
||||
|
||||
|
||||
This alphapoint package is part of the GoCryptoTrader codebase.
|
||||
@@ -36,12 +36,12 @@ When submitting a PR, please abide by our coding guidelines:
|
||||
|
||||
+ Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)).
|
||||
+ Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines.
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-corp/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Pull requests need to be based on and opened against the `master` branch.
|
||||
|
||||
## Donations
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
|
||||
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
|
||||
|
||||
|
||||
@@ -9,9 +9,9 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/common/crypto"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/crypto"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -3,9 +3,9 @@ package alphapoint
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package alphapoint
|
||||
|
||||
import exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
import exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
|
||||
// Response contains general responses from the exchange
|
||||
type Response struct {
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -15,9 +15,9 @@ const (
|
||||
// WebsocketClient starts a new webstocket connection
|
||||
func (a *Alphapoint) WebsocketClient() {
|
||||
for a.Enabled {
|
||||
var Dialer websocket.Dialer
|
||||
var dialer websocket.Dialer
|
||||
var err error
|
||||
a.WebsocketConn, _, err = Dialer.Dial(a.API.Endpoints.WebsocketURL, http.Header{})
|
||||
a.WebsocketConn, _, err = dialer.Dial(a.API.Endpoints.WebsocketURL, http.Header{})
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(log.ExchangeSys, "%s Unable to connect to Websocket. Error: %s\n", a.Name, err)
|
||||
|
||||
@@ -6,14 +6,15 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
)
|
||||
|
||||
// GetDefaultConfig returns a default exchange config for Alphapoint
|
||||
@@ -57,8 +58,6 @@ func (a *Alphapoint) SetDefaults() {
|
||||
request.NewRateLimit(time.Minute*10, alphapointAuthRate),
|
||||
request.NewRateLimit(time.Minute*10, alphapointUnauthRate),
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout))
|
||||
|
||||
a.WebsocketInit()
|
||||
}
|
||||
|
||||
// FetchTradablePairs returns a list of the exchanges tradable pairs
|
||||
@@ -288,7 +287,7 @@ func (a *Alphapoint) WithdrawFiatFundsToInternationalBank(withdrawRequest *excha
|
||||
}
|
||||
|
||||
// GetWebsocket returns a pointer to the exchange websocket
|
||||
func (a *Alphapoint) GetWebsocket() (*exchange.Websocket, error) {
|
||||
func (a *Alphapoint) GetWebsocket() (*wshandler.Websocket, error) {
|
||||
return nil, common.ErrNotYetImplemented
|
||||
}
|
||||
|
||||
@@ -382,18 +381,18 @@ func (a *Alphapoint) GetOrderHistory(getOrdersRequest *exchange.GetOrdersRequest
|
||||
|
||||
// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle subscribing
|
||||
func (a *Alphapoint) SubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
func (a *Alphapoint) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle unsubscribing
|
||||
func (a *Alphapoint) UnsubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
func (a *Alphapoint) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// GetSubscriptions returns a copied list of subscriptions
|
||||
func (a *Alphapoint) GetSubscriptions() ([]exchange.WebsocketChannelSubscription, error) {
|
||||
func (a *Alphapoint) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
|
||||
return nil, common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# GoCryptoTrader package Anx
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
|
||||
|
||||
[](https://travis-ci.org/thrasher-/gocryptotrader)
|
||||
[](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/anx)
|
||||
[](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
|
||||
[](https://travis-ci.org/thrasher-corp/gocryptotrader)
|
||||
[](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/anx)
|
||||
[](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-corp/gocryptotrader)
|
||||
|
||||
|
||||
This anx package is part of the GoCryptoTrader codebase.
|
||||
@@ -30,7 +30,7 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader
|
||||
|
||||
### How to enable
|
||||
|
||||
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
+ [Enable via configuration](https://github.com/thrasher-corp/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
|
||||
+ Individual package example below:
|
||||
|
||||
@@ -131,12 +131,12 @@ When submitting a PR, please abide by our coding guidelines:
|
||||
|
||||
+ Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)).
|
||||
+ Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines.
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-corp/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Pull requests need to be based on and opened against the `master` branch.
|
||||
|
||||
## Donations
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
|
||||
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
|
||||
|
||||
|
||||
@@ -8,11 +8,11 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -3,11 +3,11 @@ package anx
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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"
|
||||
)
|
||||
|
||||
// Please supply your own keys here for due diligence testing
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package anx
|
||||
|
||||
import "github.com/thrasher-/gocryptotrader/currency"
|
||||
import "github.com/thrasher-corp/gocryptotrader/currency"
|
||||
|
||||
// List of strings
|
||||
const (
|
||||
|
||||
@@ -7,15 +7,16 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
// GetDefaultConfig returns a default exchange config for Alphapoint
|
||||
@@ -457,7 +458,7 @@ func (a *ANX) WithdrawFiatFundsToInternationalBank(withdrawRequest *exchange.Fia
|
||||
}
|
||||
|
||||
// GetWebsocket returns a pointer to the exchange websocket
|
||||
func (a *ANX) GetWebsocket() (*exchange.Websocket, error) {
|
||||
func (a *ANX) GetWebsocket() (*wshandler.Websocket, error) {
|
||||
return nil, common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
@@ -543,18 +544,18 @@ func (a *ANX) GetOrderHistory(getOrdersRequest *exchange.GetOrdersRequest) ([]ex
|
||||
|
||||
// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle subscribing
|
||||
func (a *ANX) SubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
func (a *ANX) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle unsubscribing
|
||||
func (a *ANX) UnsubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
func (a *ANX) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// GetSubscriptions returns a copied list of subscriptions
|
||||
func (a *ANX) GetSubscriptions() ([]exchange.WebsocketChannelSubscription, error) {
|
||||
func (a *ANX) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
|
||||
return nil, common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package asset
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
)
|
||||
|
||||
func TestString(t *testing.T) {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# GoCryptoTrader package Binance
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
|
||||
|
||||
[](https://travis-ci.org/thrasher-/gocryptotrader)
|
||||
[](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/binance)
|
||||
[](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
|
||||
[](https://travis-ci.org/thrasher-corp/gocryptotrader)
|
||||
[](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/binance)
|
||||
[](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-corp/gocryptotrader)
|
||||
|
||||
|
||||
This binance package is part of the GoCryptoTrader codebase.
|
||||
@@ -27,7 +27,7 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader
|
||||
|
||||
### How to enable
|
||||
|
||||
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
+ [Enable via configuration](https://github.com/thrasher-corp/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
|
||||
+ Individual package example below:
|
||||
|
||||
@@ -128,12 +128,12 @@ When submitting a PR, please abide by our coding guidelines:
|
||||
|
||||
+ Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)).
|
||||
+ Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines.
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-corp/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Pull requests need to be based on and opened against the `master` branch.
|
||||
|
||||
## Donations
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
|
||||
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
|
||||
|
||||
|
||||
@@ -11,14 +11,14 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/common/convert"
|
||||
"github.com/thrasher-/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
||||
"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/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -65,7 +65,7 @@ const (
|
||||
// Binance is the overarching type across the Bithumb package
|
||||
type Binance struct {
|
||||
exchange.Base
|
||||
WebsocketConn *websocket.Conn
|
||||
WebsocketConn *wshandler.WebsocketConnection
|
||||
|
||||
// Valid string list that is required by the exchange
|
||||
validLimits []int
|
||||
|
||||
@@ -3,11 +3,11 @@ package binance
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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"
|
||||
)
|
||||
|
||||
// Please supply your own keys here for due diligence testing
|
||||
|
||||
@@ -3,7 +3,7 @@ package binance
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
)
|
||||
|
||||
// Response holds basic binance api response data
|
||||
|
||||
@@ -4,18 +4,17 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
"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/wshandler"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -69,7 +68,7 @@ func (b *Binance) UpdateLocalCache(ob *WebsocketDepthStream) error {
|
||||
ID, ok := lastUpdateID[ob.Pair]
|
||||
if !ok {
|
||||
m.Unlock()
|
||||
return errors.New("binance_websocket.go - Unable to find lastUpdateID")
|
||||
return fmt.Errorf("%v - Unable to find lastUpdateID", b.Name)
|
||||
}
|
||||
|
||||
if ob.LastUpdateID+1 <= ID || ID >= ob.LastUpdateID+1 {
|
||||
@@ -123,10 +122,10 @@ func (b *Binance) UpdateLocalCache(ob *WebsocketDepthStream) error {
|
||||
// WSConnect intiates a websocket connection
|
||||
func (b *Binance) WSConnect() error {
|
||||
if !b.Websocket.IsEnabled() || !b.IsEnabled() {
|
||||
return errors.New(exchange.WebsocketNotEnabled)
|
||||
return errors.New(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
|
||||
var Dialer websocket.Dialer
|
||||
var dialer websocket.Dialer
|
||||
var err error
|
||||
|
||||
pairs := b.GetEnabledPairs(asset.Spot).Strings()
|
||||
@@ -152,18 +151,6 @@ func (b *Binance) WSConnect() error {
|
||||
kline +
|
||||
"/" +
|
||||
depth
|
||||
|
||||
if b.Websocket.GetProxyAddress() != "" {
|
||||
var u *url.URL
|
||||
u, err = url.Parse(b.Websocket.GetProxyAddress())
|
||||
if err != nil {
|
||||
return fmt.Errorf("binance_websocket.go - Unable to connect to parse proxy address. Error: %s",
|
||||
err)
|
||||
}
|
||||
|
||||
Dialer.Proxy = http.ProxyURL(u)
|
||||
}
|
||||
|
||||
for _, ePair := range b.GetEnabledPairs(asset.Spot) {
|
||||
err = b.SeedLocalCache(ePair)
|
||||
if err != nil {
|
||||
@@ -171,9 +158,11 @@ func (b *Binance) WSConnect() error {
|
||||
}
|
||||
}
|
||||
|
||||
b.WebsocketConn, _, err = Dialer.Dial(wsurl, http.Header{})
|
||||
b.WebsocketConn.URL = wsurl
|
||||
err = b.WebsocketConn.Dial(&dialer, http.Header{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("binance_websocket.go - Unable to connect to Websocket. Error: %s",
|
||||
return fmt.Errorf("%v - Unable to connect to Websocket. Error: %s",
|
||||
b.Name,
|
||||
err)
|
||||
}
|
||||
|
||||
@@ -182,18 +171,6 @@ func (b *Binance) WSConnect() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// WSReadData reads from the websocket connection and returns the response
|
||||
func (b *Binance) WSReadData() (exchange.WebsocketResponse, error) {
|
||||
msgType, resp, err := b.WebsocketConn.ReadMessage()
|
||||
|
||||
if err != nil {
|
||||
return exchange.WebsocketResponse{}, err
|
||||
}
|
||||
|
||||
b.Websocket.TrafficAlert <- struct{}{}
|
||||
return exchange.WebsocketResponse{Type: msgType, Raw: resp}, nil
|
||||
}
|
||||
|
||||
// WsHandleData handles websocket data from WsReadData
|
||||
func (b *Binance) WsHandleData() {
|
||||
b.Websocket.Wg.Add(1)
|
||||
@@ -208,134 +185,132 @@ func (b *Binance) WsHandleData() {
|
||||
return
|
||||
|
||||
default:
|
||||
read, err := b.WSReadData()
|
||||
read, err := b.WebsocketConn.ReadMessage()
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
|
||||
if read.Type == websocket.TextMessage {
|
||||
multiStreamData := MultiStreamData{}
|
||||
err = common.JSONDecode(read.Raw, &multiStreamData)
|
||||
b.Websocket.TrafficAlert <- struct{}{}
|
||||
var multiStreamData MultiStreamData
|
||||
err = common.JSONDecode(read.Raw, &multiStreamData)
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- fmt.Errorf("%v - Could not load multi stream data: %s",
|
||||
b.Name,
|
||||
read.Raw)
|
||||
continue
|
||||
}
|
||||
streamType := strings.Split(multiStreamData.Stream, "@")
|
||||
switch streamType[1] {
|
||||
case "trade":
|
||||
trade := TradeStream{}
|
||||
err := common.JSONDecode(multiStreamData.Data, &trade)
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- fmt.Errorf("binance_websocket.go - Could not load multi stream data: %s",
|
||||
string(read.Raw))
|
||||
b.Websocket.DataHandler <- fmt.Errorf("%v - Could not unmarshal trade data: %s",
|
||||
b.Name,
|
||||
err)
|
||||
continue
|
||||
}
|
||||
streamType := strings.Split(multiStreamData.Stream, "@")
|
||||
switch streamType[1] {
|
||||
case "trade":
|
||||
trade := TradeStream{}
|
||||
|
||||
err := common.JSONDecode(multiStreamData.Data, &trade)
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- fmt.Errorf("binance_websocket.go - Could not unmarshal trade data: %s",
|
||||
err)
|
||||
continue
|
||||
}
|
||||
|
||||
price, err := strconv.ParseFloat(trade.Price, 64)
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- fmt.Errorf("binance_websocket.go - price conversion error: %s",
|
||||
err)
|
||||
continue
|
||||
}
|
||||
|
||||
amount, err := strconv.ParseFloat(trade.Quantity, 64)
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- fmt.Errorf("binance_websocket.go - amount conversion error: %s",
|
||||
err)
|
||||
continue
|
||||
}
|
||||
|
||||
b.Websocket.DataHandler <- exchange.TradeData{
|
||||
CurrencyPair: currency.NewPairFromString(trade.Symbol),
|
||||
Timestamp: time.Unix(0, trade.TimeStamp*int64(time.Millisecond)),
|
||||
Price: price,
|
||||
Amount: amount,
|
||||
Exchange: b.GetName(),
|
||||
AssetType: asset.Spot,
|
||||
Side: trade.EventType,
|
||||
}
|
||||
continue
|
||||
case "ticker":
|
||||
t := TickerStream{}
|
||||
|
||||
err := common.JSONDecode(multiStreamData.Data, &t)
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- fmt.Errorf("binance_websocket.go - Could not convert to a TickerStream structure %s",
|
||||
err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
var wsTicker exchange.TickerData
|
||||
|
||||
wsTicker.Timestamp = time.Unix(t.EventTime/1000, 0)
|
||||
wsTicker.Pair = currency.NewPairFromString(t.Symbol)
|
||||
wsTicker.AssetType = asset.Spot
|
||||
wsTicker.Exchange = b.GetName()
|
||||
wsTicker.ClosePrice, _ = strconv.ParseFloat(t.CurrDayClose, 64)
|
||||
wsTicker.Quantity, _ = strconv.ParseFloat(t.TotalTradedVolume, 64)
|
||||
wsTicker.OpenPrice, _ = strconv.ParseFloat(t.OpenPrice, 64)
|
||||
wsTicker.HighPrice, _ = strconv.ParseFloat(t.HighPrice, 64)
|
||||
wsTicker.LowPrice, _ = strconv.ParseFloat(t.LowPrice, 64)
|
||||
|
||||
b.Websocket.DataHandler <- wsTicker
|
||||
|
||||
continue
|
||||
case "kline":
|
||||
kline := KlineStream{}
|
||||
|
||||
err := common.JSONDecode(multiStreamData.Data, &kline)
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- fmt.Errorf("binance_websocket.go - Could not convert to a KlineStream structure %s",
|
||||
err)
|
||||
continue
|
||||
}
|
||||
|
||||
var wsKline exchange.KlineData
|
||||
|
||||
wsKline.Timestamp = time.Unix(0, kline.EventTime)
|
||||
wsKline.Pair = currency.NewPairFromString(kline.Symbol)
|
||||
wsKline.AssetType = asset.Spot
|
||||
wsKline.Exchange = b.GetName()
|
||||
wsKline.StartTime = time.Unix(0, kline.Kline.StartTime)
|
||||
wsKline.CloseTime = time.Unix(0, kline.Kline.CloseTime)
|
||||
wsKline.Interval = kline.Kline.Interval
|
||||
wsKline.OpenPrice, _ = strconv.ParseFloat(kline.Kline.OpenPrice, 64)
|
||||
wsKline.ClosePrice, _ = strconv.ParseFloat(kline.Kline.ClosePrice, 64)
|
||||
wsKline.HighPrice, _ = strconv.ParseFloat(kline.Kline.HighPrice, 64)
|
||||
wsKline.LowPrice, _ = strconv.ParseFloat(kline.Kline.LowPrice, 64)
|
||||
wsKline.Volume, _ = strconv.ParseFloat(kline.Kline.Volume, 64)
|
||||
|
||||
b.Websocket.DataHandler <- wsKline
|
||||
continue
|
||||
case "depth":
|
||||
depth := WebsocketDepthStream{}
|
||||
|
||||
err := common.JSONDecode(multiStreamData.Data, &depth)
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- fmt.Errorf("binance_websocket.go - Could not convert to depthStream structure %s",
|
||||
err)
|
||||
continue
|
||||
}
|
||||
|
||||
err = b.UpdateLocalCache(&depth)
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- fmt.Errorf("binance_websocket.go - UpdateLocalCache error: %s",
|
||||
err)
|
||||
continue
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPairFromString(depth.Pair)
|
||||
|
||||
b.Websocket.DataHandler <- exchange.WebsocketOrderbookUpdate{
|
||||
Pair: currencyPair,
|
||||
Asset: asset.Spot,
|
||||
Exchange: b.GetName(),
|
||||
}
|
||||
price, err := strconv.ParseFloat(trade.Price, 64)
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- fmt.Errorf("%v - price conversion error: %s",
|
||||
b.Name,
|
||||
err)
|
||||
continue
|
||||
}
|
||||
|
||||
amount, err := strconv.ParseFloat(trade.Quantity, 64)
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- fmt.Errorf("%v - amount conversion error: %s",
|
||||
b.Name,
|
||||
err)
|
||||
continue
|
||||
}
|
||||
|
||||
b.Websocket.DataHandler <- wshandler.TradeData{
|
||||
CurrencyPair: currency.NewPairFromString(trade.Symbol),
|
||||
Timestamp: time.Unix(0, trade.TimeStamp),
|
||||
Price: price,
|
||||
Amount: amount,
|
||||
Exchange: b.GetName(),
|
||||
AssetType: "SPOT",
|
||||
Side: trade.EventType,
|
||||
}
|
||||
continue
|
||||
case "ticker":
|
||||
t := TickerStream{}
|
||||
err := common.JSONDecode(multiStreamData.Data, &t)
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- fmt.Errorf("%v - Could not convert to a TickerStream structure %s",
|
||||
b.Name,
|
||||
err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
var wsTicker wshandler.TickerData
|
||||
wsTicker.Timestamp = time.Unix(t.EventTime/1000, 0)
|
||||
wsTicker.Pair = currency.NewPairFromString(t.Symbol)
|
||||
wsTicker.AssetType = asset.Spot
|
||||
wsTicker.Exchange = b.GetName()
|
||||
wsTicker.ClosePrice, _ = strconv.ParseFloat(t.CurrDayClose, 64)
|
||||
wsTicker.Quantity, _ = strconv.ParseFloat(t.TotalTradedVolume, 64)
|
||||
wsTicker.OpenPrice, _ = strconv.ParseFloat(t.OpenPrice, 64)
|
||||
wsTicker.HighPrice, _ = strconv.ParseFloat(t.HighPrice, 64)
|
||||
wsTicker.LowPrice, _ = strconv.ParseFloat(t.LowPrice, 64)
|
||||
|
||||
b.Websocket.DataHandler <- wsTicker
|
||||
|
||||
continue
|
||||
case "kline":
|
||||
kline := KlineStream{}
|
||||
err := common.JSONDecode(multiStreamData.Data, &kline)
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- fmt.Errorf("%v - Could not convert to a KlineStream structure %s",
|
||||
b.Name,
|
||||
err)
|
||||
continue
|
||||
}
|
||||
|
||||
var wsKline wshandler.KlineData
|
||||
wsKline.Timestamp = time.Unix(0, kline.EventTime)
|
||||
wsKline.Pair = currency.NewPairFromString(kline.Symbol)
|
||||
wsKline.AssetType = asset.Spot
|
||||
wsKline.Exchange = b.GetName()
|
||||
wsKline.StartTime = time.Unix(0, kline.Kline.StartTime)
|
||||
wsKline.CloseTime = time.Unix(0, kline.Kline.CloseTime)
|
||||
wsKline.Interval = kline.Kline.Interval
|
||||
wsKline.OpenPrice, _ = strconv.ParseFloat(kline.Kline.OpenPrice, 64)
|
||||
wsKline.ClosePrice, _ = strconv.ParseFloat(kline.Kline.ClosePrice, 64)
|
||||
wsKline.HighPrice, _ = strconv.ParseFloat(kline.Kline.HighPrice, 64)
|
||||
wsKline.LowPrice, _ = strconv.ParseFloat(kline.Kline.LowPrice, 64)
|
||||
wsKline.Volume, _ = strconv.ParseFloat(kline.Kline.Volume, 64)
|
||||
b.Websocket.DataHandler <- wsKline
|
||||
continue
|
||||
case "depth":
|
||||
depth := WebsocketDepthStream{}
|
||||
err := common.JSONDecode(multiStreamData.Data, &depth)
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- fmt.Errorf("%v - Could not convert to depthStream structure %s",
|
||||
b.Name,
|
||||
err)
|
||||
continue
|
||||
}
|
||||
|
||||
err = b.UpdateLocalCache(&depth)
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- fmt.Errorf("%v - UpdateLocalCache error: %s",
|
||||
b.Name,
|
||||
err)
|
||||
continue
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPairFromString(depth.Pair)
|
||||
b.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
|
||||
Pair: currencyPair,
|
||||
Asset: "SPOT",
|
||||
Exchange: b.GetName(),
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,15 +8,16 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
// GetDefaultConfig returns a default exchange config
|
||||
@@ -89,12 +90,14 @@ func (b *Binance) SetDefaults() {
|
||||
|
||||
b.API.Endpoints.URLDefault = apiURL
|
||||
b.API.Endpoints.URL = b.API.Endpoints.URLDefault
|
||||
b.WebsocketInit()
|
||||
b.Websocket = wshandler.New()
|
||||
b.API.Endpoints.WebsocketURL = binanceDefaultWebsocketURL
|
||||
b.Websocket.Functionality = exchange.WebsocketTradeDataSupported |
|
||||
exchange.WebsocketTickerSupported |
|
||||
exchange.WebsocketKlineSupported |
|
||||
exchange.WebsocketOrderbookSupported
|
||||
b.Websocket.Functionality = wshandler.WebsocketTradeDataSupported |
|
||||
wshandler.WebsocketTickerSupported |
|
||||
wshandler.WebsocketKlineSupported |
|
||||
wshandler.WebsocketOrderbookSupported
|
||||
b.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
|
||||
b.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
|
||||
}
|
||||
|
||||
// Setup takes in the supplied exchange configuration details and sets params
|
||||
@@ -109,14 +112,28 @@ func (b *Binance) Setup(exch *config.ExchangeConfig) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return b.WebsocketSetup(b.WSConnect,
|
||||
err = b.Websocket.Setup(b.WSConnect,
|
||||
nil,
|
||||
nil,
|
||||
exch.Name,
|
||||
exch.Features.Enabled.Websocket,
|
||||
exch.Verbose,
|
||||
binanceDefaultWebsocketURL,
|
||||
exch.API.Endpoints.WebsocketURL)
|
||||
exch.API.Endpoints.WebsocketURL,
|
||||
exch.API.AuthenticatedWebsocketSupport)
|
||||
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 Binance go routine
|
||||
@@ -436,7 +453,7 @@ func (b *Binance) WithdrawFiatFundsToInternationalBank(withdrawRequest *exchange
|
||||
}
|
||||
|
||||
// GetWebsocket returns a pointer to the exchange websocket
|
||||
func (b *Binance) GetWebsocket() (*exchange.Websocket, error) {
|
||||
func (b *Binance) GetWebsocket() (*wshandler.Websocket, error) {
|
||||
return b.Websocket, nil
|
||||
}
|
||||
|
||||
@@ -534,18 +551,18 @@ func (b *Binance) GetOrderHistory(getOrdersRequest *exchange.GetOrdersRequest) (
|
||||
|
||||
// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle subscribing
|
||||
func (b *Binance) SubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
func (b *Binance) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle unsubscribing
|
||||
func (b *Binance) UnsubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
func (b *Binance) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// GetSubscriptions returns a copied list of subscriptions
|
||||
func (b *Binance) GetSubscriptions() ([]exchange.WebsocketChannelSubscription, error) {
|
||||
func (b *Binance) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
|
||||
return b.Websocket.GetSubscriptions(), nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# GoCryptoTrader package Bitfinex
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
|
||||
|
||||
[](https://travis-ci.org/thrasher-/gocryptotrader)
|
||||
[](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/bitfinex)
|
||||
[](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
|
||||
[](https://travis-ci.org/thrasher-corp/gocryptotrader)
|
||||
[](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/bitfinex)
|
||||
[](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-corp/gocryptotrader)
|
||||
|
||||
|
||||
This bitfinex package is part of the GoCryptoTrader codebase.
|
||||
@@ -27,7 +27,7 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader
|
||||
|
||||
### How to enable
|
||||
|
||||
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
+ [Enable via configuration](https://github.com/thrasher-corp/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
|
||||
+ Individual package example below:
|
||||
|
||||
@@ -128,12 +128,12 @@ When submitting a PR, please abide by our coding guidelines:
|
||||
|
||||
+ Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)).
|
||||
+ Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines.
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-corp/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Pull requests need to be based on and opened against the `master` branch.
|
||||
|
||||
## Donations
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
|
||||
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
|
||||
|
||||
|
||||
@@ -6,15 +6,14 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -84,9 +83,8 @@ const (
|
||||
// depending on some factors (e.g. servers load, endpoint, etc.).
|
||||
type Bitfinex struct {
|
||||
exchange.Base
|
||||
WebsocketConn *websocket.Conn
|
||||
WebsocketConn *wshandler.WebsocketConnection
|
||||
WebsocketSubdChannels map[int]WebsocketChanInfo
|
||||
wsRequestMtx sync.Mutex
|
||||
}
|
||||
|
||||
// GetPlatformStatus returns the Bifinex platform status
|
||||
|
||||
@@ -8,11 +8,12 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/sharedtestvalues"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/sharedtestvalues"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
)
|
||||
|
||||
// Please supply your own keys here to do better tests
|
||||
@@ -972,19 +973,23 @@ func TestWsAuth(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
if !b.Websocket.IsEnabled() && !b.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip(exchange.WebsocketNotEnabled)
|
||||
t.Skip(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
b.WebsocketConn = &wshandler.WebsocketConnection{
|
||||
ExchangeName: b.Name,
|
||||
URL: b.Websocket.GetWebsocketURL(),
|
||||
Verbose: b.Verbose,
|
||||
ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
|
||||
ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
|
||||
}
|
||||
var err error
|
||||
var dialer websocket.Dialer
|
||||
b.WebsocketConn, _, err = dialer.Dial(b.Websocket.GetWebsocketURL(),
|
||||
http.Header{})
|
||||
err := b.WebsocketConn.Dial(&dialer, http.Header{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
|
||||
b.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
|
||||
go b.WsDataHandler()
|
||||
defer b.WebsocketConn.Close()
|
||||
err = b.WsSendAuth()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
|
||||
@@ -4,19 +4,19 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -60,22 +60,7 @@ var pongReceive chan struct{}
|
||||
func (b *Bitfinex) WsPingHandler() error {
|
||||
req := make(map[string]string)
|
||||
req["event"] = "ping"
|
||||
|
||||
return b.wsSend(req)
|
||||
}
|
||||
|
||||
// WsSend sends data to the websocket server
|
||||
func (b *Bitfinex) wsSend(data interface{}) error {
|
||||
b.wsRequestMtx.Lock()
|
||||
defer b.wsRequestMtx.Unlock()
|
||||
json, err := common.JSONEncode(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if b.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%v sending message to websocket %v", b.Name, data)
|
||||
}
|
||||
return b.WebsocketConn.WriteMessage(websocket.TextMessage, json)
|
||||
return b.WebsocketConn.SendMessage(req)
|
||||
}
|
||||
|
||||
// WsSendAuth sends a autheticated event payload
|
||||
@@ -96,7 +81,7 @@ func (b *Bitfinex) WsSendAuth() error {
|
||||
|
||||
req["authPayload"] = payload
|
||||
|
||||
err := b.wsSend(req)
|
||||
err := b.WebsocketConn.SendMessage(req)
|
||||
if err != nil {
|
||||
b.Websocket.SetCanUseAuthenticatedEndpoints(false)
|
||||
return err
|
||||
@@ -109,7 +94,7 @@ func (b *Bitfinex) WsSendUnauth() error {
|
||||
req := make(map[string]string)
|
||||
req["event"] = "unauth"
|
||||
|
||||
return b.wsSend(req)
|
||||
return b.WebsocketConn.SendMessage(req)
|
||||
}
|
||||
|
||||
// WsAddSubscriptionChannel adds a new subscription channel to the
|
||||
@@ -130,33 +115,28 @@ func (b *Bitfinex) WsAddSubscriptionChannel(chanID int, channel, pair string) {
|
||||
// WsConnect starts a new websocket connection
|
||||
func (b *Bitfinex) WsConnect() error {
|
||||
if !b.Websocket.IsEnabled() || !b.IsEnabled() {
|
||||
return errors.New(exchange.WebsocketNotEnabled)
|
||||
return errors.New(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
|
||||
var Dialer websocket.Dialer
|
||||
var err error
|
||||
|
||||
if b.Websocket.GetProxyAddress() != "" {
|
||||
var proxy *url.URL
|
||||
proxy, err = url.Parse(b.Websocket.GetProxyAddress())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
Dialer.Proxy = http.ProxyURL(proxy)
|
||||
var dialer websocket.Dialer
|
||||
b.WebsocketConn = &wshandler.WebsocketConnection{
|
||||
ExchangeName: b.Name,
|
||||
URL: b.Websocket.GetWebsocketURL(),
|
||||
ProxyURL: b.Websocket.GetProxyAddress(),
|
||||
Verbose: b.Verbose,
|
||||
}
|
||||
|
||||
b.WebsocketConn, _, err = Dialer.Dial(b.Websocket.GetWebsocketURL(), http.Header{})
|
||||
err := b.WebsocketConn.Dial(&dialer, http.Header{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("%v unable to connect to Websocket. Error: %s", b.Name, err)
|
||||
}
|
||||
|
||||
_, resp, err := b.WebsocketConn.ReadMessage()
|
||||
resp, err := b.WebsocketConn.ReadMessage()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%v unable to read from Websocket. Error: %s", b.Name, err)
|
||||
}
|
||||
|
||||
b.Websocket.TrafficAlert <- struct{}{}
|
||||
var hs WebsocketHandshake
|
||||
err = common.JSONDecode(resp, &hs)
|
||||
err = common.JSONDecode(resp.Raw, &hs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -180,22 +160,6 @@ func (b *Bitfinex) WsConnect() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// WsReadData reads and handles websocket stream data
|
||||
func (b *Bitfinex) WsReadData() (exchange.WebsocketResponse, error) {
|
||||
msgType, resp, err := b.WebsocketConn.ReadMessage()
|
||||
if err != nil {
|
||||
return exchange.WebsocketResponse{}, err
|
||||
}
|
||||
|
||||
b.Websocket.TrafficAlert <- struct{}{}
|
||||
|
||||
return exchange.WebsocketResponse{
|
||||
Type: msgType,
|
||||
Raw: resp,
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
// WsDataHandler handles data from WsReadData
|
||||
func (b *Bitfinex) WsDataHandler() {
|
||||
b.Websocket.Wg.Add(1)
|
||||
@@ -210,11 +174,12 @@ func (b *Bitfinex) WsDataHandler() {
|
||||
return
|
||||
|
||||
default:
|
||||
stream, err := b.WsReadData()
|
||||
stream, err := b.WebsocketConn.ReadMessage()
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
b.Websocket.TrafficAlert <- struct{}{}
|
||||
|
||||
if stream.Type == websocket.TextMessage {
|
||||
var result interface{}
|
||||
@@ -223,9 +188,6 @@ func (b *Bitfinex) WsDataHandler() {
|
||||
case "map[string]interface {}":
|
||||
eventData := result.(map[string]interface{})
|
||||
event := eventData["event"]
|
||||
if b.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%v Received message. Type '%v' Message: %v", b.Name, event, eventData)
|
||||
}
|
||||
switch event {
|
||||
case "subscribed":
|
||||
b.WsAddSubscriptionChannel(int(eventData["chanId"].(float64)),
|
||||
@@ -308,7 +270,7 @@ func (b *Bitfinex) WsDataHandler() {
|
||||
}
|
||||
|
||||
case "ticker":
|
||||
b.Websocket.DataHandler <- exchange.TickerData{
|
||||
b.Websocket.DataHandler <- wshandler.TickerData{
|
||||
Quantity: chanData[8].(float64),
|
||||
ClosePrice: chanData[7].(float64),
|
||||
HighPrice: chanData[9].(float64),
|
||||
@@ -478,7 +440,7 @@ func (b *Bitfinex) WsDataHandler() {
|
||||
newAmount *= -1
|
||||
}
|
||||
|
||||
b.Websocket.DataHandler <- exchange.TradeData{
|
||||
b.Websocket.DataHandler <- wshandler.TradeData{
|
||||
CurrencyPair: currency.NewPairFromString(chanInfo.Pair),
|
||||
Timestamp: time.Unix(trades[0].Timestamp, 0),
|
||||
Price: trades[0].Price,
|
||||
@@ -526,7 +488,7 @@ func (b *Bitfinex) WsInsertSnapshot(p currency.Pair, assetType asset.Item, books
|
||||
return fmt.Errorf("bitfinex.go error - %s", err)
|
||||
}
|
||||
|
||||
b.Websocket.DataHandler <- exchange.WebsocketOrderbookUpdate{Pair: p,
|
||||
b.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{Pair: p,
|
||||
Asset: assetType,
|
||||
Exchange: b.GetName()}
|
||||
return nil
|
||||
@@ -551,7 +513,7 @@ func (b *Bitfinex) WsUpdateOrderbook(p currency.Pair, assetType asset.Item, book
|
||||
return err
|
||||
}
|
||||
|
||||
b.Websocket.DataHandler <- exchange.WebsocketOrderbookUpdate{Pair: p,
|
||||
b.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{Pair: p,
|
||||
Asset: assetType,
|
||||
Exchange: b.GetName()}
|
||||
|
||||
@@ -571,7 +533,7 @@ func (b *Bitfinex) WsUpdateOrderbook(p currency.Pair, assetType asset.Item, book
|
||||
return err
|
||||
}
|
||||
|
||||
b.Websocket.DataHandler <- exchange.WebsocketOrderbookUpdate{Pair: p,
|
||||
b.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{Pair: p,
|
||||
Asset: assetType,
|
||||
Exchange: b.GetName()}
|
||||
|
||||
@@ -592,7 +554,7 @@ func (b *Bitfinex) WsUpdateOrderbook(p currency.Pair, assetType asset.Item, book
|
||||
return err
|
||||
}
|
||||
|
||||
b.Websocket.DataHandler <- exchange.WebsocketOrderbookUpdate{Pair: p,
|
||||
b.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{Pair: p,
|
||||
Asset: assetType,
|
||||
Exchange: b.GetName()}
|
||||
|
||||
@@ -612,7 +574,7 @@ func (b *Bitfinex) WsUpdateOrderbook(p currency.Pair, assetType asset.Item, book
|
||||
return err
|
||||
}
|
||||
|
||||
b.Websocket.DataHandler <- exchange.WebsocketOrderbookUpdate{Pair: p,
|
||||
b.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{Pair: p,
|
||||
Asset: assetType,
|
||||
Exchange: b.GetName()}
|
||||
|
||||
@@ -622,7 +584,7 @@ func (b *Bitfinex) WsUpdateOrderbook(p currency.Pair, assetType asset.Item, book
|
||||
// GenerateDefaultSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions()
|
||||
func (b *Bitfinex) GenerateDefaultSubscriptions() {
|
||||
var channels = []string{"book", "trades", "ticker"}
|
||||
var subscriptions []exchange.WebsocketChannelSubscription
|
||||
var subscriptions []wshandler.WebsocketChannelSubscription
|
||||
for i := range channels {
|
||||
enabledPairs := b.GetEnabledPairs(asset.Spot)
|
||||
for j := range enabledPairs {
|
||||
@@ -630,7 +592,7 @@ func (b *Bitfinex) GenerateDefaultSubscriptions() {
|
||||
if channels[i] == "book" {
|
||||
params["prec"] = "P0"
|
||||
}
|
||||
subscriptions = append(subscriptions, exchange.WebsocketChannelSubscription{
|
||||
subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
|
||||
Channel: channels[i],
|
||||
Currency: enabledPairs[j],
|
||||
Params: params,
|
||||
@@ -641,7 +603,7 @@ func (b *Bitfinex) GenerateDefaultSubscriptions() {
|
||||
}
|
||||
|
||||
// Subscribe sends a websocket message to receive data from the channel
|
||||
func (b *Bitfinex) Subscribe(channelToSubscribe exchange.WebsocketChannelSubscription) error {
|
||||
func (b *Bitfinex) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
|
||||
req := make(map[string]interface{})
|
||||
req["event"] = "subscribe"
|
||||
req["channel"] = channelToSubscribe.Channel
|
||||
@@ -653,11 +615,11 @@ func (b *Bitfinex) Subscribe(channelToSubscribe exchange.WebsocketChannelSubscri
|
||||
req[k] = v
|
||||
}
|
||||
}
|
||||
return b.wsSend(req)
|
||||
return b.WebsocketConn.SendMessage(req)
|
||||
}
|
||||
|
||||
// Unsubscribe sends a websocket message to stop receiving data from the channel
|
||||
func (b *Bitfinex) Unsubscribe(channelToSubscribe exchange.WebsocketChannelSubscription) error {
|
||||
func (b *Bitfinex) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
|
||||
req := make(map[string]interface{})
|
||||
req["event"] = "unsubscribe"
|
||||
req["channel"] = channelToSubscribe.Channel
|
||||
@@ -667,5 +629,5 @@ func (b *Bitfinex) Unsubscribe(channelToSubscribe exchange.WebsocketChannelSubsc
|
||||
req[k] = v
|
||||
}
|
||||
}
|
||||
return b.wsSend(req)
|
||||
return b.WebsocketConn.SendMessage(req)
|
||||
}
|
||||
|
||||
@@ -9,15 +9,16 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
// GetDefaultConfig returns a default exchange config
|
||||
@@ -89,12 +90,15 @@ func (b *Bitfinex) SetDefaults() {
|
||||
b.API.Endpoints.URLDefault = bitfinexAPIURLBase
|
||||
b.API.Endpoints.URL = b.API.Endpoints.URLDefault
|
||||
b.API.Endpoints.WebsocketURL = bitfinexWebsocket
|
||||
b.WebsocketInit()
|
||||
b.Websocket.Functionality = exchange.WebsocketTickerSupported |
|
||||
exchange.WebsocketTradeDataSupported |
|
||||
exchange.WebsocketOrderbookSupported |
|
||||
exchange.WebsocketSubscribeSupported |
|
||||
exchange.WebsocketUnsubscribeSupported
|
||||
b.Websocket = wshandler.New()
|
||||
b.Websocket.Functionality = wshandler.WebsocketTickerSupported |
|
||||
wshandler.WebsocketTradeDataSupported |
|
||||
wshandler.WebsocketOrderbookSupported |
|
||||
wshandler.WebsocketSubscribeSupported |
|
||||
wshandler.WebsocketUnsubscribeSupported |
|
||||
wshandler.WebsocketAuthenticatedEndpointsSupported
|
||||
b.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
|
||||
b.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
|
||||
}
|
||||
|
||||
// Setup takes in the supplied exchange configuration details and sets params
|
||||
@@ -109,14 +113,28 @@ func (b *Bitfinex) Setup(exch *config.ExchangeConfig) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return b.WebsocketSetup(b.WsConnect,
|
||||
err = b.Websocket.Setup(b.WsConnect,
|
||||
b.Subscribe,
|
||||
b.Unsubscribe,
|
||||
exch.Name,
|
||||
exch.Features.Enabled.Websocket,
|
||||
exch.Verbose,
|
||||
bitfinexWebsocket,
|
||||
exch.API.Endpoints.WebsocketURL)
|
||||
exch.API.Endpoints.WebsocketURL,
|
||||
exch.API.AuthenticatedWebsocketSupport)
|
||||
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 Bitfinex go routine
|
||||
@@ -439,7 +457,7 @@ func (b *Bitfinex) WithdrawFiatFundsToInternationalBank(withdrawRequest *exchang
|
||||
}
|
||||
|
||||
// GetWebsocket returns a pointer to the exchange websocket
|
||||
func (b *Bitfinex) GetWebsocket() (*exchange.Websocket, error) {
|
||||
func (b *Bitfinex) GetWebsocket() (*wshandler.Websocket, error) {
|
||||
return b.Websocket, nil
|
||||
}
|
||||
|
||||
@@ -571,20 +589,20 @@ func (b *Bitfinex) GetOrderHistory(getOrdersRequest *exchange.GetOrdersRequest)
|
||||
|
||||
// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle subscribing
|
||||
func (b *Bitfinex) SubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
func (b *Bitfinex) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
b.Websocket.SubscribeToChannels(channels)
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle unsubscribing
|
||||
func (b *Bitfinex) UnsubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
b.Websocket.UnsubscribeToChannels(channels)
|
||||
func (b *Bitfinex) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
b.Websocket.RemoveSubscribedChannels(channels)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetSubscriptions returns a copied list of subscriptions
|
||||
func (b *Bitfinex) GetSubscriptions() ([]exchange.WebsocketChannelSubscription, error) {
|
||||
func (b *Bitfinex) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
|
||||
return b.Websocket.GetSubscriptions(), nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# GoCryptoTrader package Bitflyer
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
|
||||
|
||||
[](https://travis-ci.org/thrasher-/gocryptotrader)
|
||||
[](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/bitflyer)
|
||||
[](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
|
||||
[](https://travis-ci.org/thrasher-corp/gocryptotrader)
|
||||
[](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/bitflyer)
|
||||
[](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-corp/gocryptotrader)
|
||||
|
||||
|
||||
This bitflyer package is part of the GoCryptoTrader codebase.
|
||||
@@ -26,7 +26,7 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader
|
||||
|
||||
### How to enable
|
||||
|
||||
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
+ [Enable via configuration](https://github.com/thrasher-corp/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
|
||||
+ Individual package example below:
|
||||
|
||||
@@ -127,12 +127,12 @@ When submitting a PR, please abide by our coding guidelines:
|
||||
|
||||
+ Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)).
|
||||
+ Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines.
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-corp/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Pull requests need to be based on and opened against the `master` branch.
|
||||
|
||||
## Donations
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
|
||||
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -3,12 +3,12 @@ package bitflyer
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
// Please supply your own keys here for due diligence testing
|
||||
|
||||
@@ -6,15 +6,16 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
// GetDefaultConfig returns a default exchange config
|
||||
@@ -329,7 +330,7 @@ func (b *Bitflyer) WithdrawFiatFundsToInternationalBank(withdrawRequest *exchang
|
||||
}
|
||||
|
||||
// GetWebsocket returns a pointer to the exchange websocket
|
||||
func (b *Bitflyer) GetWebsocket() (*exchange.Websocket, error) {
|
||||
func (b *Bitflyer) GetWebsocket() (*wshandler.Websocket, error) {
|
||||
return nil, common.ErrNotYetImplemented
|
||||
}
|
||||
|
||||
@@ -355,18 +356,18 @@ func (b *Bitflyer) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error
|
||||
|
||||
// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle subscribing
|
||||
func (b *Bitflyer) SubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
func (b *Bitflyer) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle unsubscribing
|
||||
func (b *Bitflyer) UnsubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
func (b *Bitflyer) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// GetSubscriptions returns a copied list of subscriptions
|
||||
func (b *Bitflyer) GetSubscriptions() ([]exchange.WebsocketChannelSubscription, error) {
|
||||
func (b *Bitflyer) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
|
||||
return nil, common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# GoCryptoTrader package Bithumb
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
|
||||
|
||||
[](https://travis-ci.org/thrasher-/gocryptotrader)
|
||||
[](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/bithumb)
|
||||
[](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
|
||||
[](https://travis-ci.org/thrasher-corp/gocryptotrader)
|
||||
[](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/bithumb)
|
||||
[](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-corp/gocryptotrader)
|
||||
|
||||
|
||||
This bithumb package is part of the GoCryptoTrader codebase.
|
||||
@@ -26,7 +26,7 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader
|
||||
|
||||
### How to enable
|
||||
|
||||
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
+ [Enable via configuration](https://github.com/thrasher-corp/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
|
||||
+ Individual package example below:
|
||||
|
||||
@@ -120,12 +120,12 @@ When submitting a PR, please abide by our coding guidelines:
|
||||
|
||||
+ Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)).
|
||||
+ Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines.
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-corp/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Pull requests need to be based on and opened against the `master` branch.
|
||||
|
||||
## Donations
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
|
||||
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
|
||||
|
||||
|
||||
@@ -11,10 +11,10 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -3,10 +3,10 @@ package bithumb
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
)
|
||||
|
||||
// Please supply your own keys here for due diligence testing
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package bithumb
|
||||
|
||||
import "github.com/thrasher-/gocryptotrader/currency"
|
||||
import "github.com/thrasher-corp/gocryptotrader/currency"
|
||||
|
||||
// Ticker holds ticker data
|
||||
type Ticker struct {
|
||||
|
||||
@@ -9,15 +9,16 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
// GetDefaultConfig returns a default exchange config
|
||||
@@ -410,7 +411,7 @@ func (b *Bithumb) WithdrawFiatFundsToInternationalBank(withdrawRequest *exchange
|
||||
}
|
||||
|
||||
// GetWebsocket returns a pointer to the exchange websocket
|
||||
func (b *Bithumb) GetWebsocket() (*exchange.Websocket, error) {
|
||||
func (b *Bithumb) GetWebsocket() (*wshandler.Websocket, error) {
|
||||
return nil, common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
@@ -511,18 +512,18 @@ func (b *Bithumb) GetOrderHistory(getOrdersRequest *exchange.GetOrdersRequest) (
|
||||
|
||||
// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle subscribing
|
||||
func (b *Bithumb) SubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
func (b *Bithumb) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle unsubscribing
|
||||
func (b *Bithumb) UnsubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
func (b *Bithumb) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// GetSubscriptions returns a copied list of subscriptions
|
||||
func (b *Bithumb) GetSubscriptions() ([]exchange.WebsocketChannelSubscription, error) {
|
||||
func (b *Bithumb) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
|
||||
return nil, common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# GoCryptoTrader package Bitmex
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
|
||||
|
||||
[](https://travis-ci.org/thrasher-/gocryptotrader)
|
||||
[](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/bitmex)
|
||||
[](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
|
||||
[](https://travis-ci.org/thrasher-corp/gocryptotrader)
|
||||
[](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/bitmex)
|
||||
[](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-corp/gocryptotrader)
|
||||
|
||||
|
||||
This bitmex package is part of the GoCryptoTrader codebase.
|
||||
@@ -26,7 +26,7 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader
|
||||
|
||||
### How to enable
|
||||
|
||||
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
+ [Enable via configuration](https://github.com/thrasher-corp/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
|
||||
+ Individual package example below:
|
||||
|
||||
@@ -120,12 +120,12 @@ When submitting a PR, please abide by our coding guidelines:
|
||||
|
||||
+ Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)).
|
||||
+ Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines.
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-corp/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Pull requests need to be based on and opened against the `master` branch.
|
||||
|
||||
## Donations
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
|
||||
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
|
||||
|
||||
|
||||
@@ -7,21 +7,19 @@ import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/wshandler"
|
||||
)
|
||||
|
||||
// Bitmex is the overarching type across this package
|
||||
type Bitmex struct {
|
||||
exchange.Base
|
||||
WebsocketConn *websocket.Conn
|
||||
wsRequestMtx sync.Mutex
|
||||
WebsocketConn *wshandler.WebsocketConnection
|
||||
}
|
||||
|
||||
const (
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
)
|
||||
|
||||
// Parameter just enforces a check on all outgoing data
|
||||
|
||||
@@ -7,11 +7,12 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/sharedtestvalues"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/sharedtestvalues"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
)
|
||||
|
||||
// Please supply your own keys here for due diligence testing
|
||||
@@ -693,22 +694,26 @@ func TestWsAuth(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
if !b.Websocket.IsEnabled() && !b.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip(exchange.WebsocketNotEnabled)
|
||||
t.Skip(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
b.WebsocketConn = &wshandler.WebsocketConnection{
|
||||
ExchangeName: b.Name,
|
||||
URL: b.Websocket.GetWebsocketURL(),
|
||||
Verbose: b.Verbose,
|
||||
ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
|
||||
ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
|
||||
}
|
||||
var err error
|
||||
var dialer websocket.Dialer
|
||||
b.WebsocketConn, _, err = dialer.Dial(b.Websocket.GetWebsocketURL(),
|
||||
http.Header{})
|
||||
err := b.WebsocketConn.Dial(&dialer, http.Header{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
|
||||
b.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
|
||||
go b.wsHandleIncomingData()
|
||||
defer b.WebsocketConn.Close()
|
||||
err = b.websocketSendAuth()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
timer := time.NewTimer(sharedtestvalues.WebsocketResponseDefaultTimeout)
|
||||
select {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package bitmex
|
||||
|
||||
import exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
import exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
|
||||
// RequestError allows for a general error capture from requests
|
||||
type RequestError struct {
|
||||
|
||||
@@ -4,19 +4,19 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -68,34 +68,21 @@ var (
|
||||
// WsConnector initiates a new websocket connection
|
||||
func (b *Bitmex) WsConnector() error {
|
||||
if !b.Websocket.IsEnabled() || !b.IsEnabled() {
|
||||
return errors.New(exchange.WebsocketNotEnabled)
|
||||
return errors.New(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
|
||||
var dialer websocket.Dialer
|
||||
var err error
|
||||
|
||||
if b.Websocket.GetProxyAddress() != "" {
|
||||
var proxy *url.URL
|
||||
proxy, err = url.Parse(b.Websocket.GetProxyAddress())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dialer.Proxy = http.ProxyURL(proxy)
|
||||
}
|
||||
|
||||
b.WebsocketConn, _, err = dialer.Dial(b.Websocket.GetWebsocketURL(), nil)
|
||||
err := b.WebsocketConn.Dial(&dialer, http.Header{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, p, err := b.WebsocketConn.ReadMessage()
|
||||
p, err := b.WebsocketConn.ReadMessage()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
b.Websocket.TrafficAlert <- struct{}{}
|
||||
var welcomeResp WebsocketWelcome
|
||||
err = common.JSONDecode(p, &welcomeResp)
|
||||
err = common.JSONDecode(p.Raw, &welcomeResp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -118,19 +105,6 @@ func (b *Bitmex) WsConnector() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Bitmex) wsReadData() (exchange.WebsocketResponse, error) {
|
||||
_, resp, err := b.WebsocketConn.ReadMessage()
|
||||
if err != nil {
|
||||
return exchange.WebsocketResponse{}, err
|
||||
}
|
||||
|
||||
b.Websocket.TrafficAlert <- struct{}{}
|
||||
|
||||
return exchange.WebsocketResponse{
|
||||
Raw: resp,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// wsHandleIncomingData services incoming data from the websocket connection
|
||||
func (b *Bitmex) wsHandleIncomingData() {
|
||||
b.Websocket.Wg.Add(1)
|
||||
@@ -145,12 +119,12 @@ func (b *Bitmex) wsHandleIncomingData() {
|
||||
return
|
||||
|
||||
default:
|
||||
resp, err := b.wsReadData()
|
||||
resp, err := b.WebsocketConn.ReadMessage()
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
|
||||
b.Websocket.TrafficAlert <- struct{}{}
|
||||
message := string(resp.Raw)
|
||||
if strings.Contains(message, "pong") {
|
||||
pongChan <- 1
|
||||
@@ -158,7 +132,7 @@ func (b *Bitmex) wsHandleIncomingData() {
|
||||
}
|
||||
|
||||
if strings.Contains(message, "ping") {
|
||||
err = b.wsSend("pong")
|
||||
err = b.WebsocketConn.SendMessage("pong")
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- err
|
||||
continue
|
||||
@@ -257,7 +231,7 @@ func (b *Bitmex) wsHandleIncomingData() {
|
||||
}
|
||||
|
||||
// TODO: update this to support multiple asset types
|
||||
b.Websocket.DataHandler <- exchange.TradeData{
|
||||
b.Websocket.DataHandler <- wshandler.TradeData{
|
||||
Timestamp: timestamp,
|
||||
Price: trade.Price,
|
||||
Amount: float64(trade.Size),
|
||||
@@ -407,7 +381,7 @@ func (b *Bitmex) processOrderbook(data []OrderBookL2, action string, currencyPai
|
||||
err)
|
||||
}
|
||||
snapshotloaded[currencyPair][assetType] = true
|
||||
b.Websocket.DataHandler <- exchange.WebsocketOrderbookUpdate{
|
||||
b.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
|
||||
Pair: currencyPair,
|
||||
Asset: assetType,
|
||||
Exchange: b.GetName(),
|
||||
@@ -442,7 +416,7 @@ func (b *Bitmex) processOrderbook(data []OrderBookL2, action string, currencyPai
|
||||
return err
|
||||
}
|
||||
|
||||
b.Websocket.DataHandler <- exchange.WebsocketOrderbookUpdate{
|
||||
b.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
|
||||
Pair: currencyPair,
|
||||
Asset: assetType,
|
||||
Exchange: b.GetName(),
|
||||
@@ -456,7 +430,7 @@ func (b *Bitmex) processOrderbook(data []OrderBookL2, action string, currencyPai
|
||||
func (b *Bitmex) GenerateDefaultSubscriptions() {
|
||||
contracts := b.GetEnabledPairs(asset.PerpetualContract)
|
||||
channels := []string{bitmexWSOrderbookL2, bitmexWSTrade}
|
||||
subscriptions := []exchange.WebsocketChannelSubscription{
|
||||
subscriptions := []wshandler.WebsocketChannelSubscription{
|
||||
{
|
||||
Channel: bitmexWSAnnouncement,
|
||||
},
|
||||
@@ -464,7 +438,7 @@ func (b *Bitmex) GenerateDefaultSubscriptions() {
|
||||
|
||||
for i := range channels {
|
||||
for j := range contracts {
|
||||
subscriptions = append(subscriptions, exchange.WebsocketChannelSubscription{
|
||||
subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
|
||||
Channel: fmt.Sprintf("%v:%v", channels[i], contracts[j].String()),
|
||||
Currency: contracts[j],
|
||||
})
|
||||
@@ -482,7 +456,7 @@ func (b *Bitmex) GenerateAuthenticatedSubscriptions() {
|
||||
channels := []string{bitmexWSExecution,
|
||||
bitmexWSPosition,
|
||||
}
|
||||
subscriptions := []exchange.WebsocketChannelSubscription{
|
||||
subscriptions := []wshandler.WebsocketChannelSubscription{
|
||||
{
|
||||
Channel: bitmexWSAffiliate,
|
||||
},
|
||||
@@ -504,7 +478,7 @@ func (b *Bitmex) GenerateAuthenticatedSubscriptions() {
|
||||
}
|
||||
for i := range channels {
|
||||
for j := range contracts {
|
||||
subscriptions = append(subscriptions, exchange.WebsocketChannelSubscription{
|
||||
subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
|
||||
Channel: fmt.Sprintf("%v:%v", channels[i], contracts[j].String()),
|
||||
Currency: contracts[j],
|
||||
})
|
||||
@@ -514,21 +488,21 @@ func (b *Bitmex) GenerateAuthenticatedSubscriptions() {
|
||||
}
|
||||
|
||||
// Subscribe subscribes to a websocket channel
|
||||
func (b *Bitmex) Subscribe(channelToSubscribe exchange.WebsocketChannelSubscription) error {
|
||||
func (b *Bitmex) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
|
||||
var subscriber WebsocketRequest
|
||||
subscriber.Command = "subscribe"
|
||||
subscriber.Arguments = append(subscriber.Arguments, channelToSubscribe.Channel)
|
||||
return b.wsSend(subscriber)
|
||||
return b.WebsocketConn.SendMessage(subscriber)
|
||||
}
|
||||
|
||||
// Unsubscribe sends a websocket message to stop receiving data from the channel
|
||||
func (b *Bitmex) Unsubscribe(channelToSubscribe exchange.WebsocketChannelSubscription) error {
|
||||
func (b *Bitmex) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
|
||||
var subscriber WebsocketRequest
|
||||
subscriber.Command = "unsubscribe"
|
||||
subscriber.Arguments = append(subscriber.Arguments,
|
||||
channelToSubscribe.Params["args"],
|
||||
channelToSubscribe.Channel+":"+channelToSubscribe.Currency.String())
|
||||
return b.wsSend(subscriber)
|
||||
return b.WebsocketConn.SendMessage(subscriber)
|
||||
}
|
||||
|
||||
// WebsocketSendAuth sends an authenticated subscription
|
||||
@@ -548,20 +522,10 @@ func (b *Bitmex) websocketSendAuth() error {
|
||||
sendAuth.Command = "authKeyExpires"
|
||||
sendAuth.Arguments = append(sendAuth.Arguments, b.API.Credentials.Key, timestamp,
|
||||
signature)
|
||||
err := b.wsSend(sendAuth)
|
||||
err := b.WebsocketConn.SendMessage(sendAuth)
|
||||
if err != nil {
|
||||
b.Websocket.SetCanUseAuthenticatedEndpoints(false)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WsSend sends data to the websocket server
|
||||
func (b *Bitmex) wsSend(data interface{}) error {
|
||||
b.wsRequestMtx.Lock()
|
||||
defer b.wsRequestMtx.Unlock()
|
||||
if b.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%v sending message to websocket %v", b.Name, data)
|
||||
}
|
||||
return b.WebsocketConn.WriteJSON(data)
|
||||
}
|
||||
|
||||
@@ -8,15 +8,16 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
// GetDefaultConfig returns a default exchange config
|
||||
@@ -112,11 +113,16 @@ func (b *Bitmex) SetDefaults() {
|
||||
b.API.Endpoints.URLDefault = bitmexAPIURL
|
||||
b.API.Endpoints.URL = b.API.Endpoints.URLDefault
|
||||
b.API.Endpoints.WebsocketURL = bitmexWSURL
|
||||
b.WebsocketInit()
|
||||
b.Websocket.Functionality = exchange.WebsocketTradeDataSupported |
|
||||
exchange.WebsocketOrderbookSupported |
|
||||
exchange.WebsocketSubscribeSupported |
|
||||
exchange.WebsocketUnsubscribeSupported
|
||||
b.Websocket = wshandler.New()
|
||||
b.Websocket.Functionality = wshandler.WebsocketTradeDataSupported |
|
||||
wshandler.WebsocketOrderbookSupported |
|
||||
wshandler.WebsocketSubscribeSupported |
|
||||
wshandler.WebsocketUnsubscribeSupported |
|
||||
wshandler.WebsocketAuthenticatedEndpointsSupported |
|
||||
wshandler.WebsocketAccountDataSupported |
|
||||
wshandler.WebsocketDeadMansSwitchSupported
|
||||
b.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
|
||||
b.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
|
||||
}
|
||||
|
||||
// Setup takes in the supplied exchange configuration details and sets params
|
||||
@@ -131,14 +137,28 @@ func (b *Bitmex) Setup(exch *config.ExchangeConfig) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return b.WebsocketSetup(b.WsConnector,
|
||||
err = b.Websocket.Setup(b.WsConnector,
|
||||
b.Subscribe,
|
||||
b.Unsubscribe,
|
||||
exch.Name,
|
||||
exch.Features.Enabled.Websocket,
|
||||
exch.Verbose,
|
||||
bitmexWSURL,
|
||||
exch.API.Endpoints.WebsocketURL)
|
||||
exch.API.Endpoints.WebsocketURL,
|
||||
exch.API.AuthenticatedWebsocketSupport)
|
||||
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 Bitmex go routine
|
||||
@@ -478,7 +498,7 @@ func (b *Bitmex) WithdrawFiatFundsToInternationalBank(withdrawRequest *exchange.
|
||||
}
|
||||
|
||||
// GetWebsocket returns a pointer to the exchange websocket
|
||||
func (b *Bitmex) GetWebsocket() (*exchange.Websocket, error) {
|
||||
func (b *Bitmex) GetWebsocket() (*wshandler.Websocket, error) {
|
||||
return b.Websocket, nil
|
||||
}
|
||||
|
||||
@@ -577,20 +597,20 @@ func (b *Bitmex) GetOrderHistory(getOrdersRequest *exchange.GetOrdersRequest) ([
|
||||
|
||||
// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle subscribing
|
||||
func (b *Bitmex) SubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
func (b *Bitmex) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
b.Websocket.SubscribeToChannels(channels)
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle unsubscribing
|
||||
func (b *Bitmex) UnsubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
b.Websocket.UnsubscribeToChannels(channels)
|
||||
func (b *Bitmex) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
b.Websocket.RemoveSubscribedChannels(channels)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetSubscriptions returns a copied list of subscriptions
|
||||
func (b *Bitmex) GetSubscriptions() ([]exchange.WebsocketChannelSubscription, error) {
|
||||
func (b *Bitmex) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
|
||||
return b.Websocket.GetSubscriptions(), nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# GoCryptoTrader package Bitstamp
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
|
||||
|
||||
[](https://travis-ci.org/thrasher-/gocryptotrader)
|
||||
[](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/bitstamp)
|
||||
[](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
|
||||
[](https://travis-ci.org/thrasher-corp/gocryptotrader)
|
||||
[](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/bitstamp)
|
||||
[](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-corp/gocryptotrader)
|
||||
|
||||
|
||||
This bitstamp package is part of the GoCryptoTrader codebase.
|
||||
@@ -27,7 +27,7 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader
|
||||
|
||||
### How to enable
|
||||
|
||||
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
+ [Enable via configuration](https://github.com/thrasher-corp/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
|
||||
+ Individual package example below:
|
||||
|
||||
@@ -128,12 +128,12 @@ When submitting a PR, please abide by our coding guidelines:
|
||||
|
||||
+ Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)).
|
||||
+ Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines.
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-corp/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Pull requests need to be based on and opened against the `master` branch.
|
||||
|
||||
## Donations
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
|
||||
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
|
||||
|
||||
|
||||
@@ -9,14 +9,13 @@ import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -59,8 +58,7 @@ const (
|
||||
type Bitstamp struct {
|
||||
exchange.Base
|
||||
Balance Balances
|
||||
WebsocketConn *websocket.Conn
|
||||
wsRequestMtx sync.Mutex
|
||||
WebsocketConn *wshandler.WebsocketConnection
|
||||
}
|
||||
|
||||
// GetFee returns an estimate of fee based on type of transaction
|
||||
|
||||
@@ -4,9 +4,9 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
)
|
||||
|
||||
// Please add your private keys and customerID for better tests
|
||||
|
||||
@@ -4,18 +4,17 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"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/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -25,26 +24,13 @@ const (
|
||||
// WsConnect connects to a websocket feed
|
||||
func (b *Bitstamp) WsConnect() error {
|
||||
if !b.Websocket.IsEnabled() || !b.IsEnabled() {
|
||||
return errors.New(exchange.WebsocketNotEnabled)
|
||||
return errors.New(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
|
||||
var dialer websocket.Dialer
|
||||
if b.Websocket.GetProxyAddress() != "" {
|
||||
proxy, err := url.Parse(b.Websocket.GetProxyAddress())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dialer.Proxy = http.ProxyURL(proxy)
|
||||
}
|
||||
|
||||
var err error
|
||||
b.WebsocketConn, _, err = dialer.Dial(b.Websocket.GetWebsocketURL(), http.Header{})
|
||||
err := b.WebsocketConn.Dial(&dialer, http.Header{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s Unable to connect to Websocket. Error: %s",
|
||||
b.Name,
|
||||
err)
|
||||
return err
|
||||
}
|
||||
|
||||
if b.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%s Connected to Websocket.\n", b.GetName())
|
||||
}
|
||||
@@ -60,22 +46,6 @@ func (b *Bitstamp) WsConnect() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// WsReadData reads data coming from bitstamp websocket connection
|
||||
func (b *Bitstamp) WsReadData() (exchange.WebsocketResponse, error) {
|
||||
msgType, resp, err := b.WebsocketConn.ReadMessage()
|
||||
|
||||
if err != nil {
|
||||
return exchange.WebsocketResponse{}, err
|
||||
}
|
||||
|
||||
if b.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%s websocket raw response: %s", b.GetName(), resp)
|
||||
}
|
||||
|
||||
b.Websocket.TrafficAlert <- struct{}{}
|
||||
return exchange.WebsocketResponse{Type: msgType, Raw: resp}, nil
|
||||
}
|
||||
|
||||
// WsHandleData handles websocket data from WsReadData
|
||||
func (b *Bitstamp) WsHandleData() {
|
||||
b.Websocket.Wg.Add(1)
|
||||
@@ -90,12 +60,12 @@ func (b *Bitstamp) WsHandleData() {
|
||||
return
|
||||
|
||||
default:
|
||||
resp, err := b.WsReadData()
|
||||
resp, err := b.WebsocketConn.ReadMessage()
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
|
||||
b.Websocket.TrafficAlert <- struct{}{}
|
||||
wsResponse := websocketResponse{}
|
||||
err = common.JSONDecode(resp.Raw, &wsResponse)
|
||||
if err != nil {
|
||||
@@ -139,7 +109,7 @@ func (b *Bitstamp) WsHandleData() {
|
||||
currencyPair := strings.Split(wsResponse.Channel, "_")
|
||||
p := currency.NewPairFromString(strings.ToUpper(currencyPair[2]))
|
||||
|
||||
b.Websocket.DataHandler <- exchange.TradeData{
|
||||
b.Websocket.DataHandler <- wshandler.TradeData{
|
||||
Price: wsTradeTemp.Data.Price,
|
||||
Amount: wsTradeTemp.Data.Amount,
|
||||
CurrencyPair: p,
|
||||
@@ -154,10 +124,10 @@ func (b *Bitstamp) WsHandleData() {
|
||||
func (b *Bitstamp) generateDefaultSubscriptions() {
|
||||
var channels = []string{"live_trades_", "diff_order_book_"}
|
||||
enabledCurrencies := b.GetEnabledPairs(asset.Spot)
|
||||
var subscriptions []exchange.WebsocketChannelSubscription
|
||||
var subscriptions []wshandler.WebsocketChannelSubscription
|
||||
for i := range channels {
|
||||
for j := range enabledCurrencies {
|
||||
subscriptions = append(subscriptions, exchange.WebsocketChannelSubscription{
|
||||
subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
|
||||
Channel: fmt.Sprintf("%v%v", channels[i], enabledCurrencies[j].Lower().String()),
|
||||
})
|
||||
}
|
||||
@@ -166,31 +136,25 @@ func (b *Bitstamp) generateDefaultSubscriptions() {
|
||||
}
|
||||
|
||||
// Subscribe sends a websocket message to receive data from the channel
|
||||
func (b *Bitstamp) Subscribe(channelToSubscribe exchange.WebsocketChannelSubscription) error {
|
||||
b.wsRequestMtx.Lock()
|
||||
defer b.wsRequestMtx.Unlock()
|
||||
|
||||
func (b *Bitstamp) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
|
||||
req := websocketEventRequest{
|
||||
Event: "bts:subscribe",
|
||||
Data: websocketData{
|
||||
Channel: channelToSubscribe.Channel,
|
||||
},
|
||||
}
|
||||
return b.WebsocketConn.WriteJSON(req)
|
||||
return b.WebsocketConn.SendMessage(req)
|
||||
}
|
||||
|
||||
// Unsubscribe sends a websocket message to stop receiving data from the channel
|
||||
func (b *Bitstamp) Unsubscribe(channelToSubscribe exchange.WebsocketChannelSubscription) error {
|
||||
b.wsRequestMtx.Lock()
|
||||
defer b.wsRequestMtx.Unlock()
|
||||
|
||||
func (b *Bitstamp) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
|
||||
req := websocketEventRequest{
|
||||
Event: "bts:unsubscribe",
|
||||
Data: websocketData{
|
||||
Channel: channelToSubscribe.Channel,
|
||||
},
|
||||
}
|
||||
return b.WebsocketConn.WriteJSON(req)
|
||||
return b.WebsocketConn.SendMessage(req)
|
||||
}
|
||||
|
||||
func (b *Bitstamp) wsUpdateOrderbook(ob websocketOrderBook, p currency.Pair, assetType asset.Item) error {
|
||||
@@ -241,7 +205,7 @@ func (b *Bitstamp) wsUpdateOrderbook(ob websocketOrderBook, p currency.Pair, ass
|
||||
return err
|
||||
}
|
||||
|
||||
b.Websocket.DataHandler <- exchange.WebsocketOrderbookUpdate{
|
||||
b.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
|
||||
Pair: p,
|
||||
Asset: assetType,
|
||||
Exchange: b.GetName(),
|
||||
@@ -285,7 +249,7 @@ func (b *Bitstamp) seedOrderBook() error {
|
||||
return err
|
||||
}
|
||||
|
||||
b.Websocket.DataHandler <- exchange.WebsocketOrderbookUpdate{
|
||||
b.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
|
||||
Pair: p[x],
|
||||
Asset: asset.Spot,
|
||||
Exchange: b.GetName(),
|
||||
|
||||
@@ -8,15 +8,16 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
// GetDefaultConfig returns a default exchange config
|
||||
@@ -88,11 +89,13 @@ func (b *Bitstamp) SetDefaults() {
|
||||
b.API.Endpoints.URLDefault = bitstampAPIURL
|
||||
b.API.Endpoints.URL = b.API.Endpoints.URLDefault
|
||||
b.API.Endpoints.WebsocketURL = bitstampWSURL
|
||||
b.WebsocketInit()
|
||||
b.Websocket.Functionality = exchange.WebsocketOrderbookSupported |
|
||||
exchange.WebsocketTradeDataSupported |
|
||||
exchange.WebsocketSubscribeSupported |
|
||||
exchange.WebsocketUnsubscribeSupported
|
||||
b.Websocket = wshandler.New()
|
||||
b.Websocket.Functionality = wshandler.WebsocketOrderbookSupported |
|
||||
wshandler.WebsocketTradeDataSupported |
|
||||
wshandler.WebsocketSubscribeSupported |
|
||||
wshandler.WebsocketUnsubscribeSupported
|
||||
b.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
|
||||
b.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
|
||||
}
|
||||
|
||||
// Setup sets configuration values to bitstamp
|
||||
@@ -107,14 +110,28 @@ func (b *Bitstamp) Setup(exch *config.ExchangeConfig) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return b.WebsocketSetup(b.WsConnect,
|
||||
err = b.Websocket.Setup(b.WsConnect,
|
||||
b.Subscribe,
|
||||
b.Unsubscribe,
|
||||
exch.Name,
|
||||
exch.Features.Enabled.Websocket,
|
||||
exch.Verbose,
|
||||
bitstampWSURL,
|
||||
exch.API.Endpoints.WebsocketURL)
|
||||
exch.API.Endpoints.WebsocketURL,
|
||||
exch.API.AuthenticatedWebsocketSupport)
|
||||
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 Bitstamp go routine
|
||||
@@ -427,7 +444,7 @@ func (b *Bitstamp) WithdrawFiatFundsToInternationalBank(withdrawRequest *exchang
|
||||
}
|
||||
|
||||
// GetWebsocket returns a pointer to the exchange websocket
|
||||
func (b *Bitstamp) GetWebsocket() (*exchange.Websocket, error) {
|
||||
func (b *Bitstamp) GetWebsocket() (*wshandler.Websocket, error) {
|
||||
return b.Websocket, nil
|
||||
}
|
||||
|
||||
@@ -524,20 +541,20 @@ func (b *Bitstamp) GetOrderHistory(getOrdersRequest *exchange.GetOrdersRequest)
|
||||
|
||||
// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle subscribing
|
||||
func (b *Bitstamp) SubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
func (b *Bitstamp) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
b.Websocket.SubscribeToChannels(channels)
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle unsubscribing
|
||||
func (b *Bitstamp) UnsubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
b.Websocket.UnsubscribeToChannels(channels)
|
||||
func (b *Bitstamp) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
b.Websocket.RemoveSubscribedChannels(channels)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetSubscriptions returns a copied list of subscriptions
|
||||
func (b *Bitstamp) GetSubscriptions() ([]exchange.WebsocketChannelSubscription, error) {
|
||||
func (b *Bitstamp) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
|
||||
return b.Websocket.GetSubscriptions(), nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# GoCryptoTrader package Bittrex
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
|
||||
|
||||
[](https://travis-ci.org/thrasher-/gocryptotrader)
|
||||
[](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/bittrex)
|
||||
[](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
|
||||
[](https://travis-ci.org/thrasher-corp/gocryptotrader)
|
||||
[](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/bittrex)
|
||||
[](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-corp/gocryptotrader)
|
||||
|
||||
|
||||
This bittrex package is part of the GoCryptoTrader codebase.
|
||||
@@ -26,7 +26,7 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader
|
||||
|
||||
### How to enable
|
||||
|
||||
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
+ [Enable via configuration](https://github.com/thrasher-corp/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
|
||||
+ Individual package example below:
|
||||
|
||||
@@ -120,12 +120,12 @@ When submitting a PR, please abide by our coding guidelines:
|
||||
|
||||
+ Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)).
|
||||
+ Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines.
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-corp/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Pull requests need to be based on and opened against the `master` branch.
|
||||
|
||||
## Donations
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
|
||||
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -3,10 +3,10 @@ package bittrex
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
)
|
||||
|
||||
// Please supply you own test keys here to run better tests.
|
||||
|
||||
@@ -7,15 +7,16 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
// GetDefaultConfig returns a default exchange config
|
||||
@@ -394,7 +395,7 @@ func (b *Bittrex) WithdrawFiatFundsToInternationalBank(withdrawRequest *exchange
|
||||
}
|
||||
|
||||
// GetWebsocket returns a pointer to the exchange websocket
|
||||
func (b *Bittrex) GetWebsocket() (*exchange.Websocket, error) {
|
||||
func (b *Bittrex) GetWebsocket() (*wshandler.Websocket, error) {
|
||||
return nil, common.ErrNotYetImplemented
|
||||
}
|
||||
|
||||
@@ -498,18 +499,18 @@ func (b *Bittrex) GetOrderHistory(getOrdersRequest *exchange.GetOrdersRequest) (
|
||||
|
||||
// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle subscribing
|
||||
func (b *Bittrex) SubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
func (b *Bittrex) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle unsubscribing
|
||||
func (b *Bittrex) UnsubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
func (b *Bittrex) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// GetSubscriptions returns a copied list of subscriptions
|
||||
func (b *Bittrex) GetSubscriptions() ([]exchange.WebsocketChannelSubscription, error) {
|
||||
func (b *Bittrex) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
|
||||
return nil, common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# GoCryptoTrader package Btcmarkets
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
|
||||
|
||||
[](https://travis-ci.org/thrasher-/gocryptotrader)
|
||||
[](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/btcmarkets)
|
||||
[](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
|
||||
[](https://travis-ci.org/thrasher-corp/gocryptotrader)
|
||||
[](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/btcmarkets)
|
||||
[](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-corp/gocryptotrader)
|
||||
|
||||
|
||||
This btcmarkets package is part of the GoCryptoTrader codebase.
|
||||
@@ -26,7 +26,7 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader
|
||||
|
||||
### How to enable
|
||||
|
||||
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
+ [Enable via configuration](https://github.com/thrasher-corp/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
|
||||
+ Individual package example below:
|
||||
|
||||
@@ -120,12 +120,12 @@ When submitting a PR, please abide by our coding guidelines:
|
||||
|
||||
+ Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)).
|
||||
+ Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines.
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-corp/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Pull requests need to be based on and opened against the `master` branch.
|
||||
|
||||
## Donations
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
|
||||
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
|
||||
|
||||
|
||||
@@ -8,11 +8,11 @@ import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -4,10 +4,10 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
)
|
||||
|
||||
var b BTCMarkets
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package btcmarkets
|
||||
|
||||
import "github.com/thrasher-/gocryptotrader/currency"
|
||||
import "github.com/thrasher-corp/gocryptotrader/currency"
|
||||
|
||||
// Response is the genralized response type
|
||||
type Response struct {
|
||||
|
||||
@@ -8,15 +8,16 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
// GetDefaultConfig returns a default exchange config
|
||||
@@ -431,7 +432,7 @@ func (b *BTCMarkets) WithdrawFiatFundsToInternationalBank(withdrawRequest *excha
|
||||
}
|
||||
|
||||
// GetWebsocket returns a pointer to the exchange websocket
|
||||
func (b *BTCMarkets) GetWebsocket() (*exchange.Websocket, error) {
|
||||
func (b *BTCMarkets) GetWebsocket() (*wshandler.Websocket, error) {
|
||||
return nil, common.ErrNotYetImplemented
|
||||
}
|
||||
|
||||
@@ -569,18 +570,18 @@ func (b *BTCMarkets) GetOrderHistory(getOrdersRequest *exchange.GetOrdersRequest
|
||||
|
||||
// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle subscribing
|
||||
func (b *BTCMarkets) SubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
func (b *BTCMarkets) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle unsubscribing
|
||||
func (b *BTCMarkets) UnsubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
func (b *BTCMarkets) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// GetSubscriptions returns a copied list of subscriptions
|
||||
func (b *BTCMarkets) GetSubscriptions() ([]exchange.WebsocketChannelSubscription, error) {
|
||||
func (b *BTCMarkets) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
|
||||
return nil, common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
# GoCryptoTrader Btse Exchange Wrapper
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
|
||||
An exchange interface wrapper for the GoCryptoTrader application.
|
||||
|
||||
|
||||
@@ -6,21 +6,19 @@ import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
// BTSE is the overarching type across this package
|
||||
type BTSE struct {
|
||||
exchange.Base
|
||||
WebsocketConn *websocket.Conn
|
||||
wsRequestMtx sync.Mutex
|
||||
WebsocketConn *wshandler.WebsocketConnection
|
||||
}
|
||||
|
||||
const (
|
||||
|
||||
@@ -3,10 +3,10 @@ package btse
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
)
|
||||
|
||||
// Please supply your own keys here to do better tests
|
||||
|
||||
@@ -2,21 +2,19 @@ package btse
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -26,27 +24,12 @@ const (
|
||||
// WsConnect connects the websocket client
|
||||
func (b *BTSE) WsConnect() error {
|
||||
if !b.Websocket.IsEnabled() || !b.IsEnabled() {
|
||||
return errors.New(exchange.WebsocketNotEnabled)
|
||||
return errors.New(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
|
||||
var dialer websocket.Dialer
|
||||
|
||||
if b.Websocket.GetProxyAddress() != "" {
|
||||
proxy, err := url.Parse(b.Websocket.GetProxyAddress())
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s websocket error - proxy address %s",
|
||||
b.Name, err)
|
||||
}
|
||||
|
||||
dialer.Proxy = http.ProxyURL(proxy)
|
||||
}
|
||||
|
||||
var err error
|
||||
b.WebsocketConn, _, err = dialer.Dial(b.Websocket.GetWebsocketURL(),
|
||||
http.Header{})
|
||||
err := b.WebsocketConn.Dial(&dialer, http.Header{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s websocket error - unable to connect %s",
|
||||
b.Name, err)
|
||||
return err
|
||||
}
|
||||
|
||||
go b.WsHandleData()
|
||||
@@ -55,17 +38,6 @@ func (b *BTSE) WsConnect() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// WsReadData reads data from the websocket connection
|
||||
func (b *BTSE) WsReadData() (exchange.WebsocketResponse, error) {
|
||||
_, resp, err := b.WebsocketConn.ReadMessage()
|
||||
if err != nil {
|
||||
return exchange.WebsocketResponse{}, err
|
||||
}
|
||||
|
||||
b.Websocket.TrafficAlert <- struct{}{}
|
||||
return exchange.WebsocketResponse{Raw: resp}, nil
|
||||
}
|
||||
|
||||
// WsHandleData handles read data from websocket connection
|
||||
func (b *BTSE) WsHandleData() {
|
||||
b.Websocket.Wg.Add(1)
|
||||
@@ -80,11 +52,12 @@ func (b *BTSE) WsHandleData() {
|
||||
return
|
||||
|
||||
default:
|
||||
resp, err := b.WsReadData()
|
||||
resp, err := b.WebsocketConn.ReadMessage()
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
b.Websocket.TrafficAlert <- struct{}{}
|
||||
|
||||
type MsgType struct {
|
||||
Type string `json:"type"`
|
||||
@@ -120,7 +93,7 @@ func (b *BTSE) WsHandleData() {
|
||||
continue
|
||||
}
|
||||
|
||||
b.Websocket.DataHandler <- exchange.TickerData{
|
||||
b.Websocket.DataHandler <- wshandler.TickerData{
|
||||
Timestamp: time.Now(),
|
||||
Pair: currency.NewPairDelimiter(t.ProductID, "-"),
|
||||
AssetType: asset.Spot,
|
||||
@@ -194,7 +167,7 @@ func (b *BTSE) wsProcessSnapshot(snapshot *websocketOrderbookSnapshot) error {
|
||||
return err
|
||||
}
|
||||
|
||||
b.Websocket.DataHandler <- exchange.WebsocketOrderbookUpdate{
|
||||
b.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
|
||||
Pair: p,
|
||||
Asset: asset.Spot,
|
||||
Exchange: b.GetName(),
|
||||
@@ -207,10 +180,10 @@ func (b *BTSE) wsProcessSnapshot(snapshot *websocketOrderbookSnapshot) error {
|
||||
func (b *BTSE) GenerateDefaultSubscriptions() {
|
||||
var channels = []string{"snapshot", "ticker"}
|
||||
enabledCurrencies := b.GetEnabledPairs(asset.Spot)
|
||||
var subscriptions []exchange.WebsocketChannelSubscription
|
||||
var subscriptions []wshandler.WebsocketChannelSubscription
|
||||
for i := range channels {
|
||||
for j := range enabledCurrencies {
|
||||
subscriptions = append(subscriptions, exchange.WebsocketChannelSubscription{
|
||||
subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
|
||||
Channel: channels[i],
|
||||
Currency: enabledCurrencies[j],
|
||||
})
|
||||
@@ -220,7 +193,7 @@ func (b *BTSE) GenerateDefaultSubscriptions() {
|
||||
}
|
||||
|
||||
// Subscribe sends a websocket message to receive data from the channel
|
||||
func (b *BTSE) Subscribe(channelToSubscribe exchange.WebsocketChannelSubscription) error {
|
||||
func (b *BTSE) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
|
||||
subscribe := websocketSubscribe{
|
||||
Type: "subscribe",
|
||||
Channels: []websocketChannel{
|
||||
@@ -230,11 +203,11 @@ func (b *BTSE) Subscribe(channelToSubscribe exchange.WebsocketChannelSubscriptio
|
||||
},
|
||||
},
|
||||
}
|
||||
return b.wsSend(subscribe)
|
||||
return b.WebsocketConn.SendMessage(subscribe)
|
||||
}
|
||||
|
||||
// Unsubscribe sends a websocket message to stop receiving data from the channel
|
||||
func (b *BTSE) Unsubscribe(channelToSubscribe exchange.WebsocketChannelSubscription) error {
|
||||
func (b *BTSE) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
|
||||
subscribe := websocketSubscribe{
|
||||
Type: "unsubscribe",
|
||||
Channels: []websocketChannel{
|
||||
@@ -244,19 +217,5 @@ func (b *BTSE) Unsubscribe(channelToSubscribe exchange.WebsocketChannelSubscript
|
||||
},
|
||||
},
|
||||
}
|
||||
return b.wsSend(subscribe)
|
||||
}
|
||||
|
||||
// WsSend sends data to the websocket server
|
||||
func (b *BTSE) wsSend(data interface{}) error {
|
||||
b.wsRequestMtx.Lock()
|
||||
defer b.wsRequestMtx.Unlock()
|
||||
if b.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%v sending message to websocket %v", b.Name, data)
|
||||
}
|
||||
json, err := common.JSONEncode(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return b.WebsocketConn.WriteMessage(websocket.TextMessage, json)
|
||||
return b.WebsocketConn.SendMessage(subscribe)
|
||||
}
|
||||
|
||||
@@ -7,15 +7,16 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
// GetDefaultConfig returns a default exchange config
|
||||
@@ -85,11 +86,14 @@ func (b *BTSE) SetDefaults() {
|
||||
|
||||
b.API.Endpoints.URLDefault = btseAPIURL
|
||||
b.API.Endpoints.URL = b.API.Endpoints.URLDefault
|
||||
b.WebsocketInit()
|
||||
b.Websocket.Functionality = exchange.WebsocketOrderbookSupported |
|
||||
exchange.WebsocketTickerSupported |
|
||||
exchange.WebsocketSubscribeSupported |
|
||||
exchange.WebsocketUnsubscribeSupported
|
||||
b.Websocket = wshandler.New()
|
||||
b.Websocket.Functionality = wshandler.WebsocketOrderbookSupported |
|
||||
wshandler.WebsocketTickerSupported |
|
||||
wshandler.WebsocketSubscribeSupported |
|
||||
wshandler.WebsocketUnsubscribeSupported
|
||||
b.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
|
||||
b.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
|
||||
|
||||
}
|
||||
|
||||
// Setup takes in the supplied exchange configuration details and sets params
|
||||
@@ -104,14 +108,28 @@ func (b *BTSE) Setup(exch *config.ExchangeConfig) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return b.WebsocketSetup(b.WsConnect,
|
||||
err = b.Websocket.Setup(b.WsConnect,
|
||||
b.Subscribe,
|
||||
b.Unsubscribe,
|
||||
exch.Name,
|
||||
exch.Features.Enabled.Websocket,
|
||||
exch.Verbose,
|
||||
btseWebsocket,
|
||||
exch.API.Endpoints.WebsocketURL)
|
||||
exch.API.Endpoints.WebsocketURL,
|
||||
exch.API.AuthenticatedWebsocketSupport)
|
||||
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 BTSE go routine
|
||||
@@ -411,7 +429,7 @@ func (b *BTSE) WithdrawFiatFundsToInternationalBank(withdrawRequest *exchange.Fi
|
||||
}
|
||||
|
||||
// GetWebsocket returns a pointer to the exchange websocket
|
||||
func (b *BTSE) GetWebsocket() (*exchange.Websocket, error) {
|
||||
func (b *BTSE) GetWebsocket() (*wshandler.Websocket, error) {
|
||||
return b.Websocket, nil
|
||||
}
|
||||
|
||||
@@ -488,20 +506,20 @@ func (b *BTSE) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
|
||||
|
||||
// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle subscribing
|
||||
func (b *BTSE) SubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
func (b *BTSE) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
b.Websocket.SubscribeToChannels(channels)
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle unsubscribing
|
||||
func (b *BTSE) UnsubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
b.Websocket.UnsubscribeToChannels(channels)
|
||||
func (b *BTSE) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
b.Websocket.RemoveSubscribedChannels(channels)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetSubscriptions returns a copied list of subscriptions
|
||||
func (b *BTSE) GetSubscriptions() ([]exchange.WebsocketChannelSubscription, error) {
|
||||
func (b *BTSE) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
|
||||
return b.Websocket.GetSubscriptions(), nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# GoCryptoTrader package Coinbasepro
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
|
||||
|
||||
[](https://travis-ci.org/thrasher-/gocryptotrader)
|
||||
[](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/coinbasepro)
|
||||
[](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
|
||||
[](https://travis-ci.org/thrasher-corp/gocryptotrader)
|
||||
[](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/coinbasepro)
|
||||
[](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-corp/gocryptotrader)
|
||||
|
||||
|
||||
This coinbasepro package is part of the GoCryptoTrader codebase.
|
||||
@@ -27,7 +27,7 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader
|
||||
|
||||
### How to enable
|
||||
|
||||
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
+ [Enable via configuration](https://github.com/thrasher-corp/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
|
||||
+ Individual package example below:
|
||||
|
||||
@@ -128,12 +128,12 @@ When submitting a PR, please abide by our coding guidelines:
|
||||
|
||||
+ Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)).
|
||||
+ Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines.
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-corp/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Pull requests need to be based on and opened against the `master` branch.
|
||||
|
||||
## Donations
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
|
||||
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
|
||||
|
||||
|
||||
@@ -8,14 +8,13 @@ import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -58,8 +57,7 @@ const (
|
||||
// CoinbasePro is the overarching type across the coinbasepro package
|
||||
type CoinbasePro struct {
|
||||
exchange.Base
|
||||
WebsocketConn *websocket.Conn
|
||||
wsRequestMtx sync.Mutex
|
||||
WebsocketConn *wshandler.WebsocketConnection
|
||||
}
|
||||
|
||||
// GetProducts returns supported currency pairs on the exchange with specific
|
||||
|
||||
@@ -6,10 +6,11 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/sharedtestvalues"
|
||||
"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/sharedtestvalues"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
)
|
||||
|
||||
var c CoinbasePro
|
||||
@@ -594,20 +595,24 @@ func TestWsAuth(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
if !c.Websocket.IsEnabled() && !c.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip(exchange.WebsocketNotEnabled)
|
||||
t.Skip(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
c.WebsocketConn = &wshandler.WebsocketConnection{
|
||||
ExchangeName: c.Name,
|
||||
URL: c.Websocket.GetWebsocketURL(),
|
||||
Verbose: c.Verbose,
|
||||
ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
|
||||
ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
|
||||
}
|
||||
var err error
|
||||
var dialer websocket.Dialer
|
||||
c.WebsocketConn, _, err = dialer.Dial(c.Websocket.GetWebsocketURL(),
|
||||
http.Header{})
|
||||
err := c.WebsocketConn.Dial(&dialer, http.Header{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
c.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
|
||||
c.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
|
||||
go c.WsHandleData()
|
||||
defer c.WebsocketConn.Close()
|
||||
err = c.Subscribe(exchange.WebsocketChannelSubscription{
|
||||
err = c.Subscribe(wshandler.WebsocketChannelSubscription{
|
||||
Channel: "user",
|
||||
Currency: currency.NewPairFromString("BTC-USD"),
|
||||
})
|
||||
|
||||
@@ -4,18 +4,17 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -25,27 +24,12 @@ const (
|
||||
// WsConnect initiates a websocket connection
|
||||
func (c *CoinbasePro) WsConnect() error {
|
||||
if !c.Websocket.IsEnabled() || !c.IsEnabled() {
|
||||
return errors.New(exchange.WebsocketNotEnabled)
|
||||
return errors.New(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
|
||||
var dialer websocket.Dialer
|
||||
|
||||
if c.Websocket.GetProxyAddress() != "" {
|
||||
proxy, err := url.Parse(c.Websocket.GetProxyAddress())
|
||||
if err != nil {
|
||||
return fmt.Errorf("coinbasepro_websocket.go error - proxy address %s",
|
||||
err)
|
||||
}
|
||||
|
||||
dialer.Proxy = http.ProxyURL(proxy)
|
||||
}
|
||||
|
||||
var err error
|
||||
c.WebsocketConn, _, err = dialer.Dial(c.Websocket.GetWebsocketURL(),
|
||||
http.Header{})
|
||||
err := c.WebsocketConn.Dial(&dialer, http.Header{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("coinbasepro_websocket.go error - unable to connect to websocket %s",
|
||||
err)
|
||||
return err
|
||||
}
|
||||
|
||||
c.GenerateDefaultSubscriptions()
|
||||
@@ -54,16 +38,6 @@ func (c *CoinbasePro) WsConnect() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// WsReadData reads data from the websocket connection
|
||||
func (c *CoinbasePro) WsReadData() (exchange.WebsocketResponse, error) {
|
||||
_, resp, err := c.WebsocketConn.ReadMessage()
|
||||
if err != nil {
|
||||
return exchange.WebsocketResponse{}, err
|
||||
}
|
||||
c.Websocket.TrafficAlert <- struct{}{}
|
||||
return exchange.WebsocketResponse{Raw: resp}, nil
|
||||
}
|
||||
|
||||
// WsHandleData handles read data from websocket connection
|
||||
func (c *CoinbasePro) WsHandleData() {
|
||||
c.Websocket.Wg.Add(1)
|
||||
@@ -77,11 +51,13 @@ func (c *CoinbasePro) WsHandleData() {
|
||||
case <-c.Websocket.ShutdownC:
|
||||
return
|
||||
default:
|
||||
resp, err := c.WsReadData()
|
||||
resp, err := c.WebsocketConn.ReadMessage()
|
||||
if err != nil {
|
||||
c.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
c.Websocket.TrafficAlert <- struct{}{}
|
||||
|
||||
type MsgType struct {
|
||||
Type string `json:"type"`
|
||||
Sequence int64 `json:"sequence"`
|
||||
@@ -111,7 +87,7 @@ func (c *CoinbasePro) WsHandleData() {
|
||||
continue
|
||||
}
|
||||
|
||||
c.Websocket.DataHandler <- exchange.TickerData{
|
||||
c.Websocket.DataHandler <- wshandler.TickerData{
|
||||
Timestamp: ticker.Time,
|
||||
Pair: currency.NewPairFromString(ticker.ProductID),
|
||||
AssetType: asset.Spot,
|
||||
@@ -243,7 +219,7 @@ func (c *CoinbasePro) ProcessSnapshot(snapshot *WebsocketOrderbookSnapshot) erro
|
||||
return err
|
||||
}
|
||||
|
||||
c.Websocket.DataHandler <- exchange.WebsocketOrderbookUpdate{
|
||||
c.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
|
||||
Pair: p,
|
||||
Asset: asset.Spot,
|
||||
Exchange: c.GetName(),
|
||||
@@ -278,7 +254,7 @@ func (c *CoinbasePro) ProcessUpdate(update WebsocketL2Update) error {
|
||||
return err
|
||||
}
|
||||
|
||||
c.Websocket.DataHandler <- exchange.WebsocketOrderbookUpdate{
|
||||
c.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
|
||||
Pair: p,
|
||||
Asset: asset.Spot,
|
||||
Exchange: c.GetName(),
|
||||
@@ -291,14 +267,14 @@ func (c *CoinbasePro) ProcessUpdate(update WebsocketL2Update) error {
|
||||
func (c *CoinbasePro) GenerateDefaultSubscriptions() {
|
||||
var channels = []string{"heartbeat", "level2", "ticker", "user"}
|
||||
enabledCurrencies := c.GetEnabledPairs(asset.Spot)
|
||||
var subscriptions []exchange.WebsocketChannelSubscription
|
||||
var subscriptions []wshandler.WebsocketChannelSubscription
|
||||
for i := range channels {
|
||||
if (channels[i] == "user" || channels[i] == "full") && !c.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
|
||||
continue
|
||||
}
|
||||
for j := range enabledCurrencies {
|
||||
enabledCurrencies[j].Delimiter = "-"
|
||||
subscriptions = append(subscriptions, exchange.WebsocketChannelSubscription{
|
||||
subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
|
||||
Channel: channels[i],
|
||||
Currency: enabledCurrencies[j],
|
||||
})
|
||||
@@ -308,7 +284,7 @@ func (c *CoinbasePro) GenerateDefaultSubscriptions() {
|
||||
}
|
||||
|
||||
// Subscribe sends a websocket message to receive data from the channel
|
||||
func (c *CoinbasePro) Subscribe(channelToSubscribe exchange.WebsocketChannelSubscription) error {
|
||||
func (c *CoinbasePro) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
|
||||
subscribe := WebsocketSubscribe{
|
||||
Type: "subscribe",
|
||||
Channels: []WsChannels{
|
||||
@@ -330,11 +306,11 @@ func (c *CoinbasePro) Subscribe(channelToSubscribe exchange.WebsocketChannelSubs
|
||||
subscribe.Passphrase = c.API.Credentials.ClientID
|
||||
subscribe.Timestamp = n
|
||||
}
|
||||
return c.wsSend(subscribe)
|
||||
return c.WebsocketConn.SendMessage(subscribe)
|
||||
}
|
||||
|
||||
// Unsubscribe sends a websocket message to stop receiving data from the channel
|
||||
func (c *CoinbasePro) Unsubscribe(channelToSubscribe exchange.WebsocketChannelSubscription) error {
|
||||
func (c *CoinbasePro) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
|
||||
subscribe := WebsocketSubscribe{
|
||||
Type: "unsubscribe",
|
||||
Channels: []WsChannels{
|
||||
@@ -346,19 +322,5 @@ func (c *CoinbasePro) Unsubscribe(channelToSubscribe exchange.WebsocketChannelSu
|
||||
},
|
||||
},
|
||||
}
|
||||
return c.wsSend(subscribe)
|
||||
}
|
||||
|
||||
// WsSend sends data to the websocket server
|
||||
func (c *CoinbasePro) wsSend(data interface{}) error {
|
||||
c.wsRequestMtx.Lock()
|
||||
defer c.wsRequestMtx.Unlock()
|
||||
if c.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%v sending message to websocket %v", c.Name, data)
|
||||
}
|
||||
json, err := common.JSONEncode(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.WebsocketConn.WriteMessage(websocket.TextMessage, json)
|
||||
return c.WebsocketConn.SendMessage(subscribe)
|
||||
}
|
||||
|
||||
@@ -7,15 +7,16 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
// GetDefaultConfig returns a default exchange config
|
||||
@@ -89,11 +90,15 @@ func (c *CoinbasePro) SetDefaults() {
|
||||
c.API.Endpoints.URLDefault = coinbaseproAPIURL
|
||||
c.API.Endpoints.URL = c.API.Endpoints.URLDefault
|
||||
c.API.Endpoints.WebsocketURL = coinbaseproWebsocketURL
|
||||
c.WebsocketInit()
|
||||
c.Websocket.Functionality = exchange.WebsocketTickerSupported |
|
||||
exchange.WebsocketOrderbookSupported |
|
||||
exchange.WebsocketSubscribeSupported |
|
||||
exchange.WebsocketUnsubscribeSupported
|
||||
c.Websocket = wshandler.New()
|
||||
c.Websocket.Functionality = wshandler.WebsocketTickerSupported |
|
||||
wshandler.WebsocketOrderbookSupported |
|
||||
wshandler.WebsocketSubscribeSupported |
|
||||
wshandler.WebsocketUnsubscribeSupported |
|
||||
wshandler.WebsocketAuthenticatedEndpointsSupported |
|
||||
wshandler.WebsocketSequenceNumberSupported
|
||||
c.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
|
||||
c.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
|
||||
}
|
||||
|
||||
// Setup initialises the exchange parameters with the current configuration
|
||||
@@ -108,14 +113,28 @@ func (c *CoinbasePro) Setup(exch *config.ExchangeConfig) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.WebsocketSetup(c.WsConnect,
|
||||
err = c.Websocket.Setup(c.WsConnect,
|
||||
c.Subscribe,
|
||||
c.Unsubscribe,
|
||||
exch.Name,
|
||||
exch.Features.Enabled.Websocket,
|
||||
exch.Verbose,
|
||||
coinbaseproWebsocketURL,
|
||||
exch.API.Endpoints.WebsocketURL)
|
||||
exch.API.Endpoints.WebsocketURL,
|
||||
exch.API.AuthenticatedWebsocketSupport)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.WebsocketConn = &wshandler.WebsocketConnection{
|
||||
ExchangeName: c.Name,
|
||||
URL: c.Websocket.GetWebsocketURL(),
|
||||
ProxyURL: c.Websocket.GetProxyAddress(),
|
||||
Verbose: c.Verbose,
|
||||
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
|
||||
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Start starts the coinbasepro go routine
|
||||
@@ -401,7 +420,7 @@ func (c *CoinbasePro) WithdrawFiatFundsToInternationalBank(withdrawRequest *exch
|
||||
}
|
||||
|
||||
// GetWebsocket returns a pointer to the exchange websocket
|
||||
func (c *CoinbasePro) GetWebsocket() (*exchange.Websocket, error) {
|
||||
func (c *CoinbasePro) GetWebsocket() (*wshandler.Websocket, error) {
|
||||
return c.Websocket, nil
|
||||
}
|
||||
|
||||
@@ -502,20 +521,20 @@ func (c *CoinbasePro) GetOrderHistory(getOrdersRequest *exchange.GetOrdersReques
|
||||
|
||||
// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle subscribing
|
||||
func (c *CoinbasePro) SubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
func (c *CoinbasePro) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
c.Websocket.SubscribeToChannels(channels)
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle unsubscribing
|
||||
func (c *CoinbasePro) UnsubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
c.Websocket.UnsubscribeToChannels(channels)
|
||||
func (c *CoinbasePro) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
c.Websocket.RemoveSubscribedChannels(channels)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetSubscriptions returns a copied list of subscriptions
|
||||
func (c *CoinbasePro) GetSubscriptions() ([]exchange.WebsocketChannelSubscription, error) {
|
||||
func (c *CoinbasePro) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
|
||||
return c.Websocket.GetSubscriptions(), nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# GoCryptoTrader package Coinut
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
|
||||
|
||||
[](https://travis-ci.org/thrasher-/gocryptotrader)
|
||||
[](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/coinut)
|
||||
[](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
|
||||
[](https://travis-ci.org/thrasher-corp/gocryptotrader)
|
||||
[](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/coinut)
|
||||
[](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-corp/gocryptotrader)
|
||||
|
||||
|
||||
This coinut package is part of the GoCryptoTrader codebase.
|
||||
@@ -27,7 +27,7 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader
|
||||
|
||||
### How to enable
|
||||
|
||||
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
+ [Enable via configuration](https://github.com/thrasher-corp/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
|
||||
+ Individual package example below:
|
||||
|
||||
@@ -128,12 +128,12 @@ When submitting a PR, please abide by our coding guidelines:
|
||||
|
||||
+ Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)).
|
||||
+ Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines.
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-corp/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Pull requests need to be based on and opened against the `master` branch.
|
||||
|
||||
## Donations
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
|
||||
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
|
||||
|
||||
|
||||
@@ -7,15 +7,14 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -46,9 +45,8 @@ const (
|
||||
// COINUT is the overarching type across the coinut package
|
||||
type COINUT struct {
|
||||
exchange.Base
|
||||
WebsocketConn *websocket.Conn
|
||||
WebsocketConn *wshandler.WebsocketConnection
|
||||
InstrumentMap map[string]int
|
||||
wsRequestMtx sync.Mutex
|
||||
}
|
||||
|
||||
// GetInstruments returns instruments
|
||||
|
||||
@@ -3,14 +3,14 @@ package coinut
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/sharedtestvalues"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/sharedtestvalues"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
)
|
||||
|
||||
var c COINUT
|
||||
@@ -54,12 +54,18 @@ func setupWSTestAuth(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
if !c.Websocket.IsEnabled() && !c.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip(exchange.WebsocketNotEnabled)
|
||||
t.Skip(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
c.WebsocketConn = &wshandler.WebsocketConnection{
|
||||
ExchangeName: c.Name,
|
||||
URL: coinutWebsocketURL,
|
||||
Verbose: c.Verbose,
|
||||
RateLimit: coinutWebsocketRateLimit,
|
||||
ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
|
||||
ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
|
||||
}
|
||||
var err error
|
||||
var dialer websocket.Dialer
|
||||
c.WebsocketConn, _, err = dialer.Dial(c.Websocket.GetWebsocketURL(),
|
||||
http.Header{})
|
||||
err := c.WebsocketConn.Dial(&dialer, http.Header{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -71,17 +77,6 @@ func setupWSTestAuth(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
timer := time.NewTimer(5 * time.Second)
|
||||
select {
|
||||
case resp := <-c.Websocket.DataHandler:
|
||||
if resp.(WsLoginResponse).Username != clientID {
|
||||
t.Fatal("Unsuccessful login")
|
||||
}
|
||||
case <-timer.C:
|
||||
t.Fatal("Expected response")
|
||||
}
|
||||
timer.Stop()
|
||||
time.Sleep(2 * time.Second)
|
||||
instrumentListByString = make(map[string]int64)
|
||||
instrumentListByString[currency.NewPair(currency.LTC, currency.BTC).String()] = 1
|
||||
wsSetupRan = true
|
||||
@@ -450,28 +445,21 @@ func TestGetDepositAddress(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestWsAuthGetAccountBalance dials websocket, sends login request.
|
||||
// TestWsAuthGetAccountBalance dials websocket, retrieves account balance
|
||||
func TestWsAuthGetAccountBalance(t *testing.T) {
|
||||
setupWSTestAuth(t)
|
||||
err := c.wsGetAccountBalance()
|
||||
_, err := c.wsGetAccountBalance()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
timer := time.NewTimer(sharedtestvalues.WebsocketResponseExtendedTimeout)
|
||||
select {
|
||||
case resp := <-c.Websocket.DataHandler:
|
||||
if resp.(WsUserBalanceResponse).Status[0] != "OK" {
|
||||
t.Error("Expected successful response")
|
||||
}
|
||||
case <-timer.C:
|
||||
t.Error("Expected response")
|
||||
}
|
||||
timer.Stop()
|
||||
}
|
||||
|
||||
// TestWsAuthSubmitOrders dials websocket, sends login request.
|
||||
func TestWsAuthSubmitOrders(t *testing.T) {
|
||||
// TestWsAuthSubmitOrder dials websocket, submit order
|
||||
func TestWsAuthSubmitOrder(t *testing.T) {
|
||||
setupWSTestAuth(t)
|
||||
if !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
order := WsSubmitOrderParameters{
|
||||
Amount: 1,
|
||||
Currency: currency.NewPair(currency.LTC, currency.BTC),
|
||||
@@ -479,42 +467,64 @@ func TestWsAuthSubmitOrders(t *testing.T) {
|
||||
Price: 1,
|
||||
Side: exchange.BuyOrderSide,
|
||||
}
|
||||
err := c.wsSubmitOrders([]WsSubmitOrderParameters{order, order})
|
||||
_, err := c.wsSubmitOrder(&order)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
timer := time.NewTimer(sharedtestvalues.WebsocketResponseExtendedTimeout)
|
||||
select {
|
||||
case <-c.Websocket.DataHandler:
|
||||
case <-timer.C:
|
||||
t.Error("Expected response")
|
||||
}
|
||||
timer.Stop()
|
||||
}
|
||||
|
||||
// TestWsAuthCancelOrders dials websocket, sends login request.
|
||||
// TestWsAuthCancelOrders dials websocket, submit orders
|
||||
func TestWsAuthSubmitOrders(t *testing.T) {
|
||||
setupWSTestAuth(t)
|
||||
if !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
order1 := WsSubmitOrderParameters{
|
||||
Amount: 1,
|
||||
Currency: currency.NewPair(currency.LTC, currency.BTC),
|
||||
OrderID: 1,
|
||||
Price: 1,
|
||||
Side: exchange.BuyOrderSide,
|
||||
}
|
||||
order2 := WsSubmitOrderParameters{
|
||||
Amount: 3,
|
||||
Currency: currency.NewPair(currency.LTC, currency.BTC),
|
||||
OrderID: 2,
|
||||
Price: 2,
|
||||
Side: exchange.BuyOrderSide,
|
||||
}
|
||||
_, err := c.wsSubmitOrders([]WsSubmitOrderParameters{order1, order2})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestWsAuthCancelOrders dials websocket, cancels orders
|
||||
func TestWsAuthCancelOrders(t *testing.T) {
|
||||
setupWSTestAuth(t)
|
||||
if !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
order := WsCancelOrderParameters{
|
||||
Currency: currency.NewPair(currency.LTC, currency.BTC),
|
||||
OrderID: 1,
|
||||
}
|
||||
err := c.wsCancelOrders([]WsCancelOrderParameters{order, order})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
order2 := WsCancelOrderParameters{
|
||||
Currency: currency.NewPair(currency.LTC, currency.BTC),
|
||||
OrderID: 2,
|
||||
}
|
||||
timer := time.NewTimer(sharedtestvalues.WebsocketResponseExtendedTimeout)
|
||||
select {
|
||||
case <-c.Websocket.DataHandler:
|
||||
case <-timer.C:
|
||||
t.Error("Expected response")
|
||||
_, errs := c.wsCancelOrders([]WsCancelOrderParameters{order, order2})
|
||||
if len(errs) > 0 {
|
||||
t.Error(errs)
|
||||
}
|
||||
timer.Stop()
|
||||
}
|
||||
|
||||
// TestWsAuthCancelOrder dials websocket, sends login request.
|
||||
// TestWsAuthCancelOrder dials websocket, cancels order
|
||||
func TestWsAuthCancelOrder(t *testing.T) {
|
||||
setupWSTestAuth(t)
|
||||
if !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
order := WsCancelOrderParameters{
|
||||
Currency: currency.NewPair(currency.LTC, currency.BTC),
|
||||
OrderID: 1,
|
||||
@@ -523,27 +533,13 @@ func TestWsAuthCancelOrder(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
timer := time.NewTimer(sharedtestvalues.WebsocketResponseExtendedTimeout)
|
||||
select {
|
||||
case <-c.Websocket.DataHandler:
|
||||
case <-timer.C:
|
||||
t.Error("Expected response")
|
||||
}
|
||||
timer.Stop()
|
||||
}
|
||||
|
||||
// TestWsAuthGetOpenOrders dials websocket, sends login request.
|
||||
// TestWsAuthGetOpenOrders dials websocket, retrieves open orders
|
||||
func TestWsAuthGetOpenOrders(t *testing.T) {
|
||||
setupWSTestAuth(t)
|
||||
err := c.wsGetOpenOrders(currency.NewPair(currency.LTC, currency.BTC))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
timer := time.NewTimer(sharedtestvalues.WebsocketResponseExtendedTimeout)
|
||||
select {
|
||||
case <-c.Websocket.DataHandler:
|
||||
case <-timer.C:
|
||||
t.Error("Expected response")
|
||||
}
|
||||
timer.Stop()
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package coinut
|
||||
|
||||
import (
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
)
|
||||
|
||||
// GenericResponse is the generic response you will get from coinut
|
||||
@@ -263,11 +263,12 @@ type wsRequest struct {
|
||||
SecType string `json:"sec_type,omitempty"`
|
||||
InstID int64 `json:"inst_id,omitempty"`
|
||||
TopN int64 `json:"top_n,omitempty"`
|
||||
Subscribe bool `json:"subscribe"`
|
||||
Nonce int64 `json:"nonce"`
|
||||
Subscribe bool `json:"subscribe,omitempty"`
|
||||
Nonce int64 `json:"nonce,omitempty"`
|
||||
}
|
||||
|
||||
type wsResponse struct {
|
||||
Nonce int64 `json:"nonce,omitempty"`
|
||||
Reply string `json:"reply"`
|
||||
}
|
||||
|
||||
@@ -400,14 +401,14 @@ type WsCancelOrderParameters struct {
|
||||
OrderID int64
|
||||
}
|
||||
|
||||
// WsCancelOrderRequest ws request
|
||||
// WsCancelOrderRequest data required for cancelling an order
|
||||
type WsCancelOrderRequest struct {
|
||||
InstID int64 `json:"inst_id"`
|
||||
OrderID int64 `json:"order_id"`
|
||||
WsRequest
|
||||
}
|
||||
|
||||
// WsCancelOrderResponse ws response
|
||||
// WsCancelOrderResponse contains cancelled order data
|
||||
type WsCancelOrderResponse struct {
|
||||
Nonce int64 `json:"nonce"`
|
||||
Reply string `json:"reply"`
|
||||
@@ -416,16 +417,20 @@ type WsCancelOrderResponse struct {
|
||||
Status []string `json:"status"`
|
||||
}
|
||||
|
||||
// WsCancelOrdersResponse ws response
|
||||
// WsCancelOrdersResponse contains all cancelled order data
|
||||
type WsCancelOrdersResponse struct {
|
||||
WsRequest
|
||||
Entries []WsCancelOrdersResponseEntry `json:"entries"`
|
||||
Nonce int64 `json:"nonce"`
|
||||
Reply string `json:"reply"`
|
||||
Results []WsCancelOrdersResponseData `json:"results"`
|
||||
Status []string `json:"status"`
|
||||
TransID int64 `json:"trans_id"`
|
||||
}
|
||||
|
||||
// WsCancelOrdersResponseEntry ws response entry
|
||||
type WsCancelOrdersResponseEntry struct {
|
||||
InstID int64 `json:"inst_id"`
|
||||
OrderID int64 `json:"order_id"`
|
||||
// WsCancelOrdersResponseData individual cancellation response data
|
||||
type WsCancelOrdersResponseData struct {
|
||||
InstID int64 `json:"inst_id"`
|
||||
OrderID int64 `json:"order_id"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
// WsGetOpenOrdersRequest ws request
|
||||
@@ -547,6 +552,25 @@ type WsOrderRejectedResponse struct {
|
||||
TransID int64 `json:"trans_id"`
|
||||
}
|
||||
|
||||
// WsStandardOrderResponse a standardised order
|
||||
type WsStandardOrderResponse struct {
|
||||
InstID int64
|
||||
OrderID int64
|
||||
ClientOrdID int64
|
||||
TransID int64
|
||||
Nonce int64
|
||||
Status []string
|
||||
Qty float64
|
||||
OpenQty float64
|
||||
Price float64
|
||||
Side string
|
||||
Reasons []string
|
||||
Timestamp int64
|
||||
OrderType string
|
||||
CommissionAmount float64
|
||||
CommissionCurrency currency.Pair
|
||||
}
|
||||
|
||||
// WsUserOpenOrdersResponse ws response
|
||||
type WsUserOpenOrdersResponse struct {
|
||||
Nonce int64 `json:"nonce"`
|
||||
@@ -612,3 +636,25 @@ type WsNewOrderResponse struct {
|
||||
Reply string `json:"reply"`
|
||||
Status []string `json:"status"`
|
||||
}
|
||||
|
||||
// WsGetAccountBalanceResponse contains values of each currency
|
||||
type WsGetAccountBalanceResponse struct {
|
||||
BCH string `json:"BCH"`
|
||||
BTC string `json:"BTC"`
|
||||
BTG string `json:"BTG"`
|
||||
CAD string `json:"CAD"`
|
||||
ETC string `json:"ETC"`
|
||||
ETH string `json:"ETH"`
|
||||
LCH string `json:"LCH"`
|
||||
LTC string `json:"LTC"`
|
||||
MYR string `json:"MYR"`
|
||||
SGD string `json:"SGD"`
|
||||
USD string `json:"USD"`
|
||||
USDT string `json:"USDT"`
|
||||
XMR string `json:"XMR"`
|
||||
ZEC string `json:"ZEC"`
|
||||
Nonce int64 `json:"nonce"`
|
||||
Reply string `json:"reply"`
|
||||
Status []string `json:"status"`
|
||||
TransID int64 `json:"trans_id"`
|
||||
}
|
||||
|
||||
@@ -4,22 +4,21 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
)
|
||||
|
||||
const coinutWebsocketURL = "wss://wsapi.coinut.com"
|
||||
const coinutWebsocketRateLimit = 30 * time.Millisecond
|
||||
const coinutWebsocketRateLimit = 30
|
||||
|
||||
var nNonce map[int64]string
|
||||
var channels map[string]chan []byte
|
||||
@@ -35,32 +34,18 @@ var populatedList bool
|
||||
// WsConnect intiates a websocket connection
|
||||
func (c *COINUT) WsConnect() error {
|
||||
if !c.Websocket.IsEnabled() || !c.IsEnabled() {
|
||||
return errors.New(exchange.WebsocketNotEnabled)
|
||||
return errors.New(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
|
||||
var Dialer websocket.Dialer
|
||||
|
||||
if c.Websocket.GetProxyAddress() != "" {
|
||||
proxy, err := url.Parse(c.Websocket.GetProxyAddress())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Dialer.Proxy = http.ProxyURL(proxy)
|
||||
}
|
||||
|
||||
var err error
|
||||
c.WebsocketConn, _, err = Dialer.Dial(c.Websocket.GetWebsocketURL(),
|
||||
http.Header{})
|
||||
|
||||
var dialer websocket.Dialer
|
||||
err := c.WebsocketConn.Dial(&dialer, http.Header{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go c.WsHandleData()
|
||||
|
||||
if !populatedList {
|
||||
instrumentListByString = make(map[string]int64)
|
||||
instrumentListByCode = make(map[int64]string)
|
||||
|
||||
err = c.WsSetInstrumentList()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -74,21 +59,9 @@ func (c *COINUT) WsConnect() error {
|
||||
channels = make(map[string]chan []byte)
|
||||
channels["hb"] = make(chan []byte, 1)
|
||||
|
||||
go c.WsHandleData()
|
||||
return nil
|
||||
}
|
||||
|
||||
// WsReadData reads data from the websocket connection
|
||||
func (c *COINUT) WsReadData() (exchange.WebsocketResponse, error) {
|
||||
_, resp, err := c.WebsocketConn.ReadMessage()
|
||||
if err != nil {
|
||||
return exchange.WebsocketResponse{}, err
|
||||
}
|
||||
|
||||
c.Websocket.TrafficAlert <- struct{}{}
|
||||
return exchange.WebsocketResponse{Raw: resp}, nil
|
||||
}
|
||||
|
||||
// WsHandleData handles read data
|
||||
func (c *COINUT) WsHandleData() {
|
||||
c.Websocket.Wg.Add(1)
|
||||
@@ -103,11 +76,12 @@ func (c *COINUT) WsHandleData() {
|
||||
return
|
||||
|
||||
default:
|
||||
resp, err := c.WsReadData()
|
||||
resp, err := c.WebsocketConn.ReadMessage()
|
||||
if err != nil {
|
||||
c.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
c.Websocket.TrafficAlert <- struct{}{}
|
||||
|
||||
if strings.HasPrefix(string(resp.Raw), "[") {
|
||||
var incoming []wsResponse
|
||||
@@ -117,6 +91,10 @@ func (c *COINUT) WsHandleData() {
|
||||
continue
|
||||
}
|
||||
for i := range incoming {
|
||||
if incoming[i].Nonce > 0 {
|
||||
c.WebsocketConn.AddResponseWithID(incoming[i].Nonce, resp.Raw)
|
||||
break
|
||||
}
|
||||
var individualJSON []byte
|
||||
individualJSON, err = common.JSONEncode(incoming[i])
|
||||
if err != nil {
|
||||
@@ -133,6 +111,7 @@ func (c *COINUT) WsHandleData() {
|
||||
c.Websocket.DataHandler <- err
|
||||
continue
|
||||
}
|
||||
|
||||
c.wsProcessResponse(resp.Raw)
|
||||
}
|
||||
|
||||
@@ -148,15 +127,6 @@ func (c *COINUT) wsProcessResponse(resp []byte) {
|
||||
return
|
||||
}
|
||||
switch incoming.Reply {
|
||||
case "login":
|
||||
var login WsLoginResponse
|
||||
err := common.JSONDecode(resp, &login)
|
||||
if err != nil {
|
||||
c.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
c.Websocket.SetCanUseAuthenticatedEndpoints(login.Username == c.API.Credentials.ClientID)
|
||||
c.Websocket.DataHandler <- login
|
||||
case "hb":
|
||||
channels["hb"] <- resp
|
||||
case "inst_tick":
|
||||
@@ -167,7 +137,7 @@ func (c *COINUT) wsProcessResponse(resp []byte) {
|
||||
return
|
||||
}
|
||||
currencyPair := instrumentListByCode[ticker.InstID]
|
||||
c.Websocket.DataHandler <- exchange.TickerData{
|
||||
c.Websocket.DataHandler <- wshandler.TickerData{
|
||||
Timestamp: time.Unix(0, ticker.Timestamp),
|
||||
Pair: currency.NewPairFromString(currencyPair),
|
||||
Exchange: c.GetName(),
|
||||
@@ -191,7 +161,7 @@ func (c *COINUT) wsProcessResponse(resp []byte) {
|
||||
return
|
||||
}
|
||||
currencyPair := instrumentListByCode[orderbooksnapshot.InstID]
|
||||
c.Websocket.DataHandler <- exchange.WebsocketOrderbookUpdate{
|
||||
c.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
|
||||
Exchange: c.GetName(),
|
||||
Asset: asset.Spot,
|
||||
Pair: currency.NewPairFromString(currencyPair),
|
||||
@@ -209,7 +179,7 @@ func (c *COINUT) wsProcessResponse(resp []byte) {
|
||||
return
|
||||
}
|
||||
currencyPair := instrumentListByCode[orderbookUpdate.InstID]
|
||||
c.Websocket.DataHandler <- exchange.WebsocketOrderbookUpdate{
|
||||
c.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
|
||||
Exchange: c.GetName(),
|
||||
Asset: asset.Spot,
|
||||
Pair: currency.NewPairFromString(currencyPair),
|
||||
@@ -230,7 +200,7 @@ func (c *COINUT) wsProcessResponse(resp []byte) {
|
||||
return
|
||||
}
|
||||
currencyPair := instrumentListByCode[tradeUpdate.InstID]
|
||||
c.Websocket.DataHandler <- exchange.TradeData{
|
||||
c.Websocket.DataHandler <- wshandler.TradeData{
|
||||
Timestamp: time.Unix(tradeUpdate.Timestamp, 0),
|
||||
CurrencyPair: currency.NewPairFromString(currencyPair),
|
||||
AssetType: asset.Spot,
|
||||
@@ -238,78 +208,12 @@ func (c *COINUT) wsProcessResponse(resp []byte) {
|
||||
Price: tradeUpdate.Price,
|
||||
Side: tradeUpdate.Side,
|
||||
}
|
||||
case "user_balance":
|
||||
var userBalance WsUserBalanceResponse
|
||||
err := common.JSONDecode(resp, &userBalance)
|
||||
if err != nil {
|
||||
c.Websocket.DataHandler <- err
|
||||
default:
|
||||
if incoming.Nonce > 0 {
|
||||
c.WebsocketConn.AddResponseWithID(incoming.Nonce, resp)
|
||||
return
|
||||
}
|
||||
c.Websocket.DataHandler <- userBalance
|
||||
case "new_order":
|
||||
var newOrder WsNewOrderResponse
|
||||
err := common.JSONDecode(resp, &newOrder)
|
||||
if err != nil {
|
||||
c.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
c.Websocket.DataHandler <- newOrder
|
||||
case "order_accepted":
|
||||
var orderAccepted WsOrderAcceptedResponse
|
||||
err := common.JSONDecode(resp, &orderAccepted)
|
||||
if err != nil {
|
||||
c.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
c.Websocket.DataHandler <- orderAccepted
|
||||
case "order_filled":
|
||||
var orderFilled WsOrderFilledResponse
|
||||
err := common.JSONDecode(resp, &orderFilled)
|
||||
if err != nil {
|
||||
c.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
c.Websocket.DataHandler <- orderFilled
|
||||
case "order_rejected":
|
||||
var orderRejected WsOrderRejectedResponse
|
||||
err := common.JSONDecode(resp, &orderRejected)
|
||||
if err != nil {
|
||||
c.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
c.Websocket.DataHandler <- orderRejected
|
||||
case "user_open_orders":
|
||||
var openOrders WsUserOpenOrdersResponse
|
||||
err := common.JSONDecode(resp, &openOrders)
|
||||
if err != nil {
|
||||
c.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
c.Websocket.DataHandler <- openOrders
|
||||
case "trade_history":
|
||||
var tradeHistory WsTradeHistoryResponse
|
||||
err := common.JSONDecode(resp, &tradeHistory)
|
||||
if err != nil {
|
||||
c.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
c.Websocket.DataHandler <- tradeHistory
|
||||
case "cancel_orders":
|
||||
var cancelOrders WsCancelOrdersResponse
|
||||
err := common.JSONDecode(resp, &cancelOrders)
|
||||
if err != nil {
|
||||
c.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
c.Websocket.DataHandler <- cancelOrders
|
||||
case "cancel_order":
|
||||
var cancelOrder WsCancelOrderResponse
|
||||
err := common.JSONDecode(resp, &cancelOrder)
|
||||
if err != nil {
|
||||
c.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
c.Websocket.DataHandler <- cancelOrder
|
||||
c.Websocket.DataHandler <- fmt.Errorf("%v unhandled websocket response: %s", c.Name, resp)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,37 +230,27 @@ func (c *COINUT) GetNonce() int64 {
|
||||
|
||||
// WsSetInstrumentList fetches instrument list and propagates a local cache
|
||||
func (c *COINUT) WsSetInstrumentList() error {
|
||||
err := c.wsSend(wsRequest{
|
||||
request := wsRequest{
|
||||
Request: "inst_list",
|
||||
SecType: strings.ToUpper(asset.Spot.String()),
|
||||
Nonce: c.GetNonce(),
|
||||
})
|
||||
Nonce: c.WebsocketConn.GenerateMessageID(false),
|
||||
}
|
||||
resp, err := c.WebsocketConn.SendMessageReturnResponse(request.Nonce, request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, resp, err := c.WebsocketConn.ReadMessage()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.Websocket.TrafficAlert <- struct{}{}
|
||||
|
||||
var list WsInstrumentList
|
||||
err = common.JSONDecode(resp, &list)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for currency, data := range list.Spot {
|
||||
instrumentListByString[currency] = data[0].InstID
|
||||
instrumentListByCode[data[0].InstID] = currency
|
||||
}
|
||||
|
||||
if len(instrumentListByString) == 0 || len(instrumentListByCode) == 0 {
|
||||
return errors.New("instrument lists failed to populate")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -414,11 +308,11 @@ func (c *COINUT) WsProcessOrderbookUpdate(ob *WsOrderbookUpdate) error {
|
||||
// GenerateDefaultSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions()
|
||||
func (c *COINUT) GenerateDefaultSubscriptions() {
|
||||
var channels = []string{"inst_tick", "inst_order_book"}
|
||||
var subscriptions []exchange.WebsocketChannelSubscription
|
||||
var subscriptions []wshandler.WebsocketChannelSubscription
|
||||
enabledCurrencies := c.GetEnabledPairs(asset.Spot)
|
||||
for i := range channels {
|
||||
for j := range enabledCurrencies {
|
||||
subscriptions = append(subscriptions, exchange.WebsocketChannelSubscription{
|
||||
subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
|
||||
Channel: channels[i],
|
||||
Currency: enabledCurrencies[j],
|
||||
})
|
||||
@@ -428,42 +322,37 @@ func (c *COINUT) GenerateDefaultSubscriptions() {
|
||||
}
|
||||
|
||||
// Subscribe sends a websocket message to receive data from the channel
|
||||
func (c *COINUT) Subscribe(channelToSubscribe exchange.WebsocketChannelSubscription) error {
|
||||
func (c *COINUT) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
|
||||
subscribe := wsRequest{
|
||||
Request: channelToSubscribe.Channel,
|
||||
InstID: instrumentListByString[channelToSubscribe.Currency.String()],
|
||||
Subscribe: true,
|
||||
Nonce: c.GetNonce(),
|
||||
Nonce: c.WebsocketConn.GenerateMessageID(false),
|
||||
}
|
||||
return c.wsSend(subscribe)
|
||||
return c.WebsocketConn.SendMessage(subscribe)
|
||||
}
|
||||
|
||||
// Unsubscribe sends a websocket message to stop receiving data from the channel
|
||||
func (c *COINUT) Unsubscribe(channelToSubscribe exchange.WebsocketChannelSubscription) error {
|
||||
func (c *COINUT) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
|
||||
subscribe := wsRequest{
|
||||
Request: channelToSubscribe.Channel,
|
||||
InstID: instrumentListByString[channelToSubscribe.Currency.String()],
|
||||
Subscribe: false,
|
||||
Nonce: c.GetNonce(),
|
||||
Nonce: c.WebsocketConn.GenerateMessageID(false),
|
||||
}
|
||||
return c.wsSend(subscribe)
|
||||
}
|
||||
|
||||
// WsSend sends data to the websocket server
|
||||
func (c *COINUT) wsSend(data interface{}) error {
|
||||
c.wsRequestMtx.Lock()
|
||||
defer c.wsRequestMtx.Unlock()
|
||||
|
||||
json, err := common.JSONEncode(data)
|
||||
resp, err := c.WebsocketConn.SendMessageReturnResponse(subscribe.Nonce, subscribe)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if c.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%v sending message to websocket %v", c.Name, string(json))
|
||||
var response map[string]interface{}
|
||||
err = common.JSONDecode(resp, &response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Basic rate limiter
|
||||
time.Sleep(coinutWebsocketRateLimit)
|
||||
return c.WebsocketConn.WriteMessage(websocket.TextMessage, json)
|
||||
if response["status"].([]interface{})[0] != "OK" {
|
||||
return fmt.Errorf("%v unsubscribe failed for channel %v", c.Name, channelToSubscribe.Channel)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *COINUT) wsAuthenticate() error {
|
||||
@@ -471,7 +360,7 @@ func (c *COINUT) wsAuthenticate() error {
|
||||
return fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", c.Name)
|
||||
}
|
||||
timestamp := time.Now().Unix()
|
||||
nonce := c.GetNonce()
|
||||
nonce := c.WebsocketConn.GenerateMessageID(false)
|
||||
payload := fmt.Sprintf("%v|%v|%v", c.API.Credentials.ClientID, timestamp, nonce)
|
||||
hmac := crypto.GetHMAC(crypto.HashSHA256, []byte(payload), []byte(c.API.Credentials.Key))
|
||||
loginRequest := struct {
|
||||
@@ -488,34 +377,54 @@ func (c *COINUT) wsAuthenticate() error {
|
||||
Timestamp: timestamp,
|
||||
}
|
||||
|
||||
err := c.wsSend(loginRequest)
|
||||
resp, err := c.WebsocketConn.SendMessageReturnResponse(loginRequest.Nonce, loginRequest)
|
||||
if err != nil {
|
||||
c.Websocket.SetCanUseAuthenticatedEndpoints(false)
|
||||
return err
|
||||
}
|
||||
var response map[string]interface{}
|
||||
err = common.JSONDecode(resp, &response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if response["status"].([]interface{})[0] != "OK" {
|
||||
c.Websocket.SetCanUseAuthenticatedEndpoints(false)
|
||||
return fmt.Errorf("%v failed to authenticate", c.Name)
|
||||
}
|
||||
c.Websocket.SetCanUseAuthenticatedEndpoints(true)
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func (c *COINUT) wsGetAccountBalance() error {
|
||||
func (c *COINUT) wsGetAccountBalance() (*WsGetAccountBalanceResponse, error) {
|
||||
if !c.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
return fmt.Errorf("%v not authorised to submit order", c.Name)
|
||||
return nil, fmt.Errorf("%v not authorised to submit order", c.Name)
|
||||
}
|
||||
accBalance := wsRequest{
|
||||
Request: "user_balance",
|
||||
Nonce: c.GetNonce(),
|
||||
Nonce: c.WebsocketConn.GenerateMessageID(false),
|
||||
}
|
||||
return c.wsSend(accBalance)
|
||||
resp, err := c.WebsocketConn.SendMessageReturnResponse(accBalance.Nonce, accBalance)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var response WsGetAccountBalanceResponse
|
||||
err = common.JSONDecode(resp, &response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if response.Status[0] != "OK" {
|
||||
return &response, fmt.Errorf("%v get account balance failed", c.Name)
|
||||
}
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
func (c *COINUT) wsSubmitOrder(order *WsSubmitOrderParameters) error {
|
||||
func (c *COINUT) wsSubmitOrder(order *WsSubmitOrderParameters) (*WsStandardOrderResponse, error) {
|
||||
if !c.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
return fmt.Errorf("%v not authorised to submit order", c.Name)
|
||||
return nil, fmt.Errorf("%v not authorised to submit order", c.Name)
|
||||
}
|
||||
currency := c.FormatExchangeCurrency(order.Currency, asset.Spot).String()
|
||||
var orderSubmissionRequest WsSubmitOrderRequest
|
||||
orderSubmissionRequest.Request = "new_order"
|
||||
orderSubmissionRequest.Nonce = c.GetNonce()
|
||||
orderSubmissionRequest.Nonce = c.WebsocketConn.GenerateMessageID(false)
|
||||
orderSubmissionRequest.InstID = instrumentListByString[currency]
|
||||
orderSubmissionRequest.Qty = order.Amount
|
||||
orderSubmissionRequest.Price = order.Price
|
||||
@@ -524,12 +433,100 @@ func (c *COINUT) wsSubmitOrder(order *WsSubmitOrderParameters) error {
|
||||
if order.OrderID > 0 {
|
||||
orderSubmissionRequest.OrderID = order.OrderID
|
||||
}
|
||||
return c.wsSend(orderSubmissionRequest)
|
||||
resp, err := c.WebsocketConn.SendMessageReturnResponse(orderSubmissionRequest.Nonce, orderSubmissionRequest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var standardOrder WsStandardOrderResponse
|
||||
standardOrder, err = c.wsStandardiseOrderResponse(resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if standardOrder.Status[0] != "OK" {
|
||||
return &standardOrder, fmt.Errorf("%v order submission failed. %v", c.Name, standardOrder)
|
||||
}
|
||||
if len(standardOrder.Reasons) > 0 && standardOrder.Reasons[0] != "" {
|
||||
return &standardOrder, fmt.Errorf("%v order submission failed. %v", c.Name, standardOrder.Reasons[0])
|
||||
}
|
||||
return &standardOrder, nil
|
||||
}
|
||||
|
||||
func (c *COINUT) wsSubmitOrders(orders []WsSubmitOrderParameters) error {
|
||||
func (c *COINUT) wsStandardiseOrderResponse(resp []byte) (WsStandardOrderResponse, error) {
|
||||
var response WsStandardOrderResponse
|
||||
var incoming wsResponse
|
||||
err := common.JSONDecode(resp, &incoming)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
switch incoming.Reply {
|
||||
case "order_accepted":
|
||||
var orderAccepted WsOrderAcceptedResponse
|
||||
err := common.JSONDecode(resp, &orderAccepted)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
response = WsStandardOrderResponse{
|
||||
InstID: orderAccepted.InstID,
|
||||
Nonce: orderAccepted.Nonce,
|
||||
OpenQty: orderAccepted.OpenQty,
|
||||
OrderID: orderAccepted.OrderID,
|
||||
OrderType: orderAccepted.Reply,
|
||||
Price: orderAccepted.OrderPrice,
|
||||
Qty: orderAccepted.Qty,
|
||||
Side: orderAccepted.Side,
|
||||
Status: orderAccepted.Status,
|
||||
TransID: orderAccepted.TransID,
|
||||
ClientOrdID: orderAccepted.ClientOrdID,
|
||||
}
|
||||
case "order_filled":
|
||||
var orderFilled WsOrderFilledResponse
|
||||
err := common.JSONDecode(resp, &orderFilled)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
response = WsStandardOrderResponse{
|
||||
InstID: orderFilled.Order.InstID,
|
||||
Nonce: orderFilled.Nonce,
|
||||
OpenQty: orderFilled.Order.OpenQty,
|
||||
OrderID: orderFilled.Order.OrderID,
|
||||
OrderType: orderFilled.Reply,
|
||||
Price: orderFilled.Order.Price,
|
||||
Qty: orderFilled.Order.Qty,
|
||||
Side: orderFilled.Order.Side,
|
||||
Status: orderFilled.Status,
|
||||
TransID: orderFilled.TransID,
|
||||
ClientOrdID: orderFilled.Order.ClientOrdID,
|
||||
}
|
||||
case "order_rejected":
|
||||
var orderRejected WsOrderRejectedResponse
|
||||
err := common.JSONDecode(resp, &orderRejected)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
response = WsStandardOrderResponse{
|
||||
InstID: orderRejected.InstID,
|
||||
Nonce: orderRejected.Nonce,
|
||||
OpenQty: orderRejected.OpenQty,
|
||||
OrderID: orderRejected.OrderID,
|
||||
OrderType: orderRejected.Reply,
|
||||
Price: orderRejected.Price,
|
||||
Qty: orderRejected.Qty,
|
||||
Side: orderRejected.Side,
|
||||
Status: orderRejected.Status,
|
||||
TransID: orderRejected.TransID,
|
||||
ClientOrdID: orderRejected.ClientOrdID,
|
||||
Reasons: orderRejected.Reasons,
|
||||
}
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (c *COINUT) wsSubmitOrders(orders []WsSubmitOrderParameters) ([]WsStandardOrderResponse, []error) {
|
||||
var errors []error
|
||||
var ordersResponse []WsStandardOrderResponse
|
||||
if !c.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
return fmt.Errorf("%v not authorised to submit orders", c.Name)
|
||||
errors = append(errors, fmt.Errorf("%v not authorised to submit orders", c.Name))
|
||||
return nil, errors
|
||||
}
|
||||
orderRequest := WsSubmitOrdersRequest{}
|
||||
for i := range orders {
|
||||
@@ -544,9 +541,48 @@ func (c *COINUT) wsSubmitOrders(orders []WsSubmitOrderParameters) error {
|
||||
})
|
||||
}
|
||||
|
||||
orderRequest.Nonce = c.GetNonce()
|
||||
orderRequest.Nonce = c.WebsocketConn.GenerateMessageID(false)
|
||||
orderRequest.Request = "new_orders"
|
||||
return c.wsSend(orderRequest)
|
||||
resp, err := c.WebsocketConn.SendMessageReturnResponse(orderRequest.Nonce, orderRequest)
|
||||
if err != nil {
|
||||
errors = append(errors, err)
|
||||
return nil, errors
|
||||
}
|
||||
var incoming []interface{}
|
||||
err = common.JSONDecode(resp, &incoming)
|
||||
if err != nil {
|
||||
errors = append(errors, err)
|
||||
return nil, errors
|
||||
}
|
||||
for i := range incoming {
|
||||
var individualJSON []byte
|
||||
individualJSON, err = common.JSONEncode(incoming[i])
|
||||
if err != nil {
|
||||
errors = append(errors, err)
|
||||
continue
|
||||
}
|
||||
standardOrder, err := c.wsStandardiseOrderResponse(individualJSON)
|
||||
if err != nil {
|
||||
errors = append(errors, err)
|
||||
continue
|
||||
}
|
||||
if standardOrder.Status[0] != "OK" {
|
||||
errors = append(errors, fmt.Errorf("%v order submission failed. %v", c.Name, standardOrder))
|
||||
continue
|
||||
}
|
||||
if len(standardOrder.Reasons) > 0 && standardOrder.Reasons[0] != "" {
|
||||
errors = append(errors, fmt.Errorf("%v order submission failed for currency %v and orderID %v, message %v ",
|
||||
c.Name,
|
||||
instrumentListByCode[standardOrder.InstID],
|
||||
standardOrder.OrderID,
|
||||
standardOrder.Reasons[0]))
|
||||
|
||||
continue
|
||||
}
|
||||
ordersResponse = append(ordersResponse, standardOrder)
|
||||
}
|
||||
|
||||
return ordersResponse, errors
|
||||
}
|
||||
|
||||
func (c *COINUT) wsGetOpenOrders(p currency.Pair) error {
|
||||
@@ -556,10 +592,24 @@ func (c *COINUT) wsGetOpenOrders(p currency.Pair) error {
|
||||
currency := c.FormatExchangeCurrency(p, asset.Spot).String()
|
||||
var openOrdersRequest WsGetOpenOrdersRequest
|
||||
openOrdersRequest.Request = "user_open_orders"
|
||||
openOrdersRequest.Nonce = c.GetNonce()
|
||||
openOrdersRequest.Nonce = c.WebsocketConn.GenerateMessageID(false)
|
||||
openOrdersRequest.InstID = instrumentListByString[currency]
|
||||
|
||||
return c.wsSend(openOrdersRequest)
|
||||
resp, err := c.WebsocketConn.SendMessageReturnResponse(openOrdersRequest.Nonce, openOrdersRequest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var response map[string]interface{}
|
||||
err = common.JSONDecode(resp, &response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if response["status"].([]interface{})[0] != "OK" {
|
||||
return fmt.Errorf("%v get open orders failed for currency %v",
|
||||
c.Name,
|
||||
p)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *COINUT) wsCancelOrder(cancellation WsCancelOrderParameters) error {
|
||||
@@ -571,14 +621,31 @@ func (c *COINUT) wsCancelOrder(cancellation WsCancelOrderParameters) error {
|
||||
cancellationRequest.Request = "cancel_order"
|
||||
cancellationRequest.InstID = instrumentListByString[currency]
|
||||
cancellationRequest.OrderID = cancellation.OrderID
|
||||
cancellationRequest.Nonce = c.GetNonce()
|
||||
cancellationRequest.Nonce = c.WebsocketConn.GenerateMessageID(false)
|
||||
|
||||
return c.wsSend(cancellationRequest)
|
||||
resp, err := c.WebsocketConn.SendMessageReturnResponse(cancellationRequest.Nonce, cancellationRequest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var response map[string]interface{}
|
||||
err = common.JSONDecode(resp, &response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if response["status"].([]interface{})[0] != "OK" {
|
||||
return fmt.Errorf("%v order cancellation failed for currency %v and orderID %v, message %v",
|
||||
c.Name,
|
||||
cancellation.Currency,
|
||||
cancellation.OrderID,
|
||||
response["status"])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *COINUT) wsCancelOrders(cancellations []WsCancelOrderParameters) error {
|
||||
func (c *COINUT) wsCancelOrders(cancellations []WsCancelOrderParameters) (*WsCancelOrdersResponse, []error) {
|
||||
var errors []error
|
||||
if !c.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
return fmt.Errorf("%v not authorised to cancel orders", c.Name)
|
||||
return nil, errors
|
||||
}
|
||||
cancelOrderRequest := WsCancelOrdersRequest{}
|
||||
for i := range cancellations {
|
||||
@@ -590,8 +657,29 @@ func (c *COINUT) wsCancelOrders(cancellations []WsCancelOrderParameters) error {
|
||||
}
|
||||
|
||||
cancelOrderRequest.Request = "cancel_orders"
|
||||
cancelOrderRequest.Nonce = c.GetNonce()
|
||||
return c.wsSend(cancelOrderRequest)
|
||||
cancelOrderRequest.Nonce = c.WebsocketConn.GenerateMessageID(false)
|
||||
resp, err := c.WebsocketConn.SendMessageReturnResponse(cancelOrderRequest.Nonce, cancelOrderRequest)
|
||||
if err != nil {
|
||||
return nil, []error{err}
|
||||
}
|
||||
var response WsCancelOrdersResponse
|
||||
err = common.JSONDecode(resp, &response)
|
||||
if err != nil {
|
||||
return nil, []error{err}
|
||||
}
|
||||
if response.Status[0] != "OK" {
|
||||
return &response, []error{err}
|
||||
}
|
||||
for i := range response.Results {
|
||||
if response.Results[i].Status != "OK" {
|
||||
errors = append(errors, fmt.Errorf("%v order cancellation failed for currency %v and orderID %v, message %v",
|
||||
c.Name,
|
||||
instrumentListByCode[response.Results[i].InstID],
|
||||
response.Results[i].OrderID,
|
||||
response.Results[i].Status))
|
||||
}
|
||||
}
|
||||
return &response, errors
|
||||
}
|
||||
|
||||
func (c *COINUT) wsGetTradeHistory(p currency.Pair, start, limit int64) error {
|
||||
@@ -602,9 +690,23 @@ func (c *COINUT) wsGetTradeHistory(p currency.Pair, start, limit int64) error {
|
||||
var request WsTradeHistoryRequest
|
||||
request.Request = "trade_history"
|
||||
request.InstID = instrumentListByString[currency]
|
||||
request.Nonce = c.GetNonce()
|
||||
request.Nonce = c.WebsocketConn.GenerateMessageID(false)
|
||||
request.Start = start
|
||||
request.Limit = limit
|
||||
|
||||
return c.wsSend(request)
|
||||
resp, err := c.WebsocketConn.SendMessageReturnResponse(request.Nonce, request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var response map[string]interface{}
|
||||
err = common.JSONDecode(resp, &response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if response["status"].([]interface{})[0] != "OK" {
|
||||
return fmt.Errorf("%v get trade history failed for %v",
|
||||
c.Name,
|
||||
request)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -7,15 +7,16 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
// GetDefaultConfig returns a default exchange config
|
||||
@@ -86,12 +87,18 @@ func (c *COINUT) SetDefaults() {
|
||||
c.API.Endpoints.URLDefault = coinutAPIURL
|
||||
c.API.Endpoints.URL = c.API.Endpoints.URLDefault
|
||||
c.API.Endpoints.WebsocketURL = coinutWebsocketURL
|
||||
c.WebsocketInit()
|
||||
c.Websocket.Functionality = exchange.WebsocketTickerSupported |
|
||||
exchange.WebsocketOrderbookSupported |
|
||||
exchange.WebsocketTradeDataSupported |
|
||||
exchange.WebsocketSubscribeSupported |
|
||||
exchange.WebsocketUnsubscribeSupported
|
||||
c.Websocket = wshandler.New()
|
||||
c.Websocket.Functionality = wshandler.WebsocketTickerSupported |
|
||||
wshandler.WebsocketOrderbookSupported |
|
||||
wshandler.WebsocketTradeDataSupported |
|
||||
wshandler.WebsocketSubscribeSupported |
|
||||
wshandler.WebsocketUnsubscribeSupported |
|
||||
wshandler.WebsocketAuthenticatedEndpointsSupported |
|
||||
wshandler.WebsocketSubmitOrderSupported |
|
||||
wshandler.WebsocketCancelOrderSupported |
|
||||
wshandler.WebsocketMessageCorrelationSupported
|
||||
c.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
|
||||
c.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
|
||||
}
|
||||
|
||||
// Setup sets the current exchange configuration
|
||||
@@ -106,14 +113,28 @@ func (c *COINUT) Setup(exch *config.ExchangeConfig) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.WebsocketSetup(c.WsConnect,
|
||||
err = c.Websocket.Setup(c.WsConnect,
|
||||
c.Subscribe,
|
||||
c.Unsubscribe,
|
||||
exch.Name,
|
||||
exch.Features.Enabled.Websocket,
|
||||
exch.Verbose,
|
||||
coinutWebsocketURL,
|
||||
exch.API.Endpoints.WebsocketURL)
|
||||
exch.API.Endpoints.WebsocketURL,
|
||||
exch.API.AuthenticatedWebsocketSupport)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.WebsocketConn = &wshandler.WebsocketConnection{
|
||||
ExchangeName: c.Name,
|
||||
URL: c.Websocket.GetWebsocketURL(),
|
||||
ProxyURL: c.Websocket.GetProxyAddress(),
|
||||
Verbose: c.Verbose,
|
||||
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
|
||||
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Start starts the COINUT go routine
|
||||
@@ -496,7 +517,7 @@ func (c *COINUT) WithdrawFiatFundsToInternationalBank(withdrawRequest *exchange.
|
||||
}
|
||||
|
||||
// GetWebsocket returns a pointer to the exchange websocket
|
||||
func (c *COINUT) GetWebsocket() (*exchange.Websocket, error) {
|
||||
func (c *COINUT) GetWebsocket() (*wshandler.Websocket, error) {
|
||||
return c.Websocket, nil
|
||||
}
|
||||
|
||||
@@ -621,20 +642,20 @@ func (c *COINUT) GetOrderHistory(getOrdersRequest *exchange.GetOrdersRequest) ([
|
||||
|
||||
// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle subscribing
|
||||
func (c *COINUT) SubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
func (c *COINUT) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
c.Websocket.SubscribeToChannels(channels)
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle unsubscribing
|
||||
func (c *COINUT) UnsubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
c.Websocket.UnsubscribeToChannels(channels)
|
||||
func (c *COINUT) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
c.Websocket.RemoveSubscribedChannels(channels)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetSubscriptions returns a copied list of subscriptions
|
||||
func (c *COINUT) GetSubscriptions() ([]exchange.WebsocketChannelSubscription, error) {
|
||||
func (c *COINUT) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
|
||||
return c.Websocket.GetSubscriptions(), nil
|
||||
}
|
||||
|
||||
|
||||
@@ -8,12 +8,12 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -22,6 +22,10 @@ const (
|
||||
WarningAuthenticatedRequestWithoutCredentialsSet = "exchange %s authenticated HTTP request called but not supported due to unset/default API keys"
|
||||
// DefaultHTTPTimeout is the default HTTP/HTTPS Timeout for exchange requests
|
||||
DefaultHTTPTimeout = time.Second * 15
|
||||
// DefaultWebsocketResponseCheckTimeout is the default delay in checking for an expected websocket response
|
||||
DefaultWebsocketResponseCheckTimeout = time.Millisecond * 30
|
||||
// DefaultWebsocketResponseMaxLimit is the default max wait for an expected websocket response before a timeout
|
||||
DefaultWebsocketResponseMaxLimit = time.Second * 7
|
||||
)
|
||||
|
||||
func (e *Base) checkAndInitRequester() {
|
||||
|
||||
@@ -6,11 +6,12 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -86,7 +87,7 @@ func TestSetClientProxyAddress(t *testing.T) {
|
||||
|
||||
newBase := Base{Name: "Testicles", Requester: requester}
|
||||
|
||||
newBase.WebsocketInit()
|
||||
newBase.Websocket = wshandler.New()
|
||||
|
||||
err := newBase.SetClientProxyAddress(":invalid")
|
||||
if err == nil {
|
||||
|
||||
@@ -3,9 +3,10 @@ package exchange
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
)
|
||||
|
||||
// Endpoint authentication types
|
||||
@@ -299,18 +300,20 @@ type API struct {
|
||||
|
||||
// Base stores the individual exchange information
|
||||
type Base struct {
|
||||
Name string
|
||||
Enabled bool
|
||||
Verbose bool
|
||||
LoadedByConfig bool
|
||||
API API
|
||||
BaseCurrencies currency.Currencies
|
||||
CurrencyPairs currency.PairsManager
|
||||
Features Features
|
||||
HTTPTimeout time.Duration
|
||||
HTTPUserAgent string
|
||||
HTTPDebugging bool
|
||||
Websocket *Websocket
|
||||
Name string
|
||||
Enabled bool
|
||||
Verbose bool
|
||||
LoadedByConfig bool
|
||||
API API
|
||||
BaseCurrencies currency.Currencies
|
||||
CurrencyPairs currency.PairsManager
|
||||
Features Features
|
||||
HTTPTimeout time.Duration
|
||||
HTTPUserAgent string
|
||||
HTTPDebugging bool
|
||||
WebsocketResponseCheckTimeout time.Duration
|
||||
WebsocketResponseMaxLimit time.Duration
|
||||
Websocket *wshandler.Websocket
|
||||
*request.Requester
|
||||
Config *config.ExchangeConfig
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# GoCryptoTrader package Exmo
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
|
||||
|
||||
[](https://travis-ci.org/thrasher-/gocryptotrader)
|
||||
[](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/exmo)
|
||||
[](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
|
||||
[](https://travis-ci.org/thrasher-corp/gocryptotrader)
|
||||
[](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/exmo)
|
||||
[](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-corp/gocryptotrader)
|
||||
|
||||
|
||||
This exmo package is part of the GoCryptoTrader codebase.
|
||||
@@ -26,7 +26,7 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader
|
||||
|
||||
### How to enable
|
||||
|
||||
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
+ [Enable via configuration](https://github.com/thrasher-corp/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
|
||||
+ Individual package example below:
|
||||
|
||||
@@ -120,12 +120,12 @@ When submitting a PR, please abide by our coding guidelines:
|
||||
|
||||
+ Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)).
|
||||
+ Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines.
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-corp/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Pull requests need to be based on and opened against the `master` branch.
|
||||
|
||||
## Donations
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
|
||||
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
|
||||
|
||||
|
||||
@@ -8,11 +8,11 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -3,10 +3,10 @@ package exmo
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package exmo
|
||||
|
||||
import "github.com/thrasher-/gocryptotrader/currency"
|
||||
import "github.com/thrasher-corp/gocryptotrader/currency"
|
||||
|
||||
// Trades holds trade data
|
||||
type Trades struct {
|
||||
|
||||
@@ -8,15 +8,16 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
// GetDefaultConfig returns a default exchange config
|
||||
@@ -414,7 +415,7 @@ func (e *EXMO) WithdrawFiatFundsToInternationalBank(withdrawRequest *exchange.Fi
|
||||
}
|
||||
|
||||
// GetWebsocket returns a pointer to the exchange websocket
|
||||
func (e *EXMO) GetWebsocket() (*exchange.Websocket, error) {
|
||||
func (e *EXMO) GetWebsocket() (*wshandler.Websocket, error) {
|
||||
return nil, common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
@@ -498,18 +499,18 @@ func (e *EXMO) GetOrderHistory(getOrdersRequest *exchange.GetOrdersRequest) ([]e
|
||||
|
||||
// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle subscribing
|
||||
func (e *EXMO) SubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
func (e *EXMO) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle unsubscribing
|
||||
func (e *EXMO) UnsubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
func (e *EXMO) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// GetSubscriptions returns a copied list of subscriptions
|
||||
func (e *EXMO) GetSubscriptions() ([]exchange.WebsocketChannelSubscription, error) {
|
||||
func (e *EXMO) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
|
||||
return nil, common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# GoCryptoTrader package Gateio
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
|
||||
|
||||
[](https://travis-ci.org/thrasher-/gocryptotrader)
|
||||
[](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/gateio)
|
||||
[](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
|
||||
[](https://travis-ci.org/thrasher-corp/gocryptotrader)
|
||||
[](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/gateio)
|
||||
[](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-corp/gocryptotrader)
|
||||
|
||||
|
||||
This gateio package is part of the GoCryptoTrader codebase.
|
||||
@@ -26,7 +26,7 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader
|
||||
|
||||
### How to enable
|
||||
|
||||
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
+ [Enable via configuration](https://github.com/thrasher-corp/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
|
||||
+ Individual package example below:
|
||||
|
||||
@@ -127,12 +127,12 @@ When submitting a PR, please abide by our coding guidelines:
|
||||
|
||||
+ Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)).
|
||||
+ Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines.
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-corp/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Pull requests need to be based on and opened against the `master` branch.
|
||||
|
||||
## Donations
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
|
||||
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
|
||||
|
||||
|
||||
@@ -7,14 +7,13 @@ import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/common/convert"
|
||||
"github.com/thrasher-/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
||||
"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/wshandler"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -45,9 +44,8 @@ const (
|
||||
|
||||
// Gateio is the overarching type across this package
|
||||
type Gateio struct {
|
||||
WebsocketConn *websocket.Conn
|
||||
WebsocketConn *wshandler.WebsocketConnection
|
||||
exchange.Base
|
||||
wsRequestMtx sync.Mutex
|
||||
}
|
||||
|
||||
// GetSymbols returns all supported symbols
|
||||
|
||||
@@ -2,16 +2,15 @@ package gateio
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/sharedtestvalues"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/sharedtestvalues"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
)
|
||||
|
||||
// Please supply your own APIKEYS here for due diligence testing
|
||||
@@ -23,6 +22,7 @@ const (
|
||||
)
|
||||
|
||||
var g Gateio
|
||||
var wsSetupRan bool
|
||||
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
g.SetDefaults()
|
||||
@@ -500,47 +500,126 @@ func TestGetOrderInfo(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestWsAuth dials websocket, sends login request.
|
||||
func TestWsAuth(t *testing.T) {
|
||||
// TestWsGetBalance dials websocket, sends balance request.
|
||||
func TestWsGetBalance(t *testing.T) {
|
||||
g.SetDefaults()
|
||||
TestSetup(t)
|
||||
if !g.Websocket.IsEnabled() && !g.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip(exchange.WebsocketNotEnabled)
|
||||
t.Skip(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
g.WebsocketConn = &wshandler.WebsocketConnection{
|
||||
ExchangeName: g.Name,
|
||||
URL: gateioWebsocketEndpoint,
|
||||
Verbose: g.Verbose,
|
||||
RateLimit: gateioWebsocketRateLimit,
|
||||
ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
|
||||
ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
|
||||
}
|
||||
var err error
|
||||
var dialer websocket.Dialer
|
||||
g.WebsocketConn, _, err = dialer.Dial(g.Websocket.GetWebsocketURL(),
|
||||
http.Header{})
|
||||
err := g.WebsocketConn.Dial(&dialer, http.Header{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
go g.WsHandleData()
|
||||
g.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
|
||||
g.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
|
||||
go g.WsHandleData()
|
||||
defer g.WebsocketConn.Close()
|
||||
err = g.wsServerSignIn()
|
||||
resp, err := g.wsServerSignIn()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if resp.Result.Status != "success" {
|
||||
t.Fatal("Unsuccessful login")
|
||||
}
|
||||
_, err = g.wsGetBalance([]string{"EOS", "BTC"})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestWsGetOrderInfo dials websocket, sends order info request.
|
||||
func TestWsGetOrderInfo(t *testing.T) {
|
||||
g.SetDefaults()
|
||||
TestSetup(t)
|
||||
if !g.Websocket.IsEnabled() && !g.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
g.WebsocketConn = &wshandler.WebsocketConnection{
|
||||
ExchangeName: g.Name,
|
||||
URL: gateioWebsocketEndpoint,
|
||||
Verbose: g.Verbose,
|
||||
RateLimit: gateioWebsocketRateLimit,
|
||||
ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
|
||||
ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
|
||||
}
|
||||
var dialer websocket.Dialer
|
||||
err := g.WebsocketConn.Dial(&dialer, http.Header{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
go g.WsHandleData()
|
||||
g.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
|
||||
g.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
|
||||
resp, err := g.wsServerSignIn()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if resp.Result.Status != "success" {
|
||||
t.Fatal("Unsuccessful login")
|
||||
}
|
||||
_, err = g.wsGetOrderInfo("EOS_USDT", 0, 10)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func setupWSTestAuth(t *testing.T) {
|
||||
if wsSetupRan {
|
||||
return
|
||||
}
|
||||
g.SetDefaults()
|
||||
TestSetup(t)
|
||||
if !g.Websocket.IsEnabled() && !g.API.AuthenticatedWebsocketSupport {
|
||||
t.Skip(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
g.WebsocketConn = &wshandler.WebsocketConnection{
|
||||
ExchangeName: g.Name,
|
||||
URL: gateioWebsocketEndpoint,
|
||||
Verbose: g.Verbose,
|
||||
RateLimit: gateioWebsocketRateLimit,
|
||||
ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
|
||||
ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
|
||||
}
|
||||
var dialer websocket.Dialer
|
||||
err := g.WebsocketConn.Dial(&dialer, http.Header{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
go g.WsHandleData()
|
||||
g.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
|
||||
g.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
|
||||
wsSetupRan = true
|
||||
}
|
||||
|
||||
// TestWsSubscribe dials websocket, sends a subscribe request.
|
||||
func TestWsSubscribe(t *testing.T) {
|
||||
setupWSTestAuth(t)
|
||||
err := g.Subscribe(wshandler.WebsocketChannelSubscription{
|
||||
Channel: "ticker.subscribe",
|
||||
Currency: currency.NewPairWithDelimiter(currency.BTC.String(), currency.USDT.String(), "_"),
|
||||
})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestWsUnsubscribe dials websocket, sends an unsubscribe request.
|
||||
func TestWsUnsubscribe(t *testing.T) {
|
||||
setupWSTestAuth(t)
|
||||
err := g.Unsubscribe(wshandler.WebsocketChannelSubscription{
|
||||
Channel: "ticker.subscribe",
|
||||
Currency: currency.NewPairWithDelimiter(currency.BTC.String(), currency.USDT.String(), "_"),
|
||||
})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
timer := time.NewTimer(sharedtestvalues.WebsocketResponseDefaultTimeout)
|
||||
select {
|
||||
case resultString := <-g.Websocket.DataHandler:
|
||||
if !strings.Contains(resultString.(string), "success") {
|
||||
t.Error("Authentication failed")
|
||||
}
|
||||
case <-timer.C:
|
||||
t.Error("Expected response")
|
||||
}
|
||||
timer.Stop()
|
||||
err = g.wsGetBalance()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
timer = time.NewTimer(sharedtestvalues.WebsocketResponseDefaultTimeout)
|
||||
select {
|
||||
case <-g.Websocket.DataHandler:
|
||||
case <-timer.C:
|
||||
t.Error("Expected response")
|
||||
}
|
||||
timer.Stop()
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
)
|
||||
|
||||
// TimeInterval Interval represents interval enum.
|
||||
@@ -24,14 +24,6 @@ var (
|
||||
TimeIntervalDay = TimeInterval(60 * 60 * 24)
|
||||
)
|
||||
|
||||
// IDs for requests
|
||||
const (
|
||||
IDGeneric = 0000
|
||||
IDSignIn = 1010
|
||||
IDBalance = 2000
|
||||
IDOrderQuery = 3001
|
||||
)
|
||||
|
||||
// MarketInfoResponse holds the market info data
|
||||
type MarketInfoResponse struct {
|
||||
Result string `json:"result"`
|
||||
@@ -467,3 +459,32 @@ type WebSocketOrderQueryRecords struct {
|
||||
FilledAmount string `json:"filledAmount"`
|
||||
FilledTotal string `json:"filledTotal"`
|
||||
}
|
||||
|
||||
// WebsocketAuthenticationResponse contains the result of a login request
|
||||
type WebsocketAuthenticationResponse struct {
|
||||
Error string `json:"error"`
|
||||
Result struct {
|
||||
Status string `json:"status"`
|
||||
} `json:"result"`
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
|
||||
// wsGetBalanceRequest
|
||||
type wsGetBalanceRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
Method string `json:"method"`
|
||||
Params []string `json:"params,omitempty"`
|
||||
}
|
||||
|
||||
// WsGetBalanceResponse stores WS GetBalance response
|
||||
type WsGetBalanceResponse struct {
|
||||
Error interface{} `json:"error"`
|
||||
Result map[currency.Code]WsGetBalanceResponseData `json:"result,omitempty"`
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
|
||||
// WsGetBalanceResponseData contains currency data
|
||||
type WsGetBalanceResponseData struct {
|
||||
Available float64 `json:"available,string"`
|
||||
Freeze float64 `json:"freeze,string"`
|
||||
}
|
||||
|
||||
@@ -1,56 +1,42 @@
|
||||
package gateio
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
gateioWebsocketEndpoint = "wss://ws.gate.io/v3/"
|
||||
gatioWsMethodPing = "ping"
|
||||
gateioWebsocketRateLimit = 120 * time.Millisecond
|
||||
gateioWebsocketRateLimit = 120
|
||||
)
|
||||
|
||||
// WsConnect initiates a websocket connection
|
||||
func (g *Gateio) WsConnect() error {
|
||||
if !g.Websocket.IsEnabled() || !g.IsEnabled() {
|
||||
return errors.New(exchange.WebsocketNotEnabled)
|
||||
return errors.New(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
|
||||
var dialer websocket.Dialer
|
||||
if g.Websocket.GetProxyAddress() != "" {
|
||||
proxy, err := url.Parse(g.Websocket.GetProxyAddress())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dialer.Proxy = http.ProxyURL(proxy)
|
||||
}
|
||||
|
||||
var err error
|
||||
g.WebsocketConn, _, err = dialer.Dial(g.Websocket.GetWebsocketURL(),
|
||||
http.Header{})
|
||||
err := g.WebsocketConn.Dial(&dialer, http.Header{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go g.WsHandleData()
|
||||
|
||||
err = g.wsServerSignIn()
|
||||
_, err = g.wsServerSignIn()
|
||||
if err != nil {
|
||||
log.Errorf(log.ExchangeSys, "%v - authentication failed: %v\n", g.Name, err)
|
||||
}
|
||||
@@ -59,37 +45,33 @@ func (g *Gateio) WsConnect() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) wsServerSignIn() error {
|
||||
func (g *Gateio) wsServerSignIn() (*WebsocketAuthenticationResponse, error) {
|
||||
if !g.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
|
||||
return fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", g.Name)
|
||||
return nil, fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", g.Name)
|
||||
}
|
||||
nonce := int(time.Now().Unix() * 1000)
|
||||
sigTemp := g.GenerateSignature(strconv.Itoa(nonce))
|
||||
signature := crypto.Base64Encode(sigTemp)
|
||||
signinWsRequest := WebsocketRequest{
|
||||
ID: IDSignIn,
|
||||
ID: g.WebsocketConn.GenerateMessageID(true),
|
||||
Method: "server.sign",
|
||||
Params: []interface{}{g.API.Credentials.Key, signature, nonce},
|
||||
}
|
||||
err := g.wsSend(signinWsRequest)
|
||||
resp, err := g.WebsocketConn.SendMessageReturnResponse(signinWsRequest.ID, signinWsRequest)
|
||||
if err != nil {
|
||||
g.Websocket.SetCanUseAuthenticatedEndpoints(false)
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
time.Sleep(time.Second * 2) // sleep to allow server to complete sign-on if further authenticated requests are sent prior to this they will fail
|
||||
return nil
|
||||
}
|
||||
|
||||
// WsReadData reads from the websocket connection and returns the websocket
|
||||
// response
|
||||
func (g *Gateio) WsReadData() (exchange.WebsocketResponse, error) {
|
||||
_, resp, err := g.WebsocketConn.ReadMessage()
|
||||
var response WebsocketAuthenticationResponse
|
||||
err = common.JSONDecode(resp, &response)
|
||||
if err != nil {
|
||||
return exchange.WebsocketResponse{}, err
|
||||
g.Websocket.SetCanUseAuthenticatedEndpoints(false)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
g.Websocket.TrafficAlert <- struct{}{}
|
||||
return exchange.WebsocketResponse{Raw: resp}, nil
|
||||
if response.Result.Status == "success" {
|
||||
g.Websocket.SetCanUseAuthenticatedEndpoints(true)
|
||||
}
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
// WsHandleData handles all the websocket data coming from the websocket
|
||||
@@ -107,25 +89,28 @@ func (g *Gateio) WsHandleData() {
|
||||
return
|
||||
|
||||
default:
|
||||
resp, err := g.WsReadData()
|
||||
resp, err := g.WebsocketConn.ReadMessage()
|
||||
if err != nil {
|
||||
g.Websocket.DataHandler <- err
|
||||
// Read data error messages can overwhelm and panic the application
|
||||
time.Sleep(time.Second)
|
||||
continue
|
||||
return
|
||||
}
|
||||
|
||||
g.Websocket.TrafficAlert <- struct{}{}
|
||||
var result WebsocketResponse
|
||||
err = common.JSONDecode(resp.Raw, &result)
|
||||
if err != nil {
|
||||
g.Websocket.DataHandler <- err
|
||||
continue
|
||||
}
|
||||
|
||||
if result.ID > 0 {
|
||||
g.WebsocketConn.AddResponseWithID(result.ID, resp.Raw)
|
||||
continue
|
||||
}
|
||||
|
||||
if result.Error.Code != 0 {
|
||||
if strings.Contains(result.Error.Message, "authentication") {
|
||||
g.Websocket.DataHandler <- fmt.Errorf("%v - authentication failed: %v", g.Name, err)
|
||||
g.Websocket.SetCanUseAuthenticatedEndpoints(false)
|
||||
|
||||
continue
|
||||
}
|
||||
g.Websocket.DataHandler <- fmt.Errorf("%v error %s",
|
||||
@@ -133,49 +118,6 @@ func (g *Gateio) WsHandleData() {
|
||||
continue
|
||||
}
|
||||
|
||||
switch result.ID {
|
||||
case IDSignIn:
|
||||
g.Websocket.SetCanUseAuthenticatedEndpoints(true)
|
||||
g.Websocket.DataHandler <- string(result.Result)
|
||||
case IDBalance:
|
||||
var balance WebsocketBalance
|
||||
var balanceInterface interface{}
|
||||
err = json.Unmarshal(result.Result, &balanceInterface)
|
||||
if err != nil {
|
||||
g.Websocket.DataHandler <- err
|
||||
}
|
||||
var p WebsocketBalanceCurrency
|
||||
switch x := balanceInterface.(type) {
|
||||
case map[string]interface{}:
|
||||
for xx := range x {
|
||||
switch kk := x[xx].(type) {
|
||||
case map[string]interface{}:
|
||||
p = WebsocketBalanceCurrency{
|
||||
Currency: xx,
|
||||
Available: kk["available"].(string),
|
||||
Locked: kk["freeze"].(string),
|
||||
}
|
||||
balance.Currency = append(balance.Currency, p)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
g.Websocket.DataHandler <- balance
|
||||
case IDOrderQuery:
|
||||
var orderQuery WebSocketOrderQueryResult
|
||||
err = common.JSONDecode(result.Result, &orderQuery)
|
||||
if err != nil {
|
||||
g.Websocket.DataHandler <- err
|
||||
continue
|
||||
}
|
||||
g.Websocket.DataHandler <- orderQuery
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
switch {
|
||||
case strings.Contains(result.Method, "ticker"):
|
||||
var ticker WebsocketTicker
|
||||
@@ -192,7 +134,7 @@ func (g *Gateio) WsHandleData() {
|
||||
continue
|
||||
}
|
||||
|
||||
g.Websocket.DataHandler <- exchange.TickerData{
|
||||
g.Websocket.DataHandler <- wshandler.TickerData{
|
||||
Timestamp: time.Now(),
|
||||
Pair: currency.NewPairFromString(c),
|
||||
AssetType: asset.Spot,
|
||||
@@ -220,7 +162,7 @@ func (g *Gateio) WsHandleData() {
|
||||
}
|
||||
|
||||
for _, trade := range trades {
|
||||
g.Websocket.DataHandler <- exchange.TradeData{
|
||||
g.Websocket.DataHandler <- wshandler.TradeData{
|
||||
Timestamp: time.Now(),
|
||||
CurrencyPair: currency.NewPairFromString(c),
|
||||
AssetType: asset.Spot,
|
||||
@@ -313,7 +255,7 @@ func (g *Gateio) WsHandleData() {
|
||||
}
|
||||
}
|
||||
|
||||
g.Websocket.DataHandler <- exchange.WebsocketOrderbookUpdate{
|
||||
g.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
|
||||
Pair: currency.NewPairFromString(c),
|
||||
Asset: asset.Spot,
|
||||
Exchange: g.GetName(),
|
||||
@@ -333,7 +275,7 @@ func (g *Gateio) WsHandleData() {
|
||||
low, _ := strconv.ParseFloat(data[4].(string), 64)
|
||||
volume, _ := strconv.ParseFloat(data[5].(string), 64)
|
||||
|
||||
g.Websocket.DataHandler <- exchange.KlineData{
|
||||
g.Websocket.DataHandler <- wshandler.KlineData{
|
||||
Timestamp: time.Now(),
|
||||
Pair: currency.NewPairFromString(data[7].(string)),
|
||||
AssetType: asset.Spot,
|
||||
@@ -355,11 +297,11 @@ func (g *Gateio) GenerateAuthenticatedSubscriptions() {
|
||||
return
|
||||
}
|
||||
var channels = []string{"balance.subscribe", "order.subscribe"}
|
||||
var subscriptions []exchange.WebsocketChannelSubscription
|
||||
var subscriptions []wshandler.WebsocketChannelSubscription
|
||||
enabledCurrencies := g.GetEnabledPairs(asset.Spot)
|
||||
for i := range channels {
|
||||
for j := range enabledCurrencies {
|
||||
subscriptions = append(subscriptions, exchange.WebsocketChannelSubscription{
|
||||
subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
|
||||
Channel: channels[i],
|
||||
Currency: enabledCurrencies[j],
|
||||
})
|
||||
@@ -371,7 +313,7 @@ func (g *Gateio) GenerateAuthenticatedSubscriptions() {
|
||||
// GenerateDefaultSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions()
|
||||
func (g *Gateio) GenerateDefaultSubscriptions() {
|
||||
var channels = []string{"ticker.subscribe", "trades.subscribe", "depth.subscribe", "kline.subscribe"}
|
||||
var subscriptions []exchange.WebsocketChannelSubscription
|
||||
var subscriptions []wshandler.WebsocketChannelSubscription
|
||||
enabledCurrencies := g.GetEnabledPairs(asset.Spot)
|
||||
for i := range channels {
|
||||
for j := range enabledCurrencies {
|
||||
@@ -382,7 +324,7 @@ func (g *Gateio) GenerateDefaultSubscriptions() {
|
||||
} else if strings.EqualFold(channels[i], "kline.subscribe") {
|
||||
params["interval"] = 1800
|
||||
}
|
||||
subscriptions = append(subscriptions, exchange.WebsocketChannelSubscription{
|
||||
subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
|
||||
Channel: channels[i],
|
||||
Currency: enabledCurrencies[j],
|
||||
Params: params,
|
||||
@@ -393,54 +335,84 @@ func (g *Gateio) GenerateDefaultSubscriptions() {
|
||||
}
|
||||
|
||||
// Subscribe sends a websocket message to receive data from the channel
|
||||
func (g *Gateio) Subscribe(channelToSubscribe exchange.WebsocketChannelSubscription) error {
|
||||
func (g *Gateio) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
|
||||
params := []interface{}{channelToSubscribe.Currency.String()}
|
||||
for _, paramValue := range channelToSubscribe.Params {
|
||||
params = append(params, paramValue)
|
||||
}
|
||||
|
||||
subscribe := WebsocketRequest{
|
||||
ID: IDGeneric,
|
||||
ID: g.WebsocketConn.GenerateMessageID(true),
|
||||
Method: channelToSubscribe.Channel,
|
||||
Params: params,
|
||||
}
|
||||
|
||||
if strings.EqualFold(channelToSubscribe.Channel, "balance.subscribe") {
|
||||
subscribe.ID = IDBalance
|
||||
resp, err := g.WebsocketConn.SendMessageReturnResponse(subscribe.ID, subscribe)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return g.wsSend(subscribe)
|
||||
var response WebsocketAuthenticationResponse
|
||||
err = common.JSONDecode(resp, &response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if response.Result.Status != "success" {
|
||||
return fmt.Errorf("%v could not subscribe to %v", g.Name, channelToSubscribe.Channel)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Unsubscribe sends a websocket message to stop receiving data from the channel
|
||||
func (g *Gateio) Unsubscribe(channelToSubscribe exchange.WebsocketChannelSubscription) error {
|
||||
func (g *Gateio) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
|
||||
unsbuscribeText := strings.Replace(channelToSubscribe.Channel, "subscribe", "unsubscribe", 1)
|
||||
subscribe := WebsocketRequest{
|
||||
ID: IDGeneric,
|
||||
ID: g.WebsocketConn.GenerateMessageID(true),
|
||||
Method: unsbuscribeText,
|
||||
Params: []interface{}{channelToSubscribe.Currency.String(), 1800},
|
||||
}
|
||||
return g.wsSend(subscribe)
|
||||
resp, err := g.WebsocketConn.SendMessageReturnResponse(subscribe.ID, subscribe)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var response WebsocketAuthenticationResponse
|
||||
err = common.JSONDecode(resp, &response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if response.Result.Status != "success" {
|
||||
return fmt.Errorf("%v could not subscribe to %v", g.Name, channelToSubscribe.Channel)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) wsGetBalance() error {
|
||||
func (g *Gateio) wsGetBalance(currencies []string) (*WsGetBalanceResponse, error) {
|
||||
if !g.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
return fmt.Errorf("%v not authorised to get balance", g.Name)
|
||||
return nil, fmt.Errorf("%v not authorised to get balance", g.Name)
|
||||
}
|
||||
balanceWsRequest := WebsocketRequest{
|
||||
ID: IDBalance,
|
||||
balanceWsRequest := wsGetBalanceRequest{
|
||||
ID: g.WebsocketConn.GenerateMessageID(false),
|
||||
Method: "balance.query",
|
||||
Params: []interface{}{},
|
||||
Params: currencies,
|
||||
}
|
||||
return g.wsSend(balanceWsRequest)
|
||||
resp, err := g.WebsocketConn.SendMessageReturnResponse(balanceWsRequest.ID, balanceWsRequest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var balance WsGetBalanceResponse
|
||||
err = common.JSONDecode(resp, &balance)
|
||||
if err != nil {
|
||||
return &balance, err
|
||||
}
|
||||
|
||||
return &balance, nil
|
||||
}
|
||||
|
||||
func (g *Gateio) wsGetOrderInfo(market string, offset, limit int) error {
|
||||
func (g *Gateio) wsGetOrderInfo(market string, offset, limit int) (*WebSocketOrderQueryResult, error) {
|
||||
if !g.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
return fmt.Errorf("%v not authorised to get order info", g.Name)
|
||||
return nil, fmt.Errorf("%v not authorised to get order info", g.Name)
|
||||
}
|
||||
order := WebsocketRequest{
|
||||
ID: IDOrderQuery,
|
||||
ID: g.WebsocketConn.GenerateMessageID(true),
|
||||
Method: "order.query",
|
||||
Params: []interface{}{
|
||||
market,
|
||||
@@ -448,17 +420,14 @@ func (g *Gateio) wsGetOrderInfo(market string, offset, limit int) error {
|
||||
limit,
|
||||
},
|
||||
}
|
||||
return g.wsSend(order)
|
||||
}
|
||||
|
||||
// WsSend sends data to the websocket server
|
||||
func (g *Gateio) wsSend(data interface{}) error {
|
||||
g.wsRequestMtx.Lock()
|
||||
defer g.wsRequestMtx.Unlock()
|
||||
if g.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%v sending message to websocket %v", g.Name, data)
|
||||
resp, err := g.WebsocketConn.SendMessageReturnResponse(order.ID, order)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Basic rate limiter
|
||||
time.Sleep(gateioWebsocketRateLimit)
|
||||
return g.WebsocketConn.WriteJSON(data)
|
||||
var orderQuery WebSocketOrderQueryResult
|
||||
err = common.JSONDecode(resp, &orderQuery)
|
||||
if err != nil {
|
||||
return &orderQuery, err
|
||||
}
|
||||
return &orderQuery, nil
|
||||
}
|
||||
|
||||
@@ -8,15 +8,16 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
// GetDefaultConfig returns a default exchange config
|
||||
@@ -90,13 +91,17 @@ func (g *Gateio) SetDefaults() {
|
||||
g.API.Endpoints.URLSecondaryDefault = gateioMarketURL
|
||||
g.API.Endpoints.URLSecondary = g.API.Endpoints.URLSecondaryDefault
|
||||
g.API.Endpoints.WebsocketURL = gateioWebsocketEndpoint
|
||||
g.WebsocketInit()
|
||||
g.Websocket.Functionality = exchange.WebsocketTickerSupported |
|
||||
exchange.WebsocketTradeDataSupported |
|
||||
exchange.WebsocketOrderbookSupported |
|
||||
exchange.WebsocketKlineSupported |
|
||||
exchange.WebsocketSubscribeSupported |
|
||||
exchange.WebsocketUnsubscribeSupported
|
||||
g.Websocket = wshandler.New()
|
||||
g.Websocket.Functionality = wshandler.WebsocketTickerSupported |
|
||||
wshandler.WebsocketTradeDataSupported |
|
||||
wshandler.WebsocketOrderbookSupported |
|
||||
wshandler.WebsocketKlineSupported |
|
||||
wshandler.WebsocketSubscribeSupported |
|
||||
wshandler.WebsocketUnsubscribeSupported |
|
||||
wshandler.WebsocketAuthenticatedEndpointsSupported |
|
||||
wshandler.WebsocketMessageCorrelationSupported
|
||||
g.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
|
||||
g.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
|
||||
}
|
||||
|
||||
// Setup sets user configuration
|
||||
@@ -111,14 +116,29 @@ func (g *Gateio) Setup(exch *config.ExchangeConfig) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return g.WebsocketSetup(g.WsConnect,
|
||||
err = g.Websocket.Setup(g.WsConnect,
|
||||
g.Subscribe,
|
||||
g.Unsubscribe,
|
||||
exch.Name,
|
||||
exch.Features.Enabled.Websocket,
|
||||
exch.Verbose,
|
||||
gateioWebsocketEndpoint,
|
||||
exch.API.Endpoints.WebsocketURL)
|
||||
exch.API.Endpoints.WebsocketURL,
|
||||
exch.API.AuthenticatedWebsocketSupport)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
g.WebsocketConn = &wshandler.WebsocketConnection{
|
||||
ExchangeName: g.Name,
|
||||
URL: g.Websocket.GetWebsocketURL(),
|
||||
ProxyURL: g.Websocket.GetProxyAddress(),
|
||||
Verbose: g.Verbose,
|
||||
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
|
||||
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
|
||||
RateLimit: gateioWebsocketRateLimit,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Start starts the GateIO go routine
|
||||
@@ -473,7 +493,7 @@ func (g *Gateio) WithdrawFiatFundsToInternationalBank(withdrawRequest *exchange.
|
||||
}
|
||||
|
||||
// GetWebsocket returns a pointer to the exchange websocket
|
||||
func (g *Gateio) GetWebsocket() (*exchange.Websocket, error) {
|
||||
func (g *Gateio) GetWebsocket() (*wshandler.Websocket, error) {
|
||||
return g.Websocket, nil
|
||||
}
|
||||
|
||||
@@ -564,24 +584,25 @@ func (g *Gateio) GetOrderHistory(getOrdersRequest *exchange.GetOrdersRequest) ([
|
||||
|
||||
// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle subscribing
|
||||
func (g *Gateio) SubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
func (g *Gateio) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
g.Websocket.SubscribeToChannels(channels)
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle unsubscribing
|
||||
func (g *Gateio) UnsubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
g.Websocket.UnsubscribeToChannels(channels)
|
||||
func (g *Gateio) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
g.Websocket.RemoveSubscribedChannels(channels)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetSubscriptions returns a copied list of subscriptions
|
||||
func (g *Gateio) GetSubscriptions() ([]exchange.WebsocketChannelSubscription, error) {
|
||||
func (g *Gateio) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
|
||||
return g.Websocket.GetSubscriptions(), nil
|
||||
}
|
||||
|
||||
// AuthenticateWebsocket sends an authentication message to the websocket
|
||||
func (g *Gateio) AuthenticateWebsocket() error {
|
||||
return g.wsServerSignIn()
|
||||
_, err := g.wsServerSignIn()
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# GoCryptoTrader package Gemini
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
|
||||
|
||||
[](https://travis-ci.org/thrasher-/gocryptotrader)
|
||||
[](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/gemini)
|
||||
[](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
|
||||
[](https://travis-ci.org/thrasher-corp/gocryptotrader)
|
||||
[](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/gemini)
|
||||
[](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-corp/gocryptotrader)
|
||||
|
||||
|
||||
This gemini package is part of the GoCryptoTrader codebase.
|
||||
@@ -26,7 +26,7 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader
|
||||
|
||||
### How to enable
|
||||
|
||||
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
+ [Enable via configuration](https://github.com/thrasher-corp/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
|
||||
+ Individual package example below:
|
||||
|
||||
@@ -120,12 +120,12 @@ When submitting a PR, please abide by our coding guidelines:
|
||||
|
||||
+ Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)).
|
||||
+ Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines.
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-corp/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Pull requests need to be based on and opened against the `master` branch.
|
||||
|
||||
## Donations
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
|
||||
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
|
||||
|
||||
|
||||
@@ -8,11 +8,11 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/common/crypto"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/crypto"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -64,7 +64,8 @@ var (
|
||||
// AddSession, if sandbox test is needed append a new session with with the same
|
||||
// API keys and change the IsSandbox variable to true.
|
||||
type Gemini struct {
|
||||
WebsocketConn *websocket.Conn
|
||||
WebsocketConn *wshandler.WebsocketConnection
|
||||
AuthenticatedWebsocketConn *wshandler.WebsocketConnection
|
||||
exchange.Base
|
||||
Role string
|
||||
RequiresHeartBeat bool
|
||||
@@ -92,7 +93,6 @@ func AddSession(g *Gemini, sessionID int, apiKey, apiSecret, role string, needsH
|
||||
}
|
||||
|
||||
Session[sessionID] = g
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -105,7 +105,6 @@ func (g *Gemini) GetSymbols() ([]string, error) {
|
||||
|
||||
// GetTicker returns information about recent trading activity for the symbol
|
||||
func (g *Gemini) GetTicker(currencyPair string) (Ticker, error) {
|
||||
|
||||
type TickerResponse struct {
|
||||
Ask float64 `json:"ask,string"`
|
||||
Bid float64 `json:"bid,string"`
|
||||
@@ -130,7 +129,6 @@ func (g *Gemini) GetTicker(currencyPair string) (Ticker, error) {
|
||||
ticker.Ask = resp.Ask
|
||||
ticker.Bid = resp.Bid
|
||||
ticker.Last = resp.Last
|
||||
|
||||
ticker.Volume.Currency, _ = strconv.ParseFloat(resp.Volume[currencyPair[0:3]].(string), 64)
|
||||
|
||||
if strings.Contains(currencyPair, "USD") {
|
||||
|
||||
@@ -6,11 +6,12 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/sharedtestvalues"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/sharedtestvalues"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
)
|
||||
|
||||
// Please enter sandbox API keys & assigned roles for better testing procedures
|
||||
@@ -573,7 +574,7 @@ func TestWsAuth(t *testing.T) {
|
||||
g.API.Endpoints.WebsocketURL = geminiWebsocketSandboxEndpoint
|
||||
|
||||
if !g.Websocket.IsEnabled() && !g.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip(exchange.WebsocketNotEnabled)
|
||||
t.Skip(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
var dialer websocket.Dialer
|
||||
go g.WsHandleData()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package gemini
|
||||
|
||||
import "github.com/thrasher-/gocryptotrader/currency"
|
||||
import "github.com/thrasher-corp/gocryptotrader/currency"
|
||||
|
||||
// Ticker holds returned ticker data from the exchange
|
||||
type Ticker struct {
|
||||
|
||||
@@ -10,13 +10,14 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -29,11 +30,13 @@ const (
|
||||
|
||||
// Instantiates a communications channel between websocket connections
|
||||
var comms = make(chan ReadData, 1)
|
||||
var responseMaxLimit time.Duration
|
||||
var responseCheckTimeout time.Duration
|
||||
|
||||
// WsConnect initiates a websocket connection
|
||||
func (g *Gemini) WsConnect() error {
|
||||
if !g.Websocket.IsEnabled() || !g.IsEnabled() {
|
||||
return errors.New(exchange.WebsocketNotEnabled)
|
||||
return errors.New(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
|
||||
var dialer websocket.Dialer
|
||||
@@ -64,12 +67,19 @@ func (g *Gemini) WsSubscribe(dialer *websocket.Dialer) error {
|
||||
geminiWsMarketData,
|
||||
c.String(),
|
||||
val.Encode())
|
||||
conn, conStatus, err := dialer.Dial(endpoint, http.Header{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s websocket endpoint: %v Status: %v Error: %v", g.Name,
|
||||
endpoint, conStatus, err)
|
||||
connection := &wshandler.WebsocketConnection{
|
||||
ExchangeName: g.Name,
|
||||
URL: endpoint,
|
||||
Verbose: g.Verbose,
|
||||
ResponseCheckTimeout: responseCheckTimeout,
|
||||
ResponseMaxLimit: responseMaxLimit,
|
||||
}
|
||||
go g.WsReadData(conn, c)
|
||||
err := connection.Dial(dialer, http.Header{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("%v Websocket connection %v error. Error %v",
|
||||
g.Name, endpoint, err)
|
||||
}
|
||||
go g.WsReadData(connection, c)
|
||||
if len(enabledCurrencies)-1 == i {
|
||||
return nil
|
||||
}
|
||||
@@ -102,17 +112,22 @@ func (g *Gemini) WsSecureSubscribe(dialer *websocket.Dialer, url string) error {
|
||||
headers.Add("X-GEMINI-SIGNATURE", crypto.HexEncodeToString(hmac))
|
||||
headers.Add("Cache-Control", "no-cache")
|
||||
|
||||
conn, conStatus, err := dialer.Dial(endpoint, headers)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%v %v %v Error: %v", endpoint, conStatus, conStatus.StatusCode, err)
|
||||
g.AuthenticatedWebsocketConn = &wshandler.WebsocketConnection{
|
||||
ExchangeName: g.Name,
|
||||
URL: endpoint,
|
||||
Verbose: g.Verbose,
|
||||
}
|
||||
go g.WsReadData(conn, currency.Pair{})
|
||||
err = g.AuthenticatedWebsocketConn.Dial(dialer, headers)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%v Websocket connection %v error. Error %v", g.Name, endpoint, err)
|
||||
}
|
||||
go g.WsReadData(g.AuthenticatedWebsocketConn, currency.Pair{})
|
||||
return nil
|
||||
}
|
||||
|
||||
// WsReadData reads from the websocket connection and returns the websocket
|
||||
// response
|
||||
func (g *Gemini) WsReadData(ws *websocket.Conn, c currency.Pair) {
|
||||
func (g *Gemini) WsReadData(ws *wshandler.WebsocketConnection, c currency.Pair) {
|
||||
g.Websocket.Wg.Add(1)
|
||||
defer g.Websocket.Wg.Done()
|
||||
for {
|
||||
@@ -120,13 +135,13 @@ func (g *Gemini) WsReadData(ws *websocket.Conn, c currency.Pair) {
|
||||
case <-g.Websocket.ShutdownC:
|
||||
return
|
||||
default:
|
||||
_, resp, err := ws.ReadMessage()
|
||||
resp, err := ws.ReadMessage()
|
||||
if err != nil {
|
||||
g.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
g.Websocket.TrafficAlert <- struct{}{}
|
||||
comms <- ReadData{Raw: resp, Currency: c}
|
||||
comms <- ReadData{Raw: resp.Raw, Currency: c}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -274,13 +289,13 @@ func (g *Gemini) wsProcessUpdate(result WsMarketUpdateResponse, pair currency.Pa
|
||||
return
|
||||
}
|
||||
|
||||
g.Websocket.DataHandler <- exchange.WebsocketOrderbookUpdate{Pair: pair,
|
||||
g.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{Pair: pair,
|
||||
Asset: asset.Spot,
|
||||
Exchange: g.GetName()}
|
||||
} else {
|
||||
for _, event := range result.Events {
|
||||
if event.Type == "trade" {
|
||||
g.Websocket.DataHandler <- exchange.TradeData{
|
||||
g.Websocket.DataHandler <- wshandler.TradeData{
|
||||
Timestamp: time.Now(),
|
||||
CurrencyPair: pair,
|
||||
AssetType: asset.Spot,
|
||||
@@ -319,7 +334,7 @@ func (g *Gemini) wsProcessUpdate(result WsMarketUpdateResponse, pair currency.Pa
|
||||
}
|
||||
}
|
||||
|
||||
g.Websocket.DataHandler <- exchange.WebsocketOrderbookUpdate{Pair: pair,
|
||||
g.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{Pair: pair,
|
||||
Asset: asset.Spot,
|
||||
Exchange: g.GetName()}
|
||||
}
|
||||
|
||||
@@ -9,15 +9,16 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
// GetDefaultConfig returns a default exchange config
|
||||
@@ -88,9 +89,14 @@ func (g *Gemini) SetDefaults() {
|
||||
|
||||
g.API.Endpoints.URLDefault = geminiAPIURL
|
||||
g.API.Endpoints.URL = g.API.Endpoints.URLDefault
|
||||
g.WebsocketInit()
|
||||
g.Websocket.Functionality = exchange.WebsocketOrderbookSupported |
|
||||
exchange.WebsocketTradeDataSupported
|
||||
g.API.Endpoints.WebsocketURL = geminiWebsocketEndpoint
|
||||
g.Websocket = wshandler.New()
|
||||
g.Websocket.Functionality = wshandler.WebsocketOrderbookSupported |
|
||||
wshandler.WebsocketTradeDataSupported |
|
||||
wshandler.WebsocketAuthenticatedEndpointsSupported |
|
||||
wshandler.WebsocketSequenceNumberSupported
|
||||
g.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
|
||||
g.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
|
||||
}
|
||||
|
||||
// Setup sets exchange configuration parameters
|
||||
@@ -109,14 +115,28 @@ func (g *Gemini) Setup(exch *config.ExchangeConfig) error {
|
||||
g.API.Endpoints.URL = geminiSandboxAPIURL
|
||||
}
|
||||
|
||||
return g.WebsocketSetup(g.WsConnect,
|
||||
err = g.Websocket.Setup(g.WsConnect,
|
||||
nil,
|
||||
nil,
|
||||
exch.Name,
|
||||
exch.Features.Enabled.Websocket,
|
||||
exch.Verbose,
|
||||
geminiWebsocketEndpoint,
|
||||
exch.API.Endpoints.WebsocketURL)
|
||||
exch.API.Endpoints.WebsocketURL,
|
||||
exch.API.AuthenticatedWebsocketSupport)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
g.WebsocketConn = &wshandler.WebsocketConnection{
|
||||
ExchangeName: g.Name,
|
||||
URL: g.Websocket.GetWebsocketURL(),
|
||||
ProxyURL: g.Websocket.GetProxyAddress(),
|
||||
Verbose: g.Verbose,
|
||||
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
|
||||
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Start starts the Gemini go routine
|
||||
@@ -366,7 +386,7 @@ func (g *Gemini) WithdrawFiatFundsToInternationalBank(withdrawRequest *exchange.
|
||||
}
|
||||
|
||||
// GetWebsocket returns a pointer to the exchange websocket
|
||||
func (g *Gemini) GetWebsocket() (*exchange.Websocket, error) {
|
||||
func (g *Gemini) GetWebsocket() (*wshandler.Websocket, error) {
|
||||
return g.Websocket, nil
|
||||
}
|
||||
|
||||
@@ -471,18 +491,18 @@ func (g *Gemini) GetOrderHistory(getOrdersRequest *exchange.GetOrdersRequest) ([
|
||||
|
||||
// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle subscribing
|
||||
func (g *Gemini) SubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
func (g *Gemini) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle unsubscribing
|
||||
func (g *Gemini) UnsubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
func (g *Gemini) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// GetSubscriptions returns a copied list of subscriptions
|
||||
func (g *Gemini) GetSubscriptions() ([]exchange.WebsocketChannelSubscription, error) {
|
||||
func (g *Gemini) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
|
||||
return nil, common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# GoCryptoTrader package Hitbtc
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
|
||||
|
||||
[](https://travis-ci.org/thrasher-/gocryptotrader)
|
||||
[](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/hitbtc)
|
||||
[](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
|
||||
[](https://travis-ci.org/thrasher-corp/gocryptotrader)
|
||||
[](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/hitbtc)
|
||||
[](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-corp/gocryptotrader)
|
||||
|
||||
|
||||
This hitbtc package is part of the GoCryptoTrader codebase.
|
||||
@@ -27,7 +27,7 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader
|
||||
|
||||
### How to enable
|
||||
|
||||
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
+ [Enable via configuration](https://github.com/thrasher-corp/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
|
||||
+ Individual package example below:
|
||||
|
||||
@@ -128,12 +128,12 @@ When submitting a PR, please abide by our coding guidelines:
|
||||
|
||||
+ Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)).
|
||||
+ Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines.
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-corp/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Pull requests need to be based on and opened against the `master` branch.
|
||||
|
||||
## Donations
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
|
||||
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
|
||||
|
||||
|
||||
@@ -7,12 +7,11 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"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/wshandler"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -48,8 +47,7 @@ const (
|
||||
// HitBTC is the overarching type across the hitbtc package
|
||||
type HitBTC struct {
|
||||
exchange.Base
|
||||
WebsocketConn *websocket.Conn
|
||||
wsRequestMtx sync.Mutex
|
||||
WebsocketConn *wshandler.WebsocketConnection
|
||||
}
|
||||
|
||||
// Public Market Data
|
||||
|
||||
@@ -6,14 +6,16 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/sharedtestvalues"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/sharedtestvalues"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
)
|
||||
|
||||
var h HitBTC
|
||||
var wsSetupRan bool
|
||||
|
||||
// Please supply your own APIKEYS here for due diligence testing
|
||||
const (
|
||||
@@ -102,7 +104,7 @@ func TestGetFee(t *testing.T) {
|
||||
var feeBuilder = setFeeBuilder()
|
||||
if areTestAPIKeysSet() {
|
||||
// CryptocurrencyTradeFee Basic
|
||||
if resp, err := h.GetFee(feeBuilder); resp != float64(0.001) || err != nil {
|
||||
if resp, err := h.GetFee(feeBuilder); resp != float64(0.002) || err != nil {
|
||||
t.Error(err)
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0.002), resp)
|
||||
}
|
||||
@@ -111,7 +113,7 @@ func TestGetFee(t *testing.T) {
|
||||
feeBuilder = setFeeBuilder()
|
||||
feeBuilder.Amount = 1000
|
||||
feeBuilder.PurchasePrice = 1000
|
||||
if resp, err := h.GetFee(feeBuilder); resp != float64(1000) || err != nil {
|
||||
if resp, err := h.GetFee(feeBuilder); resp != float64(2000) || err != nil {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(2000), resp)
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -119,7 +121,7 @@ func TestGetFee(t *testing.T) {
|
||||
// CryptocurrencyTradeFee IsMaker
|
||||
feeBuilder = setFeeBuilder()
|
||||
feeBuilder.IsMaker = true
|
||||
if resp, err := h.GetFee(feeBuilder); resp != float64(-0.0001) || err != nil {
|
||||
if resp, err := h.GetFee(feeBuilder); resp != float64(0.001) || err != nil {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0.001), resp)
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -127,7 +129,7 @@ func TestGetFee(t *testing.T) {
|
||||
// CryptocurrencyTradeFee Negative purchase price
|
||||
feeBuilder = setFeeBuilder()
|
||||
feeBuilder.PurchasePrice = -1000
|
||||
if resp, err := h.GetFee(feeBuilder); resp != float64(-1) || err != nil {
|
||||
if resp, err := h.GetFee(feeBuilder); resp != float64(0) || err != nil {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0), resp)
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -135,7 +137,7 @@ func TestGetFee(t *testing.T) {
|
||||
// CryptocurrencyWithdrawalFee Basic
|
||||
feeBuilder = setFeeBuilder()
|
||||
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
|
||||
if resp, err := h.GetFee(feeBuilder); resp != float64(0.009580) || err != nil {
|
||||
if resp, err := h.GetFee(feeBuilder); resp != float64(0.042800) || err != nil {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0.042800), resp)
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -389,16 +391,25 @@ func TestGetDepositAddress(t *testing.T) {
|
||||
}
|
||||
}
|
||||
func setupWsAuth(t *testing.T) {
|
||||
if wsSetupRan {
|
||||
return
|
||||
}
|
||||
TestSetDefaults(t)
|
||||
TestSetup(t)
|
||||
if !h.Websocket.IsEnabled() && !h.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip(exchange.WebsocketNotEnabled)
|
||||
t.Skip(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
var err error
|
||||
var dialer websocket.Dialer
|
||||
h.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
|
||||
h.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
|
||||
h.WebsocketConn, _, err = dialer.Dial(hitbtcWebsocketAddress, http.Header{})
|
||||
h.WebsocketConn = &wshandler.WebsocketConnection{
|
||||
ExchangeName: h.Name,
|
||||
URL: hitbtcWebsocketAddress,
|
||||
Verbose: h.Verbose,
|
||||
ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
|
||||
ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
|
||||
}
|
||||
var dialer websocket.Dialer
|
||||
err := h.WebsocketConn.Dial(&dialer, http.Header{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -411,84 +422,86 @@ func setupWsAuth(t *testing.T) {
|
||||
case <-timer.C:
|
||||
}
|
||||
timer.Stop()
|
||||
wsSetupRan = true
|
||||
}
|
||||
|
||||
// TestWsCancelOrder dials websocket, sends cancel request.
|
||||
func TestWsCancelOrder(t *testing.T) {
|
||||
setupWsAuth(t)
|
||||
err := h.wsCancelOrder("ImNotARealOrderID")
|
||||
if !canManipulateRealOrders {
|
||||
t.Skip("canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
_, err := h.wsCancelOrder("ImNotARealOrderID")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
timer := time.NewTimer(sharedtestvalues.WebsocketResponseDefaultTimeout)
|
||||
select {
|
||||
case <-h.Websocket.DataHandler:
|
||||
case <-timer.C:
|
||||
t.Error("Expecting response")
|
||||
}
|
||||
timer.Stop()
|
||||
}
|
||||
|
||||
// TestWsPlaceOrder dials websocket, sends order submission.
|
||||
func TestWsPlaceOrder(t *testing.T) {
|
||||
setupWsAuth(t)
|
||||
err := h.wsPlaceOrder(currency.NewPair(currency.LTC, currency.BTC), exchange.BuyOrderSide.ToString(), 1, 1)
|
||||
if !canManipulateRealOrders {
|
||||
t.Skip("canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
_, err := h.wsPlaceOrder(currency.NewPair(currency.LTC, currency.BTC), exchange.BuyOrderSide.ToString(), 1, 1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
timer := time.NewTimer(sharedtestvalues.WebsocketResponseDefaultTimeout)
|
||||
select {
|
||||
case <-h.Websocket.DataHandler:
|
||||
case <-timer.C:
|
||||
t.Error("Expecting response")
|
||||
}
|
||||
timer.Stop()
|
||||
}
|
||||
|
||||
// TestWsReplaceOrder dials websocket, sends replace order request.
|
||||
func TestWsReplaceOrder(t *testing.T) {
|
||||
setupWsAuth(t)
|
||||
err := h.wsReplaceOrder("ImNotARealOrderID", 1, 1)
|
||||
if !canManipulateRealOrders {
|
||||
t.Skip("canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
_, err := h.wsReplaceOrder("ImNotARealOrderID", 1, 1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
timer := time.NewTimer(sharedtestvalues.WebsocketResponseDefaultTimeout)
|
||||
select {
|
||||
case <-h.Websocket.DataHandler:
|
||||
case <-timer.C:
|
||||
t.Error("Expecting response")
|
||||
}
|
||||
timer.Stop()
|
||||
}
|
||||
|
||||
// TestWsGetActiveOrders dials websocket, sends get active orders request.
|
||||
func TestWsGetActiveOrders(t *testing.T) {
|
||||
setupWsAuth(t)
|
||||
err := h.wsGetActiveOrders()
|
||||
_, err := h.wsGetActiveOrders()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
timer := time.NewTimer(sharedtestvalues.WebsocketResponseDefaultTimeout)
|
||||
select {
|
||||
case <-h.Websocket.DataHandler:
|
||||
case <-timer.C:
|
||||
t.Error("Expecting response")
|
||||
}
|
||||
timer.Stop()
|
||||
}
|
||||
|
||||
// TestWsGetTradingBalance dials websocket, sends get trading balance request.
|
||||
func TestWsGetTradingBalance(t *testing.T) {
|
||||
setupWsAuth(t)
|
||||
err := h.wsGetTradingBalance()
|
||||
_, err := h.wsGetTradingBalance()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestWsGetTradingBalance dials websocket, sends get trading balance request.
|
||||
func TestWsGetTrades(t *testing.T) {
|
||||
setupWsAuth(t)
|
||||
_, err := h.wsGetTrades(currency.NewPair(currency.ETH, currency.BTC), 1000, "ASC", "id")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestWsGetTradingBalance dials websocket, sends get trading balance request.
|
||||
func TestWsGetSymbols(t *testing.T) {
|
||||
setupWsAuth(t)
|
||||
_, err := h.wsGetSymbols(currency.NewPair(currency.ETH, currency.BTC))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestWsGetTradingBalance dials websocket, sends get trading balance request.
|
||||
func TestSsGetCurrencies(t *testing.T) {
|
||||
setupWsAuth(t)
|
||||
_, err := h.wsGetCurrencies(currency.BTC)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
timer := time.NewTimer(sharedtestvalues.WebsocketResponseDefaultTimeout)
|
||||
select {
|
||||
case <-h.Websocket.DataHandler:
|
||||
case <-timer.C:
|
||||
t.Error("Expecting response")
|
||||
}
|
||||
timer.Stop()
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package hitbtc
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
)
|
||||
|
||||
// Ticker holds ticker information
|
||||
@@ -299,13 +299,16 @@ type LendingHistory struct {
|
||||
}
|
||||
|
||||
type capture struct {
|
||||
Method string `json:"method,omitempty"`
|
||||
Result interface{} `json:"result"`
|
||||
Error struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
} `json:"error"`
|
||||
ID int64 `json:"id,omitempty"`
|
||||
Method string `json:"method,omitempty"`
|
||||
Result interface{} `json:"result"`
|
||||
Error ResponseError `json:"error,omitempty"`
|
||||
ID int64 `json:"id,omitempty"`
|
||||
}
|
||||
|
||||
// ResponseError contains error codes from JSON responses
|
||||
type ResponseError struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// WsRequest defines a request obj for the JSON-RPC and gets a websocket
|
||||
@@ -393,12 +396,13 @@ type WsLoginData struct {
|
||||
// WsActiveOrdersResponse Active order response for auth subscription to reports
|
||||
type WsActiveOrdersResponse struct {
|
||||
Params []WsActiveOrdersResponseData `json:"params"`
|
||||
Error ResponseError `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// WsActiveOrdersResponseData Active order data for WsActiveOrdersResponse
|
||||
type WsActiveOrdersResponseData struct {
|
||||
ID string `json:"id"`
|
||||
ClientOrderID string `json:"clientOrderId"`
|
||||
ClientOrderID string `json:"clientOrderId,omitempty"`
|
||||
Symbol currency.Pair `json:"symbol"`
|
||||
Side string `json:"side"`
|
||||
Status string `json:"status"`
|
||||
@@ -416,12 +420,13 @@ type WsActiveOrdersResponseData struct {
|
||||
// WsReportResponse report response for auth subscription to reports
|
||||
type WsReportResponse struct {
|
||||
Params WsReportResponseData `json:"params"`
|
||||
Error ResponseError `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// WsReportResponseData Report data for WsReportResponse
|
||||
type WsReportResponseData struct {
|
||||
ID string `json:"id"`
|
||||
ClientOrderID string `json:"clientOrderId"`
|
||||
ClientOrderID string `json:"clientOrderId,omitempty"`
|
||||
Symbol currency.Pair `json:"symbol"`
|
||||
Side string `json:"side"`
|
||||
Status string `json:"status"`
|
||||
@@ -449,7 +454,7 @@ type WsSubmitOrderRequest struct {
|
||||
|
||||
// WsSubmitOrderRequestData WS request data
|
||||
type WsSubmitOrderRequestData struct {
|
||||
ClientOrderID string `json:"clientOrderId"`
|
||||
ClientOrderID int64 `json:"clientOrderId,string,omitempty"`
|
||||
Symbol currency.Pair `json:"symbol"`
|
||||
Side string `json:"side"`
|
||||
Price float64 `json:"price,string"`
|
||||
@@ -460,6 +465,7 @@ type WsSubmitOrderRequestData struct {
|
||||
type WsSubmitOrderSuccessResponse struct {
|
||||
Result WsSubmitOrderSuccessResponseData `json:"result"`
|
||||
ID int64 `json:"id"`
|
||||
Error ResponseError `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// WsSubmitOrderSuccessResponseData WS response data
|
||||
@@ -482,7 +488,7 @@ type WsSubmitOrderSuccessResponseData struct {
|
||||
|
||||
// WsSubmitOrderErrorResponse WS error response
|
||||
type WsSubmitOrderErrorResponse struct {
|
||||
Error WsSubmitOrderErrorResponseData `json:"error"`
|
||||
Error WsSubmitOrderErrorResponseData `json:"error,omitempty"`
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
|
||||
@@ -497,12 +503,13 @@ type WsSubmitOrderErrorResponseData struct {
|
||||
type WsCancelOrderResponse struct {
|
||||
Result WsCancelOrderResponseData `json:"result"`
|
||||
ID int64 `json:"id"`
|
||||
Error ResponseError `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// WsCancelOrderResponseData WS response data
|
||||
type WsCancelOrderResponseData struct {
|
||||
ID string `json:"id"`
|
||||
ClientOrderID string `json:"clientOrderId"`
|
||||
ClientOrderID string `json:"clientOrderId,omitempty"`
|
||||
Symbol currency.Pair `json:"symbol"`
|
||||
Side string `json:"side"`
|
||||
Status string `json:"status"`
|
||||
@@ -521,12 +528,13 @@ type WsCancelOrderResponseData struct {
|
||||
type WsReplaceOrderResponse struct {
|
||||
Result WsReplaceOrderResponseData `json:"result"`
|
||||
ID int64 `json:"id"`
|
||||
Error ResponseError `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// WsReplaceOrderResponseData WS response data
|
||||
type WsReplaceOrderResponseData struct {
|
||||
ID string `json:"id"`
|
||||
ClientOrderID string `json:"clientOrderId"`
|
||||
ClientOrderID string `json:"clientOrderId,omitempty"`
|
||||
Symbol currency.Pair `json:"symbol"`
|
||||
Side string `json:"side"`
|
||||
Status string `json:"status"`
|
||||
@@ -546,12 +554,13 @@ type WsReplaceOrderResponseData struct {
|
||||
type WsGetActiveOrdersResponse struct {
|
||||
Result []WsGetActiveOrdersResponseData `json:"result"`
|
||||
ID int64 `json:"id"`
|
||||
Error ResponseError `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// WsGetActiveOrdersResponseData WS response data
|
||||
type WsGetActiveOrdersResponseData struct {
|
||||
ID string `json:"id"`
|
||||
ClientOrderID string `json:"clientOrderId"`
|
||||
ClientOrderID string `json:"clientOrderId,omitempty"`
|
||||
Symbol currency.Pair `json:"symbol"`
|
||||
Side string `json:"side"`
|
||||
Status string `json:"status"`
|
||||
@@ -571,6 +580,7 @@ type WsGetActiveOrdersResponseData struct {
|
||||
type WsGetTradingBalanceResponse struct {
|
||||
Result []WsGetTradingBalanceResponseData `json:"result"`
|
||||
ID int64 `json:"id"`
|
||||
Error ResponseError `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// WsGetTradingBalanceResponseData WS response data
|
||||
@@ -606,3 +616,106 @@ type WsReplaceOrderRequestData struct {
|
||||
Quantity float64 `json:"quantity,string,omitempty"`
|
||||
Price float64 `json:"price,string,omitempty"`
|
||||
}
|
||||
|
||||
// WsGetCurrenciesRequest gets currencies
|
||||
type WsGetCurrenciesRequest struct {
|
||||
Method string `json:"method"`
|
||||
Params WsGetCurrenciesRequestParameters `json:"params"`
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
|
||||
// WsGetCurrenciesRequestParameters parameters
|
||||
type WsGetCurrenciesRequestParameters struct {
|
||||
Currency currency.Code `json:"currency"`
|
||||
}
|
||||
|
||||
// WsGetCurrenciesResponse currency response
|
||||
type WsGetCurrenciesResponse struct {
|
||||
Result WsGetCurrenciesResponseData `json:"result"`
|
||||
ID int64 `json:"id"`
|
||||
Error ResponseError `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// WsGetCurrenciesResponseData currency response data
|
||||
type WsGetCurrenciesResponseData struct {
|
||||
ID currency.Code `json:"id"`
|
||||
FullName string `json:"fullName"`
|
||||
Crypto bool `json:"crypto"`
|
||||
PayinEnabled bool `json:"payinEnabled"`
|
||||
PayinPaymentID bool `json:"payinPaymentId"`
|
||||
PayinConfirmations int64 `json:"payinConfirmations"`
|
||||
PayoutEnabled bool `json:"payoutEnabled"`
|
||||
PayoutIsPaymentID bool `json:"payoutIsPaymentId"`
|
||||
TransferEnabled bool `json:"transferEnabled"`
|
||||
Delisted bool `json:"delisted"`
|
||||
PayoutFee string `json:"payoutFee"`
|
||||
}
|
||||
|
||||
// WsGetSymbolsRequest request data
|
||||
type WsGetSymbolsRequest struct {
|
||||
Method string `json:"method"`
|
||||
Params WsGetSymbolsRequestParameters `json:"params"`
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
|
||||
// WsGetSymbolsRequestParameters request parameters
|
||||
type WsGetSymbolsRequestParameters struct {
|
||||
Symbol currency.Pair `json:"symbol"`
|
||||
}
|
||||
|
||||
// WsGetSymbolsResponse symbol response
|
||||
type WsGetSymbolsResponse struct {
|
||||
Result WsGetSymbolsResponseData `json:"result"`
|
||||
ID int64 `json:"id"`
|
||||
Error ResponseError `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// WsGetSymbolsResponseData symbol response data
|
||||
type WsGetSymbolsResponseData struct {
|
||||
ID currency.Pair `json:"id"`
|
||||
BaseCurrency currency.Code `json:"baseCurrency"`
|
||||
QuoteCurrency currency.Code `json:"quoteCurrency"`
|
||||
QuantityIncrement float64 `json:"quantityIncrement,string"`
|
||||
TickSize float64 `json:"tickSize,string"`
|
||||
TakeLiquidityRate float64 `json:"takeLiquidityRate,string"`
|
||||
ProvideLiquidityRate float64 `json:"provideLiquidityRate,string"`
|
||||
FeeCurrency currency.Code `json:"feeCurrency"`
|
||||
}
|
||||
|
||||
// WsGetTradesRequest trade request
|
||||
type WsGetTradesRequest struct {
|
||||
Method string `json:"method"`
|
||||
Params WsGetTradesRequestParameters `json:"params"`
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
|
||||
// WsGetTradesRequestParameters trade request params
|
||||
type WsGetTradesRequestParameters struct {
|
||||
Symbol currency.Pair `json:"symbol"`
|
||||
Limit int64 `json:"limit"`
|
||||
Sort string `json:"sort"`
|
||||
By string `json:"by"`
|
||||
}
|
||||
|
||||
// WsGetTradesResponse response
|
||||
type WsGetTradesResponse struct {
|
||||
Jsonrpc string `json:"jsonrpc"`
|
||||
Result WsGetTradesResponseData `json:"result"`
|
||||
ID int64 `json:"id"`
|
||||
Error ResponseError `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// WsGetTradesResponseData trade response data
|
||||
type WsGetTradesResponseData struct {
|
||||
Data []WsGetTradesResponseTrades `json:"data"`
|
||||
Symbol string `json:"symbol"`
|
||||
}
|
||||
|
||||
// WsGetTradesResponseTrades trade response
|
||||
type WsGetTradesResponseTrades struct {
|
||||
ID int64 `json:"id"`
|
||||
Price float64 `json:"price,string"`
|
||||
Quantity float64 `json:"quantity,string"`
|
||||
Side string `json:"side"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
}
|
||||
|
||||
@@ -4,24 +4,25 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/nonce"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/nonce"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
hitbtcWebsocketAddress = "wss://api.hitbtc.com/api/2/ws"
|
||||
rpcVersion = "2.0"
|
||||
rateLimit = 20
|
||||
)
|
||||
|
||||
var requestID nonce.Nonce
|
||||
@@ -29,26 +30,13 @@ var requestID nonce.Nonce
|
||||
// WsConnect starts a new connection with the websocket API
|
||||
func (h *HitBTC) WsConnect() error {
|
||||
if !h.Websocket.IsEnabled() || !h.IsEnabled() {
|
||||
return errors.New(exchange.WebsocketNotEnabled)
|
||||
return errors.New(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
|
||||
var dialer websocket.Dialer
|
||||
|
||||
if h.Websocket.GetProxyAddress() != "" {
|
||||
proxy, err := url.Parse(h.Websocket.GetProxyAddress())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dialer.Proxy = http.ProxyURL(proxy)
|
||||
}
|
||||
|
||||
var err error
|
||||
h.WebsocketConn, _, err = dialer.Dial(hitbtcWebsocketAddress, http.Header{})
|
||||
err := h.WebsocketConn.Dial(&dialer, http.Header{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go h.WsHandleData()
|
||||
err = h.wsLogin()
|
||||
if err != nil {
|
||||
@@ -60,17 +48,6 @@ func (h *HitBTC) WsConnect() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// WsReadData reads from the websocket connection
|
||||
func (h *HitBTC) WsReadData() (exchange.WebsocketResponse, error) {
|
||||
_, resp, err := h.WebsocketConn.ReadMessage()
|
||||
if err != nil {
|
||||
return exchange.WebsocketResponse{}, err
|
||||
}
|
||||
|
||||
h.Websocket.TrafficAlert <- struct{}{}
|
||||
return exchange.WebsocketResponse{Raw: resp}, nil
|
||||
}
|
||||
|
||||
// WsHandleData handles websocket data
|
||||
func (h *HitBTC) WsHandleData() {
|
||||
h.Websocket.Wg.Add(1)
|
||||
@@ -85,11 +62,12 @@ func (h *HitBTC) WsHandleData() {
|
||||
return
|
||||
|
||||
default:
|
||||
resp, err := h.WsReadData()
|
||||
resp, err := h.WebsocketConn.ReadMessage()
|
||||
if err != nil {
|
||||
h.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
h.Websocket.TrafficAlert <- struct{}{}
|
||||
|
||||
var init capture
|
||||
err = common.JSONDecode(resp.Raw, &init)
|
||||
@@ -97,11 +75,14 @@ func (h *HitBTC) WsHandleData() {
|
||||
h.Websocket.DataHandler <- err
|
||||
continue
|
||||
}
|
||||
|
||||
if init.Error.Code == 1002 {
|
||||
h.Websocket.SetCanUseAuthenticatedEndpoints(false)
|
||||
}
|
||||
if init.ID > 0 {
|
||||
h.WebsocketConn.AddResponseWithID(init.ID, resp.Raw)
|
||||
continue
|
||||
}
|
||||
if init.Error.Message != "" || init.Error.Code != 0 {
|
||||
if init.Error.Code == 1002 {
|
||||
h.Websocket.SetCanUseAuthenticatedEndpoints(false)
|
||||
}
|
||||
h.Websocket.DataHandler <- fmt.Errorf("hitbtc.go error - Code: %d, Message: %s",
|
||||
init.Error.Code,
|
||||
init.Error.Message)
|
||||
@@ -119,7 +100,7 @@ func (h *HitBTC) WsHandleData() {
|
||||
}
|
||||
}
|
||||
|
||||
func (h *HitBTC) handleSubscriptionUpdates(resp exchange.WebsocketResponse, init capture) {
|
||||
func (h *HitBTC) handleSubscriptionUpdates(resp wshandler.WebsocketResponse, init capture) {
|
||||
switch init.Method {
|
||||
case "ticker":
|
||||
var ticker WsTicker
|
||||
@@ -133,7 +114,7 @@ func (h *HitBTC) handleSubscriptionUpdates(resp exchange.WebsocketResponse, init
|
||||
h.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
h.Websocket.DataHandler <- exchange.TickerData{
|
||||
h.Websocket.DataHandler <- wshandler.TickerData{
|
||||
Exchange: h.GetName(),
|
||||
AssetType: asset.Spot,
|
||||
Pair: currency.NewPairFromString(ticker.Params.Symbol),
|
||||
@@ -189,7 +170,7 @@ func (h *HitBTC) handleSubscriptionUpdates(resp exchange.WebsocketResponse, init
|
||||
}
|
||||
}
|
||||
|
||||
func (h *HitBTC) handleCommandResponses(resp exchange.WebsocketResponse, init capture) {
|
||||
func (h *HitBTC) handleCommandResponses(resp wshandler.WebsocketResponse, init capture) {
|
||||
switch resultType := init.Result.(type) {
|
||||
case map[string]interface{}:
|
||||
switch resultType["reportType"].(string) {
|
||||
@@ -269,7 +250,7 @@ func (h *HitBTC) WsProcessOrderbookSnapshot(ob WsOrderbook) error {
|
||||
return err
|
||||
}
|
||||
|
||||
h.Websocket.DataHandler <- exchange.WebsocketOrderbookUpdate{
|
||||
h.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
|
||||
Exchange: h.GetName(),
|
||||
Asset: asset.Spot,
|
||||
Pair: p,
|
||||
@@ -300,7 +281,7 @@ func (h *HitBTC) WsProcessOrderbookUpdate(ob WsOrderbook) error {
|
||||
return err
|
||||
}
|
||||
|
||||
h.Websocket.DataHandler <- exchange.WebsocketOrderbookUpdate{
|
||||
h.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
|
||||
Exchange: h.GetName(),
|
||||
Asset: asset.Spot,
|
||||
Pair: p,
|
||||
@@ -311,9 +292,9 @@ func (h *HitBTC) WsProcessOrderbookUpdate(ob WsOrderbook) error {
|
||||
// GenerateDefaultSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions()
|
||||
func (h *HitBTC) GenerateDefaultSubscriptions() {
|
||||
var channels = []string{"subscribeTicker", "subscribeOrderbook", "subscribeTrades", "subscribeCandles"}
|
||||
var subscriptions []exchange.WebsocketChannelSubscription
|
||||
var subscriptions []wshandler.WebsocketChannelSubscription
|
||||
if h.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
subscriptions = append(subscriptions, exchange.WebsocketChannelSubscription{
|
||||
subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
|
||||
Channel: "subscribeReports",
|
||||
})
|
||||
}
|
||||
@@ -321,7 +302,7 @@ func (h *HitBTC) GenerateDefaultSubscriptions() {
|
||||
for i := range channels {
|
||||
for j := range enabledCurrencies {
|
||||
enabledCurrencies[j].Delimiter = ""
|
||||
subscriptions = append(subscriptions, exchange.WebsocketChannelSubscription{
|
||||
subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
|
||||
Channel: channels[i],
|
||||
Currency: enabledCurrencies[j],
|
||||
})
|
||||
@@ -331,7 +312,7 @@ func (h *HitBTC) GenerateDefaultSubscriptions() {
|
||||
}
|
||||
|
||||
// Subscribe sends a websocket message to receive data from the channel
|
||||
func (h *HitBTC) Subscribe(channelToSubscribe exchange.WebsocketChannelSubscription) error {
|
||||
func (h *HitBTC) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
|
||||
subscribe := WsNotification{
|
||||
Method: channelToSubscribe.Channel,
|
||||
}
|
||||
@@ -353,11 +334,11 @@ func (h *HitBTC) Subscribe(channelToSubscribe exchange.WebsocketChannelSubscript
|
||||
}
|
||||
}
|
||||
|
||||
return h.wsSend(subscribe)
|
||||
return h.WebsocketConn.SendMessage(subscribe)
|
||||
}
|
||||
|
||||
// Unsubscribe sends a websocket message to stop receiving data from the channel
|
||||
func (h *HitBTC) Unsubscribe(channelToSubscribe exchange.WebsocketChannelSubscription) error {
|
||||
func (h *HitBTC) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
|
||||
unsubscribeChannel := strings.Replace(channelToSubscribe.Channel, "subscribe", "unsubscribe", 1)
|
||||
subscribe := WsNotification{
|
||||
JSONRPCVersion: rpcVersion,
|
||||
@@ -379,21 +360,7 @@ func (h *HitBTC) Unsubscribe(channelToSubscribe exchange.WebsocketChannelSubscri
|
||||
}
|
||||
}
|
||||
|
||||
return h.wsSend(subscribe)
|
||||
}
|
||||
|
||||
// WsSend sends data to the websocket server
|
||||
func (h *HitBTC) wsSend(data interface{}) error {
|
||||
h.wsRequestMtx.Lock()
|
||||
defer h.wsRequestMtx.Unlock()
|
||||
json, err := common.JSONEncode(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if h.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%v sending message to websocket %v", h.Name, string(json))
|
||||
}
|
||||
return h.WebsocketConn.WriteMessage(websocket.TextMessage, json)
|
||||
return h.WebsocketConn.SendMessage(subscribe)
|
||||
}
|
||||
|
||||
// Unsubscribe sends a websocket message to stop receiving data from the channel
|
||||
@@ -414,7 +381,7 @@ func (h *HitBTC) wsLogin() error {
|
||||
},
|
||||
}
|
||||
|
||||
err := h.wsSend(request)
|
||||
err := h.WebsocketConn.SendMessage(request)
|
||||
if err != nil {
|
||||
h.Websocket.SetCanUseAuthenticatedEndpoints(false)
|
||||
return err
|
||||
@@ -423,43 +390,68 @@ func (h *HitBTC) wsLogin() error {
|
||||
}
|
||||
|
||||
// wsPlaceOrder sends a websocket message to submit an order
|
||||
func (h *HitBTC) wsPlaceOrder(pair currency.Pair, side string, price, quantity float64) error {
|
||||
func (h *HitBTC) wsPlaceOrder(pair currency.Pair, side string, price, quantity float64) (*WsSubmitOrderSuccessResponse, error) {
|
||||
if !h.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
return fmt.Errorf("%v not authenticated, cannot place order", h.Name)
|
||||
return nil, fmt.Errorf("%v not authenticated, cannot place order", h.Name)
|
||||
}
|
||||
id := h.WebsocketConn.GenerateMessageID(false)
|
||||
request := WsSubmitOrderRequest{
|
||||
Method: "newOrder",
|
||||
Params: WsSubmitOrderRequestData{
|
||||
ClientOrderID: fmt.Sprintf("%v", time.Now().Unix()),
|
||||
ClientOrderID: id,
|
||||
Symbol: pair,
|
||||
Side: strings.ToLower(side),
|
||||
Price: price,
|
||||
Quantity: quantity,
|
||||
},
|
||||
ID: int64(requestID.GetInc()),
|
||||
ID: id,
|
||||
}
|
||||
return h.wsSend(request)
|
||||
resp, err := h.WebsocketConn.SendMessageReturnResponse(id, request)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%v %v", h.Name, err)
|
||||
}
|
||||
var response WsSubmitOrderSuccessResponse
|
||||
err = common.JSONDecode(resp, &response)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%v %v", h.Name, err)
|
||||
}
|
||||
if response.Error.Code > 0 || response.Error.Message != "" {
|
||||
return &response, fmt.Errorf("%v Error:%v Message:%v", h.Name, response.Error.Code, response.Error.Message)
|
||||
}
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
// wsCancelOrder sends a websocket message to cancel an order
|
||||
func (h *HitBTC) wsCancelOrder(clientOrderID string) error {
|
||||
func (h *HitBTC) wsCancelOrder(clientOrderID string) (*WsCancelOrderResponse, error) {
|
||||
if !h.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
return fmt.Errorf("%v not authenticated, cannot place order", h.Name)
|
||||
return nil, fmt.Errorf("%v not authenticated, cannot place order", h.Name)
|
||||
}
|
||||
request := WsCancelOrderRequest{
|
||||
Method: "cancelOrder",
|
||||
Params: WsCancelOrderRequestData{
|
||||
ClientOrderID: clientOrderID,
|
||||
},
|
||||
ID: int64(requestID.GetInc()),
|
||||
ID: h.WebsocketConn.GenerateMessageID(false),
|
||||
}
|
||||
return h.wsSend(request)
|
||||
resp, err := h.WebsocketConn.SendMessageReturnResponse(request.ID, request)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%v %v", h.Name, err)
|
||||
}
|
||||
var response WsCancelOrderResponse
|
||||
err = common.JSONDecode(resp, &response)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%v %v", h.Name, err)
|
||||
}
|
||||
if response.Error.Code > 0 || response.Error.Message != "" {
|
||||
return &response, fmt.Errorf("%v Error:%v Message:%v", h.Name, response.Error.Code, response.Error.Message)
|
||||
}
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
// wsReplaceOrder sends a websocket message to replace an order
|
||||
func (h *HitBTC) wsReplaceOrder(clientOrderID string, quantity, price float64) error {
|
||||
func (h *HitBTC) wsReplaceOrder(clientOrderID string, quantity, price float64) (*WsReplaceOrderResponse, error) {
|
||||
if !h.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
return fmt.Errorf("%v not authenticated, cannot place order", h.Name)
|
||||
return nil, fmt.Errorf("%v not authenticated, cannot place order", h.Name)
|
||||
}
|
||||
request := WsReplaceOrderRequest{
|
||||
Method: "cancelReplaceOrder",
|
||||
@@ -469,33 +461,144 @@ func (h *HitBTC) wsReplaceOrder(clientOrderID string, quantity, price float64) e
|
||||
Quantity: quantity,
|
||||
Price: price,
|
||||
},
|
||||
ID: int64(requestID.GetInc()),
|
||||
ID: h.WebsocketConn.GenerateMessageID(false),
|
||||
}
|
||||
return h.wsSend(request)
|
||||
resp, err := h.WebsocketConn.SendMessageReturnResponse(request.ID, request)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%v %v", h.Name, err)
|
||||
}
|
||||
var response WsReplaceOrderResponse
|
||||
err = common.JSONDecode(resp, &response)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%v %v", h.Name, err)
|
||||
}
|
||||
if response.Error.Code > 0 || response.Error.Message != "" {
|
||||
return &response, fmt.Errorf("%v Error:%v Message:%v", h.Name, response.Error.Code, response.Error.Message)
|
||||
}
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
// wsGetActiveOrders sends a websocket message to get all active orders
|
||||
func (h *HitBTC) wsGetActiveOrders() error {
|
||||
func (h *HitBTC) wsGetActiveOrders() (*WsActiveOrdersResponse, error) {
|
||||
if !h.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
return fmt.Errorf("%v not authenticated, cannot place order", h.Name)
|
||||
return nil, fmt.Errorf("%v not authenticated, cannot place order", h.Name)
|
||||
}
|
||||
request := WsReplaceOrderRequest{
|
||||
Method: "getOrders",
|
||||
Params: WsReplaceOrderRequestData{},
|
||||
ID: int64(requestID.GetInc()),
|
||||
ID: h.WebsocketConn.GenerateMessageID(false),
|
||||
}
|
||||
return h.wsSend(request)
|
||||
resp, err := h.WebsocketConn.SendMessageReturnResponse(request.ID, request)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%v %v", h.Name, err)
|
||||
}
|
||||
var response WsActiveOrdersResponse
|
||||
err = common.JSONDecode(resp, &response)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%v %v", h.Name, err)
|
||||
}
|
||||
if response.Error.Code > 0 || response.Error.Message != "" {
|
||||
return &response, fmt.Errorf("%v Error:%v Message:%v", h.Name, response.Error.Code, response.Error.Message)
|
||||
}
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
// wsGetTradingBalance sends a websocket message to get trading balance
|
||||
func (h *HitBTC) wsGetTradingBalance() error {
|
||||
func (h *HitBTC) wsGetTradingBalance() (*WsGetTradingBalanceResponse, error) {
|
||||
if !h.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
return fmt.Errorf("%v not authenticated, cannot place order", h.Name)
|
||||
return nil, fmt.Errorf("%v not authenticated, cannot place order", h.Name)
|
||||
}
|
||||
request := WsReplaceOrderRequest{
|
||||
Method: "getTradingBalance",
|
||||
Params: WsReplaceOrderRequestData{},
|
||||
ID: int64(requestID.GetInc()),
|
||||
ID: h.WebsocketConn.GenerateMessageID(false),
|
||||
}
|
||||
return h.wsSend(request)
|
||||
resp, err := h.WebsocketConn.SendMessageReturnResponse(request.ID, request)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%v %v", h.Name, err)
|
||||
}
|
||||
var response WsGetTradingBalanceResponse
|
||||
err = common.JSONDecode(resp, &response)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%v %v", h.Name, err)
|
||||
}
|
||||
if response.Error.Code > 0 || response.Error.Message != "" {
|
||||
return &response, fmt.Errorf("%v Error:%v Message:%v", h.Name, response.Error.Code, response.Error.Message)
|
||||
}
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
// wsGetCurrencies sends a websocket message to get trading balance
|
||||
func (h *HitBTC) wsGetCurrencies(currencyItem currency.Code) (*WsGetCurrenciesResponse, error) {
|
||||
request := WsGetCurrenciesRequest{
|
||||
Method: "getCurrency",
|
||||
Params: WsGetCurrenciesRequestParameters{
|
||||
Currency: currencyItem,
|
||||
},
|
||||
ID: h.WebsocketConn.GenerateMessageID(false),
|
||||
}
|
||||
resp, err := h.WebsocketConn.SendMessageReturnResponse(request.ID, request)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%v %v", h.Name, err)
|
||||
}
|
||||
var response WsGetCurrenciesResponse
|
||||
err = common.JSONDecode(resp, &response)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%v %v", h.Name, err)
|
||||
}
|
||||
if response.Error.Code > 0 || response.Error.Message != "" {
|
||||
return &response, fmt.Errorf("%v Error:%v Message:%v", h.Name, response.Error.Code, response.Error.Message)
|
||||
}
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
// wsGetSymbols sends a websocket message to get trading balance
|
||||
func (h *HitBTC) wsGetSymbols(currencyItem currency.Pair) (*WsGetSymbolsResponse, error) {
|
||||
request := WsGetSymbolsRequest{
|
||||
Method: "getSymbol",
|
||||
Params: WsGetSymbolsRequestParameters{
|
||||
Symbol: currencyItem,
|
||||
},
|
||||
ID: h.WebsocketConn.GenerateMessageID(false),
|
||||
}
|
||||
resp, err := h.WebsocketConn.SendMessageReturnResponse(request.ID, request)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%v %v", h.Name, err)
|
||||
}
|
||||
var response WsGetSymbolsResponse
|
||||
err = common.JSONDecode(resp, &response)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%v %v", h.Name, err)
|
||||
}
|
||||
if response.Error.Code > 0 || response.Error.Message != "" {
|
||||
return &response, fmt.Errorf("%v Error:%v Message:%v", h.Name, response.Error.Code, response.Error.Message)
|
||||
}
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
// wsGetSymbols sends a websocket message to get trading balance
|
||||
func (h *HitBTC) wsGetTrades(currencyItem currency.Pair, limit int64, sort, by string) (*WsGetTradesResponse, error) {
|
||||
request := WsGetTradesRequest{
|
||||
Method: "getTrades",
|
||||
Params: WsGetTradesRequestParameters{
|
||||
Symbol: currencyItem,
|
||||
Limit: limit,
|
||||
Sort: sort,
|
||||
By: by,
|
||||
},
|
||||
ID: h.WebsocketConn.GenerateMessageID(false),
|
||||
}
|
||||
resp, err := h.WebsocketConn.SendMessageReturnResponse(request.ID, request)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%v %v", h.Name, err)
|
||||
}
|
||||
var response WsGetTradesResponse
|
||||
err = common.JSONDecode(resp, &response)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%v %v", h.Name, err)
|
||||
}
|
||||
if response.Error.Code > 0 || response.Error.Message != "" {
|
||||
return &response, fmt.Errorf("%v Error:%v Message:%v", h.Name, response.Error.Code, response.Error.Message)
|
||||
}
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
@@ -8,15 +8,16 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
// GetDefaultConfig returns a default exchange config
|
||||
@@ -88,9 +89,17 @@ func (h *HitBTC) SetDefaults() {
|
||||
h.API.Endpoints.URLDefault = apiURL
|
||||
h.API.Endpoints.URL = h.API.Endpoints.URLDefault
|
||||
h.API.Endpoints.WebsocketURL = hitbtcWebsocketAddress
|
||||
h.WebsocketInit()
|
||||
h.Websocket.Functionality = exchange.WebsocketTickerSupported |
|
||||
exchange.WebsocketOrderbookSupported
|
||||
h.Websocket = wshandler.New()
|
||||
h.Websocket.Functionality = wshandler.WebsocketTickerSupported |
|
||||
wshandler.WebsocketOrderbookSupported |
|
||||
wshandler.WebsocketSubscribeSupported |
|
||||
wshandler.WebsocketUnsubscribeSupported |
|
||||
wshandler.WebsocketAuthenticatedEndpointsSupported |
|
||||
wshandler.WebsocketSubmitOrderSupported |
|
||||
wshandler.WebsocketCancelOrderSupported |
|
||||
wshandler.WebsocketMessageCorrelationSupported
|
||||
h.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
|
||||
h.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
|
||||
}
|
||||
|
||||
// Setup sets user exchange configuration settings
|
||||
@@ -105,14 +114,29 @@ func (h *HitBTC) Setup(exch *config.ExchangeConfig) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return h.WebsocketSetup(h.WsConnect,
|
||||
err = h.Websocket.Setup(h.WsConnect,
|
||||
h.Subscribe,
|
||||
h.Unsubscribe,
|
||||
exch.Name,
|
||||
exch.Features.Enabled.Websocket,
|
||||
exch.Verbose,
|
||||
hitbtcWebsocketAddress,
|
||||
exch.API.Endpoints.WebsocketURL)
|
||||
exch.API.Endpoints.WebsocketURL,
|
||||
exch.API.AuthenticatedWebsocketSupport)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
h.WebsocketConn = &wshandler.WebsocketConnection{
|
||||
ExchangeName: h.Name,
|
||||
URL: h.Websocket.GetWebsocketURL(),
|
||||
ProxyURL: h.Websocket.GetProxyAddress(),
|
||||
Verbose: h.Verbose,
|
||||
RateLimit: rateLimit,
|
||||
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
|
||||
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Start starts the HitBTC go routine
|
||||
@@ -395,7 +419,7 @@ func (h *HitBTC) WithdrawFiatFundsToInternationalBank(withdrawRequest *exchange.
|
||||
}
|
||||
|
||||
// GetWebsocket returns a pointer to the exchange websocket
|
||||
func (h *HitBTC) GetWebsocket() (*exchange.Websocket, error) {
|
||||
func (h *HitBTC) GetWebsocket() (*wshandler.Websocket, error) {
|
||||
return h.Websocket, nil
|
||||
}
|
||||
|
||||
@@ -484,20 +508,20 @@ func (h *HitBTC) GetOrderHistory(getOrdersRequest *exchange.GetOrdersRequest) ([
|
||||
|
||||
// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle subscribing
|
||||
func (h *HitBTC) SubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
func (h *HitBTC) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
h.Websocket.SubscribeToChannels(channels)
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle unsubscribing
|
||||
func (h *HitBTC) UnsubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
|
||||
h.Websocket.UnsubscribeToChannels(channels)
|
||||
func (h *HitBTC) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
h.Websocket.RemoveSubscribedChannels(channels)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetSubscriptions returns a copied list of subscriptions
|
||||
func (h *HitBTC) GetSubscriptions() ([]exchange.WebsocketChannelSubscription, error) {
|
||||
func (h *HitBTC) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
|
||||
return h.Websocket.GetSubscriptions(), nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# GoCryptoTrader package Huobi
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
|
||||
|
||||
[](https://travis-ci.org/thrasher-/gocryptotrader)
|
||||
[](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/huobi)
|
||||
[](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
|
||||
[](https://travis-ci.org/thrasher-corp/gocryptotrader)
|
||||
[](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/huobi)
|
||||
[](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-corp/gocryptotrader)
|
||||
|
||||
|
||||
This huobi package is part of the GoCryptoTrader codebase.
|
||||
@@ -27,7 +27,7 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader
|
||||
|
||||
### How to enable
|
||||
|
||||
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
+ [Enable via configuration](https://github.com/thrasher-corp/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
|
||||
+ Individual package example below:
|
||||
|
||||
@@ -127,12 +127,12 @@ When submitting a PR, please abide by our coding guidelines:
|
||||
|
||||
+ Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)).
|
||||
+ Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines.
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-corp/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Pull requests need to be based on and opened against the `master` branch.
|
||||
|
||||
## Donations
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
|
||||
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
|
||||
|
||||
|
||||
@@ -14,14 +14,13 @@ import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/wshandler"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -66,9 +65,8 @@ const (
|
||||
type HUOBI struct {
|
||||
exchange.Base
|
||||
AccountID string
|
||||
WebsocketConn *websocket.Conn
|
||||
AuthenticatedWebsocketConn *websocket.Conn
|
||||
wsRequestMtx sync.Mutex
|
||||
WebsocketConn *wshandler.WebsocketConnection
|
||||
AuthenticatedWebsocketConn *wshandler.WebsocketConnection
|
||||
}
|
||||
|
||||
// GetSpotKline returns kline data
|
||||
|
||||
@@ -9,15 +9,15 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/sharedtestvalues"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/crypto"
|
||||
"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/sharedtestvalues"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/wshandler"
|
||||
)
|
||||
|
||||
// Please supply you own test keys here for due diligence testing.
|
||||
@@ -57,37 +57,36 @@ func setupWsTests(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
TestSetup(t)
|
||||
if !h.Websocket.IsEnabled() && !h.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip(exchange.WebsocketNotEnabled)
|
||||
t.Skip(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
var err error
|
||||
var dialer websocket.Dialer
|
||||
comms = make(chan WsMessage, sharedtestvalues.WebsocketChannelOverrideCapacity)
|
||||
h.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
|
||||
h.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
|
||||
go h.WsHandleData()
|
||||
err = h.wsAuthenticatedDial(&dialer)
|
||||
h.AuthenticatedWebsocketConn = &wshandler.WebsocketConnection{
|
||||
ExchangeName: h.Name,
|
||||
URL: wsAccountsOrdersURL,
|
||||
Verbose: h.Verbose,
|
||||
ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
|
||||
ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
|
||||
}
|
||||
h.WebsocketConn = &wshandler.WebsocketConnection{
|
||||
ExchangeName: h.Name,
|
||||
URL: wsMarketURL,
|
||||
Verbose: h.Verbose,
|
||||
ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
|
||||
ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
|
||||
}
|
||||
var dialer websocket.Dialer
|
||||
err := h.wsAuthenticatedDial(&dialer)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = h.wsLogin()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
timer := time.NewTimer(sharedtestvalues.WebsocketResponseDefaultTimeout)
|
||||
select {
|
||||
case response := <-h.Websocket.DataHandler:
|
||||
switch respType := response.(type) {
|
||||
case WsAuthenticatedDataResponse:
|
||||
if respType.ErrorCode > 0 {
|
||||
t.Error(respType)
|
||||
}
|
||||
case error:
|
||||
t.Error(respType)
|
||||
}
|
||||
case <-timer.C:
|
||||
t.Error("Websocket did not receive a response")
|
||||
}
|
||||
timer.Stop()
|
||||
|
||||
wsSetupRan = true
|
||||
}
|
||||
|
||||
@@ -655,46 +654,36 @@ func TestGetDepositAddress(t *testing.T) {
|
||||
// TestWsGetAccountsList connects to WS, logs in, gets account list
|
||||
func TestWsGetAccountsList(t *testing.T) {
|
||||
setupWsTests(t)
|
||||
h.wsGetAccountsList(currency.NewPairFromString("ethbtc"))
|
||||
timer := time.NewTimer(sharedtestvalues.WebsocketResponseDefaultTimeout)
|
||||
select {
|
||||
case response := <-h.Websocket.DataHandler:
|
||||
switch respType := response.(type) {
|
||||
case WsAuthenticatedAccountsListResponse:
|
||||
if respType.ErrorCode > 0 {
|
||||
t.Error(respType)
|
||||
}
|
||||
case error:
|
||||
t.Error(respType)
|
||||
}
|
||||
case <-timer.C:
|
||||
t.Error("Websocket did not receive a response")
|
||||
resp, err := h.wsGetAccountsList(currency.NewPairFromString("ethbtc"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if resp.ErrorCode > 0 {
|
||||
t.Error(resp.ErrorMessage)
|
||||
}
|
||||
timer.Stop()
|
||||
}
|
||||
|
||||
// TestWsGetOrderList connects to WS, logs in, gets order list
|
||||
func TestWsGetOrderList(t *testing.T) {
|
||||
setupWsTests(t)
|
||||
h.wsGetOrdersList(1, currency.NewPairFromString("ethbtc"))
|
||||
timer := time.NewTimer(sharedtestvalues.WebsocketResponseDefaultTimeout)
|
||||
select {
|
||||
case <-h.Websocket.DataHandler:
|
||||
case <-timer.C:
|
||||
t.Error("Websocket did not receive a response")
|
||||
resp, err := h.wsGetOrdersList(1, currency.NewPairFromString("ethbtc"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if resp.ErrorCode > 0 {
|
||||
t.Error(resp.ErrorMessage)
|
||||
}
|
||||
timer.Stop()
|
||||
}
|
||||
|
||||
// TestWsGetOrderDetails connects to WS, logs in, gets order details
|
||||
func TestWsGetOrderDetails(t *testing.T) {
|
||||
setupWsTests(t)
|
||||
h.wsGetOrderDetails("123")
|
||||
timer := time.NewTimer(sharedtestvalues.WebsocketResponseDefaultTimeout)
|
||||
select {
|
||||
case <-h.Websocket.DataHandler:
|
||||
case <-timer.C:
|
||||
t.Error("Websocket did not receive a response")
|
||||
orderID := "123"
|
||||
resp, err := h.wsGetOrderDetails(orderID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if resp.ErrorCode > 0 && (orderID == "123" && resp.ErrorCode != 10022) {
|
||||
t.Error(resp.ErrorMessage)
|
||||
}
|
||||
timer.Stop()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package huobi
|
||||
|
||||
import "github.com/thrasher-/gocryptotrader/currency"
|
||||
import "github.com/thrasher-corp/gocryptotrader/currency"
|
||||
|
||||
// Response stores the Huobi response information
|
||||
type Response struct {
|
||||
@@ -270,10 +270,10 @@ var (
|
||||
|
||||
// WsRequest defines a request data structure
|
||||
type WsRequest struct {
|
||||
Topic string `json:"req,omitempty"`
|
||||
Subscribe string `json:"sub,omitempty"`
|
||||
Unsubscribe string `json:"unsub,omitempty"`
|
||||
ClientGeneratedID string `json:"id,omitempty"`
|
||||
Topic string `json:"req,omitempty"`
|
||||
Subscribe string `json:"sub,omitempty"`
|
||||
Unsubscribe string `json:"unsub,omitempty"`
|
||||
ClientID int64 `json:"cid,string,omitempty"`
|
||||
}
|
||||
|
||||
// WsResponse defines a response from the websocket connection when there
|
||||
@@ -286,6 +286,7 @@ type WsResponse struct {
|
||||
Ping int64 `json:"ping"`
|
||||
Channel string `json:"ch"`
|
||||
Subscribed string `json:"subbed"`
|
||||
ClientID int64 `json:"cid,string,omitempty"`
|
||||
}
|
||||
|
||||
// WsHeartBeat defines a heartbeat request
|
||||
@@ -346,6 +347,7 @@ type WsAuthenticationRequest struct {
|
||||
SignatureVersion string `json:"SignatureVersion"`
|
||||
Timestamp string `json:"Timestamp"`
|
||||
Signature string `json:"Signature"`
|
||||
ClientID int64 `json:"cid,string,omitempty"`
|
||||
}
|
||||
|
||||
// WsMessage defines read data from the websocket connection
|
||||
@@ -363,6 +365,7 @@ type WsAuthenticatedSubscriptionRequest struct {
|
||||
Timestamp string `json:"Timestamp"`
|
||||
Signature string `json:"Signature"`
|
||||
Topic string `json:"topic"`
|
||||
ClientID int64 `json:"cid,string,omitempty"`
|
||||
}
|
||||
|
||||
// WsAuthenticatedAccountsListRequest request for account list authenticated connection
|
||||
@@ -375,6 +378,7 @@ type WsAuthenticatedAccountsListRequest struct {
|
||||
Signature string `json:"Signature"`
|
||||
Topic string `json:"topic"`
|
||||
Symbol currency.Pair `json:"symbol"`
|
||||
ClientID int64 `json:"cid,string,omitempty"`
|
||||
}
|
||||
|
||||
// WsAuthenticatedOrderDetailsRequest request for order details authenticated connection
|
||||
@@ -387,6 +391,7 @@ type WsAuthenticatedOrderDetailsRequest struct {
|
||||
Signature string `json:"Signature"`
|
||||
Topic string `json:"topic"`
|
||||
OrderID string `json:"order-id"`
|
||||
ClientID int64 `json:"cid,string,omitempty"`
|
||||
}
|
||||
|
||||
// WsAuthenticatedOrdersListRequest request for orderslist authenticated connection
|
||||
@@ -401,6 +406,7 @@ type WsAuthenticatedOrdersListRequest struct {
|
||||
States string `json:"states"`
|
||||
AccountID int64 `json:"account-id"`
|
||||
Symbol currency.Pair `json:"symbol"`
|
||||
ClientID int64 `json:"cid,string,omitempty"`
|
||||
}
|
||||
|
||||
// WsAuthenticatedDataResponse response from authenticated connection
|
||||
@@ -411,7 +417,7 @@ type WsAuthenticatedDataResponse struct {
|
||||
ErrorCode int64 `json:"err-code,omitempty"`
|
||||
ErrorMessage string `json:"err-msg,omitempty"`
|
||||
Ping int64 `json:"ping,omitempty"`
|
||||
CID string `json:"cid,omitempty"`
|
||||
ClientID int64 `json:"cid,string,omitempty"`
|
||||
}
|
||||
|
||||
// WsAuthenticatedAccountsResponse response from Accounts authenticated subscription
|
||||
@@ -529,3 +535,8 @@ type WsAuthenticatedOrderDetailResponse struct {
|
||||
WsAuthenticatedDataResponse
|
||||
Data WsAuthenticatedOrdersListResponseData `json:"data"`
|
||||
}
|
||||
|
||||
// WsPong sent for pong messages
|
||||
type WsPong struct {
|
||||
Pong int64 `json:"pong"`
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user