mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 15:09:42 +00:00
fixed merge conflicts
This commit is contained in:
@@ -4,9 +4,9 @@ thrasher- | https://github.com/thrasher-
|
||||
shazbert | https://github.com/shazbert
|
||||
gloriousCode | https://github.com/gloriousCode
|
||||
140am | https://github.com/140am
|
||||
ermalguni | https://github.com/ermalguni
|
||||
marcofranssen | https://github.com/marcofranssen
|
||||
Betazoid | https://github.com/Betazoid
|
||||
ermalguni | https://github.com/ermalguni
|
||||
crackcomm | https://github.com/crackcomm
|
||||
bretep | https://github.com/bretep
|
||||
gam-phon | https://github.com/gam-phon
|
||||
|
||||
10
README.md
10
README.md
@@ -24,6 +24,7 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader
|
||||
| Bitfinex | Yes | Yes | NA |
|
||||
| Bitflyer | Yes | No | NA |
|
||||
| Bithumb | Yes | NA | NA |
|
||||
| BitMEX | Yes | No | NA |
|
||||
| Bitstamp | Yes | Yes | No |
|
||||
| Bittrex | Yes | No | NA |
|
||||
| BTCC | Yes | Yes | No |
|
||||
@@ -147,13 +148,13 @@ Binaries will be published once the codebase reaches a stable condition.
|
||||
|
||||
|User|Github|Contribution Amount|
|
||||
|--|--|--|
|
||||
| thrasher- | https://github.com/thrasher- | 453 |
|
||||
| shazbert | https://github.com/shazbert | 141 |
|
||||
| thrasher- | https://github.com/thrasher- | 456 |
|
||||
| shazbert | https://github.com/shazbert | 142 |
|
||||
| gloriousCode | https://github.com/gloriousCode | 122 |
|
||||
| 140am | https://github.com/140am | 8 |
|
||||
| ermalguni | https://github.com/ermalguni | 4 |
|
||||
| marcofranssen | https://github.com/marcofranssen | 4 |
|
||||
| Betazoid | https://github.com/Betazoid | 4 |
|
||||
| ermalguni | https://github.com/ermalguni | 3 |
|
||||
| crackcomm | https://github.com/crackcomm | 3 |
|
||||
| bretep | https://github.com/bretep | 2 |
|
||||
| gam-phon | https://github.com/gam-phon | 2 |
|
||||
@@ -175,6 +176,3 @@ Binaries will be published once the codebase reaches a stable condition.
|
||||
| askew- | https://github.com/askew- | 1 |
|
||||
| whilei | https://github.com/whilei | 1 |
|
||||
| snipesjr | https://github.com/snipesjr | 1 |
|
||||
|
||||
|
||||
|
||||
|
||||
203
config/config.go
203
config/config.go
@@ -33,8 +33,8 @@ const (
|
||||
configMaxAuthFailres = 3
|
||||
)
|
||||
|
||||
// Variables here are mainly alerts and a configuration object
|
||||
var (
|
||||
// Constants here hold some messages
|
||||
const (
|
||||
ErrExchangeNameEmpty = "Exchange #%d in config: Exchange name is empty."
|
||||
ErrExchangeAvailablePairsEmpty = "Exchange %s: Available pairs is empty."
|
||||
ErrExchangeEnabledPairsEmpty = "Exchange %s: Enabled pairs is empty."
|
||||
@@ -54,166 +54,171 @@ var (
|
||||
WarningExchangeAuthAPIDefaultOrEmptyValues = "WARNING -- Exchange %s: Authenticated API support disabled due to default/empty APIKey/Secret/ClientID values."
|
||||
WarningCurrencyExchangeProvider = "WARNING -- Currency exchange provider invalid valid. Reset to Fixer."
|
||||
WarningPairsLastUpdatedThresholdExceeded = "WARNING -- Exchange %s: Last manual update of available currency pairs has exceeded %d days. Manual update required!"
|
||||
Cfg Config
|
||||
IsInitialSetup bool
|
||||
testBypass bool
|
||||
m sync.Mutex
|
||||
)
|
||||
|
||||
// Variables here are used for configuration
|
||||
var (
|
||||
Cfg Config
|
||||
IsInitialSetup bool
|
||||
testBypass bool
|
||||
m sync.Mutex
|
||||
)
|
||||
|
||||
// WebserverConfig struct holds the prestart variables for the webserver.
|
||||
type WebserverConfig struct {
|
||||
Enabled bool
|
||||
AdminUsername string
|
||||
AdminPassword string
|
||||
ListenAddress string
|
||||
WebsocketConnectionLimit int
|
||||
WebsocketMaxAuthFailures int
|
||||
WebsocketAllowInsecureOrigin bool
|
||||
Enabled bool `json:"enabled"`
|
||||
AdminUsername string `json:"adminUsername"`
|
||||
AdminPassword string `json:"adminPassword"`
|
||||
ListenAddress string `json:"listenAddress"`
|
||||
WebsocketConnectionLimit int `json:"websocketConnectionLimit"`
|
||||
WebsocketMaxAuthFailures int `json:"websocketMaxAuthFailures"`
|
||||
WebsocketAllowInsecureOrigin bool `json:"websocketAllowInsecureOrigin"`
|
||||
}
|
||||
|
||||
// Post holds the bot configuration data
|
||||
type Post struct {
|
||||
Data Config `json:"Data"`
|
||||
Data Config `json:"data"`
|
||||
}
|
||||
|
||||
// CurrencyPairFormatConfig stores the users preferred currency pair display
|
||||
type CurrencyPairFormatConfig struct {
|
||||
Uppercase bool
|
||||
Delimiter string `json:",omitempty"`
|
||||
Separator string `json:",omitempty"`
|
||||
Index string `json:",omitempty"`
|
||||
Uppercase bool `json:"uppercase"`
|
||||
Delimiter string `json:"delimiter,omitempty"`
|
||||
Separator string `json:"separator,omitempty"`
|
||||
Index string `json:"index,omitempty"`
|
||||
}
|
||||
|
||||
// Config is the overarching object that holds all the information for
|
||||
// prestart management of Portfolio, Communications, Webserver and Enabled
|
||||
// Exchanges
|
||||
type Config struct {
|
||||
Name string
|
||||
EncryptConfig int
|
||||
GlobalHTTPTimeout time.Duration `json:"GlobalHTTPTimeout"`
|
||||
Currency CurrencyConfig `json:"CurrencyConfig"`
|
||||
Communications CommunicationsConfig `json:"Communications"`
|
||||
Portfolio portfolio.Base `json:"PortfolioAddresses"`
|
||||
Webserver WebserverConfig `json:"Webserver"`
|
||||
Exchanges []ExchangeConfig `json:"Exchanges"`
|
||||
BankAccounts []BankAccount `json:"BankAccounts"`
|
||||
Name string `json:"name"`
|
||||
EncryptConfig int `json:"encryptConfig"`
|
||||
GlobalHTTPTimeout time.Duration `json:"globalHTTPTimeout"`
|
||||
Currency CurrencyConfig `json:"currencyConfig"`
|
||||
Communications CommunicationsConfig `json:"communications"`
|
||||
Portfolio portfolio.Base `json:"portfolioAddresses"`
|
||||
Webserver WebserverConfig `json:"webserver"`
|
||||
Exchanges []ExchangeConfig `json:"exchanges"`
|
||||
BankAccounts []BankAccount `json:"bankAccounts"`
|
||||
|
||||
// Deprecated config settings, will be removed at a future date
|
||||
CurrencyPairFormat *CurrencyPairFormatConfig `json:"CurrencyPairFormat,omitempty"`
|
||||
FiatDisplayCurrency string `json:"FiatDispayCurrency,omitempty"`
|
||||
Cryptocurrencies string `json:"Cryptocurrencies,omitempty"`
|
||||
SMS *SMSGlobalConfig `json:"SMSGlobal,omitempty"`
|
||||
CurrencyPairFormat *CurrencyPairFormatConfig `json:"currencyPairFormat,omitempty"`
|
||||
FiatDisplayCurrency string `json:"fiatDispayCurrency,omitempty"`
|
||||
Cryptocurrencies string `json:"cryptocurrencies,omitempty"`
|
||||
SMS *SMSGlobalConfig `json:"smsGlobal,omitempty"`
|
||||
}
|
||||
|
||||
// ExchangeConfig holds all the information needed for each enabled Exchange.
|
||||
type ExchangeConfig struct {
|
||||
Name string
|
||||
Enabled bool
|
||||
Verbose bool
|
||||
Websocket bool
|
||||
UseSandbox bool
|
||||
RESTPollingDelay time.Duration
|
||||
HTTPTimeout time.Duration
|
||||
AuthenticatedAPISupport bool
|
||||
APIKey string
|
||||
APISecret string
|
||||
APIAuthPEMKey string `json:",omitempty"`
|
||||
ClientID string `json:",omitempty"`
|
||||
AvailablePairs string
|
||||
EnabledPairs string
|
||||
BaseCurrencies string
|
||||
AssetTypes string
|
||||
SupportsAutoPairUpdates bool
|
||||
PairsLastUpdated int64 `json:",omitempty"`
|
||||
ConfigCurrencyPairFormat *CurrencyPairFormatConfig `json:"ConfigCurrencyPairFormat"`
|
||||
RequestCurrencyPairFormat *CurrencyPairFormatConfig `json:"RequestCurrencyPairFormat"`
|
||||
BankAccounts []BankAccount
|
||||
Name string `json:"name"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Verbose bool `json:"verbose"`
|
||||
Websocket bool `json:"websocket"`
|
||||
UseSandbox bool `json:"useSandbox"`
|
||||
RESTPollingDelay time.Duration `json:"restPollingDelay"`
|
||||
HTTPTimeout time.Duration `json:"httpTimeout"`
|
||||
HTTPUserAgent string `json:"httpUserAgent"`
|
||||
AuthenticatedAPISupport bool `json:"authenticatedApiSupport"`
|
||||
APIKey string `json:"apiKey"`
|
||||
APISecret string `json:"apiSecret"`
|
||||
APIAuthPEMKey string `json:"apiAuthPemKey,omitempty"`
|
||||
ClientID string `json:"clientId,omitempty"`
|
||||
AvailablePairs string `json:"availablePairs"`
|
||||
EnabledPairs string `json:"enabledPairs"`
|
||||
BaseCurrencies string `json:"baseCurrencies"`
|
||||
AssetTypes string `json:"assetTypes"`
|
||||
SupportsAutoPairUpdates bool `json:"supportsAutoPairUpdates"`
|
||||
PairsLastUpdated int64 `json:"pairsLastUpdated,omitempty"`
|
||||
ConfigCurrencyPairFormat *CurrencyPairFormatConfig `json:"configCurrencyPairFormat"`
|
||||
RequestCurrencyPairFormat *CurrencyPairFormatConfig `json:"requestCurrencyPairFormat"`
|
||||
BankAccounts []BankAccount `json:"bankAccounts"`
|
||||
}
|
||||
|
||||
// BankAccount holds differing bank account details by supported funding
|
||||
// currency
|
||||
type BankAccount struct {
|
||||
Enabled bool `json:",omitempty"`
|
||||
BankName string
|
||||
BankAddress string
|
||||
AccountName string
|
||||
AccountNumber string
|
||||
SWIFTCode string
|
||||
IBAN string
|
||||
BSBNumber string `json:",omitempty"`
|
||||
SupportedCurrencies string
|
||||
SupportedExchanges string `json:",omitempty"`
|
||||
Enabled bool `json:",omitempty"`
|
||||
BankName string `json:"bankName"`
|
||||
BankAddress string `json:"bankAddress"`
|
||||
AccountName string `json:"accountName"`
|
||||
AccountNumber string `json:"accountNumber"`
|
||||
SWIFTCode string `json:"swiftCode"`
|
||||
IBAN string `json:"iban"`
|
||||
BSBNumber string `json:"bsbNumber,omitempty"`
|
||||
SupportedCurrencies string `json:"supportedCurrencies"`
|
||||
SupportedExchanges string `json:"supportedExchanges,omitempty"`
|
||||
}
|
||||
|
||||
// BankTransaction defines a related banking transaction
|
||||
type BankTransaction struct {
|
||||
ReferenceNumber string
|
||||
TransactionNumber string
|
||||
PaymentInstructions string
|
||||
ReferenceNumber string `json:"referenceNumber"`
|
||||
TransactionNumber string `json:"transactionNumber"`
|
||||
PaymentInstructions string `json:"paymentInstructions"`
|
||||
}
|
||||
|
||||
// CurrencyConfig holds all the information needed for currency related manipulation
|
||||
type CurrencyConfig struct {
|
||||
ForexProviders []base.Settings `json:"ForexProviders"`
|
||||
Cryptocurrencies string `json:"Cryptocurrencies"`
|
||||
CurrencyPairFormat *CurrencyPairFormatConfig `json:"CurrencyPairFormat"`
|
||||
FiatDisplayCurrency string
|
||||
ForexProviders []base.Settings `json:"forexProviders"`
|
||||
Cryptocurrencies string `json:"cryptocurrencies"`
|
||||
CurrencyPairFormat *CurrencyPairFormatConfig `json:"currencyPairFormat"`
|
||||
FiatDisplayCurrency string `json:"fiatDisplayCurrency"`
|
||||
}
|
||||
|
||||
// CommunicationsConfig holds all the information needed for each
|
||||
// enabled communication package
|
||||
type CommunicationsConfig struct {
|
||||
SlackConfig SlackConfig `json:"Slack"`
|
||||
SMSGlobalConfig SMSGlobalConfig `json:"SMSGlobal"`
|
||||
SMTPConfig SMTPConfig `json:"SMTP"`
|
||||
TelegramConfig TelegramConfig `json:"Telegram"`
|
||||
SlackConfig SlackConfig `json:"slack"`
|
||||
SMSGlobalConfig SMSGlobalConfig `json:"smsGlobal"`
|
||||
SMTPConfig SMTPConfig `json:"smtp"`
|
||||
TelegramConfig TelegramConfig `json:"telegram"`
|
||||
}
|
||||
|
||||
// SlackConfig holds all variables to start and run the Slack package
|
||||
type SlackConfig struct {
|
||||
Name string `json:"Name"`
|
||||
Enabled bool `json:"Enabled"`
|
||||
Verbose bool `json:"Verbose"`
|
||||
TargetChannel string `json:"TargetChannel"`
|
||||
VerificationToken string `json:"VerificationToken"`
|
||||
Name string `json:"name"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Verbose bool `json:"verbose"`
|
||||
TargetChannel string `json:"targetChannel"`
|
||||
VerificationToken string `json:"verificationToken"`
|
||||
}
|
||||
|
||||
// SMSContact stores the SMS contact info
|
||||
type SMSContact struct {
|
||||
Name string `json:"Name"`
|
||||
Number string `json:"Number"`
|
||||
Enabled bool `json:"Enabled"`
|
||||
Name string `json:"name"`
|
||||
Number string `json:"number"`
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
|
||||
// SMSGlobalConfig structure holds all the variables you need for instant
|
||||
// messaging and broadcast used by SMSGlobal
|
||||
type SMSGlobalConfig struct {
|
||||
Name string `json:"Name"`
|
||||
Enabled bool `json:"Enabled"`
|
||||
Verbose bool `json:"Verbose"`
|
||||
Username string `json:"Username"`
|
||||
Password string `json:"Password"`
|
||||
Contacts []SMSContact `json:"Contacts"`
|
||||
Name string `json:"name"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Verbose bool `json:"verbose"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Contacts []SMSContact `json:"contacts"`
|
||||
}
|
||||
|
||||
// SMTPConfig holds all variables to start and run the SMTP package
|
||||
type SMTPConfig struct {
|
||||
Name string `json:"Name"`
|
||||
Enabled bool `json:"Enabled"`
|
||||
Verbose bool `json:"Verbose"`
|
||||
Host string `json:"Host"`
|
||||
Port string `json:"Port"`
|
||||
AccountName string `json:"AccountName"`
|
||||
AccountPassword string `json:"AccountPassword"`
|
||||
RecipientList string `json:"RecipientList"`
|
||||
Name string `json:"name"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Verbose bool `json:"verbose"`
|
||||
Host string `json:"host"`
|
||||
Port string `json:"port"`
|
||||
AccountName string `json:"accountName"`
|
||||
AccountPassword string `json:"accountPassword"`
|
||||
RecipientList string `json:"recipientList"`
|
||||
}
|
||||
|
||||
// TelegramConfig holds all variables to start and run the Telegram package
|
||||
type TelegramConfig struct {
|
||||
Name string `json:"Name"`
|
||||
Enabled bool `json:"Enabled"`
|
||||
Verbose bool `json:"Verbose"`
|
||||
VerificationToken string `json:"VerificationToken"`
|
||||
Name string `json:"name"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Verbose bool `json:"verbose"`
|
||||
VerificationToken string `json:"verificationToken"`
|
||||
}
|
||||
|
||||
// GetCurrencyConfig returns currency configurations
|
||||
|
||||
@@ -206,7 +206,7 @@ func TestGetEnabledExchanges(t *testing.T) {
|
||||
}
|
||||
|
||||
exchanges := cfg.GetEnabledExchanges()
|
||||
if len(exchanges) != 29 {
|
||||
if len(exchanges) != 30 {
|
||||
t.Error(
|
||||
"Test failed. TestGetEnabledExchanges. Enabled exchanges value mismatch",
|
||||
)
|
||||
@@ -258,7 +258,7 @@ func TestGetDisabledExchanges(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCountEnabledExchanges(t *testing.T) {
|
||||
defaultEnabledExchanges := 29
|
||||
defaultEnabledExchanges := 30
|
||||
GetConfigEnabledExchanges := GetConfig()
|
||||
err := GetConfigEnabledExchanges.LoadConfig(ConfigTestFile)
|
||||
if err != nil {
|
||||
|
||||
1804
config_example.json
1804
config_example.json
File diff suppressed because one or more lines are too long
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/bitfinex"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/bitflyer"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/bithumb"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/bitmex"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/bitstamp"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/bittrex"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/btcc"
|
||||
@@ -145,6 +146,8 @@ func LoadExchange(name string, useWG bool, wg *sync.WaitGroup) error {
|
||||
exch = new(bitflyer.Bitflyer)
|
||||
case "bithumb":
|
||||
exch = new(bithumb.Bithumb)
|
||||
case "bitmex":
|
||||
exch = new(bitmex.Bitmex)
|
||||
case "bitstamp":
|
||||
exch = new(bitstamp.Bitstamp)
|
||||
case "bittrex":
|
||||
|
||||
@@ -70,6 +70,7 @@ func (a *ANX) Setup(exch config.ExchangeConfig) {
|
||||
a.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
a.SetAPIKeys(exch.APIKey, exch.APISecret, "", true)
|
||||
a.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
a.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
a.RESTPollingDelay = exch.RESTPollingDelay
|
||||
a.Verbose = exch.Verbose
|
||||
a.Websocket = exch.Websocket
|
||||
|
||||
@@ -83,6 +83,7 @@ func (b *Binance) Setup(exch config.ExchangeConfig) {
|
||||
b.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
b.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
|
||||
b.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
b.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
b.RESTPollingDelay = exch.RESTPollingDelay
|
||||
b.Verbose = exch.Verbose
|
||||
b.Websocket = exch.Websocket
|
||||
|
||||
@@ -114,6 +114,7 @@ func (b *Bitfinex) Setup(exch config.ExchangeConfig) {
|
||||
b.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
b.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
|
||||
b.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
b.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
b.RESTPollingDelay = exch.RESTPollingDelay
|
||||
b.Verbose = exch.Verbose
|
||||
b.Websocket = exch.Websocket
|
||||
|
||||
@@ -100,6 +100,7 @@ func (b *Bitflyer) Setup(exch config.ExchangeConfig) {
|
||||
b.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
b.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
|
||||
b.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
b.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
b.RESTPollingDelay = exch.RESTPollingDelay
|
||||
b.Verbose = exch.Verbose
|
||||
b.Websocket = exch.Websocket
|
||||
|
||||
@@ -82,6 +82,7 @@ func (b *Bithumb) Setup(exch config.ExchangeConfig) {
|
||||
b.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
b.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
|
||||
b.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
b.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
b.RESTPollingDelay = exch.RESTPollingDelay
|
||||
b.Verbose = exch.Verbose
|
||||
b.Websocket = exch.Websocket
|
||||
|
||||
133
exchanges/bitmex/README.md
Normal file
133
exchanges/bitmex/README.md
Normal file
@@ -0,0 +1,133 @@
|
||||
# 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">
|
||||
|
||||
|
||||
[](https://travis-ci.org/thrasher-/gocryptotrader)
|
||||
[](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/bitmex)
|
||||
[](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
|
||||
|
||||
|
||||
This bitmex package is part of the GoCryptoTrader codebase.
|
||||
|
||||
## This is still in active development
|
||||
|
||||
You can track ideas, planned features and what's in progresss on this Trello board: [https://trello.com/b/ZAhMhpOy/gocryptotrader](https://trello.com/b/ZAhMhpOy/gocryptotrader).
|
||||
|
||||
Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader Slack](https://gocryptotrader.herokuapp.com/)
|
||||
|
||||
## Bithumb Exchange
|
||||
|
||||
### Current Features
|
||||
|
||||
+ REST Support
|
||||
|
||||
### How to enable
|
||||
|
||||
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
|
||||
+ Individual package example below:
|
||||
|
||||
```go
|
||||
// Exchanges will be abstracted out in further updates and examples will be
|
||||
// supplied then
|
||||
```
|
||||
|
||||
### How to do REST public/private calls
|
||||
|
||||
+ If enabled via "configuration".json file the exchange will be added to the
|
||||
IBotExchange array in the ```go var bot Bot``` and you will only be able to use
|
||||
the wrapper interface functions for accessing exchange data. View routines.go
|
||||
for an example of integration usage with GoCryptoTrader. Rudimentary example
|
||||
below:
|
||||
|
||||
main.go
|
||||
```go
|
||||
var b exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "Bitmex" {
|
||||
b = bot.exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := b.GetTickerPrice()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := b.GetOrderbookEx()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Private calls - wrapper functions - make sure your APIKEY and APISECRET are
|
||||
// set and AuthenticatedAPISupport is set to true
|
||||
|
||||
// Fetches current account information
|
||||
accountInfo, err := b.GetExchangeAccountInfo()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
+ If enabled via individually importing package, rudimentary example below:
|
||||
|
||||
```go
|
||||
// Public calls
|
||||
|
||||
// Fetches current ticker information
|
||||
ticker, err := b.GetTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := b.GetOrderBook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Private calls - make sure your APIKEY and APISECRET are set and
|
||||
// AuthenticatedAPISupport is set to true
|
||||
|
||||
// GetUserInfo returns account info
|
||||
accountInfo, err := b.GetUserInfo(...)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Submits an order and the exchange and returns its tradeID
|
||||
tradeID, err := b.Trade(...)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
### Please click GoDocs chevron above to view current GoDoc information for this package
|
||||
|
||||
## Contribution
|
||||
|
||||
Please feel free to submit any pull requests or suggest any desired features to be added.
|
||||
|
||||
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).
|
||||
+ 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">
|
||||
|
||||
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
|
||||
|
||||
***1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB***
|
||||
|
||||
893
exchanges/bitmex/bitmex.go
Normal file
893
exchanges/bitmex/bitmex.go
Normal file
@@ -0,0 +1,893 @@
|
||||
package bitmex
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
// Bitmex is the overarching type across this package
|
||||
type Bitmex struct {
|
||||
exchange.Base
|
||||
WebsocketConn *websocket.Conn
|
||||
shutdown *Shutdown
|
||||
}
|
||||
|
||||
const (
|
||||
bitmexAPIVersion = "v1"
|
||||
bitmexAPIURL = "https://www.bitmex.com/api/v1"
|
||||
bitmexAPItestnetURL = "https://testnet.bitmex.com/api/v1"
|
||||
|
||||
// Public endpoints
|
||||
bitmexEndpointAnnouncement = "/announcement"
|
||||
bitmexEndpointAnnouncementUrgent = "/announcement/urgent"
|
||||
bitmexEndpointOrderbookL2 = "/orderBook/L2"
|
||||
bitmexEndpointTrollbox = "/chat"
|
||||
bitmexEndpointTrollboxChannels = "/chat/channels"
|
||||
bitmexEndpointTrollboxConnected = "/chat/connected"
|
||||
bitmexEndpointFundingHistory = "/funding"
|
||||
bitmexEndpointInstruments = "/instrument"
|
||||
bitmexEndpointActiveInstruments = "/instrument/active"
|
||||
bitmexEndpointActiveAndIndexInstruments = "/instrument/activeAndIndices"
|
||||
bitmexEndpointActiveIntervals = "/instrument/activeIntervals"
|
||||
bitmexEndpointCompositeIndex = "/instrument/compositeIndex"
|
||||
bitmexEndpointIndices = "/instrument/indices"
|
||||
bitmexEndpointInsuranceHistory = "/insurance"
|
||||
bitmexEndpointLiquidation = "/liquidation"
|
||||
bitmexEndpointLeader = "/leaderboard"
|
||||
bitmexEndpointAlias = "/leaderboard/name"
|
||||
bitmexEndpointQuote = "/quote"
|
||||
bitmexEndpointQuoteBucketed = "/quote/bucketed"
|
||||
bitmexEndpointSettlement = "/settlement"
|
||||
bitmexEndpointStats = "/stats"
|
||||
bitmexEndpointStatsHistory = "/stats/history"
|
||||
bitmexEndpointStatsSummary = "/stats/historyUSD"
|
||||
bitmexEndpointTrade = "/trade"
|
||||
bitmexEndpointTradeBucketed = "/trade/bucketed"
|
||||
bitmexEndpointUserCheckReferralCode = "/user/checkReferralCode"
|
||||
bitmexEndpointUserMinWithdrawalFee = "/user/minWithdrawalFee"
|
||||
|
||||
// Authenticated endpoints
|
||||
bitmexEndpointAPIkeys = "/apiKey"
|
||||
bitmexEndpointDisableAPIkey = "/apiKey/disable"
|
||||
bitmexEndpointEnableAPIkey = "/apiKey/enable"
|
||||
bitmexEndpointTrollboxSend = "/chat"
|
||||
bitmexEndpointExecution = "/execution"
|
||||
bitmexEndpointExecutionTradeHistory = "/execution/tradeHistory"
|
||||
bitmexEndpointNotifications = "/notification"
|
||||
bitmexEndpointOrder = "/order"
|
||||
bitmexEndpointCancelAllOrders = "/order/all"
|
||||
bitmexEndpointBulk = "/order/bulk"
|
||||
bitmexEndpointCancelOrderAfter = "/order/cancelAllAfter"
|
||||
bitmexEndpointClosePosition = "/order/closePosition"
|
||||
bitmexEndpointPosition = "/position"
|
||||
bitmexEndpointIsolatePosition = "/position/isolate"
|
||||
bitmexEndpointLeveragePosition = "/position/leverage"
|
||||
bitmexEndpointAdjustRiskLimit = "/position/riskLimit"
|
||||
bitmexEndpointTransferMargin = "/position/transferMargin"
|
||||
bitmexEndpointUser = "/user"
|
||||
bitmexEndpointUserAffiliate = "/user/affiliateStatus"
|
||||
bitmexEndpointUserCancelWithdraw = "/user/cancelWithdrawal"
|
||||
bitmexEndpointUserCommision = "/user/commission"
|
||||
bitmexEndpointUserConfirmEmail = "/user/confirmEmail"
|
||||
bitmexEndpointUserConfirmTFA = "/user/confirmEnableTFA"
|
||||
bitmexEndpointUserConfirmWithdrawal = "/user/confirmWithdrawal"
|
||||
bitmexEndpointUserDepositAddress = "/user/depositAddress"
|
||||
bitmexEndpointUserDisableTFA = "/user/disableTFA"
|
||||
bitmexEndpointUserLogout = "/user/logout"
|
||||
bitmexEndpointUserLogoutAll = "/user/logoutAll"
|
||||
bitmexEndpointUserMargin = "/user/margin"
|
||||
bitmexEndpointUserPreferences = "/user/preferences"
|
||||
bitmexEndpointUserRequestTFA = "/user/requestEnableTFA"
|
||||
bitmexEndpointUserWallet = "/user/wallet"
|
||||
bitmexEndpointUserWalletHistory = "/user/walletHistory"
|
||||
bitmexEndpointUserWalletSummary = "/user/walletSummary"
|
||||
bitmexEndpointUserRequestWithdraw = "/user/requestWithdrawal"
|
||||
|
||||
// Rate limits - 150 requests per 5 minutes
|
||||
bitmexUnauthRate = 30
|
||||
// 300 requests per 5 minutes
|
||||
bitmexAuthRate = 40
|
||||
|
||||
// ContractPerpetual perpetual contract type
|
||||
ContractPerpetual = iota
|
||||
// ContractFutures futures contract type
|
||||
ContractFutures
|
||||
// ContractDownsideProfit downside profit contract type
|
||||
ContractDownsideProfit
|
||||
// ContractUpsideProfit upside profit contract type
|
||||
ContractUpsideProfit
|
||||
)
|
||||
|
||||
// SetDefaults sets the basic defaults for Bitmex
|
||||
func (b *Bitmex) SetDefaults() {
|
||||
b.Name = "Bitmex"
|
||||
b.Enabled = false
|
||||
b.Verbose = false
|
||||
b.Websocket = false
|
||||
b.RESTPollingDelay = 10
|
||||
b.RequestCurrencyPairFormat.Delimiter = ""
|
||||
b.RequestCurrencyPairFormat.Uppercase = true
|
||||
b.ConfigCurrencyPairFormat.Delimiter = ""
|
||||
b.ConfigCurrencyPairFormat.Uppercase = true
|
||||
b.AssetTypes = []string{ticker.Spot}
|
||||
b.Requester = request.New(b.Name,
|
||||
request.NewRateLimit(time.Second, bitmexAuthRate),
|
||||
request.NewRateLimit(time.Second, bitmexUnauthRate),
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout))
|
||||
b.shutdown = b.NewRoutineManagement()
|
||||
}
|
||||
|
||||
// Setup takes in the supplied exchange configuration details and sets params
|
||||
func (b *Bitmex) Setup(exch config.ExchangeConfig) {
|
||||
if !exch.Enabled {
|
||||
b.SetEnabled(false)
|
||||
} else {
|
||||
b.Enabled = true
|
||||
b.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
b.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
|
||||
b.RESTPollingDelay = exch.RESTPollingDelay
|
||||
b.Verbose = exch.Verbose
|
||||
b.Websocket = exch.Websocket
|
||||
b.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",")
|
||||
b.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",")
|
||||
b.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",")
|
||||
err := b.SetCurrencyPairFormat()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = b.SetAssetTypes()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GetAnnouncement returns the general announcements from Bitmex
|
||||
func (b *Bitmex) GetAnnouncement() ([]Announcement, error) {
|
||||
var announcement []Announcement
|
||||
|
||||
return announcement, b.SendHTTPRequest(bitmexEndpointAnnouncement,
|
||||
nil,
|
||||
&announcement)
|
||||
}
|
||||
|
||||
// GetUrgentAnnouncement returns an urgent announcement for your account
|
||||
func (b *Bitmex) GetUrgentAnnouncement() ([]Announcement, error) {
|
||||
var announcement []Announcement
|
||||
|
||||
return announcement, b.SendAuthenticatedHTTPRequest("GET",
|
||||
bitmexEndpointAnnouncementUrgent,
|
||||
nil,
|
||||
&announcement)
|
||||
}
|
||||
|
||||
// GetAPIKeys returns the APIkeys from bitmex
|
||||
func (b *Bitmex) GetAPIKeys() ([]APIKey, error) {
|
||||
var keys []APIKey
|
||||
|
||||
return keys, b.SendAuthenticatedHTTPRequest("GET",
|
||||
bitmexEndpointAPIkeys,
|
||||
nil,
|
||||
&keys)
|
||||
}
|
||||
|
||||
// RemoveAPIKey removes an Apikey from the bitmex trading engine
|
||||
func (b *Bitmex) RemoveAPIKey(params APIKeyParams) (bool, error) {
|
||||
var keyDeleted bool
|
||||
|
||||
return keyDeleted, b.SendAuthenticatedHTTPRequest("DELETE",
|
||||
bitmexEndpointAPIkeys,
|
||||
params,
|
||||
&keyDeleted)
|
||||
}
|
||||
|
||||
// DisableAPIKey disables an Apikey from the bitmex trading engine
|
||||
func (b *Bitmex) DisableAPIKey(params APIKeyParams) (APIKey, error) {
|
||||
var keyInfo APIKey
|
||||
|
||||
return keyInfo, b.SendAuthenticatedHTTPRequest("POST",
|
||||
bitmexEndpointDisableAPIkey,
|
||||
params,
|
||||
&keyInfo)
|
||||
}
|
||||
|
||||
// EnableAPIKey enables an Apikey from the bitmex trading engine
|
||||
func (b *Bitmex) EnableAPIKey(params APIKeyParams) (APIKey, error) {
|
||||
var keyInfo APIKey
|
||||
|
||||
return keyInfo, b.SendAuthenticatedHTTPRequest("POST",
|
||||
bitmexEndpointEnableAPIkey,
|
||||
params,
|
||||
&keyInfo)
|
||||
}
|
||||
|
||||
// GetTrollboxMessages returns messages from the bitmex trollbox
|
||||
func (b *Bitmex) GetTrollboxMessages(params ChatGetParams) ([]Chat, error) {
|
||||
var messages []Chat
|
||||
|
||||
return messages, b.SendHTTPRequest(bitmexEndpointTrollbox, params, &messages)
|
||||
}
|
||||
|
||||
// SendTrollboxMessage sends a message to the bitmex trollbox
|
||||
func (b *Bitmex) SendTrollboxMessage(params ChatSendParams) ([]Chat, error) {
|
||||
var messages []Chat
|
||||
|
||||
return messages, b.SendAuthenticatedHTTPRequest("POST",
|
||||
bitmexEndpointTrollboxSend,
|
||||
params,
|
||||
&messages)
|
||||
}
|
||||
|
||||
// GetTrollboxChannels the channels from the the bitmex trollbox
|
||||
func (b *Bitmex) GetTrollboxChannels() ([]ChatChannel, error) {
|
||||
var channels []ChatChannel
|
||||
|
||||
return channels, b.SendHTTPRequest(bitmexEndpointTrollboxChannels,
|
||||
nil,
|
||||
&channels)
|
||||
}
|
||||
|
||||
// GetTrollboxConnectedUsers the channels from the the bitmex trollbox
|
||||
func (b *Bitmex) GetTrollboxConnectedUsers() (ConnectedUsers, error) {
|
||||
var users ConnectedUsers
|
||||
|
||||
return users, b.SendHTTPRequest(bitmexEndpointTrollboxConnected, nil, &users)
|
||||
}
|
||||
|
||||
// GetAccountExecutions returns all raw transactions, which includes order
|
||||
// opening and cancelation, and order status changes. It can be quite noisy.
|
||||
// More focused information is available at /execution/tradeHistory.
|
||||
func (b *Bitmex) GetAccountExecutions(params GenericRequestParams) ([]Execution, error) {
|
||||
var executionList []Execution
|
||||
|
||||
return executionList, b.SendAuthenticatedHTTPRequest("GET",
|
||||
bitmexEndpointExecution,
|
||||
params,
|
||||
&executionList)
|
||||
}
|
||||
|
||||
// GetAccountExecutionTradeHistory returns all balance-affecting executions.
|
||||
// This includes each trade, insurance charge, and settlement.
|
||||
func (b *Bitmex) GetAccountExecutionTradeHistory(params GenericRequestParams) ([]Execution, error) {
|
||||
var tradeHistory []Execution
|
||||
|
||||
return tradeHistory, b.SendAuthenticatedHTTPRequest("GET",
|
||||
bitmexEndpointExecutionTradeHistory,
|
||||
params,
|
||||
&tradeHistory)
|
||||
}
|
||||
|
||||
// GetFundingHistory returns funding history
|
||||
func (b *Bitmex) GetFundingHistory() ([]Funding, error) {
|
||||
var fundingHistory []Funding
|
||||
|
||||
return fundingHistory, b.SendHTTPRequest(bitmexEndpointFundingHistory,
|
||||
nil,
|
||||
&fundingHistory)
|
||||
}
|
||||
|
||||
// GetInstruments returns instrument data
|
||||
func (b *Bitmex) GetInstruments(params GenericRequestParams) ([]Instrument, error) {
|
||||
var instruments []Instrument
|
||||
|
||||
return instruments, b.SendHTTPRequest(bitmexEndpointInstruments,
|
||||
params,
|
||||
&instruments)
|
||||
}
|
||||
|
||||
// GetActiveInstruments returns active instruments
|
||||
func (b *Bitmex) GetActiveInstruments(params GenericRequestParams) ([]Instrument, error) {
|
||||
var activeInstruments []Instrument
|
||||
|
||||
return activeInstruments, b.SendHTTPRequest(bitmexEndpointActiveInstruments,
|
||||
params,
|
||||
&activeInstruments)
|
||||
}
|
||||
|
||||
// GetActiveAndIndexInstruments returns all active instruments and all indices
|
||||
func (b *Bitmex) GetActiveAndIndexInstruments() ([]Instrument, error) {
|
||||
var activeAndIndices []Instrument
|
||||
|
||||
return activeAndIndices,
|
||||
b.SendHTTPRequest(bitmexEndpointActiveAndIndexInstruments,
|
||||
nil,
|
||||
&activeAndIndices)
|
||||
}
|
||||
|
||||
// GetActiveIntervals returns funding history
|
||||
func (b *Bitmex) GetActiveIntervals() (InstrumentInterval, error) {
|
||||
var interval InstrumentInterval
|
||||
|
||||
return interval, b.SendHTTPRequest(bitmexEndpointActiveIntervals,
|
||||
nil,
|
||||
&interval)
|
||||
}
|
||||
|
||||
// GetCompositeIndex returns composite index
|
||||
func (b *Bitmex) GetCompositeIndex(params GenericRequestParams) ([]IndexComposite, error) {
|
||||
var compositeIndices []IndexComposite
|
||||
|
||||
return compositeIndices, b.SendHTTPRequest(bitmexEndpointCompositeIndex,
|
||||
params,
|
||||
&compositeIndices)
|
||||
}
|
||||
|
||||
// GetIndices returns all price indices
|
||||
func (b *Bitmex) GetIndices() ([]Instrument, error) {
|
||||
var indices []Instrument
|
||||
|
||||
return indices, b.SendHTTPRequest(bitmexEndpointIndices, nil, &indices)
|
||||
}
|
||||
|
||||
// GetInsuranceFundHistory returns insurance fund history
|
||||
func (b *Bitmex) GetInsuranceFundHistory(params GenericRequestParams) ([]Insurance, error) {
|
||||
var history []Insurance
|
||||
|
||||
return history, b.SendHTTPRequest(bitmexEndpointIndices, params, &history)
|
||||
}
|
||||
|
||||
// GetLeaderboard returns leaderboard information
|
||||
func (b *Bitmex) GetLeaderboard(params LeaderboardGetParams) ([]Leaderboard, error) {
|
||||
var leader []Leaderboard
|
||||
|
||||
return leader, b.SendHTTPRequest(bitmexEndpointLeader, params, &leader)
|
||||
}
|
||||
|
||||
// GetAliasOnLeaderboard returns your alias on the leaderboard
|
||||
func (b *Bitmex) GetAliasOnLeaderboard() (Alias, error) {
|
||||
var alias Alias
|
||||
|
||||
return alias, b.SendHTTPRequest(bitmexEndpointAlias, nil, &alias)
|
||||
}
|
||||
|
||||
// GetLiquidationOrders returns liquidation orders
|
||||
func (b *Bitmex) GetLiquidationOrders(params GenericRequestParams) ([]Liquidation, error) {
|
||||
var orders []Liquidation
|
||||
|
||||
return orders, b.SendHTTPRequest(bitmexEndpointLiquidation,
|
||||
params,
|
||||
&orders)
|
||||
}
|
||||
|
||||
// GetCurrentNotifications returns your current notifications
|
||||
func (b *Bitmex) GetCurrentNotifications() ([]Notification, error) {
|
||||
var notifications []Notification
|
||||
|
||||
return notifications, b.SendAuthenticatedHTTPRequest("GET",
|
||||
bitmexEndpointNotifications,
|
||||
nil,
|
||||
¬ifications)
|
||||
}
|
||||
|
||||
// GetOrders returns all the orders, open and closed
|
||||
func (b *Bitmex) GetOrders(params GenericRequestParams) ([]Order, error) {
|
||||
var orders []Order
|
||||
|
||||
return orders, b.SendAuthenticatedHTTPRequest("GET",
|
||||
bitmexEndpointOrder,
|
||||
params,
|
||||
&orders)
|
||||
}
|
||||
|
||||
// AmendOrder amends the quantity or price of an open order
|
||||
func (b *Bitmex) AmendOrder(params OrderAmendParams) ([]Order, error) {
|
||||
var orders []Order
|
||||
|
||||
return orders, b.SendAuthenticatedHTTPRequest("PUT",
|
||||
bitmexEndpointOrder,
|
||||
params,
|
||||
&orders)
|
||||
}
|
||||
|
||||
// CreateOrder creates a new order
|
||||
func (b *Bitmex) CreateOrder(params OrderNewParams) (Order, error) {
|
||||
var orderInfo Order
|
||||
|
||||
return orderInfo, b.SendAuthenticatedHTTPRequest("POST",
|
||||
bitmexEndpointOrder,
|
||||
params,
|
||||
&orderInfo)
|
||||
}
|
||||
|
||||
// CancelOrders cancels one or a batch of orders on the exchange and returns
|
||||
// a cancelled order list
|
||||
func (b *Bitmex) CancelOrders(params OrderCancelParams) ([]Order, error) {
|
||||
var cancelledOrders []Order
|
||||
|
||||
return cancelledOrders, b.SendAuthenticatedHTTPRequest("DELETE",
|
||||
bitmexEndpointOrder,
|
||||
params,
|
||||
&cancelledOrders)
|
||||
}
|
||||
|
||||
// CancelAllOrders cancels all open orders on the exchange
|
||||
func (b *Bitmex) CancelAllOrders(params OrderCancelAllParams) ([]Order, error) {
|
||||
var cancelledOrders []Order
|
||||
|
||||
return cancelledOrders, b.SendAuthenticatedHTTPRequest("DELETE",
|
||||
bitmexEndpointCancelAllOrders,
|
||||
params,
|
||||
&cancelledOrders)
|
||||
}
|
||||
|
||||
// AmendBulkOrders amends multiple orders for the same symbol
|
||||
func (b *Bitmex) AmendBulkOrders(params OrderAmendBulkParams) ([]Order, error) {
|
||||
var amendedOrders []Order
|
||||
|
||||
return amendedOrders, b.SendAuthenticatedHTTPRequest("PUT",
|
||||
bitmexEndpointBulk,
|
||||
params,
|
||||
&amendedOrders)
|
||||
}
|
||||
|
||||
// CreateBulkOrders creates multiple orders for the same symbol
|
||||
func (b *Bitmex) CreateBulkOrders(params OrderNewBulkParams) ([]Order, error) {
|
||||
var orders []Order
|
||||
|
||||
return orders, b.SendAuthenticatedHTTPRequest("POST",
|
||||
bitmexEndpointBulk,
|
||||
params,
|
||||
&orders)
|
||||
}
|
||||
|
||||
// CancelAllOrdersAfterTime closes all positions after a certain time period
|
||||
func (b *Bitmex) CancelAllOrdersAfterTime(params OrderCancelAllAfterParams) ([]Order, error) {
|
||||
var cancelledOrder []Order
|
||||
|
||||
return cancelledOrder, b.SendAuthenticatedHTTPRequest("POST",
|
||||
bitmexEndpointCancelOrderAfter,
|
||||
params,
|
||||
&cancelledOrder)
|
||||
}
|
||||
|
||||
// ClosePosition closes a position WARNING deprecated use /order endpoint
|
||||
func (b *Bitmex) ClosePosition(params OrderClosePositionParams) ([]Order, error) {
|
||||
var closedPositions []Order
|
||||
|
||||
return closedPositions, b.SendAuthenticatedHTTPRequest("POST",
|
||||
bitmexEndpointOrder,
|
||||
params,
|
||||
&closedPositions)
|
||||
}
|
||||
|
||||
// GetOrderbook returns layer two orderbook data
|
||||
func (b *Bitmex) GetOrderbook(params OrderBookGetL2Params) ([]OrderBookL2, error) {
|
||||
var orderBooks []OrderBookL2
|
||||
|
||||
return orderBooks, b.SendHTTPRequest(bitmexEndpointOrderbookL2,
|
||||
params,
|
||||
&orderBooks)
|
||||
}
|
||||
|
||||
// GetPositions returns positions
|
||||
func (b *Bitmex) GetPositions(params PositionGetParams) ([]Position, error) {
|
||||
var positions []Position
|
||||
|
||||
return positions, b.SendAuthenticatedHTTPRequest("GET",
|
||||
bitmexEndpointPosition,
|
||||
params,
|
||||
&positions)
|
||||
}
|
||||
|
||||
// IsolatePosition enables isolated margin or cross margin per-position
|
||||
func (b *Bitmex) IsolatePosition(params PositionIsolateMarginParams) (Position, error) {
|
||||
var position Position
|
||||
|
||||
return position, b.SendAuthenticatedHTTPRequest("POST",
|
||||
bitmexEndpointIsolatePosition,
|
||||
params,
|
||||
&position)
|
||||
}
|
||||
|
||||
// LeveragePosition chooses leverage for a position
|
||||
func (b *Bitmex) LeveragePosition(params PositionUpdateLeverageParams) (Position, error) {
|
||||
var position Position
|
||||
|
||||
return position, b.SendAuthenticatedHTTPRequest("POST",
|
||||
bitmexEndpointLeveragePosition,
|
||||
params,
|
||||
&position)
|
||||
}
|
||||
|
||||
// UpdateRiskLimit updates risk limit on a position
|
||||
func (b *Bitmex) UpdateRiskLimit(params PositionUpdateRiskLimitParams) (Position, error) {
|
||||
var position Position
|
||||
|
||||
return position, b.SendAuthenticatedHTTPRequest("POST",
|
||||
bitmexEndpointAdjustRiskLimit,
|
||||
params,
|
||||
&position)
|
||||
}
|
||||
|
||||
// TransferMargin transfers equity in or out of a position
|
||||
func (b *Bitmex) TransferMargin(params PositionTransferIsolatedMarginParams) (Position, error) {
|
||||
var position Position
|
||||
|
||||
return position, b.SendAuthenticatedHTTPRequest("POST",
|
||||
bitmexEndpointTransferMargin,
|
||||
params,
|
||||
&position)
|
||||
}
|
||||
|
||||
// GetQuotes returns quotations
|
||||
func (b *Bitmex) GetQuotes(params GenericRequestParams) ([]Quote, error) {
|
||||
var quotations []Quote
|
||||
|
||||
return quotations, b.SendHTTPRequest(bitmexEndpointQuote,
|
||||
params,
|
||||
"ations)
|
||||
}
|
||||
|
||||
// GetQuotesByBuckets returns previous quotes in time buckets
|
||||
func (b *Bitmex) GetQuotesByBuckets(params QuoteGetBucketedParams) ([]Quote, error) {
|
||||
var quotations []Quote
|
||||
|
||||
return quotations, b.SendHTTPRequest(bitmexEndpointQuoteBucketed,
|
||||
params,
|
||||
"ations)
|
||||
}
|
||||
|
||||
// GetSettlementHistory returns settlement history
|
||||
func (b *Bitmex) GetSettlementHistory(params GenericRequestParams) ([]Settlement, error) {
|
||||
var history []Settlement
|
||||
|
||||
return history, b.SendHTTPRequest(bitmexEndpointSettlement,
|
||||
params,
|
||||
&history)
|
||||
}
|
||||
|
||||
// GetStats returns exchange wide per series turnover and volume statistics
|
||||
func (b *Bitmex) GetStats() ([]Stats, error) {
|
||||
var stats []Stats
|
||||
|
||||
return stats, b.SendHTTPRequest(bitmexEndpointStats, nil, &stats)
|
||||
}
|
||||
|
||||
// GetStatsHistorical historic stats
|
||||
func (b *Bitmex) GetStatsHistorical() ([]StatsHistory, error) {
|
||||
var history []StatsHistory
|
||||
|
||||
return history, b.SendHTTPRequest(bitmexEndpointStatsHistory, nil, &history)
|
||||
}
|
||||
|
||||
// GetStatSummary returns the stats summary in USD terms
|
||||
func (b *Bitmex) GetStatSummary() ([]StatsUSD, error) {
|
||||
var summary []StatsUSD
|
||||
|
||||
return summary, b.SendHTTPRequest(bitmexEndpointStatsSummary, nil, &summary)
|
||||
}
|
||||
|
||||
// GetTrade returns executed trades on the desk
|
||||
func (b *Bitmex) GetTrade(params GenericRequestParams) ([]Trade, error) {
|
||||
var trade []Trade
|
||||
|
||||
return trade, b.SendHTTPRequest(bitmexEndpointTrade, params, &trade)
|
||||
}
|
||||
|
||||
// GetPreviousTrades previous trade history in time buckets
|
||||
func (b *Bitmex) GetPreviousTrades(params TradeGetBucketedParams) ([]Trade, error) {
|
||||
var trade []Trade
|
||||
|
||||
return trade, b.SendHTTPRequest(bitmexEndpointTradeBucketed,
|
||||
params,
|
||||
&trade)
|
||||
}
|
||||
|
||||
// GetUserInfo returns your user information
|
||||
func (b *Bitmex) GetUserInfo() (User, error) {
|
||||
var userInfo User
|
||||
|
||||
return userInfo, b.SendAuthenticatedHTTPRequest("GET",
|
||||
bitmexEndpointUser,
|
||||
nil,
|
||||
&userInfo)
|
||||
}
|
||||
|
||||
// UpdateUserInfo updates user information
|
||||
func (b *Bitmex) UpdateUserInfo(params UserUpdateParams) (User, error) {
|
||||
var userInfo User
|
||||
|
||||
return userInfo, b.SendAuthenticatedHTTPRequest("PUT",
|
||||
bitmexEndpointUser,
|
||||
params,
|
||||
&userInfo)
|
||||
}
|
||||
|
||||
// GetAffiliateStatus returns your affiliate status
|
||||
func (b *Bitmex) GetAffiliateStatus() (AffiliateStatus, error) {
|
||||
var status AffiliateStatus
|
||||
|
||||
return status, b.SendAuthenticatedHTTPRequest("GET",
|
||||
bitmexEndpointUserAffiliate,
|
||||
nil,
|
||||
&status)
|
||||
}
|
||||
|
||||
// CancelWithdraw cancels a current withdrawal
|
||||
func (b *Bitmex) CancelWithdraw(token string) (TransactionInfo, error) {
|
||||
var info TransactionInfo
|
||||
|
||||
return info, b.SendAuthenticatedHTTPRequest("POST",
|
||||
bitmexEndpointUserCancelWithdraw,
|
||||
UserTokenParams{Token: token},
|
||||
&info)
|
||||
}
|
||||
|
||||
// CheckReferalCode checks a code, will return a percentage eg 0.1 for 10% or
|
||||
// if err a 404
|
||||
func (b *Bitmex) CheckReferalCode(referralCode string) (float64, error) {
|
||||
var percentage float64
|
||||
|
||||
return percentage, b.SendHTTPRequest(bitmexEndpointUserCheckReferralCode,
|
||||
UserCheckReferralCodeParams{ReferralCode: referralCode},
|
||||
&percentage)
|
||||
}
|
||||
|
||||
// GetUserCommision returns your account's commission status.
|
||||
func (b *Bitmex) GetUserCommision(token string) (UserCommission, error) {
|
||||
var commissionInfo UserCommission
|
||||
|
||||
return commissionInfo, b.SendAuthenticatedHTTPRequest("GET",
|
||||
bitmexEndpointUserCommision,
|
||||
nil,
|
||||
&commissionInfo)
|
||||
}
|
||||
|
||||
// ConfirmEmail confirms email address with a token
|
||||
func (b *Bitmex) ConfirmEmail(token string) (ConfirmEmail, error) {
|
||||
var confirmation ConfirmEmail
|
||||
|
||||
return confirmation, b.SendAuthenticatedHTTPRequest("GET",
|
||||
bitmexEndpointUserConfirmEmail,
|
||||
UserTokenParams{Token: token},
|
||||
&confirmation)
|
||||
}
|
||||
|
||||
// ConfirmTwoFactorAuth confirmas 2FA for this account.
|
||||
func (b *Bitmex) ConfirmTwoFactorAuth(token, typ string) (bool, error) {
|
||||
var working bool
|
||||
|
||||
return working, b.SendAuthenticatedHTTPRequest("POST",
|
||||
bitmexEndpointUserConfirmTFA,
|
||||
UserConfirmTFAParams{Token: token, Type: typ},
|
||||
&working)
|
||||
}
|
||||
|
||||
// ConfirmWithdrawal confirmas a withdrawal
|
||||
func (b *Bitmex) ConfirmWithdrawal(token string) (TransactionInfo, error) {
|
||||
var info TransactionInfo
|
||||
|
||||
return info, b.SendAuthenticatedHTTPRequest("POST",
|
||||
bitmexEndpointUserCancelWithdraw,
|
||||
UserTokenParams{Token: token},
|
||||
&info)
|
||||
}
|
||||
|
||||
// GetDepositAddress returns a deposit address for a cryptocurency
|
||||
func (b *Bitmex) GetDepositAddress(currency string) (string, error) {
|
||||
var address string
|
||||
|
||||
return address, b.SendAuthenticatedHTTPRequest("GET",
|
||||
bitmexEndpointUserDepositAddress,
|
||||
UserCurrencyParams{Currency: currency},
|
||||
&address)
|
||||
}
|
||||
|
||||
// DisableTFA dsiables 2 factor authentication for your account
|
||||
func (b *Bitmex) DisableTFA(token, typ string) (bool, error) {
|
||||
var disabled bool
|
||||
|
||||
return disabled, b.SendAuthenticatedHTTPRequest("POST",
|
||||
bitmexEndpointUserDisableTFA,
|
||||
UserConfirmTFAParams{Token: token, Type: typ},
|
||||
&disabled)
|
||||
}
|
||||
|
||||
// UserLogOut logs you out of BitMEX
|
||||
func (b *Bitmex) UserLogOut() error {
|
||||
return b.SendAuthenticatedHTTPRequest("POST",
|
||||
bitmexEndpointUserLogout,
|
||||
nil,
|
||||
nil)
|
||||
}
|
||||
|
||||
// UserLogOutAll logs you out of all systems for BitMEX
|
||||
func (b *Bitmex) UserLogOutAll() (int64, error) {
|
||||
var status int64
|
||||
|
||||
return status, b.SendAuthenticatedHTTPRequest("POST",
|
||||
bitmexEndpointUserLogoutAll,
|
||||
nil,
|
||||
&status)
|
||||
}
|
||||
|
||||
// GetUserMargin returns user margin information
|
||||
func (b *Bitmex) GetUserMargin(currency string) (UserMargin, error) {
|
||||
var info UserMargin
|
||||
|
||||
return info, b.SendAuthenticatedHTTPRequest("GET",
|
||||
bitmexEndpointUserMargin,
|
||||
UserCurrencyParams{Currency: currency},
|
||||
&info)
|
||||
}
|
||||
|
||||
// GetMinimumWithdrawalFee returns minimum withdrawal fee information
|
||||
func (b *Bitmex) GetMinimumWithdrawalFee(currency string) (MinWithdrawalFee, error) {
|
||||
var fee MinWithdrawalFee
|
||||
|
||||
return fee, b.SendAuthenticatedHTTPRequest("GET",
|
||||
bitmexEndpointUserMinWithdrawalFee,
|
||||
UserCurrencyParams{Currency: currency},
|
||||
&fee)
|
||||
}
|
||||
|
||||
// GetUserPreferences returns user preferences
|
||||
func (b *Bitmex) GetUserPreferences(params UserPreferencesParams) (User, error) {
|
||||
var userInfo User
|
||||
|
||||
return userInfo, b.SendAuthenticatedHTTPRequest("POST",
|
||||
bitmexEndpointUserPreferences,
|
||||
params,
|
||||
&userInfo)
|
||||
}
|
||||
|
||||
// EnableTFA enables 2 factor authentication
|
||||
func (b *Bitmex) EnableTFA(typ string) (bool, error) {
|
||||
var enabled bool
|
||||
|
||||
return enabled, b.SendAuthenticatedHTTPRequest("POST",
|
||||
bitmexEndpointUserRequestTFA,
|
||||
UserConfirmTFAParams{Type: typ},
|
||||
&enabled)
|
||||
}
|
||||
|
||||
// UserRequestWithdrawal This will send a confirmation email to the email
|
||||
// address on record, unless requested via an API Key with the withdraw
|
||||
// permission.
|
||||
func (b *Bitmex) UserRequestWithdrawal(params UserRequestWithdrawalParams) (TransactionInfo, error) {
|
||||
var info TransactionInfo
|
||||
|
||||
return info, b.SendAuthenticatedHTTPRequest("POST",
|
||||
bitmexEndpointUserRequestWithdraw,
|
||||
params,
|
||||
&info)
|
||||
}
|
||||
|
||||
// GetWalletInfo returns user wallet information
|
||||
func (b *Bitmex) GetWalletInfo(currency string) (WalletInfo, error) {
|
||||
var info WalletInfo
|
||||
|
||||
return info, b.SendAuthenticatedHTTPRequest("GET",
|
||||
bitmexEndpointUserWallet,
|
||||
UserCurrencyParams{Currency: currency},
|
||||
&info)
|
||||
}
|
||||
|
||||
// GetWalletHistory returns user wallet history transaction data
|
||||
func (b *Bitmex) GetWalletHistory(currency string) ([]TransactionInfo, error) {
|
||||
var info []TransactionInfo
|
||||
|
||||
return info, b.SendAuthenticatedHTTPRequest("GET",
|
||||
bitmexEndpointUserWalletHistory,
|
||||
UserCurrencyParams{Currency: currency},
|
||||
&info)
|
||||
}
|
||||
|
||||
// GetWalletSummary returns user wallet summary
|
||||
func (b *Bitmex) GetWalletSummary(currency string) ([]TransactionInfo, error) {
|
||||
var info []TransactionInfo
|
||||
|
||||
return info, b.SendAuthenticatedHTTPRequest("GET",
|
||||
bitmexEndpointUserWalletSummary,
|
||||
UserCurrencyParams{Currency: currency},
|
||||
&info)
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (b *Bitmex) SendHTTPRequest(path string, params Parameter, result interface{}) error {
|
||||
var respCheck interface{}
|
||||
path = bitmexAPIURL + path
|
||||
if params != nil {
|
||||
if !params.IsNil() {
|
||||
encodedPath, err := params.ToURLVals(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = b.SendPayload("GET", encodedPath, nil, nil, &respCheck, false, b.Verbose)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return b.CaptureError(respCheck, result)
|
||||
}
|
||||
}
|
||||
err := b.SendPayload("GET", path, nil, nil, &respCheck, false, b.Verbose)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return b.CaptureError(respCheck, result)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request to bitmex
|
||||
func (b *Bitmex) SendAuthenticatedHTTPRequest(verb, path string, params Parameter, result interface{}) error {
|
||||
if !b.AuthenticatedAPISupport {
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet,
|
||||
b.Name)
|
||||
}
|
||||
|
||||
timestamp := time.Now().Add(time.Second * 10).UnixNano()
|
||||
timestampStr := strconv.FormatInt(timestamp, 10)
|
||||
timestampNew := timestampStr[:13]
|
||||
|
||||
headers := make(map[string]string)
|
||||
headers["Content-Type"] = "application/json"
|
||||
headers["api-expires"] = timestampNew
|
||||
headers["api-key"] = b.APIKey
|
||||
|
||||
var payload string
|
||||
if params != nil {
|
||||
err := params.VerifyData()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data, err := common.JSONEncode(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
payload = string(data)
|
||||
}
|
||||
|
||||
hmac := common.GetHMAC(common.HashSHA256,
|
||||
[]byte(verb+"/api/v1"+path+timestampNew+payload),
|
||||
[]byte(b.APISecret))
|
||||
|
||||
headers["api-signature"] = common.HexEncodeToString(hmac)
|
||||
|
||||
var respCheck interface{}
|
||||
|
||||
err := b.SendPayload(verb,
|
||||
bitmexAPIURL+path,
|
||||
headers,
|
||||
bytes.NewBuffer([]byte(payload)),
|
||||
&respCheck,
|
||||
true,
|
||||
b.Verbose)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return b.CaptureError(respCheck, result)
|
||||
}
|
||||
|
||||
// CaptureError little hack that captures an error
|
||||
func (b *Bitmex) CaptureError(resp, reType interface{}) error {
|
||||
var Error RequestError
|
||||
|
||||
marshalled, err := json.Marshal(resp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = common.JSONDecode(marshalled, &Error)
|
||||
if err == nil {
|
||||
return fmt.Errorf("bitmex error %s: %s",
|
||||
Error.Error.Name,
|
||||
Error.Error.Message)
|
||||
}
|
||||
|
||||
err = common.JSONDecode(marshalled, reType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
1123
exchanges/bitmex/bitmex_parameters.go
Normal file
1123
exchanges/bitmex/bitmex_parameters.go
Normal file
File diff suppressed because it is too large
Load Diff
365
exchanges/bitmex/bitmex_test.go
Normal file
365
exchanges/bitmex/bitmex_test.go
Normal file
@@ -0,0 +1,365 @@
|
||||
package bitmex
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
)
|
||||
|
||||
// Please supply your own keys here for due diligence testing
|
||||
const (
|
||||
testAPIKey = ""
|
||||
testAPISecret = ""
|
||||
)
|
||||
|
||||
var b Bitmex
|
||||
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
cfg := config.GetConfig()
|
||||
cfg.LoadConfig("../../testdata/configtest.json")
|
||||
bitmexConfig, err := cfg.GetExchangeConfig("Bitmex")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - Bitmex Setup() init error")
|
||||
}
|
||||
|
||||
bitmexConfig.AuthenticatedAPISupport = true
|
||||
bitmexConfig.APIKey = testAPIKey
|
||||
bitmexConfig.APISecret = testAPISecret
|
||||
|
||||
b.Setup(bitmexConfig)
|
||||
}
|
||||
|
||||
func TestStart(t *testing.T) {
|
||||
var testWg sync.WaitGroup
|
||||
b.Start(&testWg)
|
||||
testWg.Wait()
|
||||
}
|
||||
|
||||
func TestGetUrgentAnnouncement(t *testing.T) {
|
||||
_, err := b.GetUrgentAnnouncement()
|
||||
if err == nil {
|
||||
t.Error("test failed - GetUrgentAnnouncement() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAPIKeys(t *testing.T) {
|
||||
_, err := b.GetAPIKeys()
|
||||
if err == nil {
|
||||
t.Error("test failed - GetAPIKeys() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveAPIKey(t *testing.T) {
|
||||
_, err := b.RemoveAPIKey(APIKeyParams{APIKeyID: "1337"})
|
||||
if err == nil {
|
||||
t.Error("test failed - RemoveAPIKey() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDisableAPIKey(t *testing.T) {
|
||||
_, err := b.DisableAPIKey(APIKeyParams{APIKeyID: "1337"})
|
||||
if err == nil {
|
||||
t.Error("test failed - DisableAPIKey() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnableAPIKey(t *testing.T) {
|
||||
_, err := b.EnableAPIKey(APIKeyParams{APIKeyID: "1337"})
|
||||
if err == nil {
|
||||
t.Error("test failed - EnableAPIKey() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTrollboxMessages(t *testing.T) {
|
||||
_, err := b.GetTrollboxMessages(ChatGetParams{Count: 5})
|
||||
if err != nil {
|
||||
t.Error("test failed - GetTrollboxMessages() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSendTrollboxMessage(t *testing.T) {
|
||||
_, err := b.SendTrollboxMessage(ChatSendParams{
|
||||
ChannelID: 1337,
|
||||
Message: "Hello,World!"})
|
||||
if err == nil {
|
||||
t.Error("test failed - SendTrollboxMessage() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTrollboxChannels(t *testing.T) {
|
||||
_, err := b.GetTrollboxChannels()
|
||||
if err != nil {
|
||||
t.Error("test failed - GetTrollboxChannels() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTrollboxConnectedUsers(t *testing.T) {
|
||||
_, err := b.GetTrollboxConnectedUsers()
|
||||
if err == nil {
|
||||
t.Error("test failed - GetTrollboxConnectedUsers() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAccountExecutions(t *testing.T) {
|
||||
_, err := b.GetAccountExecutions(GenericRequestParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - GetAccountExecutions() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAccountExecutionTradeHistory(t *testing.T) {
|
||||
_, err := b.GetAccountExecutionTradeHistory(GenericRequestParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - GetAccountExecutionTradeHistory() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetFundingHistory(t *testing.T) {
|
||||
_, err := b.GetFundingHistory()
|
||||
if err != nil {
|
||||
t.Error("test failed - GetFundingHistory() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetInstruments(t *testing.T) {
|
||||
_, err := b.GetInstruments(GenericRequestParams{})
|
||||
if err != nil {
|
||||
t.Error("test failed - GetInstruments() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetActiveInstruments(t *testing.T) {
|
||||
_, err := b.GetActiveInstruments(GenericRequestParams{})
|
||||
if err != nil {
|
||||
t.Error("test failed - GetActiveInstruments() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetActiveAndIndexInstruments(t *testing.T) {
|
||||
_, err := b.GetActiveAndIndexInstruments()
|
||||
if err != nil {
|
||||
t.Error("test failed - GetActiveAndIndexInstruments() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetActiveIntervals(t *testing.T) {
|
||||
_, err := b.GetActiveIntervals()
|
||||
if err == nil {
|
||||
t.Error("test failed - GetActiveIntervals() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCompositeIndex(t *testing.T) {
|
||||
_, err := b.GetCompositeIndex(GenericRequestParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - GetCompositeIndex() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetIndices(t *testing.T) {
|
||||
_, err := b.GetIndices()
|
||||
if err != nil {
|
||||
t.Error("test failed - GetIndices() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetInsuranceFundHistory(t *testing.T) {
|
||||
_, err := b.GetInsuranceFundHistory(GenericRequestParams{})
|
||||
if err != nil {
|
||||
t.Error("test failed - GetInsuranceFundHistory() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetLeaderboard(t *testing.T) {
|
||||
_, err := b.GetLeaderboard(LeaderboardGetParams{})
|
||||
if err != nil {
|
||||
t.Error("test failed - GetLeaderboard() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAliasOnLeaderboard(t *testing.T) {
|
||||
_, err := b.GetAliasOnLeaderboard()
|
||||
if err == nil {
|
||||
t.Error("test failed - GetAliasOnLeaderboard() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetLiquidationOrders(t *testing.T) {
|
||||
_, err := b.GetLiquidationOrders(GenericRequestParams{})
|
||||
if err != nil {
|
||||
t.Error("test failed - GetLiquidationOrders() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCurrentNotifications(t *testing.T) {
|
||||
_, err := b.GetCurrentNotifications()
|
||||
if err == nil {
|
||||
t.Error("test failed - GetCurrentNotifications() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetOrders(t *testing.T) {
|
||||
_, err := b.GetOrders(GenericRequestParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - GetOrders() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAmendOrder(t *testing.T) {
|
||||
_, err := b.AmendOrder(OrderAmendParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - AmendOrder() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateOrder(t *testing.T) {
|
||||
_, err := b.CreateOrder(OrderNewParams{Symbol: "XBTM15",
|
||||
Price: 219.0,
|
||||
ClOrdID: "mm_bitmex_1a/oemUeQ4CAJZgP3fjHsA",
|
||||
OrderQty: 98})
|
||||
if err == nil {
|
||||
t.Error("test failed - CreateOrder() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCancelOrders(t *testing.T) {
|
||||
_, err := b.CancelOrders(OrderCancelParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - CancelOrders() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCancelAllOrders(t *testing.T) {
|
||||
_, err := b.CancelAllOrders(OrderCancelAllParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - CancelAllOrders() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAmendBulkOrders(t *testing.T) {
|
||||
_, err := b.AmendBulkOrders(OrderAmendBulkParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - AmendBulkOrders() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateBulkOrders(t *testing.T) {
|
||||
_, err := b.CreateBulkOrders(OrderNewBulkParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - CreateBulkOrders() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCancelAllOrdersAfterTime(t *testing.T) {
|
||||
_, err := b.CancelAllOrdersAfterTime(OrderCancelAllAfterParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - CancelAllOrdersAfterTime() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClosePosition(t *testing.T) {
|
||||
_, err := b.ClosePosition(OrderClosePositionParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - ClosePosition() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetOrderbook(t *testing.T) {
|
||||
_, err := b.GetOrderbook(OrderBookGetL2Params{Symbol: "XBT"})
|
||||
if err != nil {
|
||||
t.Error("test failed - GetOrderbook() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPositions(t *testing.T) {
|
||||
_, err := b.GetPositions(PositionGetParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - GetPositions() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsolatePosition(t *testing.T) {
|
||||
_, err := b.IsolatePosition(PositionIsolateMarginParams{Symbol: "XBT"})
|
||||
if err == nil {
|
||||
t.Error("test failed - IsolatePosition() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLeveragePosition(t *testing.T) {
|
||||
_, err := b.LeveragePosition(PositionUpdateLeverageParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - LeveragePosition() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateRiskLimit(t *testing.T) {
|
||||
_, err := b.UpdateRiskLimit(PositionUpdateRiskLimitParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - UpdateRiskLimit() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTransferMargin(t *testing.T) {
|
||||
_, err := b.TransferMargin(PositionTransferIsolatedMarginParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - TransferMargin() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetQuotesByBuckets(t *testing.T) {
|
||||
_, err := b.GetQuotesByBuckets(QuoteGetBucketedParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - GetQuotesByBuckets() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSettlementHistory(t *testing.T) {
|
||||
_, err := b.GetSettlementHistory(GenericRequestParams{})
|
||||
if err != nil {
|
||||
t.Error("test failed - GetSettlementHistory() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetStats(t *testing.T) {
|
||||
_, err := b.GetStats()
|
||||
if err != nil {
|
||||
t.Error("test failed - GetStats() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetStatsHistorical(t *testing.T) {
|
||||
_, err := b.GetStatsHistorical()
|
||||
if err != nil {
|
||||
t.Error("test failed - GetStatsHistorical() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetStatSummary(t *testing.T) {
|
||||
_, err := b.GetStatSummary()
|
||||
if err != nil {
|
||||
t.Error("test failed - GetStatSummary() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTrade(t *testing.T) {
|
||||
_, err := b.GetTrade(GenericRequestParams{
|
||||
Symbol: "XBTUSD",
|
||||
StartTime: time.Now().Format(time.RFC3339),
|
||||
Reverse: true})
|
||||
if err != nil {
|
||||
t.Error("test failed - GetTrade() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPreviousTrades(t *testing.T) {
|
||||
_, err := b.GetPreviousTrades(TradeGetBucketedParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - GetPreviousTrades() error", err)
|
||||
}
|
||||
}
|
||||
668
exchanges/bitmex/bitmex_types.go
Normal file
668
exchanges/bitmex/bitmex_types.go
Normal file
@@ -0,0 +1,668 @@
|
||||
package bitmex
|
||||
|
||||
// RequestError allows for a general error capture from requests
|
||||
type RequestError struct {
|
||||
Error struct {
|
||||
Message string `json:"message"`
|
||||
Name string `json:"name"`
|
||||
} `json:"error"`
|
||||
}
|
||||
|
||||
// Announcement General Announcements
|
||||
type Announcement struct {
|
||||
Content string `json:"content"`
|
||||
Date string `json:"date"`
|
||||
ID int32 `json:"id"`
|
||||
Link string `json:"link"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
|
||||
// APIKey Persistent API Keys for Developers
|
||||
type APIKey struct {
|
||||
Cidr string `json:"cidr"`
|
||||
Created string `json:"created"`
|
||||
Enabled bool `json:"enabled"`
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Nonce int64 `json:"nonce"`
|
||||
Permissions []interface{} `json:"permissions"`
|
||||
Secret string `json:"secret"`
|
||||
UserID int32 `json:"userId"`
|
||||
}
|
||||
|
||||
// Chat Trollbox Data
|
||||
type Chat struct {
|
||||
ChannelID float64 `json:"channelID"`
|
||||
Date string `json:"date"`
|
||||
FromBot bool `json:"fromBot"`
|
||||
HTML string `json:"html"`
|
||||
ID int32 `json:"id"`
|
||||
Message string `json:"message"`
|
||||
User string `json:"user"`
|
||||
}
|
||||
|
||||
// ChatChannel chat channel
|
||||
type ChatChannel struct {
|
||||
ID int32 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// ConnectedUsers connected users
|
||||
type ConnectedUsers struct {
|
||||
Bots int32 `json:"bots"`
|
||||
Users int32 `json:"users"`
|
||||
}
|
||||
|
||||
// Execution Raw Order and Balance Data
|
||||
type Execution struct {
|
||||
Account int64 `json:"account"`
|
||||
AvgPx float64 `json:"avgPx"`
|
||||
ClOrdID string `json:"clOrdID"`
|
||||
ClOrdLinkID string `json:"clOrdLinkID"`
|
||||
Commission float64 `json:"commission"`
|
||||
ContingencyType string `json:"contingencyType"`
|
||||
CumQty int64 `json:"cumQty"`
|
||||
Currency string `json:"currency"`
|
||||
DisplayQty int64 `json:"displayQty"`
|
||||
ExDestination string `json:"exDestination"`
|
||||
ExecComm int64 `json:"execComm"`
|
||||
ExecCost int64 `json:"execCost"`
|
||||
ExecID string `json:"execID"`
|
||||
ExecInst string `json:"execInst"`
|
||||
ExecType string `json:"execType"`
|
||||
ForeignNotional float64 `json:"foreignNotional"`
|
||||
HomeNotional float64 `json:"homeNotional"`
|
||||
LastLiquidityInd string `json:"lastLiquidityInd"`
|
||||
LastMkt string `json:"lastMkt"`
|
||||
LastPx float64 `json:"lastPx"`
|
||||
LastQty int64 `json:"lastQty"`
|
||||
LeavesQty int64 `json:"leavesQty"`
|
||||
MultiLegReportingType string `json:"multiLegReportingType"`
|
||||
OrdRejReason string `json:"ordRejReason"`
|
||||
OrdStatus string `json:"ordStatus"`
|
||||
OrdType string `json:"ordType"`
|
||||
OrderID string `json:"orderID"`
|
||||
OrderQty int64 `json:"orderQty"`
|
||||
PegOffsetValue float64 `json:"pegOffsetValue"`
|
||||
PegPriceType string `json:"pegPriceType"`
|
||||
Price float64 `json:"price"`
|
||||
SettlCurrency string `json:"settlCurrency"`
|
||||
Side string `json:"side"`
|
||||
SimpleCumQty float64 `json:"simpleCumQty"`
|
||||
SimpleLeavesQty float64 `json:"simpleLeavesQty"`
|
||||
SimpleOrderQty float64 `json:"simpleOrderQty"`
|
||||
StopPx float64 `json:"stopPx"`
|
||||
Symbol string `json:"symbol"`
|
||||
Text string `json:"text"`
|
||||
TimeInForce string `json:"timeInForce"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
TradePublishIndicator string `json:"tradePublishIndicator"`
|
||||
TransactTime string `json:"transactTime"`
|
||||
TrdMatchID string `json:"trdMatchID"`
|
||||
Triggered string `json:"triggered"`
|
||||
UnderlyingLastPx float64 `json:"underlyingLastPx"`
|
||||
WorkingIndicator bool `json:"workingIndicator"`
|
||||
}
|
||||
|
||||
// Funding Swap Funding History
|
||||
type Funding struct {
|
||||
FundingInterval string `json:"fundingInterval"`
|
||||
FundingRate float64 `json:"fundingRate"`
|
||||
FundingRateDaily float64 `json:"fundingRateDaily"`
|
||||
Symbol string `json:"symbol"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
}
|
||||
|
||||
// Instrument Tradeable Contracts, Indices, and History
|
||||
type Instrument struct {
|
||||
AskPrice float64 `json:"askPrice"`
|
||||
BankruptLimitDownPrice float64 `json:"bankruptLimitDownPrice"`
|
||||
BankruptLimitUpPrice float64 `json:"bankruptLimitUpPrice"`
|
||||
BidPrice float64 `json:"bidPrice"`
|
||||
BuyLeg string `json:"buyLeg"`
|
||||
CalcInterval string `json:"calcInterval"`
|
||||
Capped bool `json:"capped"`
|
||||
ClosingTimestamp string `json:"closingTimestamp"`
|
||||
Deleverage bool `json:"deleverage"`
|
||||
Expiry string `json:"expiry"`
|
||||
FairBasis float64 `json:"fairBasis"`
|
||||
FairBasisRate float64 `json:"fairBasisRate"`
|
||||
FairMethod string `json:"fairMethod"`
|
||||
FairPrice float64 `json:"fairPrice"`
|
||||
Front string `json:"front"`
|
||||
FundingBaseSymbol string `json:"fundingBaseSymbol"`
|
||||
FundingInterval string `json:"fundingInterval"`
|
||||
FundingPremiumSymbol string `json:"fundingPremiumSymbol"`
|
||||
FundingQuoteSymbol string `json:"fundingQuoteSymbol"`
|
||||
FundingRate float64 `json:"fundingRate"`
|
||||
FundingTimestamp string `json:"fundingTimestamp"`
|
||||
HasLiquidity bool `json:"hasLiquidity"`
|
||||
HighPrice float64 `json:"highPrice"`
|
||||
ImpactAskPrice float64 `json:"impactAskPrice"`
|
||||
ImpactBidPrice float64 `json:"impactBidPrice"`
|
||||
ImpactMidPrice float64 `json:"impactMidPrice"`
|
||||
IndicativeFundingRate float64 `json:"indicativeFundingRate"`
|
||||
IndicativeSettlePrice float64 `json:"indicativeSettlePrice"`
|
||||
IndicativeTaxRate float64 `json:"indicativeTaxRate"`
|
||||
InitMargin float64 `json:"initMargin"`
|
||||
InsuranceFee float64 `json:"insuranceFee"`
|
||||
InverseLeg string `json:"inverseLeg"`
|
||||
IsInverse bool `json:"isInverse"`
|
||||
IsQuanto bool `json:"isQuanto"`
|
||||
LastChangePcnt float64 `json:"lastChangePcnt"`
|
||||
LastPrice float64 `json:"lastPrice"`
|
||||
LastPriceProtected float64 `json:"lastPriceProtected"`
|
||||
LastTickDirection string `json:"lastTickDirection"`
|
||||
Limit float64 `json:"limit"`
|
||||
LimitDownPrice float64 `json:"limitDownPrice"`
|
||||
LimitUpPrice float64 `json:"limitUpPrice"`
|
||||
Listing string `json:"listing"`
|
||||
LotSize int64 `json:"lotSize"`
|
||||
LowPrice float64 `json:"lowPrice"`
|
||||
MaintMargin float64 `json:"maintMargin"`
|
||||
MakerFee float64 `json:"makerFee"`
|
||||
MarkMethod string `json:"markMethod"`
|
||||
MarkPrice float64 `json:"markPrice"`
|
||||
MaxOrderQty int64 `json:"maxOrderQty"`
|
||||
MaxPrice float64 `json:"maxPrice"`
|
||||
MidPrice float64 `json:"midPrice"`
|
||||
Multiplier int64 `json:"multiplier"`
|
||||
OpenInterest int64 `json:"openInterest"`
|
||||
OpenValue int64 `json:"openValue"`
|
||||
OpeningTimestamp string `json:"openingTimestamp"`
|
||||
OptionMultiplier float64 `json:"optionMultiplier"`
|
||||
OptionStrikePcnt float64 `json:"optionStrikePcnt"`
|
||||
OptionStrikePrice float64 `json:"optionStrikePrice"`
|
||||
OptionStrikeRound float64 `json:"optionStrikeRound"`
|
||||
OptionUnderlyingPrice float64 `json:"optionUnderlyingPrice"`
|
||||
PositionCurrency string `json:"positionCurrency"`
|
||||
PrevClosePrice float64 `json:"prevClosePrice"`
|
||||
PrevPrice24h float64 `json:"prevPrice24h"`
|
||||
PrevTotalTurnover int64 `json:"prevTotalTurnover"`
|
||||
PrevTotalVolume int64 `json:"prevTotalVolume"`
|
||||
PublishInterval string `json:"publishInterval"`
|
||||
PublishTime string `json:"publishTime"`
|
||||
QuoteCurrency string `json:"quoteCurrency"`
|
||||
QuoteToSettleMultiplier int64 `json:"quoteToSettleMultiplier"`
|
||||
RebalanceInterval string `json:"rebalanceInterval"`
|
||||
RebalanceTimestamp string `json:"rebalanceTimestamp"`
|
||||
Reference string `json:"reference"`
|
||||
ReferenceSymbol string `json:"referenceSymbol"`
|
||||
RelistInterval string `json:"relistInterval"`
|
||||
RiskLimit int64 `json:"riskLimit"`
|
||||
RiskStep int64 `json:"riskStep"`
|
||||
RootSymbol string `json:"rootSymbol"`
|
||||
SellLeg string `json:"sellLeg"`
|
||||
SessionInterval string `json:"sessionInterval"`
|
||||
SettlCurrency string `json:"settlCurrency"`
|
||||
Settle string `json:"settle"`
|
||||
SettledPrice float64 `json:"settledPrice"`
|
||||
SettlementFee float64 `json:"settlementFee"`
|
||||
State string `json:"state"`
|
||||
Symbol string `json:"symbol"`
|
||||
TakerFee float64 `json:"takerFee"`
|
||||
Taxed bool `json:"taxed"`
|
||||
TickSize float64 `json:"tickSize"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
TotalTurnover int64 `json:"totalTurnover"`
|
||||
TotalVolume int64 `json:"totalVolume"`
|
||||
Turnover int64 `json:"turnover"`
|
||||
Turnover24h int64 `json:"turnover24h"`
|
||||
Typ string `json:"typ"`
|
||||
Underlying string `json:"underlying"`
|
||||
UnderlyingSymbol string `json:"underlyingSymbol"`
|
||||
UnderlyingToPositionMultiplier int64 `json:"underlyingToPositionMultiplier"`
|
||||
UnderlyingToSettleMultiplier int64 `json:"underlyingToSettleMultiplier"`
|
||||
Volume int64 `json:"volume"`
|
||||
Volume24h int64 `json:"volume24h"`
|
||||
Vwap float64 `json:"vwap"`
|
||||
}
|
||||
|
||||
// InstrumentInterval instrument interval
|
||||
type InstrumentInterval struct {
|
||||
Intervals []string `json:"intervals"`
|
||||
Symbols []string `json:"symbols"`
|
||||
}
|
||||
|
||||
// IndexComposite index composite
|
||||
type IndexComposite struct {
|
||||
IndexSymbol string `json:"indexSymbol"`
|
||||
LastPrice float64 `json:"lastPrice"`
|
||||
Logged string `json:"logged"`
|
||||
Reference string `json:"reference"`
|
||||
Symbol string `json:"symbol"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
Weight float64 `json:"weight"`
|
||||
}
|
||||
|
||||
// Insurance Insurance Fund Data
|
||||
type Insurance struct {
|
||||
Currency string `json:"currency"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
WalletBalance int64 `json:"walletBalance"`
|
||||
}
|
||||
|
||||
// Leaderboard Information on Top Users
|
||||
type Leaderboard struct {
|
||||
IsRealName bool `json:"isRealName"`
|
||||
Name string `json:"name"`
|
||||
Profit float64 `json:"profit"`
|
||||
}
|
||||
|
||||
// Alias Name refers to Trollbox client name
|
||||
type Alias struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// Liquidation Active Liquidations
|
||||
type Liquidation struct {
|
||||
LeavesQty int64 `json:"leavesQty"`
|
||||
OrderID string `json:"orderID"`
|
||||
Price float64 `json:"price"`
|
||||
Side string `json:"side"`
|
||||
Symbol string `json:"symbol"`
|
||||
}
|
||||
|
||||
// Notification Account Notifications
|
||||
type Notification struct {
|
||||
Body string `json:"body"`
|
||||
Closable bool `json:"closable"`
|
||||
Date string `json:"date"`
|
||||
ID int32 `json:"id"`
|
||||
Persist bool `json:"persist"`
|
||||
Sound string `json:"sound"`
|
||||
Title string `json:"title"`
|
||||
TTL int32 `json:"ttl"`
|
||||
Type string `json:"type"`
|
||||
WaitForVisibility bool `json:"waitForVisibility"`
|
||||
}
|
||||
|
||||
// Order Placement, Cancellation, Amending, and History
|
||||
type Order struct {
|
||||
Account int64 `json:"account"`
|
||||
AvgPx float64 `json:"avgPx"`
|
||||
ClOrdID string `json:"clOrdID"`
|
||||
ClOrdLinkID string `json:"clOrdLinkID"`
|
||||
ContingencyType string `json:"contingencyType"`
|
||||
CumQty int64 `json:"cumQty"`
|
||||
Currency string `json:"currency"`
|
||||
DisplayQty int64 `json:"displayQty"`
|
||||
ExDestination string `json:"exDestination"`
|
||||
ExecInst string `json:"execInst"`
|
||||
LeavesQty int64 `json:"leavesQty"`
|
||||
MultiLegReportingType string `json:"multiLegReportingType"`
|
||||
OrdRejReason string `json:"ordRejReason"`
|
||||
OrdStatus string `json:"ordStatus"`
|
||||
OrdType string `json:"ordType"`
|
||||
OrderID string `json:"orderID"`
|
||||
OrderQty int64 `json:"orderQty"`
|
||||
PegOffsetValue float64 `json:"pegOffsetValue"`
|
||||
PegPriceType string `json:"pegPriceType"`
|
||||
Price float64 `json:"price"`
|
||||
SettlCurrency string `json:"settlCurrency"`
|
||||
Side string `json:"side"`
|
||||
SimpleCumQty float64 `json:"simpleCumQty"`
|
||||
SimpleLeavesQty float64 `json:"simpleLeavesQty"`
|
||||
SimpleOrderQty float64 `json:"simpleOrderQty"`
|
||||
StopPx float64 `json:"stopPx"`
|
||||
Symbol string `json:"symbol"`
|
||||
Text string `json:"text"`
|
||||
TimeInForce string `json:"timeInForce"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
TransactTime string `json:"transactTime"`
|
||||
Triggered string `json:"triggered"`
|
||||
WorkingIndicator bool `json:"workingIndicator"`
|
||||
}
|
||||
|
||||
// OrderBookL2 contains order book l2
|
||||
type OrderBookL2 struct {
|
||||
ID int64 `json:"id"`
|
||||
Price float64 `json:"price"`
|
||||
Side string `json:"side"`
|
||||
Size int64 `json:"size"`
|
||||
Symbol string `json:"symbol"`
|
||||
}
|
||||
|
||||
// Position Summary of Open and Closed Positions
|
||||
type Position struct {
|
||||
Account int64 `json:"account"`
|
||||
AvgCostPrice float64 `json:"avgCostPrice"`
|
||||
AvgEntryPrice float64 `json:"avgEntryPrice"`
|
||||
BankruptPrice float64 `json:"bankruptPrice"`
|
||||
BreakEvenPrice float64 `json:"breakEvenPrice"`
|
||||
Commission float64 `json:"commission"`
|
||||
CrossMargin bool `json:"crossMargin"`
|
||||
Currency string `json:"currency"`
|
||||
CurrentComm int64 `json:"currentComm"`
|
||||
CurrentCost int64 `json:"currentCost"`
|
||||
CurrentQty int64 `json:"currentQty"`
|
||||
CurrentTimestamp string `json:"currentTimestamp"`
|
||||
DeleveragePercentile float64 `json:"deleveragePercentile"`
|
||||
ExecBuyCost int64 `json:"execBuyCost"`
|
||||
ExecBuyQty int64 `json:"execBuyQty"`
|
||||
ExecComm int64 `json:"execComm"`
|
||||
ExecCost int64 `json:"execCost"`
|
||||
ExecQty int64 `json:"execQty"`
|
||||
ExecSellCost int64 `json:"execSellCost"`
|
||||
ExecSellQty int64 `json:"execSellQty"`
|
||||
ForeignNotional float64 `json:"foreignNotional"`
|
||||
GrossExecCost int64 `json:"grossExecCost"`
|
||||
GrossOpenCost int64 `json:"grossOpenCost"`
|
||||
GrossOpenPremium int64 `json:"grossOpenPremium"`
|
||||
HomeNotional float64 `json:"homeNotional"`
|
||||
IndicativeTax int64 `json:"indicativeTax"`
|
||||
IndicativeTaxRate float64 `json:"indicativeTaxRate"`
|
||||
InitMargin int64 `json:"initMargin"`
|
||||
InitMarginReq float64 `json:"initMarginReq"`
|
||||
IsOpen bool `json:"isOpen"`
|
||||
LastPrice float64 `json:"lastPrice"`
|
||||
LastValue int64 `json:"lastValue"`
|
||||
Leverage float64 `json:"leverage"`
|
||||
LiquidationPrice float64 `json:"liquidationPrice"`
|
||||
LongBankrupt int64 `json:"longBankrupt"`
|
||||
MaintMargin int64 `json:"maintMargin"`
|
||||
MaintMarginReq float64 `json:"maintMarginReq"`
|
||||
MarginCallPrice float64 `json:"marginCallPrice"`
|
||||
MarkPrice float64 `json:"markPrice"`
|
||||
MarkValue int64 `json:"markValue"`
|
||||
OpenOrderBuyCost int64 `json:"openOrderBuyCost"`
|
||||
OpenOrderBuyPremium int64 `json:"openOrderBuyPremium"`
|
||||
OpenOrderBuyQty int64 `json:"openOrderBuyQty"`
|
||||
OpenOrderSellCost int64 `json:"openOrderSellCost"`
|
||||
OpenOrderSellPremium int64 `json:"openOrderSellPremium"`
|
||||
OpenOrderSellQty int64 `json:"openOrderSellQty"`
|
||||
OpeningComm int64 `json:"openingComm"`
|
||||
OpeningCost int64 `json:"openingCost"`
|
||||
OpeningQty int64 `json:"openingQty"`
|
||||
OpeningTimestamp string `json:"openingTimestamp"`
|
||||
PosAllowance int64 `json:"posAllowance"`
|
||||
PosComm int64 `json:"posComm"`
|
||||
PosCost int64 `json:"posCost"`
|
||||
PosCost2 int64 `json:"posCost2"`
|
||||
PosCross int64 `json:"posCross"`
|
||||
PosInit int64 `json:"posInit"`
|
||||
PosLoss int64 `json:"posLoss"`
|
||||
PosMaint int64 `json:"posMaint"`
|
||||
PosMargin int64 `json:"posMargin"`
|
||||
PosState string `json:"posState"`
|
||||
PrevClosePrice float64 `json:"prevClosePrice"`
|
||||
PrevRealisedPnl int64 `json:"prevRealisedPnl"`
|
||||
PrevUnrealisedPnl int64 `json:"prevUnrealisedPnl"`
|
||||
QuoteCurrency string `json:"quoteCurrency"`
|
||||
RealisedCost int64 `json:"realisedCost"`
|
||||
RealisedGrossPnl int64 `json:"realisedGrossPnl"`
|
||||
RealisedPnl int64 `json:"realisedPnl"`
|
||||
RealisedTax int64 `json:"realisedTax"`
|
||||
RebalancedPnl int64 `json:"rebalancedPnl"`
|
||||
RiskLimit int64 `json:"riskLimit"`
|
||||
RiskValue int64 `json:"riskValue"`
|
||||
SessionMargin int64 `json:"sessionMargin"`
|
||||
ShortBankrupt int64 `json:"shortBankrupt"`
|
||||
SimpleCost float64 `json:"simpleCost"`
|
||||
SimplePnl float64 `json:"simplePnl"`
|
||||
SimplePnlPcnt float64 `json:"simplePnlPcnt"`
|
||||
SimpleQty float64 `json:"simpleQty"`
|
||||
SimpleValue float64 `json:"simpleValue"`
|
||||
Symbol string `json:"symbol"`
|
||||
TargetExcessMargin int64 `json:"targetExcessMargin"`
|
||||
TaxBase int64 `json:"taxBase"`
|
||||
TaxableMargin int64 `json:"taxableMargin"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
Underlying string `json:"underlying"`
|
||||
UnrealisedCost int64 `json:"unrealisedCost"`
|
||||
UnrealisedGrossPnl int64 `json:"unrealisedGrossPnl"`
|
||||
UnrealisedPnl int64 `json:"unrealisedPnl"`
|
||||
UnrealisedPnlPcnt float64 `json:"unrealisedPnlPcnt"`
|
||||
UnrealisedRoePcnt float64 `json:"unrealisedRoePcnt"`
|
||||
UnrealisedTax int64 `json:"unrealisedTax"`
|
||||
VarMargin int64 `json:"varMargin"`
|
||||
}
|
||||
|
||||
// Quote Best Bid/Offer Snapshots & Historical Bins
|
||||
type Quote struct {
|
||||
AskPrice float64 `json:"askPrice"`
|
||||
AskSize int64 `json:"askSize"`
|
||||
BidPrice float64 `json:"bidPrice"`
|
||||
BidSize int64 `json:"bidSize"`
|
||||
Symbol string `json:"symbol"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
}
|
||||
|
||||
// Settlement Historical Settlement Data
|
||||
type Settlement struct {
|
||||
Bankrupt int64 `json:"bankrupt"`
|
||||
OptionStrikePrice float64 `json:"optionStrikePrice"`
|
||||
OptionUnderlyingPrice float64 `json:"optionUnderlyingPrice"`
|
||||
SettledPrice float64 `json:"settledPrice"`
|
||||
SettlementType string `json:"settlementType"`
|
||||
Symbol string `json:"symbol"`
|
||||
TaxBase int64 `json:"taxBase"`
|
||||
TaxRate float64 `json:"taxRate"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
}
|
||||
|
||||
// Stats Exchange Statistics
|
||||
type Stats struct {
|
||||
Currency string `json:"currency"`
|
||||
OpenInterest int64 `json:"openInterest"`
|
||||
OpenValue int64 `json:"openValue"`
|
||||
RootSymbol string `json:"rootSymbol"`
|
||||
Turnover24h int64 `json:"turnover24h"`
|
||||
Volume24h int64 `json:"volume24h"`
|
||||
}
|
||||
|
||||
// StatsHistory stats history
|
||||
type StatsHistory struct {
|
||||
Currency string `json:"currency"`
|
||||
Date string `json:"date"`
|
||||
RootSymbol string `json:"rootSymbol"`
|
||||
Turnover int64 `json:"turnover"`
|
||||
Volume int64 `json:"volume"`
|
||||
}
|
||||
|
||||
// StatsUSD contains summary of exchange stats
|
||||
type StatsUSD struct {
|
||||
Currency string `json:"currency"`
|
||||
RootSymbol string `json:"rootSymbol"`
|
||||
Turnover int64 `json:"turnover"`
|
||||
Turnover24h int64 `json:"turnover24h"`
|
||||
Turnover30d int64 `json:"turnover30d"`
|
||||
Turnover365d int64 `json:"turnover365d"`
|
||||
}
|
||||
|
||||
// Trade Individual & Bucketed Trades
|
||||
type Trade struct {
|
||||
ForeignNotional float64 `json:"foreignNotional"`
|
||||
GrossValue int64 `json:"grossValue"`
|
||||
HomeNotional float64 `json:"homeNotional"`
|
||||
Price float64 `json:"price"`
|
||||
Side string `json:"side"`
|
||||
Size int64 `json:"size"`
|
||||
Symbol string `json:"symbol"`
|
||||
TickDirection string `json:"tickDirection"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
TrdMatchID string `json:"trdMatchID"`
|
||||
}
|
||||
|
||||
// User Account Operations
|
||||
type User struct {
|
||||
TFAEnabled string `json:"TFAEnabled"`
|
||||
AffiliateID string `json:"affiliateID"`
|
||||
Country string `json:"country"`
|
||||
Created string `json:"created"`
|
||||
Email string `json:"email"`
|
||||
Firstname string `json:"firstname"`
|
||||
GeoipCountry string `json:"geoipCountry"`
|
||||
GeoipRegion string `json:"geoipRegion"`
|
||||
ID int32 `json:"id"`
|
||||
LastUpdated string `json:"lastUpdated"`
|
||||
Lastname string `json:"lastname"`
|
||||
OwnerID int32 `json:"ownerId"`
|
||||
PgpPubKey string `json:"pgpPubKey"`
|
||||
Phone string `json:"phone"`
|
||||
Preferences UserPreferences `json:"preferences"`
|
||||
Typ string `json:"typ"`
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
// UserPreferences user preferences
|
||||
type UserPreferences struct {
|
||||
AlertOnLiquidations bool `json:"alertOnLiquidations"`
|
||||
AnimationsEnabled bool `json:"animationsEnabled"`
|
||||
AnnouncementsLastSeen string `json:"announcementsLastSeen"`
|
||||
ChatChannelID float64 `json:"chatChannelID"`
|
||||
ColorTheme string `json:"colorTheme"`
|
||||
Currency string `json:"currency"`
|
||||
Debug bool `json:"debug"`
|
||||
DisableEmails []string `json:"disableEmails"`
|
||||
HideConfirmDialogs []string `json:"hideConfirmDialogs"`
|
||||
HideConnectionModal bool `json:"hideConnectionModal"`
|
||||
HideFromLeaderboard bool `json:"hideFromLeaderboard"`
|
||||
HideNameFromLeaderboard bool `json:"hideNameFromLeaderboard"`
|
||||
HideNotifications []string `json:"hideNotifications"`
|
||||
Locale string `json:"locale"`
|
||||
MsgsSeen []string `json:"msgsSeen"`
|
||||
OrderBookBinning interface{} `json:"orderBookBinning"`
|
||||
OrderBookType string `json:"orderBookType"`
|
||||
OrderClearImmediate bool `json:"orderClearImmediate"`
|
||||
OrderControlsPlusMinus bool `json:"orderControlsPlusMinus"`
|
||||
ShowLocaleNumbers bool `json:"showLocaleNumbers"`
|
||||
Sounds []string `json:"sounds"`
|
||||
StrictIPCheck bool `json:"strictIPCheck"`
|
||||
StrictTimeout bool `json:"strictTimeout"`
|
||||
TickerGroup string `json:"tickerGroup"`
|
||||
TickerPinned bool `json:"tickerPinned"`
|
||||
TradeLayout string `json:"tradeLayout"`
|
||||
}
|
||||
|
||||
// AffiliateStatus affiliate Status details
|
||||
type AffiliateStatus struct {
|
||||
Account int64 `json:"account"`
|
||||
Currency string `json:"currency"`
|
||||
ExecComm int64 `json:"execComm"`
|
||||
ExecTurnover int64 `json:"execTurnover"`
|
||||
PayoutPcnt float64 `json:"payoutPcnt"`
|
||||
PendingPayout int64 `json:"pendingPayout"`
|
||||
PrevComm int64 `json:"prevComm"`
|
||||
PrevPayout int64 `json:"prevPayout"`
|
||||
PrevTimestamp string `json:"prevTimestamp"`
|
||||
PrevTurnover int64 `json:"prevTurnover"`
|
||||
ReferrerAccount float64 `json:"referrerAccount"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
TotalComm int64 `json:"totalComm"`
|
||||
TotalReferrals int64 `json:"totalReferrals"`
|
||||
TotalTurnover int64 `json:"totalTurnover"`
|
||||
}
|
||||
|
||||
// TransactionInfo Information
|
||||
type TransactionInfo struct {
|
||||
Account int64 `json:"account"`
|
||||
Address string `json:"address"`
|
||||
Amount int64 `json:"amount"`
|
||||
Currency string `json:"currency"`
|
||||
Fee int64 `json:"fee"`
|
||||
Text string `json:"text"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
TransactID string `json:"transactID"`
|
||||
TransactStatus string `json:"transactStatus"`
|
||||
TransactTime string `json:"transactTime"`
|
||||
TransactType string `json:"transactType"`
|
||||
Tx string `json:"tx"`
|
||||
}
|
||||
|
||||
// UserCommission user commission
|
||||
type UserCommission struct {
|
||||
MakerFee float64 `json:"makerFee"`
|
||||
MaxFee float64 `json:"maxFee"`
|
||||
SettlementFee float64 `json:"settlementFee"`
|
||||
TakerFee float64 `json:"takerFee"`
|
||||
}
|
||||
|
||||
// ConfirmEmail confirmatin email endpoint data
|
||||
type ConfirmEmail struct {
|
||||
ID string `json:"id"`
|
||||
TTL int64 `json:"ttl"`
|
||||
Created string `json:"created"`
|
||||
UserID int64 `json:"userId"`
|
||||
}
|
||||
|
||||
// UserMargin margin information
|
||||
type UserMargin struct {
|
||||
Account int64 `json:"account"`
|
||||
Action string `json:"action"`
|
||||
Amount int64 `json:"amount"`
|
||||
AvailableMargin int64 `json:"availableMargin"`
|
||||
Commission float64 `json:"commission"`
|
||||
ConfirmedDebit int64 `json:"confirmedDebit"`
|
||||
Currency string `json:"currency"`
|
||||
ExcessMargin int64 `json:"excessMargin"`
|
||||
ExcessMarginPcnt float64 `json:"excessMarginPcnt"`
|
||||
GrossComm int64 `json:"grossComm"`
|
||||
GrossExecCost int64 `json:"grossExecCost"`
|
||||
GrossLastValue int64 `json:"grossLastValue"`
|
||||
GrossMarkValue int64 `json:"grossMarkValue"`
|
||||
GrossOpenCost int64 `json:"grossOpenCost"`
|
||||
GrossOpenPremium int64 `json:"grossOpenPremium"`
|
||||
IndicativeTax int64 `json:"indicativeTax"`
|
||||
InitMargin int64 `json:"initMargin"`
|
||||
MaintMargin int64 `json:"maintMargin"`
|
||||
MarginBalance int64 `json:"marginBalance"`
|
||||
MarginBalancePcnt float64 `json:"marginBalancePcnt"`
|
||||
MarginLeverage float64 `json:"marginLeverage"`
|
||||
MarginUsedPcnt float64 `json:"marginUsedPcnt"`
|
||||
PendingCredit int64 `json:"pendingCredit"`
|
||||
PendingDebit int64 `json:"pendingDebit"`
|
||||
PrevRealisedPnl int64 `json:"prevRealisedPnl"`
|
||||
PrevState string `json:"prevState"`
|
||||
PrevUnrealisedPnl int64 `json:"prevUnrealisedPnl"`
|
||||
RealisedPnl int64 `json:"realisedPnl"`
|
||||
RiskLimit int64 `json:"riskLimit"`
|
||||
RiskValue int64 `json:"riskValue"`
|
||||
SessionMargin int64 `json:"sessionMargin"`
|
||||
State string `json:"state"`
|
||||
SyntheticMargin int64 `json:"syntheticMargin"`
|
||||
TargetExcessMargin int64 `json:"targetExcessMargin"`
|
||||
TaxableMargin int64 `json:"taxableMargin"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
UnrealisedPnl int64 `json:"unrealisedPnl"`
|
||||
UnrealisedProfit int64 `json:"unrealisedProfit"`
|
||||
VarMargin int64 `json:"varMargin"`
|
||||
WalletBalance int64 `json:"walletBalance"`
|
||||
WithdrawableMargin int64 `json:"withdrawableMargin"`
|
||||
}
|
||||
|
||||
// MinWithdrawalFee minimum withdrawal fee information
|
||||
type MinWithdrawalFee struct {
|
||||
Currency string `json:"currency"`
|
||||
Fee int64 `json:"fee"`
|
||||
MinFee int64 `json:"minFee"`
|
||||
}
|
||||
|
||||
// WalletInfo wallet information
|
||||
type WalletInfo struct {
|
||||
Account int64 `json:"account"`
|
||||
Addr string `json:"addr"`
|
||||
Amount int64 `json:"amount"`
|
||||
ConfirmedDebit int64 `json:"confirmedDebit"`
|
||||
Currency string `json:"currency"`
|
||||
DeltaAmount int64 `json:"deltaAmount"`
|
||||
DeltaDeposited int64 `json:"deltaDeposited"`
|
||||
DeltaTransferIn int64 `json:"deltaTransferIn"`
|
||||
DeltaTransferOut int64 `json:"deltaTransferOut"`
|
||||
DeltaWithdrawn int64 `json:"deltaWithdrawn"`
|
||||
Deposited int64 `json:"deposited"`
|
||||
PendingCredit int64 `json:"pendingCredit"`
|
||||
PendingDebit int64 `json:"pendingDebit"`
|
||||
PrevAmount int64 `json:"prevAmount"`
|
||||
PrevDeposited int64 `json:"prevDeposited"`
|
||||
PrevTimestamp string `json:"prevTimestamp"`
|
||||
PrevTransferIn int64 `json:"prevTransferIn"`
|
||||
PrevTransferOut int64 `json:"prevTransferOut"`
|
||||
PrevWithdrawn int64 `json:"prevWithdrawn"`
|
||||
Script string `json:"script"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
TransferIn int64 `json:"transferIn"`
|
||||
TransferOut int64 `json:"transferOut"`
|
||||
WithdrawalLock []string `json:"withdrawalLock"`
|
||||
Withdrawn int64 `json:"withdrawn"`
|
||||
}
|
||||
494
exchanges/bitmex/bitmex_websocket.go
Normal file
494
exchanges/bitmex/bitmex_websocket.go
Normal file
@@ -0,0 +1,494 @@
|
||||
package bitmex
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
)
|
||||
|
||||
const (
|
||||
bitmexWSURL = "wss://www.bitmex.com/realtime"
|
||||
|
||||
// Public Subscription Channels
|
||||
bitmexWSAnnouncement = "announcement"
|
||||
bitmexWSChat = "chat"
|
||||
bitmexWSConnected = "connected"
|
||||
bitmexWSFunding = "funding"
|
||||
bitmexWSInstrument = "instrument"
|
||||
bitmexWSInsurance = "insurance"
|
||||
bitmexWSLiquidation = "liquidation"
|
||||
bitmexWSOrderbookL2 = "orderBookL2"
|
||||
bitmexWSOrderbookL10 = "orderBook10"
|
||||
bitmexWSPublicNotifications = "publicNotifications"
|
||||
bitmexWSQuote = "quote"
|
||||
bitmexWSQuote1m = "quoteBin1m"
|
||||
bitmexWSQuote5m = "quoteBin5m"
|
||||
bitmexWSQuote1h = "quoteBin1h"
|
||||
bitmexWSQuote1d = "quoteBin1d"
|
||||
bitmexWSSettlement = "settlement"
|
||||
bitmexWSTrade = "trade"
|
||||
bitmexWSTrade1m = "tradeBin1m"
|
||||
bitmexWSTrade5m = "tradeBin5m"
|
||||
bitmexWSTrade1h = "tradeBin1h"
|
||||
bitmexWSTrade1d = "tradeBin1d"
|
||||
|
||||
// Authenticated Subscription Channels
|
||||
bitmexWSAffiliate = "affiliate"
|
||||
bitmexWSExecution = "execution"
|
||||
bitmexWSOrder = "order"
|
||||
bitmexWSMargin = "margin"
|
||||
bitmexWSPosition = "position"
|
||||
bitmexWSPrivateNotifications = "privateNotifications"
|
||||
bitmexWSTransact = "transact"
|
||||
bitmexWSWallet = "wallet"
|
||||
|
||||
bitmexActionInitialData = "partial"
|
||||
bitmexActionInsertData = "insert"
|
||||
bitmexActionDeleteData = "delete"
|
||||
bitmexActionUpdateData = "update"
|
||||
)
|
||||
|
||||
var (
|
||||
pongChan = make(chan int, 1)
|
||||
timer *time.Timer
|
||||
)
|
||||
|
||||
// WebsocketConnect initiates a new websocket connection
|
||||
func (b *Bitmex) WebsocketConnect() error {
|
||||
var dialer websocket.Dialer
|
||||
var err error
|
||||
|
||||
b.WebsocketConn, _, err = dialer.Dial(bitmexWSURL, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, p, err := b.WebsocketConn.ReadMessage()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var welcomeResp WebsocketWelcome
|
||||
err = common.JSONDecode(p, &welcomeResp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go b.connectionHandler()
|
||||
|
||||
if b.Verbose {
|
||||
log.Printf("Successfully connected to Bitmex %s at time: %s Limit: %d",
|
||||
welcomeResp.Info,
|
||||
welcomeResp.Timestamp,
|
||||
welcomeResp.Limit.Remaining)
|
||||
}
|
||||
|
||||
go b.handleIncomingData()
|
||||
|
||||
err = b.websocketSubscribe()
|
||||
if err != nil {
|
||||
b.WebsocketConn.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
if b.AuthenticatedAPISupport {
|
||||
err := b.websocketSendAuth()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Timer handles connection loss or failure
|
||||
func (b *Bitmex) connectionHandler() {
|
||||
defer func() {
|
||||
if b.Verbose {
|
||||
log.Println("Bitmex websocket: Connection handler routine shutdown")
|
||||
}
|
||||
}()
|
||||
|
||||
shutdown := b.shutdown.addRoutine()
|
||||
|
||||
timer = time.NewTimer(5 * time.Second)
|
||||
for {
|
||||
select {
|
||||
case <-timer.C:
|
||||
timeout := time.After(5 * time.Second)
|
||||
err := b.WebsocketConn.WriteJSON("ping")
|
||||
if err != nil {
|
||||
b.reconnect()
|
||||
return
|
||||
}
|
||||
for {
|
||||
select {
|
||||
case <-pongChan:
|
||||
if b.Verbose {
|
||||
log.Println("Bitmex websocket: PONG received")
|
||||
}
|
||||
break
|
||||
case <-timeout:
|
||||
log.Println("Bitmex websocket: Connection timed out - Closing connection....")
|
||||
b.WebsocketConn.Close()
|
||||
|
||||
log.Println("Bitmex websocket: Connection timed out - Reconnecting...")
|
||||
b.reconnect()
|
||||
return
|
||||
}
|
||||
}
|
||||
case <-shutdown:
|
||||
log.Println("Bitmex websocket: shutdown requested - Closing connection....")
|
||||
b.WebsocketConn.Close()
|
||||
log.Println("Bitmex websocket: Sending shutdown message")
|
||||
b.shutdown.routineShutdown()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reconnect handles reconnections to websocket API
|
||||
func (b *Bitmex) reconnect() {
|
||||
for {
|
||||
err := b.WebsocketConnect()
|
||||
if err != nil {
|
||||
log.Println("Bitmex websocket: Connection timed out - Failed to connect, sleeping...")
|
||||
time.Sleep(time.Second * 2)
|
||||
continue
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// handleIncomingData services incoming data from the websocket connection
|
||||
func (b *Bitmex) handleIncomingData() {
|
||||
defer func() {
|
||||
if b.Verbose {
|
||||
log.Println("Bitmex websocket: Response data handler routine shutdown")
|
||||
}
|
||||
}()
|
||||
|
||||
for {
|
||||
_, resp, err := b.WebsocketConn.ReadMessage()
|
||||
if err != nil {
|
||||
if b.Verbose {
|
||||
log.Println("Bitmex websocket: Connection error", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
message := string(resp)
|
||||
if common.StringContains(message, "pong") {
|
||||
if b.Verbose {
|
||||
log.Println("Bitmex websocket: PONG receieved")
|
||||
}
|
||||
pongChan <- 1
|
||||
continue
|
||||
}
|
||||
|
||||
if common.StringContains(message, "ping") {
|
||||
err = b.WebsocketConn.WriteJSON("pong")
|
||||
if err != nil {
|
||||
if b.Verbose {
|
||||
log.Println("Bitmex websocket error: ", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if !timer.Reset(5 * time.Second) {
|
||||
log.Fatal("Bitmex websocket: Timer failed to set")
|
||||
}
|
||||
|
||||
quickCapture := make(map[string]interface{})
|
||||
err = common.JSONDecode(resp, &quickCapture)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var respError WebsocketErrorResponse
|
||||
if _, ok := quickCapture["status"]; ok {
|
||||
err = common.JSONDecode(resp, &respError)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
log.Printf("Bitmex websocket error: %s", respError.Error)
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := quickCapture["success"]; ok {
|
||||
var decodedResp WebsocketSubscribeResp
|
||||
err := common.JSONDecode(resp, &decodedResp)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if decodedResp.Success {
|
||||
if b.Verbose {
|
||||
if len(quickCapture) == 3 {
|
||||
log.Printf("Bitmex Websocket: Successfully subscribed to %s",
|
||||
decodedResp.Subscribe)
|
||||
} else {
|
||||
log.Println("Bitmex Websocket: Successfully authenticated websocket connection")
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
log.Printf("Bitmex websocket error: Unable to subscribe %s",
|
||||
decodedResp.Subscribe)
|
||||
|
||||
} else if _, ok := quickCapture["table"]; ok {
|
||||
var decodedResp WebsocketMainResponse
|
||||
err := common.JSONDecode(resp, &decodedResp)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
switch decodedResp.Table {
|
||||
case bitmexWSOrderbookL2:
|
||||
var orderbooks OrderBookData
|
||||
err = common.JSONDecode(resp, &orderbooks)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = b.processOrderbook(orderbooks.Data, orderbooks.Action)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
case bitmexWSTrade:
|
||||
var trades TradeData
|
||||
err = common.JSONDecode(resp, &trades)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = b.processTrades(trades.Data, trades.Action)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
case bitmexWSAnnouncement:
|
||||
var announcement AnnouncementData
|
||||
err = common.JSONDecode(resp, &announcement)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = b.processAnnouncement(announcement.Data, announcement.Action)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
default:
|
||||
log.Fatal("Bitmex websocket error: Table unknown -", decodedResp.Table)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Temporary local cache of Announcements
|
||||
var localAnnouncements []Announcement
|
||||
var partialLoadedAnnouncement bool
|
||||
|
||||
// ProcessAnnouncement process announcements
|
||||
func (b *Bitmex) processAnnouncement(data []Announcement, action string) error {
|
||||
switch action {
|
||||
case bitmexActionInitialData:
|
||||
if !partialLoadedAnnouncement {
|
||||
localAnnouncements = data
|
||||
}
|
||||
partialLoadedAnnouncement = true
|
||||
default:
|
||||
return fmt.Errorf("Bitmex websocket error: ProcessAnnouncement() unallocated action - %s",
|
||||
action)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Temporary local cache of orderbooks
|
||||
var localOb []OrderBookL2
|
||||
var partialLoaded bool
|
||||
|
||||
// ProcessOrderbook processes orderbook updates
|
||||
func (b *Bitmex) processOrderbook(data []OrderBookL2, action string) error {
|
||||
switch action {
|
||||
case bitmexActionInitialData:
|
||||
if !partialLoaded {
|
||||
localOb = data
|
||||
}
|
||||
partialLoaded = true
|
||||
case bitmexActionUpdateData:
|
||||
if partialLoaded {
|
||||
updated := len(data)
|
||||
for _, elem := range data {
|
||||
for i := range localOb {
|
||||
if localOb[i].ID == elem.ID && localOb[i].Symbol == elem.Symbol {
|
||||
localOb[i].Side = elem.Side
|
||||
localOb[i].Size = elem.Size
|
||||
updated--
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if updated != 0 {
|
||||
return errors.New("Bitmex websocket error: Elements not updated correctly")
|
||||
}
|
||||
}
|
||||
case bitmexActionInsertData:
|
||||
if partialLoaded {
|
||||
updated := len(data)
|
||||
for _, elem := range data {
|
||||
localOb = append(localOb, OrderBookL2{
|
||||
Symbol: elem.Symbol,
|
||||
ID: elem.ID,
|
||||
Side: elem.Side,
|
||||
Size: elem.Size,
|
||||
Price: elem.Price,
|
||||
})
|
||||
updated--
|
||||
}
|
||||
if updated != 0 {
|
||||
return errors.New("Bitmex websocket error: Elements not updated correctly")
|
||||
}
|
||||
}
|
||||
case bitmexActionDeleteData:
|
||||
if partialLoaded {
|
||||
updated := len(data)
|
||||
for _, elem := range data {
|
||||
for i := range localOb {
|
||||
if localOb[i].ID == elem.ID && localOb[i].Symbol == elem.Symbol {
|
||||
localOb[i] = localOb[len(localOb)-1]
|
||||
localOb = localOb[:len(localOb)-1]
|
||||
updated--
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if updated != 0 {
|
||||
return errors.New("Bitmex websocket error: Elements not updated correctly")
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Temporary local cache of orderbooks
|
||||
var localTrades []Trade
|
||||
var partialLoadedTrades bool
|
||||
|
||||
// ProcessTrades processes new trades that have occured
|
||||
func (b *Bitmex) processTrades(data []Trade, action string) error {
|
||||
switch action {
|
||||
case bitmexActionInitialData:
|
||||
if !partialLoadedTrades {
|
||||
localTrades = data
|
||||
}
|
||||
partialLoadedTrades = true
|
||||
case bitmexActionInsertData:
|
||||
if partialLoadedTrades {
|
||||
localTrades = append(localTrades, data...)
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("Bitmex websocket error: ProcessTrades() unallocated action - %s",
|
||||
action)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WebsocketSubscribe subscribes to a websocket channel
|
||||
func (b *Bitmex) websocketSubscribe() error {
|
||||
contracts := b.GetEnabledCurrencies()
|
||||
|
||||
// Subscriber
|
||||
var subscriber WebsocketRequest
|
||||
subscriber.Command = "subscribe"
|
||||
|
||||
// Announcement subscribe
|
||||
subscriber.Arguments = append(subscriber.Arguments, bitmexWSAnnouncement)
|
||||
|
||||
for _, contract := range contracts {
|
||||
// Orderbook subscribe
|
||||
subscriber.Arguments = append(subscriber.Arguments,
|
||||
bitmexWSOrderbookL2+":"+contract.Pair().String())
|
||||
|
||||
// Trade subscribe
|
||||
subscriber.Arguments = append(subscriber.Arguments,
|
||||
bitmexWSTrade+":"+contract.Pair().String())
|
||||
|
||||
// NOTE more added here in future
|
||||
}
|
||||
|
||||
err := b.WebsocketConn.WriteJSON(subscriber)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WebsocketSendAuth sends an authenticated subscription
|
||||
func (b *Bitmex) websocketSendAuth() error {
|
||||
timestamp := time.Now().Add(time.Hour * 1).Unix()
|
||||
newTimestamp := strconv.FormatInt(timestamp, 10)
|
||||
hmac := common.GetHMAC(common.HashSHA256,
|
||||
[]byte("GET/realtime"+newTimestamp),
|
||||
[]byte(b.APISecret))
|
||||
|
||||
signature := common.HexEncodeToString(hmac)
|
||||
|
||||
var sendAuth WebsocketRequest
|
||||
sendAuth.Command = "authKeyExpires"
|
||||
sendAuth.Arguments = append(sendAuth.Arguments, b.APIKey)
|
||||
sendAuth.Arguments = append(sendAuth.Arguments, timestamp)
|
||||
sendAuth.Arguments = append(sendAuth.Arguments, signature)
|
||||
|
||||
return b.WebsocketConn.WriteJSON(sendAuth)
|
||||
}
|
||||
|
||||
// Shutdown to monitor and shut down routines package specific
|
||||
type Shutdown struct {
|
||||
c chan int
|
||||
routineCount int
|
||||
finishC chan int
|
||||
}
|
||||
|
||||
// NewRoutineManagement returns an new initial routine management system
|
||||
func (b *Bitmex) NewRoutineManagement() *Shutdown {
|
||||
return &Shutdown{
|
||||
c: make(chan int, 1),
|
||||
finishC: make(chan int, 1),
|
||||
}
|
||||
}
|
||||
|
||||
// AddRoutine adds a routine to the monitor and returns a channel
|
||||
func (r *Shutdown) addRoutine() chan int {
|
||||
log.Println("Bitmex Websocket: Routine added to monitor")
|
||||
r.routineCount++
|
||||
return r.c
|
||||
}
|
||||
|
||||
// RoutineShutdown sends a message to the finisher channel
|
||||
func (r *Shutdown) routineShutdown() {
|
||||
log.Println("Bitmex Websocket: Routine is shutting down")
|
||||
r.finishC <- 1
|
||||
}
|
||||
|
||||
// SignalShutdown signals a shutdown across routines
|
||||
func (r *Shutdown) SignalShutdown() {
|
||||
log.Println("Bitmex Websocket: Shutdown signal sending..")
|
||||
for i := 0; i < r.routineCount; i++ {
|
||||
log.Printf("Bitmex Websocket: Shutdown signal sent to routine %d", i+1)
|
||||
r.c <- 1
|
||||
}
|
||||
|
||||
for {
|
||||
<-r.finishC
|
||||
r.routineCount--
|
||||
if r.routineCount <= 0 {
|
||||
close(r.c)
|
||||
close(r.finishC)
|
||||
log.Println("Bitmex Websocket: All routines stopped")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
72
exchanges/bitmex/bitmex_websocket_types.go
Normal file
72
exchanges/bitmex/bitmex_websocket_types.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package bitmex
|
||||
|
||||
// WebsocketRequest is the main request type
|
||||
type WebsocketRequest struct {
|
||||
Command string `json:"op"`
|
||||
Arguments []interface{} `json:"args"`
|
||||
}
|
||||
|
||||
// WebsocketErrorResponse main error response
|
||||
type WebsocketErrorResponse struct {
|
||||
Status int `json:"status"`
|
||||
Error string `json:"error"`
|
||||
Meta interface{} `json:"meta"`
|
||||
Request WebsocketRequest `json:"request"`
|
||||
}
|
||||
|
||||
// WebsocketWelcome initial welcome type
|
||||
type WebsocketWelcome struct {
|
||||
Info string `json:"info"`
|
||||
Version string `json:"version"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
Docs string `json:"docs"`
|
||||
Limit struct {
|
||||
Remaining int64 `json:"remaining"`
|
||||
} `json:"limit"`
|
||||
}
|
||||
|
||||
// WebsocketSubscribeResp is a response that occurs after a subscription
|
||||
type WebsocketSubscribeResp struct {
|
||||
Success bool `json:"success"`
|
||||
Subscribe string `json:"subscribe"`
|
||||
Request WebsocketRequest `json:"request"`
|
||||
}
|
||||
|
||||
// WebsocketMainResponse main table defined response
|
||||
type WebsocketMainResponse struct {
|
||||
Table string `json:"table"`
|
||||
Keys []string `json:"keys"`
|
||||
Types struct {
|
||||
ID string `json:"id"`
|
||||
Price string `json:"price"`
|
||||
Side string `json:"side"`
|
||||
Size string `json:"size"`
|
||||
Symbol string `json:"symbol"`
|
||||
} `json:"types"`
|
||||
ForeignKeys struct {
|
||||
Side string `json:"side"`
|
||||
Symbol string `json:"symbol"`
|
||||
} `json:"foreignKeys"`
|
||||
Attributes struct {
|
||||
ID string `json:"id"`
|
||||
Symbol string `json:"symbol"`
|
||||
} `json:"Attributes"`
|
||||
}
|
||||
|
||||
// OrderBookData contains orderbook resp data with action to be taken
|
||||
type OrderBookData struct {
|
||||
Data []OrderBookL2 `json:"data"`
|
||||
Action string `json:"action"`
|
||||
}
|
||||
|
||||
// TradeData contains trade resp data with action to be taken
|
||||
type TradeData struct {
|
||||
Data []Trade `json:"data"`
|
||||
Action string `json:"action"`
|
||||
}
|
||||
|
||||
// AnnouncementData contains announcement resp data with action to be taken
|
||||
type AnnouncementData struct {
|
||||
Data []Announcement `json:"data"`
|
||||
Action string `json:"action"`
|
||||
}
|
||||
195
exchanges/bitmex/bitmex_wrapper.go
Normal file
195
exchanges/bitmex/bitmex_wrapper.go
Normal file
@@ -0,0 +1,195 @@
|
||||
package bitmex
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/currency/pair"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
// Start starts the Bitmex go routine
|
||||
func (b *Bitmex) Start(wg *sync.WaitGroup) {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
b.Run()
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
// Run implements the Bitmex wrapper
|
||||
func (b *Bitmex) Run() {
|
||||
if b.Verbose {
|
||||
log.Printf("%s Websocket: %s. (url: %s).\n", b.GetName(), common.IsEnabled(b.Websocket), b.WebsocketURL)
|
||||
log.Printf("%s polling delay: %ds.\n", b.GetName(), b.RESTPollingDelay)
|
||||
log.Printf("%s %d currencies enabled: %s.\n", b.GetName(), len(b.EnabledPairs), b.EnabledPairs)
|
||||
}
|
||||
|
||||
marketInfo, err := b.GetActiveInstruments(GenericRequestParams{})
|
||||
if err != nil {
|
||||
log.Printf("%s Failed to get available symbols.\n", b.GetName())
|
||||
} else {
|
||||
|
||||
var exchangeProducts []string
|
||||
|
||||
for _, info := range marketInfo {
|
||||
exchangeProducts = append(exchangeProducts, info.Symbol)
|
||||
}
|
||||
|
||||
err = b.UpdateCurrencies(exchangeProducts, false, false)
|
||||
if err != nil {
|
||||
log.Printf("%s Failed to update available currencies.\n", b.GetName())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (b *Bitmex) UpdateTicker(p pair.CurrencyPair, assetType string) (ticker.Price, error) {
|
||||
var tickerPrice ticker.Price
|
||||
currency := exchange.FormatExchangeCurrency(b.Name, p)
|
||||
|
||||
tick, err := b.GetTrade(GenericRequestParams{
|
||||
Symbol: currency.String(),
|
||||
StartTime: time.Now().Format(time.RFC3339),
|
||||
Reverse: true,
|
||||
Count: 1})
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
|
||||
if len(tick) == 0 {
|
||||
return tickerPrice, errors.New("Bitmex REST error: no ticker return")
|
||||
}
|
||||
|
||||
tickerPrice.Pair = p
|
||||
tickerPrice.LastUpdated = time.Now()
|
||||
tickerPrice.CurrencyPair = tick[0].Symbol
|
||||
tickerPrice.Last = tick[0].Price
|
||||
tickerPrice.Volume = float64(tick[0].Size)
|
||||
|
||||
ticker.ProcessTicker(b.Name, p, tickerPrice, assetType)
|
||||
|
||||
return tickerPrice, nil
|
||||
}
|
||||
|
||||
// GetTickerPrice returns the ticker for a currency pair
|
||||
func (b *Bitmex) GetTickerPrice(p pair.CurrencyPair, assetType string) (ticker.Price, error) {
|
||||
tickerNew, err := ticker.GetTicker(b.GetName(), p, assetType)
|
||||
if err != nil {
|
||||
return b.UpdateTicker(p, assetType)
|
||||
}
|
||||
return tickerNew, nil
|
||||
}
|
||||
|
||||
// GetOrderbookEx returns orderbook base on the currency pair
|
||||
func (b *Bitmex) GetOrderbookEx(currency pair.CurrencyPair, assetType string) (orderbook.Base, error) {
|
||||
ob, err := orderbook.GetOrderbook(b.GetName(), currency, assetType)
|
||||
if err != nil {
|
||||
return b.UpdateOrderbook(currency, assetType)
|
||||
}
|
||||
return ob, nil
|
||||
}
|
||||
|
||||
// UpdateOrderbook updates and returns the orderbook for a currency pair
|
||||
func (b *Bitmex) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderbook.Base, error) {
|
||||
var orderBook orderbook.Base
|
||||
|
||||
orderbookNew, err := b.GetOrderbook(OrderBookGetL2Params{
|
||||
Symbol: exchange.FormatExchangeCurrency(b.Name, p).String(),
|
||||
Depth: 500})
|
||||
if err != nil {
|
||||
return orderBook, err
|
||||
}
|
||||
|
||||
for _, ob := range orderbookNew {
|
||||
if ob.Side == "Sell" {
|
||||
orderBook.Asks = append(orderBook.Asks,
|
||||
orderbook.Item{Amount: float64(ob.Size), Price: ob.Price})
|
||||
continue
|
||||
}
|
||||
if ob.Side == "Buy" {
|
||||
orderBook.Bids = append(orderBook.Bids,
|
||||
orderbook.Item{Amount: float64(ob.Size), Price: ob.Price})
|
||||
continue
|
||||
}
|
||||
}
|
||||
orderbook.ProcessOrderbook(b.GetName(), p, orderBook, assetType)
|
||||
|
||||
return orderbook.GetOrderbook(b.Name, p, assetType)
|
||||
}
|
||||
|
||||
// GetExchangeAccountInfo retrieves balances for all enabled currencies for the
|
||||
// Bitmex exchange
|
||||
func (b *Bitmex) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
|
||||
var response exchange.AccountInfo
|
||||
return response, errors.New("not implemented")
|
||||
}
|
||||
|
||||
// GetExchangeFundTransferHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
func (b *Bitmex) GetExchangeFundTransferHistory() ([]exchange.FundHistory, error) {
|
||||
var fundHistory []exchange.FundHistory
|
||||
return fundHistory, errors.New("not supported on exchange")
|
||||
}
|
||||
|
||||
// GetExchangeHistory returns historic trade data since exchange opening.
|
||||
func (b *Bitmex) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
|
||||
var resp []exchange.TradeHistory
|
||||
|
||||
return resp, errors.New("trade history not yet implemented")
|
||||
}
|
||||
|
||||
// SubmitExchangeOrder submits a new order
|
||||
func (b *Bitmex) SubmitExchangeOrder(p pair.CurrencyPair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, clientID string) (int64, error) {
|
||||
return 0, errors.New("not yet implemented")
|
||||
}
|
||||
|
||||
// ModifyExchangeOrder will allow of changing orderbook placement and limit to
|
||||
// market conversion
|
||||
func (b *Bitmex) ModifyExchangeOrder(orderID int64, action exchange.ModifyOrder) (int64, error) {
|
||||
return 0, errors.New("not yet implemented")
|
||||
}
|
||||
|
||||
// CancelExchangeOrder cancels an order by its corresponding ID number
|
||||
func (b *Bitmex) CancelExchangeOrder(orderID int64) error {
|
||||
return errors.New("not yet implemented")
|
||||
}
|
||||
|
||||
// CancelAllExchangeOrders cancels all orders associated with a currency pair
|
||||
func (b *Bitmex) CancelAllExchangeOrders() error {
|
||||
return errors.New("not yet implemented")
|
||||
}
|
||||
|
||||
// GetExchangeOrderInfo returns information on a current open order
|
||||
func (b *Bitmex) GetExchangeOrderInfo(orderID int64) (exchange.OrderDetail, error) {
|
||||
var orderDetail exchange.OrderDetail
|
||||
return orderDetail, errors.New("not yet implemented")
|
||||
}
|
||||
|
||||
// GetExchangeDepositAddress returns a deposit address for a specified currency
|
||||
func (b *Bitmex) GetExchangeDepositAddress(cryptocurrency pair.CurrencyItem) (string, error) {
|
||||
return "", errors.New("not yet implemented")
|
||||
}
|
||||
|
||||
// WithdrawCryptoExchangeFunds returns a withdrawal ID when a withdrawal is
|
||||
// submitted
|
||||
func (b *Bitmex) WithdrawCryptoExchangeFunds(address string, cryptocurrency pair.CurrencyItem, amount float64) (string, error) {
|
||||
return "", errors.New("not yet implemented")
|
||||
}
|
||||
|
||||
// WithdrawFiatExchangeFunds returns a withdrawal ID when a withdrawal is
|
||||
// submitted
|
||||
func (b *Bitmex) WithdrawFiatExchangeFunds(currency pair.CurrencyItem, amount float64) (string, error) {
|
||||
return "", errors.New("not yet implemented")
|
||||
}
|
||||
|
||||
// WithdrawExchangeFiatFundsToInternationalBank returns a withdrawal ID when a withdrawal is
|
||||
// submitted
|
||||
func (b *Bitmex) WithdrawExchangeFiatFundsToInternationalBank(currency pair.CurrencyItem, amount float64) (string, error) {
|
||||
return "", errors.New("not yet implemented")
|
||||
}
|
||||
6125
exchanges/bitmex/swagger/swagger.json
Normal file
6125
exchanges/bitmex/swagger/swagger.json
Normal file
File diff suppressed because one or more lines are too long
@@ -85,6 +85,7 @@ func (b *Bitstamp) Setup(exch config.ExchangeConfig) {
|
||||
b.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
b.SetAPIKeys(exch.APIKey, exch.APISecret, exch.ClientID, false)
|
||||
b.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
b.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
b.RESTPollingDelay = exch.RESTPollingDelay
|
||||
b.Verbose = exch.Verbose
|
||||
b.Websocket = exch.Websocket
|
||||
|
||||
@@ -88,6 +88,7 @@ func (b *Bittrex) Setup(exch config.ExchangeConfig) {
|
||||
b.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
b.SetAPIKeys(exch.APIKey, exch.APISecret, exch.ClientID, false)
|
||||
b.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
b.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
b.RESTPollingDelay = exch.RESTPollingDelay
|
||||
b.Verbose = exch.Verbose
|
||||
b.Websocket = exch.Websocket
|
||||
|
||||
@@ -79,6 +79,7 @@ func (b *BTCC) Setup(exch config.ExchangeConfig) {
|
||||
b.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
b.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
|
||||
b.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
b.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
b.RESTPollingDelay = exch.RESTPollingDelay
|
||||
b.Verbose = exch.Verbose
|
||||
b.Websocket = exch.Websocket
|
||||
|
||||
@@ -76,6 +76,7 @@ func (b *BTCMarkets) Setup(exch config.ExchangeConfig) {
|
||||
b.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
b.SetAPIKeys(exch.APIKey, exch.APISecret, "", true)
|
||||
b.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
b.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
b.RESTPollingDelay = exch.RESTPollingDelay
|
||||
b.Verbose = exch.Verbose
|
||||
b.Websocket = exch.Websocket
|
||||
|
||||
@@ -87,6 +87,7 @@ func (c *CoinbasePro) Setup(exch config.ExchangeConfig) {
|
||||
c.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
c.SetAPIKeys(exch.APIKey, exch.APISecret, exch.ClientID, true)
|
||||
c.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
c.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
c.RESTPollingDelay = exch.RESTPollingDelay
|
||||
c.Verbose = exch.Verbose
|
||||
c.Websocket = exch.Websocket
|
||||
|
||||
@@ -74,6 +74,7 @@ func (c *COINUT) Setup(exch config.ExchangeConfig) {
|
||||
c.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
c.SetAPIKeys(exch.APIKey, exch.APISecret, exch.ClientID, true)
|
||||
c.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
c.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
c.RESTPollingDelay = exch.RESTPollingDelay
|
||||
c.Verbose = exch.Verbose
|
||||
c.Websocket = exch.Websocket
|
||||
|
||||
@@ -102,6 +102,7 @@ type Base struct {
|
||||
SupportsAutoPairUpdating bool
|
||||
SupportsRESTTickerBatching bool
|
||||
HTTPTimeout time.Duration
|
||||
HTTPUserAgent string
|
||||
WebsocketURL string
|
||||
APIUrl string
|
||||
RequestCurrencyPairFormat config.CurrencyPairFormatConfig
|
||||
@@ -175,6 +176,20 @@ func (e *Base) GetHTTPClient() *http.Client {
|
||||
return e.Requester.HTTPClient
|
||||
}
|
||||
|
||||
// SetHTTPClientUserAgent sets the exchanges HTTP user agent
|
||||
func (e *Base) SetHTTPClientUserAgent(ua string) {
|
||||
if e.Requester == nil {
|
||||
e.Requester = request.New(e.Name, request.NewRateLimit(time.Second, 0), request.NewRateLimit(time.Second, 0), new(http.Client))
|
||||
}
|
||||
e.Requester.UserAgent = ua
|
||||
e.HTTPUserAgent = ua
|
||||
}
|
||||
|
||||
// GetHTTPClientUserAgent gets the exchanges HTTP user agent
|
||||
func (e *Base) GetHTTPClientUserAgent() string {
|
||||
return e.HTTPUserAgent
|
||||
}
|
||||
|
||||
// SetAutoPairDefaults sets the default values for whether or not the exchange
|
||||
// supports auto pair updating or not
|
||||
func (e *Base) SetAutoPairDefaults() error {
|
||||
|
||||
@@ -77,6 +77,7 @@ func (e *EXMO) Setup(exch config.ExchangeConfig) {
|
||||
e.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
e.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
|
||||
e.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
e.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
e.RESTPollingDelay = exch.RESTPollingDelay
|
||||
e.Verbose = exch.Verbose
|
||||
e.Websocket = exch.Websocket
|
||||
|
||||
@@ -1,9 +1,140 @@
|
||||
# GoCryptoTrader package gateio
|
||||
# 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">
|
||||
|
||||
|
||||
[](https://travis-ci.org/thrasher-/gocryptotrader)
|
||||
[](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/gateio)
|
||||
[](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
|
||||
|
||||
|
||||
This gateio package is part of the GoCryptoTrader codebase.
|
||||
|
||||
## Gateio Exchange
|
||||
## This is still in active development
|
||||
|
||||
You can track ideas, planned features and what's in progresss on this Trello board: [https://trello.com/b/ZAhMhpOy/gocryptotrader](https://trello.com/b/ZAhMhpOy/gocryptotrader).
|
||||
|
||||
Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader Slack](https://gocryptotrader.herokuapp.com/)
|
||||
|
||||
## GateIO Exchange
|
||||
|
||||
### Current Features
|
||||
|
||||
Gateio 交易所的支持,支持获取K线、支持的交易对、交易市场参数、买/卖订单、取消订单
|
||||
+ REST functions
|
||||
|
||||
### How to enable
|
||||
|
||||
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
|
||||
+ Individual package example below:
|
||||
|
||||
```go
|
||||
// Exchanges will be abstracted out in further updates and examples will be
|
||||
// supplied then
|
||||
```
|
||||
|
||||
### How to do REST public/private calls
|
||||
|
||||
+ If enabled via "configuration".json file the exchange will be added to the
|
||||
IBotExchange array in the ```go var bot Bot``` and you will only be able to use
|
||||
the wrapper interface functions for accessing exchange data. View routines.go
|
||||
for an example of integration usage with GoCryptoTrader. Rudimentary example
|
||||
below:
|
||||
|
||||
main.go
|
||||
```go
|
||||
var g exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "GateIO" {
|
||||
g = bot.exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := g.GetTickerPrice()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := g.GetOrderbookEx()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Private calls - wrapper functions - make sure your APIKEY and APISECRET are
|
||||
// set and AuthenticatedAPISupport is set to true
|
||||
|
||||
// Fetches current account information
|
||||
accountInfo, err := g.GetExchangeAccountInfo()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
+ If enabled via individually importing package, rudimentary example below:
|
||||
|
||||
```go
|
||||
// Public calls
|
||||
|
||||
// Fetches current ticker information
|
||||
ticker, err := g.GetTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := g.GetOrderBook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Private calls - make sure your APIKEY and APISECRET are set and
|
||||
// AuthenticatedAPISupport is set to true
|
||||
|
||||
// GetUserInfo returns account info
|
||||
accountInfo, err := g.GetUserInfo(...)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Submits an order and the exchange and returns its tradeID
|
||||
tradeID, err := g.Trade(...)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
### How to do LongPolling public/private calls
|
||||
|
||||
```go
|
||||
// Exchanges will be abstracted out in further updates and examples will be
|
||||
// supplied then
|
||||
```
|
||||
|
||||
### Please click GoDocs chevron above to view current GoDoc information for this package
|
||||
|
||||
## Contribution
|
||||
|
||||
Please feel free to submit any pull requests or suggest any desired features to be added.
|
||||
|
||||
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).
|
||||
+ 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">
|
||||
|
||||
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
|
||||
|
||||
***1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB***
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@ func (g *Gateio) Setup(exch config.ExchangeConfig) {
|
||||
g.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
|
||||
g.APIAuthPEMKey = exch.APIAuthPEMKey
|
||||
g.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
g.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
g.RESTPollingDelay = exch.RESTPollingDelay
|
||||
g.Verbose = exch.Verbose
|
||||
g.Websocket = exch.Websocket
|
||||
|
||||
@@ -121,6 +121,7 @@ func (g *Gemini) Setup(exch config.ExchangeConfig) {
|
||||
g.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
g.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
|
||||
g.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
g.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
g.RESTPollingDelay = exch.RESTPollingDelay
|
||||
g.Verbose = exch.Verbose
|
||||
g.Websocket = exch.Websocket
|
||||
|
||||
@@ -78,6 +78,7 @@ func (p *HitBTC) Setup(exch config.ExchangeConfig) {
|
||||
p.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
p.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
|
||||
p.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
p.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
p.RESTPollingDelay = exch.RESTPollingDelay // Max 60000ms
|
||||
p.Verbose = exch.Verbose
|
||||
p.Websocket = exch.Websocket
|
||||
|
||||
@@ -90,6 +90,7 @@ func (h *HUOBI) Setup(exch config.ExchangeConfig) {
|
||||
h.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
|
||||
h.APIAuthPEMKey = exch.APIAuthPEMKey
|
||||
h.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
h.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
h.RESTPollingDelay = exch.RESTPollingDelay
|
||||
h.Verbose = exch.Verbose
|
||||
h.Websocket = exch.Websocket
|
||||
|
||||
140
exchanges/huobihadax/README.md
Normal file
140
exchanges/huobihadax/README.md
Normal file
@@ -0,0 +1,140 @@
|
||||
# GoCryptoTrader package Huobihadax
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
|
||||
|
||||
[](https://travis-ci.org/thrasher-/gocryptotrader)
|
||||
[](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/huobihadax)
|
||||
[](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
|
||||
|
||||
|
||||
This huobihadax package is part of the GoCryptoTrader codebase.
|
||||
|
||||
## This is still in active development
|
||||
|
||||
You can track ideas, planned features and what's in progresss on this Trello board: [https://trello.com/b/ZAhMhpOy/gocryptotrader](https://trello.com/b/ZAhMhpOy/gocryptotrader).
|
||||
|
||||
Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader Slack](https://gocryptotrader.herokuapp.com/)
|
||||
|
||||
## HuobiHadax Exchange
|
||||
|
||||
### Current Features
|
||||
|
||||
+ REST functions
|
||||
|
||||
### How to enable
|
||||
|
||||
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
|
||||
+ Individual package example below:
|
||||
|
||||
```go
|
||||
// Exchanges will be abstracted out in further updates and examples will be
|
||||
// supplied then
|
||||
```
|
||||
|
||||
### How to do REST public/private calls
|
||||
|
||||
+ If enabled via "configuration".json file the exchange will be added to the
|
||||
IBotExchange array in the ```go var bot Bot``` and you will only be able to use
|
||||
the wrapper interface functions for accessing exchange data. View routines.go
|
||||
for an example of integration usage with GoCryptoTrader. Rudimentary example
|
||||
below:
|
||||
|
||||
main.go
|
||||
```go
|
||||
var h exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "HuobiHadax" {
|
||||
h = bot.exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := h.GetTickerPrice()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := h.GetOrderbookEx()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Private calls - wrapper functions - make sure your APIKEY and APISECRET are
|
||||
// set and AuthenticatedAPISupport is set to true
|
||||
|
||||
// Fetches current account information
|
||||
accountInfo, err := h.GetExchangeAccountInfo()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
+ If enabled via individually importing package, rudimentary example below:
|
||||
|
||||
```go
|
||||
// Public calls
|
||||
|
||||
// Fetches current ticker information
|
||||
ticker, err := h.GetTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := h.GetOrderBook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Private calls - make sure your APIKEY and APISECRET are set and
|
||||
// AuthenticatedAPISupport is set to true
|
||||
|
||||
// GetUserInfo returns account info
|
||||
accountInfo, err := h.GetUserInfo(...)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Submits an order and the exchange and returns its tradeID
|
||||
tradeID, err := h.Trade(...)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
### How to do LongPolling public/private calls
|
||||
|
||||
```go
|
||||
// Exchanges will be abstracted out in further updates and examples will be
|
||||
// supplied then
|
||||
```
|
||||
|
||||
### Please click GoDocs chevron above to view current GoDoc information for this package
|
||||
|
||||
## Contribution
|
||||
|
||||
Please feel free to submit any pull requests or suggest any desired features to be added.
|
||||
|
||||
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).
|
||||
+ 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">
|
||||
|
||||
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
|
||||
|
||||
***1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB***
|
||||
|
||||
@@ -85,6 +85,7 @@ func (h *HUOBIHADAX) Setup(exch config.ExchangeConfig) {
|
||||
h.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
|
||||
h.APIAuthPEMKey = exch.APIAuthPEMKey
|
||||
h.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
h.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
h.RESTPollingDelay = exch.RESTPollingDelay
|
||||
h.Verbose = exch.Verbose
|
||||
h.Websocket = exch.Websocket
|
||||
@@ -755,7 +756,6 @@ func (h *HUOBIHADAX) SendAuthenticatedHTTPPostRequest(method, endpoint, postBody
|
||||
method, endpoint, signatureParams.Encode())
|
||||
|
||||
headers := make(map[string]string)
|
||||
headers["User-Agent"] = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36"
|
||||
headers["Content-Type"] = "application/json"
|
||||
headers["Accept-Language"] = "zh-cn"
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@ func (i *ItBit) Setup(exch config.ExchangeConfig) {
|
||||
i.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
i.SetAPIKeys(exch.APIKey, exch.APISecret, exch.ClientID, false)
|
||||
i.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
i.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
i.RESTPollingDelay = exch.RESTPollingDelay
|
||||
i.Verbose = exch.Verbose
|
||||
i.Websocket = exch.Websocket
|
||||
|
||||
@@ -81,6 +81,7 @@ func (k *Kraken) Setup(exch config.ExchangeConfig) {
|
||||
k.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
k.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
|
||||
k.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
k.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
k.RESTPollingDelay = exch.RESTPollingDelay
|
||||
k.Verbose = exch.Verbose
|
||||
k.Websocket = exch.Websocket
|
||||
@@ -111,40 +112,51 @@ func (k *Kraken) GetFee(cryptoTrade bool) float64 {
|
||||
}
|
||||
|
||||
// GetServerTime returns current server time
|
||||
func (k *Kraken) GetServerTime(unixTime bool) (interface{}, error) {
|
||||
var result GeneralResponse
|
||||
func (k *Kraken) GetServerTime() (TimeResponse, error) {
|
||||
path := fmt.Sprintf("%s/%s/public/%s", krakenAPIURL, krakenAPIVersion, krakenServerTime)
|
||||
|
||||
err := k.SendHTTPRequest(path, &result)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("getServerTime() error %s", err)
|
||||
var response struct {
|
||||
Error []string `json:"error"`
|
||||
Result TimeResponse `json:"result"`
|
||||
}
|
||||
|
||||
if unixTime {
|
||||
return result.Result["unixtime"], nil
|
||||
if err := k.SendHTTPRequest(path, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
return result.Result["rfc1123"], nil
|
||||
|
||||
return response.Result, GetError(response.Error)
|
||||
}
|
||||
|
||||
// GetAssets returns a full asset list
|
||||
func (k *Kraken) GetAssets() (interface{}, error) {
|
||||
var result GeneralResponse
|
||||
func (k *Kraken) GetAssets() (map[string]Asset, error) {
|
||||
path := fmt.Sprintf("%s/%s/public/%s", krakenAPIURL, krakenAPIVersion, krakenAssets)
|
||||
|
||||
return result.Result, k.SendHTTPRequest(path, &result)
|
||||
var response struct {
|
||||
Error []string `json:"error"`
|
||||
Result map[string]Asset `json:"result"`
|
||||
}
|
||||
|
||||
if err := k.SendHTTPRequest(path, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
return response.Result, GetError(response.Error)
|
||||
}
|
||||
|
||||
// GetAssetPairs returns a full asset pair list
|
||||
func (k *Kraken) GetAssetPairs() (map[string]AssetPairs, error) {
|
||||
type Response struct {
|
||||
Result map[string]AssetPairs `json:"result"`
|
||||
Error []interface{} `json:"error"`
|
||||
}
|
||||
|
||||
response := Response{}
|
||||
path := fmt.Sprintf("%s/%s/public/%s", krakenAPIURL, krakenAPIVersion, krakenAssetPairs)
|
||||
|
||||
return response.Result, k.SendHTTPRequest(path, &response)
|
||||
var response struct {
|
||||
Error []string `json:"error"`
|
||||
Result map[string]AssetPairs `json:"result"`
|
||||
}
|
||||
|
||||
if err := k.SendHTTPRequest(path, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
return response.Result, GetError(response.Error)
|
||||
}
|
||||
|
||||
// GetTicker returns ticker information from kraken
|
||||
@@ -371,208 +383,422 @@ func (k *Kraken) GetSpread(symbol string) ([]Spread, error) {
|
||||
}
|
||||
|
||||
// GetBalance returns your balance associated with your keys
|
||||
func (k *Kraken) GetBalance() (interface{}, error) {
|
||||
return k.SendAuthenticatedHTTPRequest(krakenBalance, url.Values{})
|
||||
func (k *Kraken) GetBalance() (map[string]float64, error) {
|
||||
var response struct {
|
||||
Error []string `json:"error"`
|
||||
Result map[string]string `json:"result"`
|
||||
}
|
||||
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenBalance, url.Values{}, &response); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make(map[string]float64)
|
||||
for curency, balance := range response.Result {
|
||||
var err error
|
||||
if result[curency], err = strconv.ParseFloat(balance, 64); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return result, GetError(response.Error)
|
||||
}
|
||||
|
||||
// GetTradeBalance returns full information about your trades on Kraken
|
||||
func (k *Kraken) GetTradeBalance(symbol, asset string) (interface{}, error) {
|
||||
values := url.Values{}
|
||||
func (k *Kraken) GetTradeBalance(args ...TradeBalanceOptions) (TradeBalanceInfo, error) {
|
||||
params := url.Values{}
|
||||
|
||||
if args != nil {
|
||||
if len(args[0].Aclass) != 0 {
|
||||
params.Set("aclass", args[0].Aclass)
|
||||
}
|
||||
|
||||
if len(args[0].Asset) != 0 {
|
||||
params.Set("asset", args[0].Asset)
|
||||
}
|
||||
|
||||
if len(symbol) > 0 {
|
||||
values.Set("aclass", symbol)
|
||||
}
|
||||
if len(asset) > 0 {
|
||||
values.Set("asset", asset)
|
||||
}
|
||||
|
||||
return k.SendAuthenticatedHTTPRequest(krakenTradeBalance, values)
|
||||
var response struct {
|
||||
Error []string `json:"error"`
|
||||
Result TradeBalanceInfo `json:"result"`
|
||||
}
|
||||
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenTradeBalance, params, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
return response.Result, GetError(response.Error)
|
||||
}
|
||||
|
||||
// GetOpenOrders returns all current open orders
|
||||
func (k *Kraken) GetOpenOrders(showTrades bool, userref int64) (interface{}, error) {
|
||||
values := url.Values{}
|
||||
func (k *Kraken) GetOpenOrders(args ...OrderInfoOptions) (OpenOrders, error) {
|
||||
params := url.Values{}
|
||||
|
||||
if showTrades {
|
||||
values.Set("trades", "true")
|
||||
if args[0].Trades {
|
||||
params.Set("trades", "true")
|
||||
}
|
||||
|
||||
if userref != 0 {
|
||||
values.Set("userref", strconv.FormatInt(userref, 10))
|
||||
if args[0].UserRef != 0 {
|
||||
params.Set("userref", strconv.FormatInt(int64(args[0].UserRef), 10))
|
||||
}
|
||||
|
||||
return k.SendAuthenticatedHTTPRequest(krakenOpenOrders, values)
|
||||
var response struct {
|
||||
Error []string `json:"error"`
|
||||
Result OpenOrders `json:"result"`
|
||||
}
|
||||
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenOpenOrders, params, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
return response.Result, GetError(response.Error)
|
||||
}
|
||||
|
||||
// GetClosedOrders returns a list of closed orders
|
||||
func (k *Kraken) GetClosedOrders(showTrades bool, userref, start, end, offset int64, closetime string) (interface{}, error) {
|
||||
values := url.Values{}
|
||||
func (k *Kraken) GetClosedOrders(args ...GetClosedOrdersOptions) (ClosedOrders, error) {
|
||||
params := url.Values{}
|
||||
|
||||
if showTrades {
|
||||
values.Set("trades", "true")
|
||||
if args != nil {
|
||||
if args[0].Trades {
|
||||
params.Set("trades", "true")
|
||||
}
|
||||
|
||||
if args[0].UserRef != 0 {
|
||||
params.Set("userref", strconv.FormatInt(int64(args[0].UserRef), 10))
|
||||
}
|
||||
|
||||
if len(args[0].Start) != 0 {
|
||||
params.Set("start", args[0].Start)
|
||||
}
|
||||
|
||||
if len(args[0].End) != 0 {
|
||||
params.Set("end", args[0].End)
|
||||
}
|
||||
|
||||
if args[0].Ofs != 0 {
|
||||
params.Set("ofs", strconv.FormatInt(args[0].Ofs, 10))
|
||||
}
|
||||
|
||||
if len(args[0].CloseTime) != 0 {
|
||||
params.Set("closetime", args[0].CloseTime)
|
||||
}
|
||||
}
|
||||
|
||||
if userref != 0 {
|
||||
values.Set("userref", strconv.FormatInt(userref, 10))
|
||||
var response struct {
|
||||
Error []string `json:"error"`
|
||||
Result ClosedOrders `json:"result"`
|
||||
}
|
||||
|
||||
if start != 0 {
|
||||
values.Set("start", strconv.FormatInt(start, 10))
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenClosedOrders, params, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
if end != 0 {
|
||||
values.Set("end", strconv.FormatInt(end, 10))
|
||||
}
|
||||
|
||||
if offset != 0 {
|
||||
values.Set("ofs", strconv.FormatInt(offset, 10))
|
||||
}
|
||||
|
||||
if len(closetime) > 0 {
|
||||
values.Set("closetime", closetime)
|
||||
}
|
||||
|
||||
return k.SendAuthenticatedHTTPRequest(krakenClosedOrders, values)
|
||||
return response.Result, GetError(response.Error)
|
||||
}
|
||||
|
||||
// QueryOrdersInfo returns order information
|
||||
func (k *Kraken) QueryOrdersInfo(showTrades bool, userref, txid int64) (interface{}, error) {
|
||||
values := url.Values{}
|
||||
|
||||
if showTrades {
|
||||
values.Set("trades", "true")
|
||||
func (k *Kraken) QueryOrdersInfo(args OrderInfoOptions, txid string, txids ...string) (map[string]OrderInfo, error) {
|
||||
params := url.Values{
|
||||
"txid": {txid},
|
||||
}
|
||||
|
||||
if userref != 0 {
|
||||
values.Set("userref", strconv.FormatInt(userref, 10))
|
||||
if txids != nil {
|
||||
params.Set("txid", txid+","+strings.Join(txids, ","))
|
||||
}
|
||||
|
||||
if txid != 0 {
|
||||
values.Set("txid", strconv.FormatInt(userref, 10))
|
||||
if args.Trades {
|
||||
params.Set("trades", "true")
|
||||
}
|
||||
|
||||
return k.SendAuthenticatedHTTPRequest(krakenQueryOrders, values)
|
||||
if args.UserRef != 0 {
|
||||
params.Set("userref", strconv.FormatInt(int64(args.UserRef), 10))
|
||||
}
|
||||
|
||||
var response struct {
|
||||
Error []string `json:"error"`
|
||||
Result map[string]OrderInfo `json:"result"`
|
||||
}
|
||||
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenQueryOrders, params, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
return response.Result, GetError(response.Error)
|
||||
}
|
||||
|
||||
// GetTradesHistory returns trade history information
|
||||
func (k *Kraken) GetTradesHistory(tradeType string, showRelatedTrades bool, start, end, offset int64) (interface{}, error) {
|
||||
values := url.Values{}
|
||||
func (k *Kraken) GetTradesHistory(args ...GetTradesHistoryOptions) (TradesHistory, error) {
|
||||
params := url.Values{}
|
||||
|
||||
if len(tradeType) > 0 {
|
||||
values.Set("aclass", tradeType)
|
||||
if args != nil {
|
||||
if len(args[0].Type) != 0 {
|
||||
params.Set("type", args[0].Type)
|
||||
}
|
||||
|
||||
if args[0].Trades {
|
||||
params.Set("trades", "true")
|
||||
}
|
||||
|
||||
if len(args[0].Start) != 0 {
|
||||
params.Set("start", args[0].Start)
|
||||
}
|
||||
|
||||
if len(args[0].End) != 0 {
|
||||
params.Set("end", args[0].End)
|
||||
}
|
||||
|
||||
if args[0].Ofs != 0 {
|
||||
params.Set("ofs", strconv.FormatInt(args[0].Ofs, 10))
|
||||
}
|
||||
}
|
||||
|
||||
if showRelatedTrades {
|
||||
values.Set("trades", "true")
|
||||
var response struct {
|
||||
Error []string `json:"error"`
|
||||
Result TradesHistory `json:"result"`
|
||||
}
|
||||
|
||||
if start != 0 {
|
||||
values.Set("start", strconv.FormatInt(start, 10))
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenTradeHistory, params, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
if end != 0 {
|
||||
values.Set("end", strconv.FormatInt(end, 10))
|
||||
}
|
||||
|
||||
if offset != 0 {
|
||||
values.Set("offset", strconv.FormatInt(offset, 10))
|
||||
}
|
||||
|
||||
return k.SendAuthenticatedHTTPRequest(krakenTradeHistory, values)
|
||||
return response.Result, GetError(response.Error)
|
||||
}
|
||||
|
||||
// QueryTrades returns information on a specific trade
|
||||
func (k *Kraken) QueryTrades(txid int64, showRelatedTrades bool) (interface{}, error) {
|
||||
values := url.Values{}
|
||||
values.Set("txid", strconv.FormatInt(txid, 10))
|
||||
|
||||
if showRelatedTrades {
|
||||
values.Set("trades", "true")
|
||||
func (k *Kraken) QueryTrades(trades bool, txid string, txids ...string) (map[string]TradeInfo, error) {
|
||||
params := url.Values{
|
||||
"txid": {txid},
|
||||
}
|
||||
|
||||
return k.SendAuthenticatedHTTPRequest(krakenQueryTrades, values)
|
||||
if trades {
|
||||
params.Set("trades", "true")
|
||||
}
|
||||
|
||||
if txids != nil {
|
||||
params.Set("txid", txid+","+strings.Join(txids, ","))
|
||||
}
|
||||
|
||||
var response struct {
|
||||
Error []string `json:"error"`
|
||||
Result map[string]TradeInfo `json:"result"`
|
||||
}
|
||||
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenQueryTrades, params, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
return response.Result, GetError(response.Error)
|
||||
}
|
||||
|
||||
// OpenPositions returns current open positions
|
||||
func (k *Kraken) OpenPositions(txid int64, showPL bool) (interface{}, error) {
|
||||
values := url.Values{}
|
||||
values.Set("txid", strconv.FormatInt(txid, 10))
|
||||
func (k *Kraken) OpenPositions(docalcs bool, txids ...string) (map[string]Position, error) {
|
||||
params := url.Values{}
|
||||
|
||||
if showPL {
|
||||
values.Set("docalcs", "true")
|
||||
if txids != nil {
|
||||
params.Set("txid", strings.Join(txids, ","))
|
||||
}
|
||||
|
||||
return k.SendAuthenticatedHTTPRequest(krakenOpenPositions, values)
|
||||
if docalcs {
|
||||
params.Set("docalcs", "true")
|
||||
}
|
||||
|
||||
var response struct {
|
||||
Error []string `json:"error"`
|
||||
Result map[string]Position `json:"result"`
|
||||
}
|
||||
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenOpenPositions, params, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
return response.Result, GetError(response.Error)
|
||||
}
|
||||
|
||||
// GetLedgers returns current ledgers
|
||||
func (k *Kraken) GetLedgers(symbol, asset, ledgerType string, start, end, offset int64) (interface{}, error) {
|
||||
values := url.Values{}
|
||||
func (k *Kraken) GetLedgers(args ...GetLedgersOptions) (Ledgers, error) {
|
||||
params := url.Values{}
|
||||
|
||||
if len(symbol) > 0 {
|
||||
values.Set("aclass", symbol)
|
||||
if args != nil {
|
||||
if len(args[0].Aclass) != 0 {
|
||||
params.Set("aclass", args[0].Aclass)
|
||||
}
|
||||
|
||||
if len(args[0].Asset) != 0 {
|
||||
params.Set("asset", args[0].Asset)
|
||||
}
|
||||
|
||||
if len(args[0].Type) != 0 {
|
||||
params.Set("type", args[0].Type)
|
||||
}
|
||||
|
||||
if len(args[0].Start) != 0 {
|
||||
params.Set("start", args[0].Start)
|
||||
}
|
||||
|
||||
if len(args[0].End) != 0 {
|
||||
params.Set("end", args[0].End)
|
||||
}
|
||||
|
||||
if args[0].Ofs != 0 {
|
||||
params.Set("ofs", strconv.FormatInt(args[0].Ofs, 10))
|
||||
}
|
||||
}
|
||||
|
||||
if len(asset) > 0 {
|
||||
values.Set("asset", asset)
|
||||
var response struct {
|
||||
Error []string `json:"error"`
|
||||
Result Ledgers `json:"result"`
|
||||
}
|
||||
|
||||
if len(ledgerType) > 0 {
|
||||
values.Set("type", ledgerType)
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenLedgers, params, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
if start != 0 {
|
||||
values.Set("start", strconv.FormatInt(start, 10))
|
||||
}
|
||||
|
||||
if end != 0 {
|
||||
values.Set("end", strconv.FormatInt(end, 10))
|
||||
}
|
||||
|
||||
if offset != 0 {
|
||||
values.Set("offset", strconv.FormatInt(offset, 10))
|
||||
}
|
||||
|
||||
return k.SendAuthenticatedHTTPRequest(krakenLedgers, values)
|
||||
return response.Result, GetError(response.Error)
|
||||
}
|
||||
|
||||
// QueryLedgers queries an individual ledger by ID
|
||||
func (k *Kraken) QueryLedgers(id string) (interface{}, error) {
|
||||
values := url.Values{}
|
||||
values.Set("id", id)
|
||||
func (k *Kraken) QueryLedgers(id string, ids ...string) (map[string]LedgerInfo, error) {
|
||||
params := url.Values{
|
||||
"id": {id},
|
||||
}
|
||||
|
||||
return k.SendAuthenticatedHTTPRequest(krakenQueryLedgers, values)
|
||||
if ids != nil {
|
||||
params.Set("id", id+","+strings.Join(ids, ","))
|
||||
}
|
||||
|
||||
var response struct {
|
||||
Error []string `json:"error"`
|
||||
Result map[string]LedgerInfo `json:"result"`
|
||||
}
|
||||
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenQueryLedgers, params, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
return response.Result, GetError(response.Error)
|
||||
}
|
||||
|
||||
// GetTradeVolume returns your trade volume by currency
|
||||
func (k *Kraken) GetTradeVolume(symbol string) (interface{}, error) {
|
||||
values := url.Values{}
|
||||
values.Set("pair", symbol)
|
||||
func (k *Kraken) GetTradeVolume(feeinfo bool, symbol ...string) (TradeVolumeResponse, error) {
|
||||
params := url.Values{}
|
||||
|
||||
return k.SendAuthenticatedHTTPRequest(krakenTradeVolume, values)
|
||||
if symbol != nil {
|
||||
params.Set("pair", strings.Join(symbol, ","))
|
||||
}
|
||||
|
||||
if feeinfo {
|
||||
params.Set("fee-info", "true")
|
||||
}
|
||||
|
||||
var response struct {
|
||||
Error []string `json:"error"`
|
||||
Result TradeVolumeResponse `json:"result"`
|
||||
}
|
||||
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenTradeVolume, params, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
return response.Result, GetError(response.Error)
|
||||
}
|
||||
|
||||
// AddOrder adds a new order for Kraken exchange
|
||||
func (k *Kraken) AddOrder(symbol, side, orderType string, price, price2, volume, leverage, position float64) (interface{}, error) {
|
||||
values := url.Values{}
|
||||
values.Set("pairs", symbol)
|
||||
values.Set("type", side)
|
||||
values.Set("ordertype", orderType)
|
||||
values.Set("price", strconv.FormatFloat(price, 'f', -1, 64))
|
||||
values.Set("price2", strconv.FormatFloat(price, 'f', -1, 64))
|
||||
values.Set("volume", strconv.FormatFloat(volume, 'f', -1, 64))
|
||||
values.Set("leverage", strconv.FormatFloat(leverage, 'f', -1, 64))
|
||||
values.Set("position", strconv.FormatFloat(position, 'f', -1, 64))
|
||||
func (k *Kraken) AddOrder(symbol, side, orderType string, volume, price, price2, leverage float64, args AddOrderOptions) (AddOrderResponse, error) {
|
||||
params := url.Values{
|
||||
"pair": {symbol},
|
||||
"type": {side},
|
||||
"ordertype": {orderType},
|
||||
"volume": {strconv.FormatFloat(volume, 'f', -1, 64)},
|
||||
}
|
||||
|
||||
return k.SendAuthenticatedHTTPRequest(krakenOrderPlace, values)
|
||||
if price != 0 {
|
||||
params.Set("price", strconv.FormatFloat(price, 'f', -1, 64))
|
||||
}
|
||||
|
||||
if price2 != 0 {
|
||||
params.Set("price2", strconv.FormatFloat(price2, 'f', -1, 64))
|
||||
}
|
||||
|
||||
if leverage != 0 {
|
||||
params.Set("leverage", strconv.FormatFloat(leverage, 'f', -1, 64))
|
||||
}
|
||||
|
||||
if len(args.Oflags) != 0 {
|
||||
params.Set("oflags", args.Oflags)
|
||||
}
|
||||
|
||||
if len(args.StartTm) != 0 {
|
||||
params.Set("starttm", args.StartTm)
|
||||
}
|
||||
|
||||
if len(args.ExpireTm) != 0 {
|
||||
params.Set("expiretm", args.ExpireTm)
|
||||
}
|
||||
|
||||
if len(args.CloseOrderType) != 0 {
|
||||
params.Set("close[ordertype]", args.ExpireTm)
|
||||
}
|
||||
|
||||
if args.ClosePrice != 0 {
|
||||
params.Set("close[price]", strconv.FormatFloat(args.ClosePrice, 'f', -1, 64))
|
||||
}
|
||||
|
||||
if args.ClosePrice2 != 0 {
|
||||
params.Set("close[price2]", strconv.FormatFloat(args.ClosePrice2, 'f', -1, 64))
|
||||
}
|
||||
|
||||
if args.Validate {
|
||||
params.Set("validate", "true")
|
||||
}
|
||||
|
||||
var response struct {
|
||||
Error []string `json:"error"`
|
||||
Result AddOrderResponse `json:"result"`
|
||||
}
|
||||
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenOrderPlace, params, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
return response.Result, GetError(response.Error)
|
||||
}
|
||||
|
||||
// CancelOrder cancels order by orderID
|
||||
func (k *Kraken) CancelOrder(orderID int64) (interface{}, error) {
|
||||
values := url.Values{}
|
||||
values.Set("txid", strconv.FormatInt(orderID, 10))
|
||||
func (k *Kraken) CancelOrder(txid string) (CancelOrderResponse, error) {
|
||||
values := url.Values{
|
||||
"txid": {txid},
|
||||
}
|
||||
|
||||
return k.SendAuthenticatedHTTPRequest(krakenOrderCancel, values)
|
||||
var response struct {
|
||||
Error []string `json:"error"`
|
||||
Result CancelOrderResponse `json:"result"`
|
||||
}
|
||||
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenOrderCancel, values, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
return response.Result, GetError(response.Error)
|
||||
}
|
||||
|
||||
// GetError parse Exchange errors in response and return the first one
|
||||
// Error format from API doc:
|
||||
// error = array of error messages in the format of:
|
||||
// <char-severity code><string-error category>:<string-error type>[:<string-extra info>]
|
||||
// severity code can be E for error or W for warning
|
||||
func GetError(errors []string) error {
|
||||
|
||||
for _, e := range errors {
|
||||
switch e[0] {
|
||||
case 'W':
|
||||
log.Printf("Kraken API warning: %v\n", e[1:])
|
||||
default:
|
||||
return fmt.Errorf("Kraken API error: %v", e[1:])
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP requests
|
||||
@@ -581,9 +807,9 @@ func (k *Kraken) SendHTTPRequest(path string, result interface{}) error {
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request
|
||||
func (k *Kraken) SendAuthenticatedHTTPRequest(method string, values url.Values) (interface{}, error) {
|
||||
func (k *Kraken) SendAuthenticatedHTTPRequest(method string, params url.Values, result interface{}) (err error) {
|
||||
if !k.AuthenticatedAPISupport {
|
||||
return nil, fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, k.Name)
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, k.Name)
|
||||
}
|
||||
|
||||
path := fmt.Sprintf("/%s/private/%s", krakenAPIVersion, method)
|
||||
@@ -593,35 +819,24 @@ func (k *Kraken) SendAuthenticatedHTTPRequest(method string, values url.Values)
|
||||
k.Nonce.Inc()
|
||||
}
|
||||
|
||||
values.Set("nonce", k.Nonce.String())
|
||||
params.Set("nonce", k.Nonce.String())
|
||||
|
||||
secret, err := common.Base64Decode(k.APISecret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
shasum := common.GetSHA256([]byte(values.Get("nonce") + values.Encode()))
|
||||
encoded := params.Encode()
|
||||
shasum := common.GetSHA256([]byte(params.Get("nonce") + encoded))
|
||||
signature := common.Base64Encode(common.GetHMAC(common.HashSHA512, append([]byte(path), shasum...), secret))
|
||||
|
||||
if k.Verbose {
|
||||
log.Printf("Sending POST request to %s, path: %s.", krakenAPIURL, path)
|
||||
log.Printf("Sending POST request to %s, path: %s, params: %s", krakenAPIURL, path, encoded)
|
||||
}
|
||||
|
||||
headers := make(map[string]string)
|
||||
headers["API-Key"] = k.APIKey
|
||||
headers["API-Sign"] = signature
|
||||
|
||||
var resp interface{}
|
||||
|
||||
err = k.SendPayload("POST", krakenAPIURL+path, headers, strings.NewReader(values.Encode()), &resp, true, k.Verbose)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
data := resp.(map[string]interface{})
|
||||
if len(data["error"].([]interface{})) != 0 {
|
||||
return nil, fmt.Errorf("kraken AuthenticattedHTTPRequest error: %s", data["error"])
|
||||
}
|
||||
|
||||
return data["result"].(interface{}), nil
|
||||
return k.SendPayload("POST", krakenAPIURL+path, headers, strings.NewReader(encoded), result, true, k.Verbose)
|
||||
}
|
||||
|
||||
@@ -47,11 +47,7 @@ func TestGetFee(t *testing.T) {
|
||||
|
||||
func TestGetServerTime(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := k.GetServerTime(false)
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetServerTime() error", err)
|
||||
}
|
||||
_, err = k.GetServerTime(true)
|
||||
_, err := k.GetServerTime()
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetServerTime() error", err)
|
||||
}
|
||||
@@ -123,7 +119,8 @@ func TestGetBalance(t *testing.T) {
|
||||
|
||||
func TestGetTradeBalance(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := k.GetTradeBalance("", "")
|
||||
args := TradeBalanceOptions{Asset: "ZEUR"}
|
||||
_, err := k.GetTradeBalance(args)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetTradeBalance() error", err)
|
||||
}
|
||||
@@ -131,7 +128,8 @@ func TestGetTradeBalance(t *testing.T) {
|
||||
|
||||
func TestGetOpenOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := k.GetOpenOrders(true, 0)
|
||||
args := OrderInfoOptions{Trades: true}
|
||||
_, err := k.GetOpenOrders(args)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetOpenOrders() error", err)
|
||||
}
|
||||
@@ -139,7 +137,8 @@ func TestGetOpenOrders(t *testing.T) {
|
||||
|
||||
func TestGetClosedOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := k.GetClosedOrders(true, 0, 0, 0, 0, "")
|
||||
args := GetClosedOrdersOptions{Trades: true, Start: "OE4KV4-4FVQ5-V7XGPU"}
|
||||
_, err := k.GetClosedOrders(args)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetClosedOrders() error", err)
|
||||
}
|
||||
@@ -147,7 +146,8 @@ func TestGetClosedOrders(t *testing.T) {
|
||||
|
||||
func TestQueryOrdersInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := k.QueryOrdersInfo(false, 0, 0)
|
||||
args := OrderInfoOptions{Trades: true}
|
||||
_, err := k.QueryOrdersInfo(args, "OR6ZFV-AA6TT-CKFFIW", "OAMUAJ-HLVKG-D3QJ5F")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - QueryOrdersInfo() error", err)
|
||||
}
|
||||
@@ -155,7 +155,8 @@ func TestQueryOrdersInfo(t *testing.T) {
|
||||
|
||||
func TestGetTradesHistory(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := k.GetTradesHistory("", false, 0, 0, 0)
|
||||
args := GetTradesHistoryOptions{Trades: true, Start: "TMZEDR-VBJN2-NGY6DX", End: "TVRXG2-R62VE-RWP3UW"}
|
||||
_, err := k.GetTradesHistory(args)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetTradesHistory() error", err)
|
||||
}
|
||||
@@ -163,7 +164,7 @@ func TestGetTradesHistory(t *testing.T) {
|
||||
|
||||
func TestQueryTrades(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := k.QueryTrades(0, false)
|
||||
_, err := k.QueryTrades(true, "TMZEDR-VBJN2-NGY6DX", "TFLWIB-KTT7L-4TWR3L", "TDVRAH-2H6OS-SLSXRX")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - QueryTrades() error", err)
|
||||
}
|
||||
@@ -171,7 +172,7 @@ func TestQueryTrades(t *testing.T) {
|
||||
|
||||
func TestOpenPositions(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := k.OpenPositions(0, false)
|
||||
_, err := k.OpenPositions(false)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - OpenPositions() error", err)
|
||||
}
|
||||
@@ -179,7 +180,8 @@ func TestOpenPositions(t *testing.T) {
|
||||
|
||||
func TestGetLedgers(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := k.GetLedgers("bla", "bla", "bla", 0, 0, 0)
|
||||
args := GetLedgersOptions{Start: "LRUHXI-IWECY-K4JYGO", End: "L5NIY7-JZQJD-3J4M2V", Ofs: 15}
|
||||
_, err := k.GetLedgers(args)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetLedgers() error", err)
|
||||
}
|
||||
@@ -187,7 +189,7 @@ func TestGetLedgers(t *testing.T) {
|
||||
|
||||
func TestQueryLedgers(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := k.QueryLedgers("1337")
|
||||
_, err := k.QueryLedgers("LVTSFS-NHZVM-EXNZ5M")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - QueryLedgers() error", err)
|
||||
}
|
||||
@@ -195,7 +197,7 @@ func TestQueryLedgers(t *testing.T) {
|
||||
|
||||
func TestGetTradeVolume(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := k.GetTradeVolume("BCHEUR")
|
||||
_, err := k.GetTradeVolume(true, "OAVY7T-MV5VK-KHDF5X")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetTradeVolume() error", err)
|
||||
}
|
||||
@@ -203,7 +205,8 @@ func TestGetTradeVolume(t *testing.T) {
|
||||
|
||||
func TestAddOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := k.AddOrder("bla", "bla", "bla", 0, 0, 0, 0, 0)
|
||||
args := AddOrderOptions{Oflags: "fcib"}
|
||||
_, err := k.AddOrder("XXBTZUSD", "sell", "market", 0.00000001, 0, 0, 0, args)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - AddOrder() error", err)
|
||||
}
|
||||
@@ -211,7 +214,7 @@ func TestAddOrder(t *testing.T) {
|
||||
|
||||
func TestCancelOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := k.CancelOrder(1337)
|
||||
_, err := k.CancelOrder("OAVY7T-MV5VK-KHDF5X")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - CancelOrder() error", err)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
package kraken
|
||||
|
||||
// GeneralResponse is a generalized response type
|
||||
type GeneralResponse struct {
|
||||
Result map[string]interface{} `json:"result"`
|
||||
Error []interface{} `json:"error"`
|
||||
// TimeResponse type
|
||||
type TimeResponse struct {
|
||||
Unixtime int64 `json:"unixtime"`
|
||||
Rfc1123 string `json:"rfc1123"`
|
||||
}
|
||||
|
||||
// Asset holds asset information
|
||||
type Asset struct {
|
||||
Altname string `json:"altname"`
|
||||
AclassBase string `json:"aclass_base"`
|
||||
Decimals int `json:"decimals"`
|
||||
DisplayDecimals int `json:"display_decimals"`
|
||||
}
|
||||
|
||||
// AssetPairs holds asset pair information
|
||||
@@ -92,3 +100,211 @@ type Spread struct {
|
||||
Bid float64
|
||||
Ask float64
|
||||
}
|
||||
|
||||
// TradeBalanceOptions type
|
||||
type TradeBalanceOptions struct {
|
||||
Aclass string
|
||||
Asset string
|
||||
}
|
||||
|
||||
// TradeBalanceInfo type
|
||||
type TradeBalanceInfo struct {
|
||||
EquivalentBalance float64 `json:"eb,string"` // combined balance of all currencies
|
||||
TradeBalance float64 `json:"tb,string"` // combined balance of all equity currencies
|
||||
MarginAmount float64 `json:"m,string"` // margin amount of open positions
|
||||
Net float64 `json:"n,string"` // unrealized net profit/loss of open positions
|
||||
Equity float64 `json:"e,string"` // trade balance + unrealized net profit/loss
|
||||
FreeMargin float64 `json:"mf,string"` // equity - initial margin (maximum margin available to open new positions)
|
||||
MarginLevel float64 `json:"ml,string"` // (equity / initial margin) * 100
|
||||
}
|
||||
|
||||
// OrderInfo type
|
||||
type OrderInfo struct {
|
||||
RefID string `json:"refid"`
|
||||
UserRef int32 `json:"userref"`
|
||||
Status string `json:"status"`
|
||||
OpenTm float64 `json:"opentm"`
|
||||
StartTm float64 `json:"starttm"`
|
||||
ExpireTm float64 `json:"expiretm"`
|
||||
Descr struct {
|
||||
Pair string `json:"pair"`
|
||||
Type string `json:"type"`
|
||||
OrderType string `json:"ordertype"`
|
||||
Price float64 `json:"price,string"`
|
||||
Price2 float64 `json:"price2,string"`
|
||||
Leverage string `json:"leverage"`
|
||||
Order string `json:"order"`
|
||||
Close string `json:"close"`
|
||||
} `json:"descr"`
|
||||
Vol float64 `json:"vol,string"`
|
||||
VolExec float64 `json:"vol_exec,string"`
|
||||
Cost float64 `json:"cost,string"`
|
||||
Fee float64 `json:"fee,string"`
|
||||
Price float64 `json:"price,string"`
|
||||
StopPrice float64 `json:"stopprice,string"`
|
||||
LimitPrice float64 `json:"limitprice,string"`
|
||||
Misc string `json:"misc"`
|
||||
Oflags string `json:"oflags"`
|
||||
Trades []string `json:"trades"`
|
||||
}
|
||||
|
||||
// OpenOrders type
|
||||
type OpenOrders struct {
|
||||
Open map[string]OrderInfo `json:"open"`
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
// ClosedOrders type
|
||||
type ClosedOrders struct {
|
||||
Closed map[string]OrderInfo `json:"closed"`
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
// GetClosedOrdersOptions type
|
||||
type GetClosedOrdersOptions struct {
|
||||
Trades bool
|
||||
UserRef int32
|
||||
Start string
|
||||
End string
|
||||
Ofs int64
|
||||
CloseTime string
|
||||
}
|
||||
|
||||
// OrderInfoOptions type
|
||||
type OrderInfoOptions struct {
|
||||
Trades bool
|
||||
UserRef int32
|
||||
}
|
||||
|
||||
// GetTradesHistoryOptions type
|
||||
type GetTradesHistoryOptions struct {
|
||||
Type string
|
||||
Trades bool
|
||||
Start string
|
||||
End string
|
||||
Ofs int64
|
||||
}
|
||||
|
||||
// TradesHistory type
|
||||
type TradesHistory struct {
|
||||
Trades map[string]TradeInfo `json:"trades"`
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
// TradeInfo type
|
||||
type TradeInfo struct {
|
||||
OrderTxID string `json:"ordertxid"`
|
||||
Pair string `json:"pair"`
|
||||
Time float64 `json:"time"`
|
||||
Type string `json:"type"`
|
||||
OrderType string `json:"ordertype"`
|
||||
Price float64 `json:"price,string"`
|
||||
Cost float64 `json:"cost,string"`
|
||||
Fee float64 `json:"fee,string"`
|
||||
Vol float64 `json:"vol,string"`
|
||||
Margin float64 `json:"margin,string"`
|
||||
Misc string `json:"misc"`
|
||||
PosTxID string `json:"postxid"`
|
||||
Cprice float64 `json:"cprice,string"`
|
||||
Cfee float64 `json:"cfee,string"`
|
||||
Cvol float64 `json:"cvol,string"`
|
||||
Cmargin float64 `json:"cmargin,string"`
|
||||
Trades []string `json:"trades"`
|
||||
PosStatus string `json:"posstatus"`
|
||||
}
|
||||
|
||||
// Position holds the opened position
|
||||
type Position struct {
|
||||
Ordertxid string `json:"ordertxid"`
|
||||
Pair string `json:"pair"`
|
||||
Time float64 `json:"time"`
|
||||
Type string `json:"type"`
|
||||
OrderType string `json:"ordertype"`
|
||||
Cost float64 `json:"cost,string"`
|
||||
Fee float64 `json:"fee,string"`
|
||||
Vol float64 `json:"vol,string"`
|
||||
VolClosed float64 `json:"vol_closed,string"`
|
||||
Margin float64 `json:"margin,string"`
|
||||
Rollovertm int64 `json:"rollovertm,string"`
|
||||
Misc string `json:"misc"`
|
||||
Oflags string `json:"oflags"`
|
||||
PosStatus string `json:"posstatus"`
|
||||
Net string `json:"net"`
|
||||
Terms string `json:"terms"`
|
||||
}
|
||||
|
||||
// GetLedgersOptions type
|
||||
type GetLedgersOptions struct {
|
||||
Aclass string
|
||||
Asset string
|
||||
Type string
|
||||
Start string
|
||||
End string
|
||||
Ofs int64
|
||||
}
|
||||
|
||||
// Ledgers type
|
||||
type Ledgers struct {
|
||||
Ledger map[string]LedgerInfo `json:"ledger"`
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
// LedgerInfo type
|
||||
type LedgerInfo struct {
|
||||
Refid string `json:"refid"`
|
||||
Time float64 `json:"time"`
|
||||
Type string `json:"type"`
|
||||
Aclass string `json:"aclass"`
|
||||
Asset string `json:"asset"`
|
||||
Amount float64 `json:"amount,string"`
|
||||
Fee float64 `json:"fee,string"`
|
||||
Balance float64 `json:"balance,string"`
|
||||
}
|
||||
|
||||
// TradeVolumeResponse type
|
||||
type TradeVolumeResponse struct {
|
||||
Currency string `json:"currency"`
|
||||
Volume float64 `json:"volume,string"`
|
||||
Fees map[string]TradeVolumeFee `json:"fees"`
|
||||
FeesMaker map[string]TradeVolumeFee `json:"fees_maker"`
|
||||
}
|
||||
|
||||
// TradeVolumeFee type
|
||||
type TradeVolumeFee struct {
|
||||
Fee float64 `json:"fee,string"`
|
||||
MinFee float64 `json:"minfee,string"`
|
||||
MaxFee float64 `json:"maxfee,string"`
|
||||
NextFee float64 `json:"nextfee,string"`
|
||||
NextVolume float64 `json:"nextvolume,string"`
|
||||
TierVolume float64 `json:"tiervolume,string"`
|
||||
}
|
||||
|
||||
// AddOrderResponse type
|
||||
type AddOrderResponse struct {
|
||||
Description OrderDescription `json:"descr"`
|
||||
TransactionIds []string `json:"txid"`
|
||||
}
|
||||
|
||||
// OrderDescription represents an orders description
|
||||
type OrderDescription struct {
|
||||
Close string `json:"close"`
|
||||
Order string `json:"order"`
|
||||
}
|
||||
|
||||
// AddOrderOptions represents the AddOrder options
|
||||
type AddOrderOptions struct {
|
||||
UserRef int32
|
||||
Oflags string
|
||||
StartTm string
|
||||
ExpireTm string
|
||||
CloseOrderType string
|
||||
ClosePrice float64
|
||||
ClosePrice2 float64
|
||||
Validate bool
|
||||
}
|
||||
|
||||
// CancelOrderResponse type
|
||||
type CancelOrderResponse struct {
|
||||
Count int64 `json:"count"`
|
||||
Pending interface{} `json:"pending"`
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ func (l *LakeBTC) Setup(exch config.ExchangeConfig) {
|
||||
l.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
l.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
|
||||
l.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
l.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
l.RESTPollingDelay = exch.RESTPollingDelay
|
||||
l.Verbose = exch.Verbose
|
||||
l.Websocket = exch.Websocket
|
||||
|
||||
@@ -73,6 +73,7 @@ func (l *Liqui) Setup(exch config.ExchangeConfig) {
|
||||
l.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
l.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
|
||||
l.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
l.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
l.RESTPollingDelay = exch.RESTPollingDelay
|
||||
l.Verbose = exch.Verbose
|
||||
l.Websocket = exch.Websocket
|
||||
|
||||
@@ -136,6 +136,7 @@ func (l *LocalBitcoins) Setup(exch config.ExchangeConfig) {
|
||||
l.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
l.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
|
||||
l.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
l.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
l.RESTPollingDelay = exch.RESTPollingDelay
|
||||
l.Verbose = exch.Verbose
|
||||
l.Websocket = exch.Websocket
|
||||
@@ -341,37 +342,57 @@ func (l *LocalBitcoins) GetCurrencies() error {
|
||||
// view contacts where the token owner is either buying or selling, respectively.
|
||||
// E.g. /api/dashboard/buyer/. All contacts where the token owner is
|
||||
// participating are returned.
|
||||
func (l *LocalBitcoins) GetDashboardInfo() (DashBoardInfo, error) {
|
||||
resp := DashBoardInfo{}
|
||||
func (l *LocalBitcoins) GetDashboardInfo() ([]DashBoardInfo, error) {
|
||||
var resp struct {
|
||||
Data struct {
|
||||
ContactList []DashBoardInfo `json:"contact_list"`
|
||||
ContactCount int `json:"contact_count"`
|
||||
}
|
||||
}
|
||||
|
||||
return resp,
|
||||
return resp.Data.ContactList,
|
||||
l.SendAuthenticatedHTTPRequest("GET", localbitcoinsAPIDashboard, nil, &resp)
|
||||
}
|
||||
|
||||
// GetDashboardReleasedTrades returns a list of all released trades where the
|
||||
// token owner is either a buyer or seller.
|
||||
func (l *LocalBitcoins) GetDashboardReleasedTrades() (DashBoardInfo, error) {
|
||||
resp := DashBoardInfo{}
|
||||
func (l *LocalBitcoins) GetDashboardReleasedTrades() ([]DashBoardInfo, error) {
|
||||
var resp struct {
|
||||
Data struct {
|
||||
ContactList []DashBoardInfo `json:"contact_list"`
|
||||
ContactCount int `json:"contact_count"`
|
||||
}
|
||||
}
|
||||
|
||||
return resp,
|
||||
return resp.Data.ContactList,
|
||||
l.SendAuthenticatedHTTPRequest("GET", localbitcoinsAPIDashboardReleased, nil, &resp)
|
||||
}
|
||||
|
||||
// GetDashboardCancelledTrades returns a list of all canceled trades where the
|
||||
// token owner is either a buyer or seller.
|
||||
func (l *LocalBitcoins) GetDashboardCancelledTrades() (DashBoardInfo, error) {
|
||||
resp := DashBoardInfo{}
|
||||
func (l *LocalBitcoins) GetDashboardCancelledTrades() ([]DashBoardInfo, error) {
|
||||
var resp struct {
|
||||
Data struct {
|
||||
ContactList []DashBoardInfo `json:"contact_list"`
|
||||
ContactCount int `json:"contact_count"`
|
||||
}
|
||||
}
|
||||
|
||||
return resp,
|
||||
return resp.Data.ContactList,
|
||||
l.SendAuthenticatedHTTPRequest("GET", localbitcoinsAPIDashboardCancelled, nil, &resp)
|
||||
}
|
||||
|
||||
// GetDashboardClosedTrades returns a list of all closed trades where the token
|
||||
// owner is either a buyer or seller.
|
||||
func (l *LocalBitcoins) GetDashboardClosedTrades() (DashBoardInfo, error) {
|
||||
resp := DashBoardInfo{}
|
||||
func (l *LocalBitcoins) GetDashboardClosedTrades() ([]DashBoardInfo, error) {
|
||||
var resp struct {
|
||||
Data struct {
|
||||
ContactList []DashBoardInfo `json:"contact_list"`
|
||||
ContactCount int `json:"contact_count"`
|
||||
}
|
||||
}
|
||||
|
||||
return resp,
|
||||
return resp.Data.ContactList,
|
||||
l.SendAuthenticatedHTTPRequest("GET", localbitcoinsAPIDashboardClosed, nil, &resp)
|
||||
}
|
||||
|
||||
|
||||
@@ -189,7 +189,7 @@ type DashBoardInfo struct {
|
||||
Buyer struct {
|
||||
Username string `json:"username"`
|
||||
TradeCount string `json:"trade_count"`
|
||||
FeedbackScore string `json:"feedback_score"`
|
||||
FeedbackScore int `json:"feedback_score"`
|
||||
Name string `json:"name"`
|
||||
LastOnline string `json:"last_online"`
|
||||
RealName string `json:"real_name"`
|
||||
@@ -200,7 +200,7 @@ type DashBoardInfo struct {
|
||||
Seller struct {
|
||||
Username string `json:"username"`
|
||||
TradeCount string `json:"trade_count"`
|
||||
FeedbackScore string `json:"feedback_score"`
|
||||
FeedbackScore int `json:"feedback_score"`
|
||||
Name string `json:"name"`
|
||||
LastOnline string `json:"last_online"`
|
||||
} `json:"seller"`
|
||||
@@ -216,7 +216,7 @@ type DashBoardInfo struct {
|
||||
Advertiser struct {
|
||||
Username string `json:"username"`
|
||||
TradeCount string `json:"trade_count"`
|
||||
FeedbackScore string `json:"feedback_score"`
|
||||
FeedbackScore int `json:"feedback_score"`
|
||||
Name string `json:"name"`
|
||||
LastOnline string `json:"last_online"`
|
||||
} `json:"advertiser"`
|
||||
|
||||
@@ -132,6 +132,7 @@ func (o *OKCoin) Setup(exch config.ExchangeConfig) {
|
||||
o.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
o.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
|
||||
o.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
o.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
o.RESTPollingDelay = exch.RESTPollingDelay
|
||||
o.Verbose = exch.Verbose
|
||||
o.Websocket = exch.Websocket
|
||||
|
||||
@@ -120,6 +120,7 @@ func (o *OKEX) Setup(exch config.ExchangeConfig) {
|
||||
o.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
o.SetAPIKeys(exch.APIKey, exch.APISecret, exch.ClientID, false)
|
||||
o.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
o.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
o.RESTPollingDelay = exch.RESTPollingDelay
|
||||
o.Verbose = exch.Verbose
|
||||
o.Websocket = exch.Websocket
|
||||
|
||||
@@ -84,6 +84,7 @@ func (p *Poloniex) Setup(exch config.ExchangeConfig) {
|
||||
p.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
p.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
|
||||
p.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
p.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
p.RESTPollingDelay = exch.RESTPollingDelay
|
||||
p.Verbose = exch.Verbose
|
||||
p.Websocket = exch.Websocket
|
||||
|
||||
@@ -25,6 +25,7 @@ type Requester struct {
|
||||
UnauthLimit *RateLimit
|
||||
AuthLimit *RateLimit
|
||||
Name string
|
||||
UserAgent string
|
||||
Cycle time.Time
|
||||
m sync.Mutex
|
||||
Jobs chan Job
|
||||
@@ -230,6 +231,10 @@ func (r *Requester) checkRequest(method, path string, body io.Reader, headers ma
|
||||
req.Header.Add(k, v)
|
||||
}
|
||||
|
||||
if r.UserAgent != "" && req.Header.Get("User-Agent") == "" {
|
||||
req.Header.Add("User-Agent", r.UserAgent)
|
||||
}
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
@@ -245,7 +250,6 @@ func (r *Requester) DoRequest(req *http.Request, method, path string, headers ma
|
||||
if r.RequiresRateLimiter() {
|
||||
r.DecrementRequests(authRequest)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
if resp == nil {
|
||||
|
||||
@@ -76,6 +76,7 @@ func (w *WEX) Setup(exch config.ExchangeConfig) {
|
||||
w.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
w.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
|
||||
w.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
w.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
w.RESTPollingDelay = exch.RESTPollingDelay
|
||||
w.Verbose = exch.Verbose
|
||||
w.Websocket = exch.Websocket
|
||||
|
||||
@@ -82,6 +82,7 @@ func (y *Yobit) Setup(exch config.ExchangeConfig) {
|
||||
y.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",")
|
||||
y.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",")
|
||||
y.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
y.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
err := y.SetCurrencyPairFormat()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
||||
@@ -1,9 +1,140 @@
|
||||
# GoCryptoTrader package zb
|
||||
# GoCryptoTrader package Zb
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
|
||||
|
||||
[](https://travis-ci.org/thrasher-/gocryptotrader)
|
||||
[](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/zb)
|
||||
[](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
|
||||
|
||||
|
||||
This zb package is part of the GoCryptoTrader codebase.
|
||||
|
||||
## ZB Exchange
|
||||
## This is still in active development
|
||||
|
||||
You can track ideas, planned features and what's in progresss on this Trello board: [https://trello.com/b/ZAhMhpOy/gocryptotrader](https://trello.com/b/ZAhMhpOy/gocryptotrader).
|
||||
|
||||
Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader Slack](https://gocryptotrader.herokuapp.com/)
|
||||
|
||||
## ZB Exchange
|
||||
|
||||
### Current Features
|
||||
|
||||
ZB 交易所的支持,支持获取K线、买/卖订单、取消订单
|
||||
+ REST functions
|
||||
|
||||
### How to enable
|
||||
|
||||
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
|
||||
+ Individual package example below:
|
||||
|
||||
```go
|
||||
// Exchanges will be abstracted out in further updates and examples will be
|
||||
// supplied then
|
||||
```
|
||||
|
||||
### How to do REST public/private calls
|
||||
|
||||
+ If enabled via "configuration".json file the exchange will be added to the
|
||||
IBotExchange array in the ```go var bot Bot``` and you will only be able to use
|
||||
the wrapper interface functions for accessing exchange data. View routines.go
|
||||
for an example of integration usage with GoCryptoTrader. Rudimentary example
|
||||
below:
|
||||
|
||||
main.go
|
||||
```go
|
||||
var z exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "ZB" {
|
||||
z = bot.exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := z.GetTickerPrice()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := z.GetOrderbookEx()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Private calls - wrapper functions - make sure your APIKEY and APISECRET are
|
||||
// set and AuthenticatedAPISupport is set to true
|
||||
|
||||
// Fetches current account information
|
||||
accountInfo, err := z.GetExchangeAccountInfo()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
+ If enabled via individually importing package, rudimentary example below:
|
||||
|
||||
```go
|
||||
// Public calls
|
||||
|
||||
// Fetches current ticker information
|
||||
ticker, err := z.GetTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := z.GetOrderBook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Private calls - make sure your APIKEY and APISECRET are set and
|
||||
// AuthenticatedAPISupport is set to true
|
||||
|
||||
// GetUserInfo returns account info
|
||||
accountInfo, err := z.GetUserInfo(...)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Submits an order and the exchange and returns its tradeID
|
||||
tradeID, err := z.Trade(...)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
### How to do LongPolling public/private calls
|
||||
|
||||
```go
|
||||
// Exchanges will be abstracted out in further updates and examples will be
|
||||
// supplied then
|
||||
```
|
||||
|
||||
### Please click GoDocs chevron above to view current GoDoc information for this package
|
||||
|
||||
## Contribution
|
||||
|
||||
Please feel free to submit any pull requests or suggest any desired features to be added.
|
||||
|
||||
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).
|
||||
+ 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">
|
||||
|
||||
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
|
||||
|
||||
***1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB***
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@ func (z *ZB) Setup(exch config.ExchangeConfig) {
|
||||
z.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
|
||||
z.APIAuthPEMKey = exch.APIAuthPEMKey
|
||||
z.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
z.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
z.RESTPollingDelay = exch.RESTPollingDelay
|
||||
z.Verbose = exch.Verbose
|
||||
z.Websocket = exch.Websocket
|
||||
@@ -303,9 +304,6 @@ func (z *ZB) SendAuthenticatedHTTPRequest(method, endpoint string, values url.Va
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, z.Name)
|
||||
}
|
||||
|
||||
headers := make(map[string]string)
|
||||
headers["User-Agent"] = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36"
|
||||
|
||||
mapParams2Sign := url.Values{}
|
||||
mapParams2Sign.Set("accesskey", z.APIKey)
|
||||
mapParams2Sign.Set("method", values.Get("method"))
|
||||
@@ -314,5 +312,5 @@ func (z *ZB) SendAuthenticatedHTTPRequest(method, endpoint string, values url.Va
|
||||
|
||||
url := fmt.Sprintf("%s/%s?%s", zbMarketURL, endpoint, values.Encode())
|
||||
|
||||
return z.SendPayload(method, url, headers, strings.NewReader(""), result, true, z.Verbose)
|
||||
return z.SendPayload(method, url, nil, strings.NewReader(""), result, true, z.Verbose)
|
||||
}
|
||||
|
||||
1815
testdata/configtest.json
vendored
1815
testdata/configtest.json
vendored
File diff suppressed because one or more lines are too long
@@ -52,6 +52,7 @@ const (
|
||||
bitfinex = "..%s..%sexchanges%sbitfinex%s"
|
||||
bitflyer = "..%s..%sexchanges%sbitflyer%s"
|
||||
bithumb = "..%s..%sexchanges%sbithumb%s"
|
||||
bitmex = "..%s..%sexchanges%sbitmex%s"
|
||||
bitstamp = "..%s..%sexchanges%sbitstamp%s"
|
||||
bittrex = "..%s..%sexchanges%sbittrex%s"
|
||||
btcc = "..%s..%sexchanges%sbtcc%s"
|
||||
@@ -59,9 +60,11 @@ const (
|
||||
coinbasepro = "..%s..%sexchanges%scoinbasepro%s"
|
||||
coinut = "..%s..%sexchanges%scoinut%s"
|
||||
exmo = "..%s..%sexchanges%sexmo%s"
|
||||
gateio = "..%s..%sexchanges%sgateio%s"
|
||||
gemini = "..%s..%sexchanges%sgemini%s"
|
||||
hitbtc = "..%s..%sexchanges%shitbtc%s"
|
||||
huobi = "..%s..%sexchanges%shuobi%s"
|
||||
huobihadax = "..%s..%sexchanges%shuobihadax%s"
|
||||
itbit = "..%s..%sexchanges%sitbit%s"
|
||||
kraken = "..%s..%sexchanges%skraken%s"
|
||||
lakebtc = "..%s..%sexchanges%slakebtc%s"
|
||||
@@ -72,6 +75,7 @@ const (
|
||||
poloniex = "..%s..%sexchanges%spoloniex%s"
|
||||
wex = "..%s..%sexchanges%swex%s"
|
||||
yobit = "..%s..%sexchanges%syobit%s"
|
||||
zb = "..%s..%sexchanges%szb%s"
|
||||
|
||||
contributorsList = "https://api.github.com/repos/thrasher-/gocryptotrader/contributors"
|
||||
|
||||
@@ -223,6 +227,7 @@ func addPaths() {
|
||||
codebasePaths["exchanges bitfinex"] = fmt.Sprintf(bitfinex, path, path, path, path)
|
||||
codebasePaths["exchanges bitflyer"] = fmt.Sprintf(bitflyer, path, path, path, path)
|
||||
codebasePaths["exchanges bithumb"] = fmt.Sprintf(bithumb, path, path, path, path)
|
||||
codebasePaths["exchanges bitmex"] = fmt.Sprintf(bitmex, path, path, path, path)
|
||||
codebasePaths["exchanges bitstamp"] = fmt.Sprintf(bitstamp, path, path, path, path)
|
||||
codebasePaths["exchanges bittrex"] = fmt.Sprintf(bittrex, path, path, path, path)
|
||||
codebasePaths["exchanges btcc"] = fmt.Sprintf(btcc, path, path, path, path)
|
||||
@@ -230,9 +235,11 @@ func addPaths() {
|
||||
codebasePaths["exchanges coinut"] = fmt.Sprintf(coinut, path, path, path, path)
|
||||
codebasePaths["exchanges exmo"] = fmt.Sprintf(exmo, path, path, path, path)
|
||||
codebasePaths["exchanges coinbasepro"] = fmt.Sprintf(coinbasepro, path, path, path, path)
|
||||
codebasePaths["exchanges gateio"] = fmt.Sprintf(gateio, path, path, path, path)
|
||||
codebasePaths["exchanges gemini"] = fmt.Sprintf(gemini, path, path, path, path)
|
||||
codebasePaths["exchanges hitbtc"] = fmt.Sprintf(hitbtc, path, path, path, path)
|
||||
codebasePaths["exchanges huobi"] = fmt.Sprintf(huobi, path, path, path, path)
|
||||
codebasePaths["exchanges huobihadax"] = fmt.Sprintf(huobihadax, path, path, path, path)
|
||||
codebasePaths["exchanges itbit"] = fmt.Sprintf(itbit, path, path, path, path)
|
||||
codebasePaths["exchanges kraken"] = fmt.Sprintf(kraken, path, path, path, path)
|
||||
codebasePaths["exchanges lakebtc"] = fmt.Sprintf(lakebtc, path, path, path, path)
|
||||
@@ -243,6 +250,7 @@ func addPaths() {
|
||||
codebasePaths["exchanges poloniex"] = fmt.Sprintf(poloniex, path, path, path, path)
|
||||
codebasePaths["exchanges wex"] = fmt.Sprintf(wex, path, path, path, path)
|
||||
codebasePaths["exchanges yobit"] = fmt.Sprintf(yobit, path, path, path, path)
|
||||
codebasePaths["exchanges zb"] = fmt.Sprintf(zb, path, path, path, path)
|
||||
|
||||
codebasePaths["CONTRIBUTORS"] = fmt.Sprintf(rootPath, path, path)
|
||||
codebasePaths["LICENSE"] = fmt.Sprintf(rootPath, path, path)
|
||||
|
||||
98
tools/documentation/exchanges_templates/bitmex.tmpl
Normal file
98
tools/documentation/exchanges_templates/bitmex.tmpl
Normal file
@@ -0,0 +1,98 @@
|
||||
{{define "exchanges bitmex" -}}
|
||||
{{template "header" .}}
|
||||
## Bithumb Exchange
|
||||
|
||||
### Current Features
|
||||
|
||||
+ REST Support
|
||||
|
||||
### How to enable
|
||||
|
||||
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
|
||||
+ Individual package example below:
|
||||
|
||||
```go
|
||||
// Exchanges will be abstracted out in further updates and examples will be
|
||||
// supplied then
|
||||
```
|
||||
|
||||
### How to do REST public/private calls
|
||||
|
||||
+ If enabled via "configuration".json file the exchange will be added to the
|
||||
IBotExchange array in the ```go var bot Bot``` and you will only be able to use
|
||||
the wrapper interface functions for accessing exchange data. View routines.go
|
||||
for an example of integration usage with GoCryptoTrader. Rudimentary example
|
||||
below:
|
||||
|
||||
main.go
|
||||
```go
|
||||
var b exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "Bitmex" {
|
||||
b = bot.exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := b.GetTickerPrice()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := b.GetOrderbookEx()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Private calls - wrapper functions - make sure your APIKEY and APISECRET are
|
||||
// set and AuthenticatedAPISupport is set to true
|
||||
|
||||
// Fetches current account information
|
||||
accountInfo, err := b.GetExchangeAccountInfo()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
+ If enabled via individually importing package, rudimentary example below:
|
||||
|
||||
```go
|
||||
// Public calls
|
||||
|
||||
// Fetches current ticker information
|
||||
ticker, err := b.GetTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := b.GetOrderBook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Private calls - make sure your APIKEY and APISECRET are set and
|
||||
// AuthenticatedAPISupport is set to true
|
||||
|
||||
// GetUserInfo returns account info
|
||||
accountInfo, err := b.GetUserInfo(...)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Submits an order and the exchange and returns its tradeID
|
||||
tradeID, err := b.Trade(...)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
### Please click GoDocs chevron above to view current GoDoc information for this package
|
||||
{{template "contributions"}}
|
||||
{{template "donations"}}
|
||||
{{end}}
|
||||
105
tools/documentation/exchanges_templates/gateio.tmpl
Normal file
105
tools/documentation/exchanges_templates/gateio.tmpl
Normal file
@@ -0,0 +1,105 @@
|
||||
{{define "exchanges gateio" -}}
|
||||
{{template "header" .}}
|
||||
## GateIO Exchange
|
||||
|
||||
### Current Features
|
||||
|
||||
+ REST functions
|
||||
|
||||
### How to enable
|
||||
|
||||
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
|
||||
+ Individual package example below:
|
||||
|
||||
```go
|
||||
// Exchanges will be abstracted out in further updates and examples will be
|
||||
// supplied then
|
||||
```
|
||||
|
||||
### How to do REST public/private calls
|
||||
|
||||
+ If enabled via "configuration".json file the exchange will be added to the
|
||||
IBotExchange array in the ```go var bot Bot``` and you will only be able to use
|
||||
the wrapper interface functions for accessing exchange data. View routines.go
|
||||
for an example of integration usage with GoCryptoTrader. Rudimentary example
|
||||
below:
|
||||
|
||||
main.go
|
||||
```go
|
||||
var g exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "GateIO" {
|
||||
g = bot.exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := g.GetTickerPrice()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := g.GetOrderbookEx()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Private calls - wrapper functions - make sure your APIKEY and APISECRET are
|
||||
// set and AuthenticatedAPISupport is set to true
|
||||
|
||||
// Fetches current account information
|
||||
accountInfo, err := g.GetExchangeAccountInfo()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
+ If enabled via individually importing package, rudimentary example below:
|
||||
|
||||
```go
|
||||
// Public calls
|
||||
|
||||
// Fetches current ticker information
|
||||
ticker, err := g.GetTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := g.GetOrderBook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Private calls - make sure your APIKEY and APISECRET are set and
|
||||
// AuthenticatedAPISupport is set to true
|
||||
|
||||
// GetUserInfo returns account info
|
||||
accountInfo, err := g.GetUserInfo(...)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Submits an order and the exchange and returns its tradeID
|
||||
tradeID, err := g.Trade(...)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
### How to do LongPolling public/private calls
|
||||
|
||||
```go
|
||||
// Exchanges will be abstracted out in further updates and examples will be
|
||||
// supplied then
|
||||
```
|
||||
|
||||
### Please click GoDocs chevron above to view current GoDoc information for this package
|
||||
{{template "contributions"}}
|
||||
{{template "donations"}}
|
||||
{{end}}
|
||||
105
tools/documentation/exchanges_templates/huobihadax.tmpl
Normal file
105
tools/documentation/exchanges_templates/huobihadax.tmpl
Normal file
@@ -0,0 +1,105 @@
|
||||
{{define "exchanges huobihadax" -}}
|
||||
{{template "header" .}}
|
||||
## HuobiHadax Exchange
|
||||
|
||||
### Current Features
|
||||
|
||||
+ REST functions
|
||||
|
||||
### How to enable
|
||||
|
||||
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
|
||||
+ Individual package example below:
|
||||
|
||||
```go
|
||||
// Exchanges will be abstracted out in further updates and examples will be
|
||||
// supplied then
|
||||
```
|
||||
|
||||
### How to do REST public/private calls
|
||||
|
||||
+ If enabled via "configuration".json file the exchange will be added to the
|
||||
IBotExchange array in the ```go var bot Bot``` and you will only be able to use
|
||||
the wrapper interface functions for accessing exchange data. View routines.go
|
||||
for an example of integration usage with GoCryptoTrader. Rudimentary example
|
||||
below:
|
||||
|
||||
main.go
|
||||
```go
|
||||
var h exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "HuobiHadax" {
|
||||
h = bot.exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := h.GetTickerPrice()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := h.GetOrderbookEx()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Private calls - wrapper functions - make sure your APIKEY and APISECRET are
|
||||
// set and AuthenticatedAPISupport is set to true
|
||||
|
||||
// Fetches current account information
|
||||
accountInfo, err := h.GetExchangeAccountInfo()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
+ If enabled via individually importing package, rudimentary example below:
|
||||
|
||||
```go
|
||||
// Public calls
|
||||
|
||||
// Fetches current ticker information
|
||||
ticker, err := h.GetTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := h.GetOrderBook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Private calls - make sure your APIKEY and APISECRET are set and
|
||||
// AuthenticatedAPISupport is set to true
|
||||
|
||||
// GetUserInfo returns account info
|
||||
accountInfo, err := h.GetUserInfo(...)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Submits an order and the exchange and returns its tradeID
|
||||
tradeID, err := h.Trade(...)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
### How to do LongPolling public/private calls
|
||||
|
||||
```go
|
||||
// Exchanges will be abstracted out in further updates and examples will be
|
||||
// supplied then
|
||||
```
|
||||
|
||||
### Please click GoDocs chevron above to view current GoDoc information for this package
|
||||
{{template "contributions"}}
|
||||
{{template "donations"}}
|
||||
{{end}}
|
||||
105
tools/documentation/exchanges_templates/zb.tmpl
Normal file
105
tools/documentation/exchanges_templates/zb.tmpl
Normal file
@@ -0,0 +1,105 @@
|
||||
{{define "exchanges zb" -}}
|
||||
{{template "header" .}}
|
||||
## ZB Exchange
|
||||
|
||||
### Current Features
|
||||
|
||||
+ REST functions
|
||||
|
||||
### How to enable
|
||||
|
||||
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
|
||||
+ Individual package example below:
|
||||
|
||||
```go
|
||||
// Exchanges will be abstracted out in further updates and examples will be
|
||||
// supplied then
|
||||
```
|
||||
|
||||
### How to do REST public/private calls
|
||||
|
||||
+ If enabled via "configuration".json file the exchange will be added to the
|
||||
IBotExchange array in the ```go var bot Bot``` and you will only be able to use
|
||||
the wrapper interface functions for accessing exchange data. View routines.go
|
||||
for an example of integration usage with GoCryptoTrader. Rudimentary example
|
||||
below:
|
||||
|
||||
main.go
|
||||
```go
|
||||
var z exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "ZB" {
|
||||
z = bot.exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := z.GetTickerPrice()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := z.GetOrderbookEx()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Private calls - wrapper functions - make sure your APIKEY and APISECRET are
|
||||
// set and AuthenticatedAPISupport is set to true
|
||||
|
||||
// Fetches current account information
|
||||
accountInfo, err := z.GetExchangeAccountInfo()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
+ If enabled via individually importing package, rudimentary example below:
|
||||
|
||||
```go
|
||||
// Public calls
|
||||
|
||||
// Fetches current ticker information
|
||||
ticker, err := z.GetTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := z.GetOrderBook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Private calls - make sure your APIKEY and APISECRET are set and
|
||||
// AuthenticatedAPISupport is set to true
|
||||
|
||||
// GetUserInfo returns account info
|
||||
accountInfo, err := z.GetUserInfo(...)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Submits an order and the exchange and returns its tradeID
|
||||
tradeID, err := z.Trade(...)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
### How to do LongPolling public/private calls
|
||||
|
||||
```go
|
||||
// Exchanges will be abstracted out in further updates and examples will be
|
||||
// supplied then
|
||||
```
|
||||
|
||||
### Please click GoDocs chevron above to view current GoDoc information for this package
|
||||
{{template "contributions"}}
|
||||
{{template "donations"}}
|
||||
{{end}}
|
||||
@@ -25,6 +25,7 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader
|
||||
| Bitfinex | Yes | Yes | NA |
|
||||
| Bitflyer | Yes | No | NA |
|
||||
| Bithumb | Yes | NA | NA |
|
||||
| BitMEX | Yes | No | NA |
|
||||
| Bitstamp | Yes | Yes | No |
|
||||
| Bittrex | Yes | No | NA |
|
||||
| BTCC | Yes | Yes | No |
|
||||
|
||||
Reference in New Issue
Block a user