Gemini: Fix pair handling and upgrade websocket connection for public market data (#644)

* Fix Gemini pairs

* Overhaul websocket for marketdata v2

* Code cleanup + returns

* Address shazbert's and glorious's nits

* Go mod tidy
This commit is contained in:
Adrian Gallagher
2021-03-09 13:18:21 +11:00
committed by GitHub
parent 2292abce61
commit b30d79b52d
8 changed files with 666 additions and 327 deletions

View File

@@ -59,8 +59,14 @@ func (g *Gemini) SetDefaults() {
g.API.CredentialsValidator.RequiresKey = true
g.API.CredentialsValidator.RequiresSecret = true
requestFmt := &currency.PairFormat{Uppercase: true}
configFmt := &currency.PairFormat{Uppercase: true}
requestFmt := &currency.PairFormat{
Uppercase: true,
Separator: ",",
}
configFmt := &currency.PairFormat{
Uppercase: true,
Delimiter: currency.DashDelimiter,
}
err := g.SetGlobalPairsManager(requestFmt, configFmt, asset.Spot)
if err != nil {
log.Errorln(log.ExchangeSys, err)
@@ -93,6 +99,8 @@ func (g *Gemini) SetDefaults() {
AuthenticatedEndpoints: true,
MessageSequenceNumbers: true,
KlineFetching: true,
Subscribe: true,
Unsubscribe: true,
},
WithdrawPermissions: exchange.AutoWithdrawCryptoWithAPIPermission |
exchange.AutoWithdrawCryptoWithSetup |
@@ -144,7 +152,7 @@ func (g *Gemini) Setup(exch *config.ExchangeConfig) error {
return err
}
return g.Websocket.Setup(&stream.WebsocketSetup{
err = g.Websocket.Setup(&stream.WebsocketSetup{
Enabled: exch.Features.Enabled.Websocket,
Verbose: exch.Verbose,
AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
@@ -153,10 +161,31 @@ func (g *Gemini) Setup(exch *config.ExchangeConfig) error {
ExchangeName: exch.Name,
RunningURL: wsRunningURL,
Connector: g.WsConnect,
Subscriber: g.Subscribe,
UnSubscriber: g.Unsubscribe,
GenerateSubscriptions: g.GenerateDefaultSubscriptions,
Features: &g.Features.Supports.WebsocketCapabilities,
OrderbookBufferLimit: exch.OrderbookConfig.WebsocketBufferLimit,
BufferEnabled: exch.OrderbookConfig.WebsocketBufferEnabled,
SortBuffer: true,
})
if err != nil {
return err
}
err = g.Websocket.SetupNewConnection(stream.ConnectionSetup{
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
URL: geminiWebsocketEndpoint + "/v2/" + geminiWsMarketData,
})
if err != nil {
return err
}
return g.Websocket.SetupNewConnection(stream.ConnectionSetup{
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
URL: geminiWebsocketEndpoint + "/v1/" + geminiWsOrderEvents,
Authenticated: true,
})
}
@@ -175,25 +204,92 @@ func (g *Gemini) Run() {
g.PrintEnabledPairs()
}
if !g.GetEnabledFeatures().AutoPairUpdates {
forceUpdate := false
format, err := g.GetPairFormat(asset.Spot, false)
if err != nil {
log.Errorf(log.ExchangeSys, "%s failed to get enabled currencies. Err %s\n",
g.Name,
err)
return
}
err := g.UpdateTradablePairs(false)
enabled, err := g.CurrencyPairs.GetPairs(asset.Spot, true)
if err != nil {
log.Errorf(log.ExchangeSys, "%s failed to update tradable pairs. Err: %s", g.Name, err)
log.Errorf(log.ExchangeSys, "%s failed to get enabled currencies. Err %s\n",
g.Name,
err)
return
}
avail, err := g.CurrencyPairs.GetPairs(asset.Spot, false)
if err != nil {
log.Errorf(log.ExchangeSys, "%s failed to get available currencies. Err %s\n",
g.Name,
err)
return
}
if !common.StringDataContains(enabled.Strings(), format.Delimiter) ||
!common.StringDataContains(avail.Strings(), format.Delimiter) {
var enabledPairs currency.Pairs
enabledPairs, err = currency.NewPairsFromStrings([]string{
currency.BTC.String() + format.Delimiter + currency.USD.String()})
if err != nil {
log.Errorf(log.ExchangeSys, "%s failed to update currencies. Err %s\n",
g.Name,
err)
} else {
log.Warn(log.ExchangeSys,
"Available pairs for Gemini reset due to config upgrade, please enable the ones you would like to use again")
forceUpdate = true
err = g.UpdatePairs(enabledPairs, asset.Spot, true, true)
if err != nil {
log.Errorf(log.ExchangeSys,
"%s failed to update currencies. Err: %s\n",
g.Name,
err)
}
}
}
if !g.GetEnabledFeatures().AutoPairUpdates && !forceUpdate {
return
}
err = g.UpdateTradablePairs(forceUpdate)
if err != nil {
log.Errorf(log.ExchangeSys,
"%s failed to update tradable pairs. Err: %s",
g.Name,
err)
}
}
// FetchTradablePairs returns a list of the exchanges tradable pairs
func (g *Gemini) FetchTradablePairs(asset asset.Item) ([]string, error) {
return g.GetSymbols()
pairs, err := g.GetSymbols()
if err != nil {
return nil, err
}
var tradablePairs []string
for x := range pairs {
switch len(pairs[x]) {
case 8:
tradablePairs = append(tradablePairs, pairs[x][0:5]+currency.DashDelimiter+pairs[x][5:])
case 7:
tradablePairs = append(tradablePairs, pairs[x][0:4]+currency.DashDelimiter+pairs[x][4:])
default:
tradablePairs = append(tradablePairs, pairs[x][0:3]+currency.DashDelimiter+pairs[x][3:])
}
}
return tradablePairs, nil
}
// UpdateTradablePairs updates the exchanges available pairs and stores
// them in the exchanges config
func (g *Gemini) UpdateTradablePairs(forceUpdate bool) error {
pairs, err := g.GetSymbols()
pairs, err := g.FetchTradablePairs(asset.Spot)
if err != nil {
return err
}
@@ -563,7 +659,12 @@ func (g *Gemini) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
return nil, err
}
format, err := g.GetPairFormat(asset.Spot, false)
availPairs, err := g.GetAvailablePairs(asset.Spot)
if err != nil {
return nil, err
}
format, err := g.GetPairFormat(asset.Spot, true)
if err != nil {
return nil, err
}
@@ -571,7 +672,7 @@ func (g *Gemini) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
var orders []order.Detail
for i := range resp {
var symbol currency.Pair
symbol, err = currency.NewPairDelimiter(resp[i].Symbol, format.Delimiter)
symbol, err = currency.NewPairFromFormattedPairs(resp[i].Symbol, availPairs, format)
if err != nil {
return nil, err
}