Merge branch 'master' into engine

This commit is contained in:
Adrian Gallagher
2019-08-09 15:46:24 +10:00
353 changed files with 4966 additions and 4196 deletions

View File

@@ -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">
[![Build Status](https://travis-ci.org/thrasher-/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges)
[![Coverage Status](http://codecov.io/github/thrasher-/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-/gocryptotrader)](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
[![Build Status](https://travis-ci.org/thrasher-corp/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-corp/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-corp/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges)
[![Coverage Status](http://codecov.io/github/thrasher-corp/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-corp/gocryptotrader)](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:

View File

@@ -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">
[![Build Status](https://travis-ci.org/thrasher-/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/alphapoint)
[![Coverage Status](http://codecov.io/github/thrasher-/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-/gocryptotrader)](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
[![Build Status](https://travis-ci.org/thrasher-corp/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-corp/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-corp/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/alphapoint)
[![Coverage Status](http://codecov.io/github/thrasher-corp/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-corp/gocryptotrader)](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:

View File

@@ -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 (

View File

@@ -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 (

View File

@@ -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 {

View File

@@ -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)

View File

@@ -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
}

View File

@@ -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">
[![Build Status](https://travis-ci.org/thrasher-/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/anx)
[![Coverage Status](http://codecov.io/github/thrasher-/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-/gocryptotrader)](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
[![Build Status](https://travis-ci.org/thrasher-corp/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-corp/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-corp/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/anx)
[![Coverage Status](http://codecov.io/github/thrasher-corp/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-corp/gocryptotrader)](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:

View File

@@ -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 (

View File

@@ -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

View File

@@ -1,6 +1,6 @@
package anx
import "github.com/thrasher-/gocryptotrader/currency"
import "github.com/thrasher-corp/gocryptotrader/currency"
// List of strings
const (

View File

@@ -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
}

View File

@@ -3,7 +3,7 @@ package asset
import (
"testing"
"github.com/thrasher-/gocryptotrader/common"
"github.com/thrasher-corp/gocryptotrader/common"
)
func TestString(t *testing.T) {

View File

@@ -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">
[![Build Status](https://travis-ci.org/thrasher-/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/binance)
[![Coverage Status](http://codecov.io/github/thrasher-/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-/gocryptotrader)](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
[![Build Status](https://travis-ci.org/thrasher-corp/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-corp/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-corp/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/binance)
[![Coverage Status](http://codecov.io/github/thrasher-corp/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-corp/gocryptotrader)](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:

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
}
}
}

View File

@@ -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
}

View File

@@ -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">
[![Build Status](https://travis-ci.org/thrasher-/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/bitfinex)
[![Coverage Status](http://codecov.io/github/thrasher-/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-/gocryptotrader)](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
[![Build Status](https://travis-ci.org/thrasher-corp/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-corp/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-corp/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/bitfinex)
[![Coverage Status](http://codecov.io/github/thrasher-corp/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-corp/gocryptotrader)](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:

View File

@@ -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

View File

@@ -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)

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -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">
[![Build Status](https://travis-ci.org/thrasher-/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/bitflyer)
[![Coverage Status](http://codecov.io/github/thrasher-/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-/gocryptotrader)](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
[![Build Status](https://travis-ci.org/thrasher-corp/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-corp/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-corp/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/bitflyer)
[![Coverage Status](http://codecov.io/github/thrasher-corp/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-corp/gocryptotrader)](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:

View File

@@ -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 (

View File

@@ -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

View File

@@ -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
}

View File

@@ -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">
[![Build Status](https://travis-ci.org/thrasher-/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/bithumb)
[![Coverage Status](http://codecov.io/github/thrasher-/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-/gocryptotrader)](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
[![Build Status](https://travis-ci.org/thrasher-corp/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-corp/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-corp/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/bithumb)
[![Coverage Status](http://codecov.io/github/thrasher-corp/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-corp/gocryptotrader)](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:

View File

@@ -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 (

View File

@@ -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

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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">
[![Build Status](https://travis-ci.org/thrasher-/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/bitmex)
[![Coverage Status](http://codecov.io/github/thrasher-/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-/gocryptotrader)](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
[![Build Status](https://travis-ci.org/thrasher-corp/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-corp/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-corp/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/bitmex)
[![Coverage Status](http://codecov.io/github/thrasher-corp/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-corp/gocryptotrader)](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:

View File

@@ -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 (

View File

@@ -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

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -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">
[![Build Status](https://travis-ci.org/thrasher-/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/bitstamp)
[![Coverage Status](http://codecov.io/github/thrasher-/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-/gocryptotrader)](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
[![Build Status](https://travis-ci.org/thrasher-corp/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-corp/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-corp/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/bitstamp)
[![Coverage Status](http://codecov.io/github/thrasher-corp/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-corp/gocryptotrader)](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:

View File

@@ -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

View File

@@ -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

View File

@@ -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(),

View File

@@ -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
}

View File

@@ -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">
[![Build Status](https://travis-ci.org/thrasher-/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/bittrex)
[![Coverage Status](http://codecov.io/github/thrasher-/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-/gocryptotrader)](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
[![Build Status](https://travis-ci.org/thrasher-corp/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-corp/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-corp/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/bittrex)
[![Coverage Status](http://codecov.io/github/thrasher-corp/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-corp/gocryptotrader)](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:

View File

@@ -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 (

View File

@@ -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.

View File

@@ -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
}

View File

@@ -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">
[![Build Status](https://travis-ci.org/thrasher-/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/btcmarkets)
[![Coverage Status](http://codecov.io/github/thrasher-/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-/gocryptotrader)](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
[![Build Status](https://travis-ci.org/thrasher-corp/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-corp/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-corp/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/btcmarkets)
[![Coverage Status](http://codecov.io/github/thrasher-corp/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-corp/gocryptotrader)](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:

View File

@@ -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 (

View File

@@ -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

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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.

View File

@@ -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 (

View File

@@ -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

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -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">
[![Build Status](https://travis-ci.org/thrasher-/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/coinbasepro)
[![Coverage Status](http://codecov.io/github/thrasher-/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-/gocryptotrader)](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
[![Build Status](https://travis-ci.org/thrasher-corp/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-corp/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-corp/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/coinbasepro)
[![Coverage Status](http://codecov.io/github/thrasher-corp/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-corp/gocryptotrader)](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:

View File

@@ -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

View File

@@ -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"),
})

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -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">
[![Build Status](https://travis-ci.org/thrasher-/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/coinut)
[![Coverage Status](http://codecov.io/github/thrasher-/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-/gocryptotrader)](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
[![Build Status](https://travis-ci.org/thrasher-corp/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-corp/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-corp/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/coinut)
[![Coverage Status](http://codecov.io/github/thrasher-corp/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-corp/gocryptotrader)](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:

View File

@@ -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

View File

@@ -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()
}

View File

@@ -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"`
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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() {

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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">
[![Build Status](https://travis-ci.org/thrasher-/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/exmo)
[![Coverage Status](http://codecov.io/github/thrasher-/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-/gocryptotrader)](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
[![Build Status](https://travis-ci.org/thrasher-corp/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-corp/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-corp/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/exmo)
[![Coverage Status](http://codecov.io/github/thrasher-corp/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-corp/gocryptotrader)](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:

View File

@@ -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 (

View File

@@ -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 (

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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">
[![Build Status](https://travis-ci.org/thrasher-/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/gateio)
[![Coverage Status](http://codecov.io/github/thrasher-/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-/gocryptotrader)](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
[![Build Status](https://travis-ci.org/thrasher-corp/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-corp/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-corp/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/gateio)
[![Coverage Status](http://codecov.io/github/thrasher-corp/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-corp/gocryptotrader)](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:

View File

@@ -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

View File

@@ -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()
}

View File

@@ -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"`
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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">
[![Build Status](https://travis-ci.org/thrasher-/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/gemini)
[![Coverage Status](http://codecov.io/github/thrasher-/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-/gocryptotrader)](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
[![Build Status](https://travis-ci.org/thrasher-corp/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-corp/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-corp/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/gemini)
[![Coverage Status](http://codecov.io/github/thrasher-corp/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-corp/gocryptotrader)](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:

View File

@@ -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") {

View File

@@ -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()

View File

@@ -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 {

View File

@@ -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()}
}

View File

@@ -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
}

View File

@@ -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">
[![Build Status](https://travis-ci.org/thrasher-/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/hitbtc)
[![Coverage Status](http://codecov.io/github/thrasher-/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-/gocryptotrader)](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
[![Build Status](https://travis-ci.org/thrasher-corp/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-corp/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-corp/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/hitbtc)
[![Coverage Status](http://codecov.io/github/thrasher-corp/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-corp/gocryptotrader)](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:

View File

@@ -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

View File

@@ -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()
}

View File

@@ -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"`
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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">
[![Build Status](https://travis-ci.org/thrasher-/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/huobi)
[![Coverage Status](http://codecov.io/github/thrasher-/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-/gocryptotrader)](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
[![Build Status](https://travis-ci.org/thrasher-corp/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-corp/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-corp/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/huobi)
[![Coverage Status](http://codecov.io/github/thrasher-corp/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-corp/gocryptotrader)](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:

View File

@@ -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

View File

@@ -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()
}

View File

@@ -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