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