Feature: Implement funding rates, futures and coin margin (exchange API coverage) (#530)

* ALMOST THERE

* more api wips

* more api thingz

* testing n more api wipz

* more apiz

* more wips

* what is goin on

* more wips

* whip n testing

* testing

* testing

no keys

* remove log

* kraken is broken

ugh

* still broken

* fixing auth funcs + usdtm api docs

* wip

* api stuffs

* whip

* more wips

* whip

* more wip

* api wip n testing

* wip

* wip

* unsaved

* wip n testing

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* whip

* wrapper authenticated functions

* adding asset type and fixing dependencies

* wip

* binance auth wrapper start

* wrapper functionality

* wip

* wip

* wip

* wrapper cancel functions

* order submission for wrappers

* wip

* more error fixing and nits

* websocket beginning n error fix

* wip

* WOW

* glorious n shazzy nits

* useless nits

* wip

* fixing things

* merge stuffs

* crapveyor

* crapveyor rebuild

* probably broke more things than he fixed

* rm lns n other thangs

* hope

* please

* stop it

* done

* ofcourse

* rm vb

* fix lbank

* appveyor please

* float lev

* DONT ASK RYAN FOR HELP EVER

* wip

* wip

* endpoint upgrades continued

* path upgrade

* NeeeNeeeNeeeNeeeNING

* fix stuffs

* fixing time issue

* fixing broken funcs

* glorious nits

* shaz changes

* fixing errors for fundmon

* more error fixing for fundmon

* test running past 30s

* basic changes

* THX AGAIN SHAZBERT

* path system upgrade

* config upgrade

* unsaved stuffs

* broken wip config upgrade

* path system upgrade contd.

* path system upgrade contd

* path upgrade ready for review

* testing verbose removed

* linter stuffs

* appveyor stuffs

* appveyor stuff

* fixed?

* bugfix

* wip

* broken stuff

* fix test

* wierd hack fix

* appveyor pls stop

* error found

* more useless nits

* bitmex err

* broken wip

* broken wip path upgrade change to uint32

* changed url lookups to uint

* WOW

* ready4review

* config fixed HOPEFULLY

* config fix and glorious changes

* efficient way of getting orders and open orders

* binance wrapper logic fixing

* testing, adding tests and fixing lot of errrrrs

* merge master

* appveyor stuffs

* appveyor stuffs

* fmt

* test

* octalLiteral issue fix?

* octalLiteral fix?

* rm vb

* prnt ln to restart

* adding testz

* test fixzzz

* READY FOR REVIEW

* Actually ready now

* FORMATTING

* addressing shazzy n glorious nits

* crapveyor

* rm vb

* small change

* fixing err

* shazbert nits

* review changes

* requested changes

* more requested changes

* noo

* last nit fixes

* restart appveyor

* improving test cov

* Update .golangci.yml

* shazbert changes

* moving pair formatting

* format pair update wip

* path upgrade complete

* error fix

* appveyor linters

* more linters

* remove testexch

* more formatting changes

* changes

* shazbert changes

* checking older requested changes to ensure completion

* wip

* fixing broken code

* error fix

* all fixed

* additional changes

* more changes

* remove commented code

* ftx margin api

* appveyor fixes

* more appveyor issues + test addition

* more appveyor issues + test addition

* remove unnecessary

* testing

* testing, fixing okex api, error fix

* git merge fix

* go sum

* glorious changes and error fix

* rm vb

* more glorious changes and go mod tidy

* fixed now

* okex testing upgrade

* old config migration and batch fetching fix

* added test

* glorious requested changes WIP

* tested and fixed

* go fmted

* go fmt and test fix

* additional funcs and tests for fundingRates

* OKEX tested and fixed

* appveyor fixes

* ineff assign

* 1 glorious change

* error fix

* typo

* shazbert changes

* glorious code changes and path fixing huobi WIP

* adding assetType to accountinfo functions

* fixing panic

* panic fix and updating account info wrappers WIP

* updateaccountinfo updated

* testing WIP binance USDT n Coin Margined and Kraken Futures

* auth functions tested and fixed

* added test

* config reverted

* shazbert and glorious changes

* shazbert and glorious changes

* latest changes and portfolio update

* go fmt change:

* remove commented codes

* improved error checking

* index out of range fix

* rm ln

* critical nit

* glorious latest changes

* appveyor changes

* shazbert change

* easier readability

* latest glorious changes

* shadow dec

* assetstore updated

* last change

* another last change

* merge changes

* go mod tidy

* thrasher requested changes wip

* improving struct layouts

* appveyor go fmt

* remove unnecessary code

* shazbert changes

* small change

* oopsie

* tidy

* configtest reverted

* error fix

* oopsie

* for what

* test patch fix

* insecurities

* fixing tests

* fix config
This commit is contained in:
Adam
2021-02-12 16:19:18 +11:00
committed by GitHub
parent e9bd2ad4d8
commit 504c2fad6d
169 changed files with 227754 additions and 31776 deletions

View File

@@ -11,6 +11,7 @@ import (
"time"
"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/config"
"github.com/thrasher-corp/gocryptotrader/currency"
@@ -578,6 +579,11 @@ func (e *Base) SetupDefaults(exch *config.ExchangeConfig) error {
}
e.SetFeatureDefaults()
if e.API.Endpoints == nil {
e.API.Endpoints = e.NewEndpoints()
}
err = e.SetAPIURL()
if err != nil {
return err
@@ -767,7 +773,6 @@ func (e *Base) UpdatePairs(exchangeProducts currency.Pairs, assetType asset.Item
e.Name,
strings.ToUpper(assetType.String()),
remove)
e.Config.CurrencyPairs.StorePairs(assetType, enabledPairs, true)
e.CurrencyPairs.StorePairs(assetType, enabledPairs, true)
}
@@ -778,52 +783,59 @@ func (e *Base) UpdatePairs(exchangeProducts currency.Pairs, assetType asset.Item
// SetAPIURL sets configuration API URL for an exchange
func (e *Base) SetAPIURL() error {
if e.Config.API.Endpoints.URL == "" || e.Config.API.Endpoints.URLSecondary == "" {
return fmt.Errorf("exchange %s: SetAPIURL error. URL vals are empty", e.Name)
}
checkInsecureEndpoint := func(endpoint string) {
if strings.Contains(endpoint, "https") {
if strings.Contains(endpoint, "https") || strings.Contains(endpoint, "wss") {
return
}
log.Warnf(log.ExchangeSys,
"%s is using HTTP instead of HTTPS [%s] for API functionality, an"+
"%s is using HTTP instead of HTTPS or WS instead of WSS [%s] for API functionality, an"+
" attacker could eavesdrop on this connection. Use at your"+
" own risk.",
e.Name, endpoint)
}
if e.Config.API.Endpoints.URL != config.APIURLNonDefaultMessage {
e.API.Endpoints.URL = e.Config.API.Endpoints.URL
checkInsecureEndpoint(e.API.Endpoints.URL)
}
if e.Config.API.Endpoints.URLSecondary != config.APIURLNonDefaultMessage {
e.API.Endpoints.URLSecondary = e.Config.API.Endpoints.URLSecondary
checkInsecureEndpoint(e.API.Endpoints.URLSecondary)
var err error
if e.Config.API.OldEndPoints != nil {
if e.Config.API.OldEndPoints.URL != "" && e.Config.API.OldEndPoints.URL != config.APIURLNonDefaultMessage {
err = e.API.Endpoints.SetRunning(RestSpot.String(), e.Config.API.OldEndPoints.URL)
if err != nil {
return err
}
checkInsecureEndpoint(e.Config.API.OldEndPoints.URL)
}
if e.Config.API.OldEndPoints.URLSecondary != "" && e.Config.API.OldEndPoints.URLSecondary != config.APIURLNonDefaultMessage {
err = e.API.Endpoints.SetRunning(RestSpotSupplementary.String(), e.Config.API.OldEndPoints.URLSecondary)
if err != nil {
return err
}
checkInsecureEndpoint(e.Config.API.OldEndPoints.URLSecondary)
}
if e.Config.API.OldEndPoints.WebsocketURL != "" && e.Config.API.OldEndPoints.WebsocketURL != config.WebsocketURLNonDefaultMessage {
err = e.API.Endpoints.SetRunning(WebsocketSpot.String(), e.Config.API.OldEndPoints.WebsocketURL)
if err != nil {
return err
}
checkInsecureEndpoint(e.Config.API.OldEndPoints.WebsocketURL)
}
e.Config.API.OldEndPoints = nil
} else if e.Config.API.Endpoints != nil {
for key, val := range e.Config.API.Endpoints {
if val == "" ||
val == config.APIURLNonDefaultMessage ||
val == config.WebsocketURLNonDefaultMessage {
continue
}
checkInsecureEndpoint(val)
err = e.API.Endpoints.SetRunning(key, val)
if err != nil {
return err
}
}
}
runningMap := e.API.Endpoints.GetURLMap()
e.Config.API.Endpoints = runningMap
return nil
}
// GetAPIURL returns the set API URL
func (e *Base) GetAPIURL() string {
return e.API.Endpoints.URL
}
// GetSecondaryAPIURL returns the set Secondary API URL
func (e *Base) GetSecondaryAPIURL() string {
return e.API.Endpoints.URLSecondary
}
// GetAPIURLDefault returns exchange default URL
func (e *Base) GetAPIURLDefault() string {
return e.API.Endpoints.URLDefault
}
// GetAPIURLSecondaryDefault returns exchange default secondary URL
func (e *Base) GetAPIURLSecondaryDefault() string {
return e.API.Endpoints.URLSecondaryDefault
}
// SupportsREST returns whether or not the exchange supports
// REST
func (e *Base) SupportsREST() bool {
@@ -946,6 +958,10 @@ func (e *Base) StoreAssetPairFormat(a asset.Item, f currency.PairStore) error {
e.Name)
}
if f.AssetEnabled == nil {
f.AssetEnabled = convert.BoolPtr(true)
}
if f.RequestFormat == nil {
return fmt.Errorf("%s cannot add to pairs manager, request pair format not provided",
e.Name)
@@ -1136,3 +1152,112 @@ func (e *Base) SetSaveTradeDataStatus(enabled bool) {
log.Debugf(log.Trade, "Set %v 'SaveTradeData' to %v", e.Name, enabled)
}
}
// NewEndpoints declares default and running URLs maps
func (e *Base) NewEndpoints() *Endpoints {
return &Endpoints{
Exchange: e.Name,
defaults: make(map[string]string),
}
}
// SetDefaultEndpoints declares and sets the default URLs map
func (e *Endpoints) SetDefaultEndpoints(m map[URL]string) error {
for k, v := range m {
err := e.SetRunning(k.String(), v)
if err != nil {
return err
}
}
return nil
}
// SetRunning populates running URLs map
func (e *Endpoints) SetRunning(key, val string) error {
e.Lock()
defer e.Unlock()
err := validateKey(key)
if err != nil {
return err
}
_, err = url.ParseRequestURI(val)
if err != nil {
log.Warnf(log.ExchangeSys, "Could not set custom URL for %s to %s for exchange %s. invalid URI for request.", key, val, e.Exchange)
return nil
}
e.defaults[key] = val
return nil
}
func validateKey(keyVal string) error {
for x := range keyURLs {
if keyURLs[x].String() == keyVal {
return nil
}
}
return errors.New("keyVal invalid")
}
// GetURL gets default url from URLs map
func (e *Endpoints) GetURL(key URL) (string, error) {
e.RLock()
defer e.RUnlock()
val, ok := e.defaults[key.String()]
if !ok {
return "", fmt.Errorf("no endpoint path found for the given key: %v", key)
}
return val, nil
}
// GetURLMap gets all urls for either running or default map based on the bool value supplied
func (e *Endpoints) GetURLMap() map[string]string {
e.RLock()
var urlMap = make(map[string]string)
for k, v := range e.defaults {
urlMap[k] = v
}
e.RUnlock()
return urlMap
}
// FormatSymbol formats the given pair to a string suitable for exchange API requests
func (e *Base) FormatSymbol(pair currency.Pair, assetType asset.Item) (string, error) {
pairFmt, err := e.GetPairFormat(assetType, true)
if err != nil {
return pair.String(), err
}
return pairFmt.Format(pair), nil
}
func (u URL) String() string {
switch u {
case RestSpot:
return "RestSpotURL"
case RestSpotSupplementary:
return "RestSpotSupplementaryURL"
case RestUSDTMargined:
return "RestUSDTMarginedFuturesURL"
case RestCoinMargined:
return "RestCoinMarginedFuturesURL"
case RestFutures:
return "RestFuturesURL"
case RestSandbox:
return "RestSandboxURL"
case RestSwap:
return "RestSwapURL"
case WebsocketSpot:
return "WebsocketSpotURL"
case WebsocketSpotSupplementary:
return "WebsocketSpotSupplementaryURL"
case ChainAnalysis:
return "ChainAnalysisURL"
case EdgeCase1:
return "EdgeCase1URL"
case EdgeCase2:
return "EdgeCase2URL"
case EdgeCase3:
return "EdgeCase3URL"
default:
return ""
}
}