mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 23:16:45 +00:00
Utilising authenticated websocket functions in exchange wrappers (#384)
* Basic concept commit * Initial changes to support bitfinex v2. Reverts linter changes as they suck. Exports bitfinex ws types * Adds ticker, trade and orderbook support * Candles sub that returns no data COMPLETE * Adds authenticated ws support * Adds the barebones endpoints to support * Adds more endpoints * Even more endpoints * minicommit to switch and test * All the interactive types * Adds support for simultaneous connections. Updates tests. Nothing is working * Successfully adds place order. Moves all authenticated endpoints to new switch case * Cancel order and modify order * Cancel all orders, cancel multi orders * Finalises implementation. Uses testMain * Adds WS wrapper support for some funcs * Fixing rebasing issues * Replaces use of currency as a variable. Updates a lot of coinut websocket auth endpoint stuff * Fixes some fun for loops with GetEnabledPairs * Fixes tests impacted by currency var change * Adds coinut support for WS functions. Replaces `order` vars with `ord`. Fixes some for loops too. Removes verbose from bitfinex * So many panics * I'm fixing a hole, where the panics get in, and stops my mind from wandering, where it will go * Moves func `CanUseAuthenticatedWebsocketEndpoint` to Websocket package as it fits better. Adds test coverage of `CanUseAuthenticatedWebsocketEndpoint` * Finishes up all of coinuts ws implementations. * GateIO implementation * Adds some helper funcs for types, sides and status. Adds support for huobi. Removes unnecessary type * Adds forgotten huobi endpoint * Fixes cancel order endpoint * go hates my formatting and so do I * The process to get authenticated kraken websocket to work. Uses testmain. Adds new auth channel, auth subscriptions, auth data handling. Not working yet * Finishes open orders handling * Mini update for status only updates * Fixes some kraken points * Finishes WS kraken since it doesn't work * Unfinished commit, cleaning up types * Finishes the const replacing * Fixes extra GetNAmes after rebase * An end to the cleanup. testmain for gateio * Adds ZB support * Bitfinex cleanup. Renamed func * Testmain-47s for everyone!!! yayaaaaaaa * Adds kraken websocket wrapper support * Fixes rebase issues * Fixes tests from rebase * Adds test for conversion. Fixes for loop. Updates test order pricing. Fixes some poor made tests. Adds proper error handling for ws responses instead of logging them. Fixed issue where commented code ruined kraken ws. * Fixes secret linting issues. Prioritises bitfinex channelID responses over authorised * Fixes sloppy error/var declarations * Fixes crazy bad logic where submit order errors weren't really considered. Parralols alphapoint/alphapoint_test.go. Removes buffer for multi-websocket comms channel. * Removal of inline string and removal of redundant nil checkerinos * Fixes err checks. Checks whether float has decimal. Fixes append. Drops omitempties. Parallel to some tests. Moves var declarations * Replaces my lazy sprintfs with strconv.FormatInt(time.Now().Unix(), 10) * Adds shiny new FullyMatched bool. Fixes coinbene buy sell consts * Fixes oopsie with coinbene const replacement * Fixes currency issue * Cleans up new places that use JSONDecode * Fixes huge panic bug from string int conversion. Adds large testtable for strings to order types * Fixes some more strconversion issues. Fixes table test var usage. Changes mapperino name * Added some new scenarios for number splitting * Fixes lint issues * negative num fix * Typo fix * Accuracy warning comment
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
package convert
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -77,3 +80,30 @@ func UnixMillis(t time.Time) int64 {
|
||||
func RecvWindow(d time.Duration) int64 {
|
||||
return int64(d) / int64(time.Millisecond)
|
||||
}
|
||||
|
||||
// SplitFloatDecimals takes in a float64 and splits
|
||||
// the decimals into their own integers
|
||||
// Warning. Passing in numbers with many decimals
|
||||
// can lead to a loss of accuracy
|
||||
func SplitFloatDecimals(input float64) (baseNum, decimalNum int64, err error) {
|
||||
if input > float64(math.MaxInt64) {
|
||||
return 0, 0, errors.New("number too large to split into integers")
|
||||
}
|
||||
if input == float64(int64(input)) {
|
||||
return int64(input), 0, nil
|
||||
}
|
||||
decStr := strconv.FormatFloat(input, 'f', -1, 64)
|
||||
splitNum := strings.Split(decStr, ".")
|
||||
baseNum, err = strconv.ParseInt(splitNum[0], 10, 64)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
decimalNum, err = strconv.ParseInt(splitNum[1], 10, 64)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
if baseNum < 0 {
|
||||
decimalNum *= -1
|
||||
}
|
||||
return baseNum, decimalNum, nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package convert
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@@ -149,3 +150,58 @@ func TestRecvWindow(t *testing.T) {
|
||||
expectedOutput, actualOutput)
|
||||
}
|
||||
}
|
||||
|
||||
// TestSplitFloatDecimals ensures SplitFloatDecimals
|
||||
// accurately splits decimals into integers
|
||||
func TestSplitFloatDecimals(t *testing.T) {
|
||||
x, y, err := SplitFloatDecimals(1.2)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if x != 1 && y != 2 {
|
||||
t.Error("Conversion error")
|
||||
}
|
||||
x, y, err = SplitFloatDecimals(123456.654321)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if x != 123456 && y != 654321 {
|
||||
t.Error("Conversion error")
|
||||
}
|
||||
x, y, err = SplitFloatDecimals(123.111000)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if x != 123 && y != 111 {
|
||||
t.Error("Conversion error")
|
||||
}
|
||||
x, y, err = SplitFloatDecimals(0123.111001)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if x != 123 && y != 111001 {
|
||||
t.Error("Conversion error")
|
||||
}
|
||||
x, y, err = SplitFloatDecimals(1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if x != 1 && y != 0 {
|
||||
t.Error("Conversion error")
|
||||
}
|
||||
_, _, err = SplitFloatDecimals(float64(math.MaxInt64) + 1)
|
||||
if err == nil {
|
||||
t.Error("Expected conversion error")
|
||||
}
|
||||
_, _, err = SplitFloatDecimals(1797693134862315700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111)
|
||||
if err == nil {
|
||||
t.Error("Expected conversion error")
|
||||
}
|
||||
x, y, err = SplitFloatDecimals(-1.2)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if x != -1 && y != -2 {
|
||||
t.Error("Conversion error")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,10 +343,10 @@ func TestNewPairDelimiter(t *testing.T) {
|
||||
// specific index
|
||||
func TestNewPairFromIndex(t *testing.T) {
|
||||
t.Parallel()
|
||||
currency := defaultPair
|
||||
curr := defaultPair
|
||||
index := "BTC"
|
||||
|
||||
pair, err := NewPairFromIndex(currency, index)
|
||||
pair, err := NewPairFromIndex(curr, index)
|
||||
if err != nil {
|
||||
t.Error("NewPairFromIndex() error", err)
|
||||
}
|
||||
@@ -362,9 +362,9 @@ func TestNewPairFromIndex(t *testing.T) {
|
||||
)
|
||||
}
|
||||
|
||||
currency = "DOGEBTC"
|
||||
curr = "DOGEBTC"
|
||||
|
||||
pair, err = NewPairFromIndex(currency, index)
|
||||
pair, err = NewPairFromIndex(curr, index)
|
||||
if err != nil {
|
||||
t.Error("NewPairFromIndex() error", err)
|
||||
}
|
||||
|
||||
@@ -175,19 +175,15 @@ func (s *Storage) SetupConversionRates() {
|
||||
// SetDefaultFiatCurrencies assigns the default fiat currency list and adds it
|
||||
// to the running list
|
||||
func (s *Storage) SetDefaultFiatCurrencies(c ...Code) {
|
||||
for _, currency := range c {
|
||||
s.defaultFiatCurrencies = append(s.defaultFiatCurrencies, currency)
|
||||
s.fiatCurrencies = append(s.fiatCurrencies, currency)
|
||||
}
|
||||
s.defaultFiatCurrencies = append(s.defaultFiatCurrencies, c...)
|
||||
s.fiatCurrencies = append(s.fiatCurrencies, c...)
|
||||
}
|
||||
|
||||
// SetDefaultCryptocurrencies assigns the default cryptocurrency list and adds
|
||||
// it to the running list
|
||||
func (s *Storage) SetDefaultCryptocurrencies(c ...Code) {
|
||||
for _, currency := range c {
|
||||
s.defaultCryptoCurrencies = append(s.defaultCryptoCurrencies, currency)
|
||||
s.cryptocurrencies = append(s.cryptocurrencies, currency)
|
||||
}
|
||||
s.defaultCryptoCurrencies = append(s.defaultCryptoCurrencies, c...)
|
||||
s.cryptocurrencies = append(s.cryptocurrencies, c...)
|
||||
}
|
||||
|
||||
// SetupForexProviders sets up a new instance of the forex providers
|
||||
@@ -507,8 +503,8 @@ func (s *Storage) GetTotalMarketCryptocurrencies() (Currencies, error) {
|
||||
// IsDefaultCurrency returns if a currency is a default currency
|
||||
func (s *Storage) IsDefaultCurrency(c Code) bool {
|
||||
t, _ := GetTranslation(c)
|
||||
for _, d := range s.defaultFiatCurrencies {
|
||||
if d.Match(c) || d.Match(t) {
|
||||
for i := range s.defaultFiatCurrencies {
|
||||
if s.defaultFiatCurrencies[i].Match(c) || s.defaultFiatCurrencies[i].Match(t) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,11 +264,11 @@ func (o *orderManager) processOrders() {
|
||||
}
|
||||
|
||||
for x := range result {
|
||||
order := &result[x]
|
||||
result := o.orderStore.Add(order)
|
||||
ord := &result[x]
|
||||
result := o.orderStore.Add(ord)
|
||||
if result != ErrOrdersAlreadyExists {
|
||||
msg := fmt.Sprintf("Order manager: Exchange %s added order ID=%v pair=%v price=%v amount=%v side=%v type=%v.",
|
||||
order.Exchange, order.ID, order.CurrencyPair, order.Price, order.Amount, order.OrderSide, order.OrderType)
|
||||
ord.Exchange, ord.ID, ord.CurrencyPair, ord.Price, ord.Amount, ord.OrderSide, ord.OrderType)
|
||||
log.Debugf(log.OrderMgr, "%v\n", msg)
|
||||
Bot.CommsManager.PushEvent(base.Event{
|
||||
Type: "order",
|
||||
|
||||
@@ -310,16 +310,17 @@ func (e *ExchangeCurrencyPairSyncer) worker() {
|
||||
}
|
||||
|
||||
for y := range assetTypes {
|
||||
for _, p := range Bot.Exchanges[x].GetEnabledPairs(assetTypes[y]) {
|
||||
enabledPairs := Bot.Exchanges[x].GetEnabledPairs(assetTypes[y])
|
||||
for i := range enabledPairs {
|
||||
if atomic.LoadInt32(&e.shutdown) == 1 {
|
||||
return
|
||||
}
|
||||
|
||||
if !e.exists(exchangeName, p, assetTypes[y]) {
|
||||
if !e.exists(exchangeName, enabledPairs[i], assetTypes[y]) {
|
||||
c := CurrencyPairSyncAgent{
|
||||
AssetType: assetTypes[y],
|
||||
Exchange: exchangeName,
|
||||
Pair: p,
|
||||
Pair: enabledPairs[i],
|
||||
}
|
||||
|
||||
if e.Cfg.SyncTicker {
|
||||
@@ -346,7 +347,7 @@ func (e *ExchangeCurrencyPairSyncer) worker() {
|
||||
e.add(&c)
|
||||
}
|
||||
|
||||
c, err := e.get(exchangeName, p, assetTypes[y])
|
||||
c, err := e.get(exchangeName, enabledPairs[i], assetTypes[y])
|
||||
if err != nil {
|
||||
log.Errorf(log.SyncMgr, "failed to get item. Err: %s\n", err)
|
||||
continue
|
||||
@@ -354,7 +355,7 @@ func (e *ExchangeCurrencyPairSyncer) worker() {
|
||||
if switchedToRest && usingWebsocket {
|
||||
log.Infof(log.SyncMgr,
|
||||
"%s %s: Websocket re-enabled, switching from rest to websocket\n",
|
||||
c.Exchange, FormatCurrency(p).String())
|
||||
c.Exchange, FormatCurrency(enabledPairs[i]).String())
|
||||
switchedToRest = false
|
||||
}
|
||||
if e.Cfg.SyncTicker {
|
||||
@@ -371,7 +372,7 @@ func (e *ExchangeCurrencyPairSyncer) worker() {
|
||||
c.Ticker.IsUsingREST = true
|
||||
log.Warnf(log.SyncMgr,
|
||||
"%s %s: No ticker update after 10 seconds, switching from websocket to rest\n",
|
||||
c.Exchange, FormatCurrency(p).String())
|
||||
c.Exchange, FormatCurrency(enabledPairs[i]).String())
|
||||
switchedToRest = true
|
||||
e.setProcessing(c.Exchange, c.Pair, c.AssetType, SyncItemTicker, false)
|
||||
}
|
||||
@@ -521,14 +522,15 @@ func (e *ExchangeCurrencyPairSyncer) Start() {
|
||||
}
|
||||
|
||||
for y := range assetTypes {
|
||||
for _, p := range Bot.Exchanges[x].GetEnabledPairs(assetTypes[y]) {
|
||||
if e.exists(exchangeName, p, assetTypes[y]) {
|
||||
enabledPairs := Bot.Exchanges[x].GetEnabledPairs(assetTypes[y])
|
||||
for i := range enabledPairs {
|
||||
if e.exists(exchangeName, enabledPairs[i], assetTypes[y]) {
|
||||
continue
|
||||
}
|
||||
c := CurrencyPairSyncAgent{
|
||||
AssetType: assetTypes[y],
|
||||
Exchange: exchangeName,
|
||||
Pair: p,
|
||||
Pair: enabledPairs[i],
|
||||
}
|
||||
|
||||
if e.Cfg.SyncTicker {
|
||||
|
||||
@@ -2,6 +2,8 @@ package alphapoint
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
@@ -17,45 +19,37 @@ const (
|
||||
canManipulateRealOrders = false
|
||||
)
|
||||
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
t.Parallel()
|
||||
SetDefaults := Alphapoint{}
|
||||
var a Alphapoint
|
||||
|
||||
SetDefaults.SetDefaults()
|
||||
if SetDefaults.API.Endpoints.URL != "https://sim3.alphapoint.com:8400" {
|
||||
t.Error("SetDefaults: String Incorrect -", SetDefaults.API.Endpoints.URL)
|
||||
}
|
||||
if SetDefaults.API.Endpoints.WebsocketURL != "wss://sim3.alphapoint.com:8401/v1/GetTicker/" {
|
||||
t.Error("SetDefaults: String Incorrect -", SetDefaults.API.Endpoints.WebsocketURL)
|
||||
}
|
||||
}
|
||||
|
||||
func testSetAPIKey(a *Alphapoint) {
|
||||
func TestMain(m *testing.M) {
|
||||
a.SetDefaults()
|
||||
a.API.Credentials.Key = apiKey
|
||||
a.API.Credentials.Secret = apiSecret
|
||||
a.API.AuthenticatedSupport = true
|
||||
}
|
||||
|
||||
func testIsAPIKeysSet(a *Alphapoint) bool {
|
||||
if apiKey != "" && apiSecret != "" && a.API.AuthenticatedSupport {
|
||||
return true
|
||||
if a.API.Endpoints.URL != "https://sim3.alphapoint.com:8400" {
|
||||
log.Fatal("SetDefaults: String Incorrect -", a.API.Endpoints.URL)
|
||||
}
|
||||
return false
|
||||
if a.API.Endpoints.WebsocketURL != "wss://sim3.alphapoint.com:8401/v1/GetTicker/" {
|
||||
log.Fatal("SetDefaults: String Incorrect -", a.API.Endpoints.WebsocketURL)
|
||||
}
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
func TestGetTicker(t *testing.T) {
|
||||
alpha := Alphapoint{}
|
||||
alpha.SetDefaults()
|
||||
|
||||
func areTestAPIKeysSet() bool {
|
||||
return a.ValidateAPICredentials()
|
||||
}
|
||||
|
||||
func TestGetTicker(t *testing.T) {
|
||||
t.Parallel()
|
||||
var ticker Ticker
|
||||
var err error
|
||||
|
||||
if onlineTest {
|
||||
ticker, err = alpha.GetTicker("BTCUSD")
|
||||
ticker, err = a.GetTicker("BTCUSD")
|
||||
if err != nil {
|
||||
t.Fatal("Alphapoint GetTicker init error: ", err)
|
||||
}
|
||||
|
||||
_, err = alpha.GetTicker("wigwham")
|
||||
_, err = a.GetTicker("wigwham")
|
||||
if err == nil {
|
||||
t.Error("Alphapoint GetTicker Expected error")
|
||||
}
|
||||
@@ -80,19 +74,16 @@ func TestGetTicker(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetTrades(t *testing.T) {
|
||||
alpha := Alphapoint{}
|
||||
alpha.SetDefaults()
|
||||
|
||||
t.Parallel()
|
||||
var trades Trades
|
||||
var err error
|
||||
|
||||
if onlineTest {
|
||||
trades, err = alpha.GetTrades("BTCUSD", 0, 10)
|
||||
trades, err = a.GetTrades("BTCUSD", 0, 10)
|
||||
if err != nil {
|
||||
t.Fatalf("Init error: %s", err)
|
||||
}
|
||||
|
||||
_, err = alpha.GetTrades("wigwham", 0, 10)
|
||||
_, err = a.GetTrades("wigwham", 0, 10)
|
||||
if err == nil {
|
||||
t.Fatal("GetTrades Expected error")
|
||||
}
|
||||
@@ -121,18 +112,15 @@ func TestGetTrades(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetTradesByDate(t *testing.T) {
|
||||
alpha := Alphapoint{}
|
||||
alpha.SetDefaults()
|
||||
|
||||
t.Parallel()
|
||||
var trades Trades
|
||||
var err error
|
||||
|
||||
if onlineTest {
|
||||
trades, err = alpha.GetTradesByDate("BTCUSD", 1414799400, 1414800000)
|
||||
trades, err = a.GetTradesByDate("BTCUSD", 1414799400, 1414800000)
|
||||
if err != nil {
|
||||
t.Errorf("Init error: %s", err)
|
||||
}
|
||||
_, err = alpha.GetTradesByDate("wigwham", 1414799400, 1414800000)
|
||||
_, err = a.GetTradesByDate("wigwham", 1414799400, 1414800000)
|
||||
if err == nil {
|
||||
t.Error("GetTradesByDate Expected error")
|
||||
}
|
||||
@@ -168,19 +156,16 @@ func TestGetTradesByDate(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetOrderbook(t *testing.T) {
|
||||
alpha := Alphapoint{}
|
||||
alpha.SetDefaults()
|
||||
|
||||
t.Parallel()
|
||||
var orderBook Orderbook
|
||||
var err error
|
||||
|
||||
if onlineTest {
|
||||
orderBook, err = alpha.GetOrderbook("BTCUSD")
|
||||
orderBook, err = a.GetOrderbook("BTCUSD")
|
||||
if err != nil {
|
||||
t.Errorf("Init error: %s", err)
|
||||
}
|
||||
|
||||
_, err = alpha.GetOrderbook("wigwham")
|
||||
_, err = a.GetOrderbook("wigwham")
|
||||
if err == nil {
|
||||
t.Error("GetOrderbook() Expected error")
|
||||
}
|
||||
@@ -213,14 +198,12 @@ func TestGetOrderbook(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetProductPairs(t *testing.T) {
|
||||
alpha := Alphapoint{}
|
||||
alpha.SetDefaults()
|
||||
|
||||
t.Parallel()
|
||||
var products ProductPairs
|
||||
var err error
|
||||
|
||||
if onlineTest {
|
||||
products, err = alpha.GetProductPairs()
|
||||
products, err = a.GetProductPairs()
|
||||
if err != nil {
|
||||
t.Errorf("Init error: %s", err)
|
||||
}
|
||||
@@ -253,14 +236,12 @@ func TestGetProductPairs(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetProducts(t *testing.T) {
|
||||
alpha := Alphapoint{}
|
||||
alpha.SetDefaults()
|
||||
|
||||
t.Parallel()
|
||||
var products Products
|
||||
var err error
|
||||
|
||||
if onlineTest {
|
||||
products, err = alpha.GetProducts()
|
||||
products, err = a.GetProducts()
|
||||
if err != nil {
|
||||
t.Errorf("Init error: %s", err)
|
||||
}
|
||||
@@ -293,12 +274,9 @@ func TestGetProducts(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCreateAccount(t *testing.T) {
|
||||
a := &Alphapoint{}
|
||||
a.SetDefaults()
|
||||
testSetAPIKey(a)
|
||||
|
||||
if !testIsAPIKeysSet(a) {
|
||||
return
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("API keys not set, skipping")
|
||||
}
|
||||
|
||||
err := a.CreateAccount("test", "account", "something@something.com", "0292383745", "lolcat123")
|
||||
@@ -316,12 +294,9 @@ func TestCreateAccount(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetUserInfo(t *testing.T) {
|
||||
a := &Alphapoint{}
|
||||
a.SetDefaults()
|
||||
testSetAPIKey(a)
|
||||
|
||||
if !testIsAPIKeysSet(a) {
|
||||
return
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("API keys not set, skipping")
|
||||
}
|
||||
|
||||
_, err := a.GetUserInfo()
|
||||
@@ -331,12 +306,9 @@ func TestGetUserInfo(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSetUserInfo(t *testing.T) {
|
||||
a := &Alphapoint{}
|
||||
a.SetDefaults()
|
||||
testSetAPIKey(a)
|
||||
|
||||
if !testIsAPIKeysSet(a) {
|
||||
return
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("API keys not set, skipping")
|
||||
}
|
||||
|
||||
_, err := a.SetUserInfo("bla", "bla", "1", "meh", true, true)
|
||||
@@ -346,12 +318,9 @@ func TestSetUserInfo(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
a := &Alphapoint{}
|
||||
a.SetDefaults()
|
||||
testSetAPIKey(a)
|
||||
|
||||
if !testIsAPIKeysSet(a) {
|
||||
return
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("API keys not set, skipping")
|
||||
}
|
||||
|
||||
_, err := a.GetAccountInfo()
|
||||
@@ -361,12 +330,9 @@ func TestGetAccountInfo(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetAccountTrades(t *testing.T) {
|
||||
a := &Alphapoint{}
|
||||
a.SetDefaults()
|
||||
testSetAPIKey(a)
|
||||
|
||||
if !testIsAPIKeysSet(a) {
|
||||
return
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("API keys not set, skipping")
|
||||
}
|
||||
|
||||
_, err := a.GetAccountTrades("", 1, 2)
|
||||
@@ -376,12 +342,9 @@ func TestGetAccountTrades(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetDepositAddresses(t *testing.T) {
|
||||
a := &Alphapoint{}
|
||||
a.SetDefaults()
|
||||
testSetAPIKey(a)
|
||||
|
||||
if !testIsAPIKeysSet(a) {
|
||||
return
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("API keys not set, skipping")
|
||||
}
|
||||
|
||||
_, err := a.GetDepositAddresses()
|
||||
@@ -391,12 +354,9 @@ func TestGetDepositAddresses(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawCoins(t *testing.T) {
|
||||
a := &Alphapoint{}
|
||||
a.SetDefaults()
|
||||
testSetAPIKey(a)
|
||||
|
||||
if !testIsAPIKeysSet(a) {
|
||||
return
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("API keys not set, skipping")
|
||||
}
|
||||
|
||||
err := a.WithdrawCoins("", "", "", 0.01)
|
||||
@@ -406,12 +366,9 @@ func TestWithdrawCoins(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCreateOrder(t *testing.T) {
|
||||
a := &Alphapoint{}
|
||||
a.SetDefaults()
|
||||
testSetAPIKey(a)
|
||||
|
||||
if !testIsAPIKeysSet(a) {
|
||||
return
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("API keys not set, skipping")
|
||||
}
|
||||
|
||||
_, err := a.CreateOrder("", "", order.Limit.String(), 0.01, 0)
|
||||
@@ -421,12 +378,9 @@ func TestCreateOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestModifyExistingOrder(t *testing.T) {
|
||||
a := &Alphapoint{}
|
||||
a.SetDefaults()
|
||||
testSetAPIKey(a)
|
||||
|
||||
if !testIsAPIKeysSet(a) {
|
||||
return
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("API keys not set, skipping")
|
||||
}
|
||||
|
||||
_, err := a.ModifyExistingOrder("", 1, 1)
|
||||
@@ -436,12 +390,9 @@ func TestModifyExistingOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelAllExistingOrders(t *testing.T) {
|
||||
a := &Alphapoint{}
|
||||
a.SetDefaults()
|
||||
testSetAPIKey(a)
|
||||
|
||||
if !testIsAPIKeysSet(a) {
|
||||
return
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("API keys not set, skipping")
|
||||
}
|
||||
|
||||
err := a.CancelAllExistingOrders("")
|
||||
@@ -451,12 +402,9 @@ func TestCancelAllExistingOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetOrders(t *testing.T) {
|
||||
a := &Alphapoint{}
|
||||
a.SetDefaults()
|
||||
testSetAPIKey(a)
|
||||
|
||||
if !testIsAPIKeysSet(a) {
|
||||
return
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("API keys not set, skipping")
|
||||
}
|
||||
|
||||
_, err := a.GetOrders()
|
||||
@@ -466,12 +414,9 @@ func TestGetOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetOrderFee(t *testing.T) {
|
||||
a := &Alphapoint{}
|
||||
a.SetDefaults()
|
||||
testSetAPIKey(a)
|
||||
|
||||
if !testIsAPIKeysSet(a) {
|
||||
return
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("API keys not set, skipping")
|
||||
}
|
||||
|
||||
_, err := a.GetOrderFee("", "", 1, 1)
|
||||
@@ -481,45 +426,38 @@ func TestGetOrderFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
a := &Alphapoint{}
|
||||
a.SetDefaults()
|
||||
t.Parallel()
|
||||
expectedResult := exchange.AutoWithdrawCryptoWithAPIPermissionText + " & " + exchange.WithdrawCryptoWith2FAText + " & " + exchange.NoFiatWithdrawalsText
|
||||
|
||||
withdrawPermissions := a.FormatWithdrawPermissions()
|
||||
|
||||
if withdrawPermissions != expectedResult {
|
||||
t.Errorf("Expected: %s, Received: %s", expectedResult, withdrawPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
a := &Alphapoint{}
|
||||
a.SetDefaults()
|
||||
|
||||
t.Parallel()
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
}
|
||||
|
||||
_, err := a.GetActiveOrders(&getOrdersRequest)
|
||||
if areTestAPIKeysSet(a) && err != nil {
|
||||
if areTestAPIKeysSet() && err != nil {
|
||||
t.Errorf("Could not get open orders: %s", err)
|
||||
} else if !areTestAPIKeysSet(a) && err == nil {
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
t.Error("Expecting an error when no keys are set")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
a := &Alphapoint{}
|
||||
a.SetDefaults()
|
||||
|
||||
t.Parallel()
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
}
|
||||
|
||||
_, err := a.GetOrderHistory(&getOrdersRequest)
|
||||
if areTestAPIKeysSet(a) && err != nil {
|
||||
if areTestAPIKeysSet() && err != nil {
|
||||
t.Errorf("Could not get order history: %s", err)
|
||||
} else if !areTestAPIKeysSet(a) && err == nil {
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
t.Error("Expecting an error when no keys are set")
|
||||
}
|
||||
}
|
||||
@@ -527,15 +465,9 @@ func TestGetOrderHistory(t *testing.T) {
|
||||
// Any tests below this line have the ability to impact your orders on the exchange. Enable canManipulateRealOrders to run them
|
||||
// ----------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
func areTestAPIKeysSet(a *Alphapoint) bool {
|
||||
return a.ValidateAPICredentials()
|
||||
}
|
||||
|
||||
func TestSubmitOrder(t *testing.T) {
|
||||
a := &Alphapoint{}
|
||||
a.SetDefaults()
|
||||
|
||||
if areTestAPIKeysSet(a) && !canManipulateRealOrders {
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
@@ -553,10 +485,10 @@ func TestSubmitOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
response, err := a.SubmitOrder(orderSubmission)
|
||||
if !areTestAPIKeysSet(a) && err == nil {
|
||||
if !areTestAPIKeysSet() && err == nil {
|
||||
t.Error("Expecting an error when no keys are set")
|
||||
}
|
||||
if areTestAPIKeysSet(a) && err != nil {
|
||||
if areTestAPIKeysSet() && err != nil {
|
||||
t.Errorf("Withdraw failed to be placed: %v", err)
|
||||
|
||||
if !response.IsOrderPlaced {
|
||||
@@ -566,15 +498,12 @@ func TestSubmitOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelExchangeOrder(t *testing.T) {
|
||||
a := &Alphapoint{}
|
||||
a.SetDefaults()
|
||||
|
||||
if areTestAPIKeysSet(a) && !canManipulateRealOrders {
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.BTC, currency.LTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -583,24 +512,21 @@ func TestCancelExchangeOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
err := a.CancelOrder(orderCancellation)
|
||||
if !areTestAPIKeysSet(a) && err == nil {
|
||||
if !areTestAPIKeysSet() && err == nil {
|
||||
t.Error("Expecting an error when no keys are set")
|
||||
}
|
||||
if areTestAPIKeysSet(a) && err != nil {
|
||||
if areTestAPIKeysSet() && err != nil {
|
||||
t.Errorf("Withdraw failed to be placed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
a := &Alphapoint{}
|
||||
a.SetDefaults()
|
||||
|
||||
if areTestAPIKeysSet(a) && !canManipulateRealOrders {
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.BTC, currency.LTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -609,11 +535,10 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
resp, err := a.CancelAllOrders(orderCancellation)
|
||||
|
||||
if !areTestAPIKeysSet(a) && err == nil {
|
||||
if !areTestAPIKeysSet() && err == nil {
|
||||
t.Error("Expecting an error when no keys are set")
|
||||
}
|
||||
if areTestAPIKeysSet(a) && err != nil {
|
||||
if areTestAPIKeysSet() && err != nil {
|
||||
t.Errorf("Withdraw failed to be placed: %v", err)
|
||||
}
|
||||
|
||||
@@ -623,9 +548,10 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestModifyOrder(t *testing.T) {
|
||||
a := &Alphapoint{}
|
||||
a.SetDefaults()
|
||||
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
_, err := a.ModifyOrder(&order.Modify{})
|
||||
if err == nil {
|
||||
t.Error("ModifyOrder() Expected error")
|
||||
@@ -633,10 +559,8 @@ func TestModifyOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdraw(t *testing.T) {
|
||||
a := &Alphapoint{}
|
||||
a.SetDefaults()
|
||||
t.Parallel()
|
||||
var withdrawCryptoRequest = exchange.CryptoWithdrawRequest{}
|
||||
|
||||
_, err := a.WithdrawCryptocurrencyFunds(&withdrawCryptoRequest)
|
||||
if err != common.ErrNotYetImplemented {
|
||||
t.Errorf("Expected 'Not implemented', received %v", err)
|
||||
@@ -644,10 +568,8 @@ func TestWithdraw(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawFiat(t *testing.T) {
|
||||
a := &Alphapoint{}
|
||||
a.SetDefaults()
|
||||
|
||||
if areTestAPIKeysSet(a) && !canManipulateRealOrders {
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
@@ -659,10 +581,8 @@ func TestWithdrawFiat(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawInternationalBank(t *testing.T) {
|
||||
a := &Alphapoint{}
|
||||
a.SetDefaults()
|
||||
|
||||
if areTestAPIKeysSet(a) && !canManipulateRealOrders {
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
|
||||
@@ -212,16 +212,18 @@ func (a *Alphapoint) SubmitOrder(s *order.Submit) (order.SubmitResponse, error)
|
||||
s.OrderSide.String(),
|
||||
s.Amount,
|
||||
s.Price)
|
||||
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
if response > 0 {
|
||||
submitOrderResponse.OrderID = strconv.FormatInt(response, 10)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
if s.OrderType == order.Market {
|
||||
submitOrderResponse.FullyMatched = true
|
||||
}
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
|
||||
return submitOrderResponse, err
|
||||
return submitOrderResponse, nil
|
||||
}
|
||||
|
||||
// ModifyOrder will allow of changing orderbook placement and limit to
|
||||
|
||||
@@ -86,7 +86,7 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
t.Parallel()
|
||||
var feeBuilder = setFeeBuilder()
|
||||
a.GetFeeByType(feeBuilder)
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
if !areTestAPIKeysSet() {
|
||||
if feeBuilder.FeeType != exchange.OfflineTradeFee {
|
||||
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
|
||||
}
|
||||
@@ -171,9 +171,7 @@ func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
t.Parallel()
|
||||
expectedResult := exchange.AutoWithdrawCryptoWithSetupText + " & " + exchange.WithdrawCryptoWith2FAText + " & " +
|
||||
exchange.WithdrawCryptoWithEmailText + " & " + exchange.WithdrawFiatViaWebsiteOnlyText
|
||||
|
||||
withdrawPermissions := a.FormatWithdrawPermissions()
|
||||
|
||||
if withdrawPermissions != expectedResult {
|
||||
t.Errorf("Expected: %s, Received: %s", expectedResult, withdrawPermissions)
|
||||
}
|
||||
@@ -254,7 +252,6 @@ func TestCancelExchangeOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.BTC, currency.LTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -280,7 +277,6 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.BTC, currency.LTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
|
||||
@@ -2,6 +2,7 @@ package anx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -346,16 +347,18 @@ func (a *ANX) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
|
||||
false,
|
||||
"",
|
||||
false)
|
||||
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
if response != "" {
|
||||
submitOrderResponse.OrderID = response
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
if s.OrderType == order.Market {
|
||||
submitOrderResponse.FullyMatched = true
|
||||
}
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
|
||||
return submitOrderResponse, err
|
||||
return submitOrderResponse, nil
|
||||
}
|
||||
|
||||
// ModifyOrder will allow of changing orderbook placement and limit to
|
||||
@@ -391,9 +394,9 @@ func (a *ANX) CancelAllOrders(_ *order.Cancel) (order.CancelAllResponse, error)
|
||||
return cancelAllOrdersResponse, err
|
||||
}
|
||||
|
||||
for _, order := range resp.OrderCancellationResponses {
|
||||
if order.Error != CancelRequestSubmitted {
|
||||
cancelAllOrdersResponse.Status[order.UUID] = order.Error
|
||||
for i := range resp.OrderCancellationResponses {
|
||||
if resp.OrderCancellationResponses[i].Error != CancelRequestSubmitted {
|
||||
cancelAllOrdersResponse.Status[resp.OrderCancellationResponses[i].UUID] = resp.OrderCancellationResponses[i].Error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -414,7 +417,7 @@ func (a *ANX) GetDepositAddress(cryptocurrency currency.Code, _ string) (string,
|
||||
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is
|
||||
// submitted
|
||||
func (a *ANX) WithdrawCryptocurrencyFunds(withdrawRequest *exchange.CryptoWithdrawRequest) (string, error) {
|
||||
return a.Send(withdrawRequest.Currency.String(), withdrawRequest.Address, "", fmt.Sprintf("%v", withdrawRequest.Amount))
|
||||
return a.Send(withdrawRequest.Currency.String(), withdrawRequest.Address, "", strconv.FormatFloat(withdrawRequest.Amount, 'f', -1, 64))
|
||||
}
|
||||
|
||||
// WithdrawFiatFunds returns a withdrawal ID when a withdrawal is
|
||||
|
||||
@@ -194,7 +194,7 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
|
||||
var feeBuilder = setFeeBuilder()
|
||||
b.GetFeeByType(feeBuilder)
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
if !areTestAPIKeysSet() {
|
||||
if feeBuilder.FeeType != exchange.OfflineTradeFee {
|
||||
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
|
||||
}
|
||||
@@ -282,7 +282,6 @@ func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
expectedResult := exchange.AutoWithdrawCryptoText + " & " + exchange.NoFiatWithdrawalsText
|
||||
|
||||
withdrawPermissions := b.FormatWithdrawPermissions()
|
||||
if withdrawPermissions != expectedResult {
|
||||
t.Errorf("Expected: %s, Received: %s", expectedResult, withdrawPermissions)
|
||||
@@ -382,7 +381,6 @@ func TestCancelExchangeOrder(t *testing.T) {
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders && !mockTests {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -407,7 +405,6 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders && !mockTests {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
|
||||
@@ -53,8 +53,9 @@ func (b *Binance) WsConnect() error {
|
||||
kline +
|
||||
"/" +
|
||||
depth
|
||||
for _, ePair := range b.GetEnabledPairs(asset.Spot) {
|
||||
err = b.SeedLocalCache(ePair)
|
||||
enabledPairs := b.GetEnabledPairs(asset.Spot)
|
||||
for i := range enabledPairs {
|
||||
err = b.SeedLocalCache(enabledPairs[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -426,16 +426,18 @@ func (b *Binance) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
|
||||
}
|
||||
|
||||
response, err := b.NewOrder(&orderRequest)
|
||||
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
if response.OrderID > 0 {
|
||||
submitOrderResponse.OrderID = strconv.FormatInt(response.OrderID, 10)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
if response.ExecutedQty == response.OrigQty {
|
||||
submitOrderResponse.FullyMatched = true
|
||||
}
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
|
||||
return submitOrderResponse, err
|
||||
return submitOrderResponse, nil
|
||||
}
|
||||
|
||||
// ModifyOrder will allow of changing orderbook placement and limit to
|
||||
|
||||
@@ -85,8 +85,9 @@ const (
|
||||
// depending on some factors (e.g. servers load, endpoint, etc.).
|
||||
type Bitfinex struct {
|
||||
exchange.Base
|
||||
WebsocketConn *wshandler.WebsocketConnection
|
||||
WebsocketSubdChannels map[int]WebsocketChanInfo
|
||||
WebsocketConn *wshandler.WebsocketConnection
|
||||
AuthenticatedWebsocketConn *wshandler.WebsocketConnection
|
||||
WebsocketSubdChannels map[int]WebsocketChanInfo
|
||||
}
|
||||
|
||||
// GetPlatformStatus returns the Bifinex platform status
|
||||
@@ -358,11 +359,11 @@ func (b *Bitfinex) GetTradesV2(currencyPair string, timestampStart, timestampEnd
|
||||
}
|
||||
|
||||
var tempHistory TradeStructureV2
|
||||
for _, data := range resp {
|
||||
tempHistory.TID = int64(data[0].(float64))
|
||||
tempHistory.Timestamp = int64(data[1].(float64))
|
||||
tempHistory.Amount = data[2].(float64)
|
||||
tempHistory.Price = data[3].(float64)
|
||||
for i := range resp {
|
||||
tempHistory.TID = int64(resp[i][0].(float64))
|
||||
tempHistory.Timestamp = int64(resp[i][1].(float64))
|
||||
tempHistory.Amount = resp[i][2].(float64)
|
||||
tempHistory.Price = resp[i][3].(float64)
|
||||
tempHistory.Exchange = b.Name
|
||||
tempHistory.Type = order.Buy.String()
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package bitfinex
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -25,37 +27,43 @@ const (
|
||||
)
|
||||
|
||||
var b Bitfinex
|
||||
var wsAuthExecuted bool
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
func TestMain(m *testing.M) {
|
||||
b.SetDefaults()
|
||||
cfg := config.GetConfig()
|
||||
err := cfg.LoadConfig("../../testdata/configtest.json", true)
|
||||
if err != nil {
|
||||
t.Fatal("Bitfinex load config error", err)
|
||||
log.Fatal("Bitfinex load config error", err)
|
||||
}
|
||||
bfxConfig, err := cfg.GetExchangeConfig("Bitfinex")
|
||||
if err != nil {
|
||||
t.Error("Bitfinex Setup() init error")
|
||||
log.Fatal("Bitfinex Setup() init error")
|
||||
}
|
||||
err = b.Setup(bfxConfig)
|
||||
if err != nil {
|
||||
t.Fatal("Bitfinex setup error", err)
|
||||
log.Fatal("Bitfinex setup error", err)
|
||||
}
|
||||
b.API.Credentials.Key = apiKey
|
||||
b.API.Credentials.Secret = apiSecret
|
||||
if !b.Enabled || b.API.AuthenticatedSupport ||
|
||||
b.Verbose || b.Websocket.IsEnabled() || len(b.BaseCurrencies) < 1 {
|
||||
t.Error("Bitfinex Setup values not set correctly")
|
||||
log.Fatal("Bitfinex Setup values not set correctly")
|
||||
}
|
||||
|
||||
if areTestAPIKeysSet() {
|
||||
b.API.AuthenticatedSupport = true
|
||||
b.API.AuthenticatedWebsocketSupport = true
|
||||
}
|
||||
|
||||
b.API.AuthenticatedSupport = true
|
||||
b.API.AuthenticatedWebsocketSupport = true
|
||||
// custom rate limit for testing
|
||||
b.Requester.SetRateLimit(true, time.Millisecond*300, 1)
|
||||
b.Requester.SetRateLimit(false, time.Millisecond*300, 1)
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestAppendOptionalDelimiter(t *testing.T) {
|
||||
t.Parallel()
|
||||
curr1 := currency.NewPairFromString("BTCUSD")
|
||||
b.appendOptionalDelimiter(&curr1)
|
||||
if curr1.Delimiter != "" {
|
||||
@@ -71,7 +79,6 @@ func TestAppendOptionalDelimiter(t *testing.T) {
|
||||
|
||||
func TestGetPlatformStatus(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
result, err := b.GetPlatformStatus()
|
||||
if err != nil {
|
||||
t.Errorf("TestGetPlatformStatus error: %s", err)
|
||||
@@ -653,7 +660,7 @@ func setFeeBuilder() *exchange.FeeBuilder {
|
||||
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
var feeBuilder = setFeeBuilder()
|
||||
b.GetFeeByType(feeBuilder)
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
if !areTestAPIKeysSet() {
|
||||
if feeBuilder.FeeType != exchange.OfflineTradeFee {
|
||||
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
|
||||
}
|
||||
@@ -665,11 +672,10 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetFee(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
var feeBuilder = setFeeBuilder()
|
||||
t.Parallel()
|
||||
|
||||
if apiKey != "" || apiSecret != "" {
|
||||
if areTestAPIKeysSet() {
|
||||
// CryptocurrencyTradeFee Basic
|
||||
if resp, err := b.GetFee(feeBuilder); resp != float64(0.002) || err != nil {
|
||||
t.Error(err)
|
||||
@@ -738,20 +744,16 @@ func TestGetFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
t.Parallel()
|
||||
expectedResult := exchange.AutoWithdrawCryptoWithAPIPermissionText + " & " + exchange.AutoWithdrawFiatWithAPIPermissionText
|
||||
|
||||
withdrawPermissions := b.FormatWithdrawPermissions()
|
||||
|
||||
if withdrawPermissions != expectedResult {
|
||||
t.Errorf("Expected: %s, Received: %s", expectedResult, withdrawPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
t.Parallel()
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
}
|
||||
@@ -765,9 +767,7 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
t.Parallel()
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
}
|
||||
@@ -787,9 +787,7 @@ func areTestAPIKeysSet() bool {
|
||||
}
|
||||
|
||||
func TestSubmitOrder(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -806,23 +804,25 @@ func TestSubmitOrder(t *testing.T) {
|
||||
ClientID: "meowOrder",
|
||||
}
|
||||
response, err := b.SubmitOrder(orderSubmission)
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
|
||||
if areTestAPIKeysSet() && err != nil {
|
||||
t.Errorf("Could not cancel orders: %v", err)
|
||||
}
|
||||
if areTestAPIKeysSet() && !response.IsOrderPlaced {
|
||||
t.Error("Order not placed")
|
||||
}
|
||||
if !areTestAPIKeysSet() && err == nil {
|
||||
t.Error("Expecting an error when no keys are set")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCancelExchangeOrder(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -840,15 +840,12 @@ func TestCancelExchangeOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelAllExchangeOrdera(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -871,6 +868,10 @@ func TestCancelAllExchangeOrdera(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestModifyOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
_, err := b.ModifyOrder(&order.Modify{})
|
||||
if err == nil {
|
||||
t.Error("ModifyOrder() Expected error")
|
||||
@@ -878,8 +879,7 @@ func TestModifyOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdraw(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -903,9 +903,7 @@ func TestWithdraw(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawFiat(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -938,9 +936,7 @@ func TestWithdrawFiat(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawInternationalBank(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -979,6 +975,7 @@ func TestWithdrawInternationalBank(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetDepositAddress(t *testing.T) {
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() {
|
||||
_, err := b.GetDepositAddress(currency.BTC, "deposit")
|
||||
if err != nil {
|
||||
@@ -992,40 +989,168 @@ func TestGetDepositAddress(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestWsAuth dials websocket, sends login request.
|
||||
func TestWsAuth(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
if !b.Websocket.IsEnabled() && !b.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
b.WebsocketConn = &wshandler.WebsocketConnection{
|
||||
func setupWs() {
|
||||
b.AuthenticatedWebsocketConn = &wshandler.WebsocketConnection{
|
||||
ExchangeName: b.Name,
|
||||
URL: b.Websocket.GetWebsocketURL(),
|
||||
URL: authenticatedBitfinexWebsocketEndpoint,
|
||||
Verbose: b.Verbose,
|
||||
ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
|
||||
ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
|
||||
}
|
||||
var dialer websocket.Dialer
|
||||
err := b.WebsocketConn.Dial(&dialer, http.Header{})
|
||||
err := b.AuthenticatedWebsocketConn.Dial(&dialer, http.Header{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
log.Fatal(err)
|
||||
}
|
||||
b.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
|
||||
b.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
|
||||
go b.WsReadData(b.AuthenticatedWebsocketConn)
|
||||
go b.WsDataHandler()
|
||||
err = b.WsSendAuth()
|
||||
}
|
||||
|
||||
// TestWsAuth dials websocket, sends login request.
|
||||
func TestWsAuth(t *testing.T) {
|
||||
if !b.Websocket.IsEnabled() && !b.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip("API keys not set, skipping")
|
||||
}
|
||||
runAuth(t)
|
||||
}
|
||||
|
||||
func runAuth(t *testing.T) {
|
||||
setupWs()
|
||||
err := b.WsSendAuth()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
timer := time.NewTimer(sharedtestvalues.WebsocketResponseDefaultTimeout)
|
||||
select {
|
||||
case resp := <-b.Websocket.DataHandler:
|
||||
if resp.(map[string]interface{})["event"] != "auth" && resp.(map[string]interface{})["status"] != "OK" {
|
||||
t.Error("expected successful login")
|
||||
if logResponse, ok := resp.(map[string]interface{}); ok {
|
||||
if logResponse["event"] != "auth" && logResponse["status"] != "OK" {
|
||||
t.Error("expected successful login")
|
||||
}
|
||||
} else {
|
||||
t.Error("Unexpected response")
|
||||
}
|
||||
case <-timer.C:
|
||||
t.Error("Have not received a response")
|
||||
}
|
||||
timer.Stop()
|
||||
wsAuthExecuted = true
|
||||
}
|
||||
|
||||
// TestWsPlaceOrder dials websocket, sends order request.
|
||||
func TestWsPlaceOrder(t *testing.T) {
|
||||
if !b.Websocket.IsEnabled() && !b.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip("API keys not set, skipping")
|
||||
}
|
||||
if !wsAuthExecuted {
|
||||
runAuth(t)
|
||||
}
|
||||
_, err := b.WsNewOrder(&WsNewOrderRequest{
|
||||
CustomID: 1337,
|
||||
Type: order.Buy.String(),
|
||||
Symbol: "tBTCUSD",
|
||||
Amount: 10,
|
||||
Price: -10,
|
||||
})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestWsCancelOrder dials websocket, sends cancel request.
|
||||
func TestWsCancelOrder(t *testing.T) {
|
||||
if !b.Websocket.IsEnabled() && !b.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip("API keys not set, skipping")
|
||||
}
|
||||
if !wsAuthExecuted {
|
||||
runAuth(t)
|
||||
}
|
||||
err := b.WsCancelOrder(1234)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestWsCancelOrder dials websocket, sends modify request.
|
||||
func TestWsUpdateOrder(t *testing.T) {
|
||||
if !b.Websocket.IsEnabled() && !b.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip("API keys not set, skipping")
|
||||
}
|
||||
if !wsAuthExecuted {
|
||||
runAuth(t)
|
||||
}
|
||||
err := b.WsModifyOrder(&WsUpdateOrderRequest{
|
||||
OrderID: 1234,
|
||||
Price: -111,
|
||||
Amount: 111,
|
||||
})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestWsCancelAllOrders dials websocket, sends cancel all request.
|
||||
func TestWsCancelAllOrders(t *testing.T) {
|
||||
if !b.Websocket.IsEnabled() && !b.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip("API keys not set, skipping")
|
||||
}
|
||||
if !wsAuthExecuted {
|
||||
runAuth(t)
|
||||
}
|
||||
err := b.WsCancelAllOrders()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestWsCancelAllOrders dials websocket, sends cancel all request.
|
||||
func TestWsCancelMultiOrders(t *testing.T) {
|
||||
if !b.Websocket.IsEnabled() && !b.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip("API keys not set, skipping")
|
||||
}
|
||||
if !wsAuthExecuted {
|
||||
runAuth(t)
|
||||
}
|
||||
err := b.WsCancelMultiOrders([]int64{1, 2, 3, 4})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestWsNewOffer dials websocket, sends new offer request.
|
||||
func TestWsNewOffer(t *testing.T) {
|
||||
if !b.Websocket.IsEnabled() && !b.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip("API keys not set, skipping")
|
||||
}
|
||||
if !wsAuthExecuted {
|
||||
runAuth(t)
|
||||
}
|
||||
err := b.WsNewOffer(&WsNewOfferRequest{
|
||||
Type: order.Limit.String(),
|
||||
Symbol: "fBTC",
|
||||
Amount: -10,
|
||||
Rate: 10,
|
||||
Period: 30,
|
||||
})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
|
||||
// TestWsCancelOffer dials websocket, sends cancel offer request.
|
||||
func TestWsCancelOffer(t *testing.T) {
|
||||
if !b.Websocket.IsEnabled() && !b.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip("API keys not set, skipping")
|
||||
}
|
||||
if !wsAuthExecuted {
|
||||
runAuth(t)
|
||||
}
|
||||
err := b.WsCancelOffer(1234)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
|
||||
@@ -385,7 +385,7 @@ type WebsocketChanInfo struct {
|
||||
// WebsocketBook holds booking information
|
||||
type WebsocketBook struct {
|
||||
Price float64
|
||||
Count int
|
||||
ID int
|
||||
Amount float64
|
||||
}
|
||||
|
||||
@@ -397,6 +397,16 @@ type WebsocketTrade struct {
|
||||
Amount float64
|
||||
}
|
||||
|
||||
// WebsocketCandle candle data
|
||||
type WebsocketCandle struct {
|
||||
Timestamp int64
|
||||
Open float64
|
||||
Close float64
|
||||
High float64
|
||||
Low float64
|
||||
Volume float64
|
||||
}
|
||||
|
||||
// WebsocketTicker holds ticker information
|
||||
type WebsocketTicker struct {
|
||||
Bid float64
|
||||
@@ -416,7 +426,11 @@ type WebsocketPosition struct {
|
||||
Amount float64
|
||||
Price float64
|
||||
MarginFunding float64
|
||||
MarginFundingType int
|
||||
MarginFundingType int64
|
||||
ProfitLoss float64
|
||||
ProfitLossPercent float64
|
||||
LiquidationPrice float64
|
||||
Leverage float64
|
||||
}
|
||||
|
||||
// WebsocketWallet holds wallet information
|
||||
@@ -459,6 +473,9 @@ type WebsocketTradeData struct {
|
||||
OrderID int64
|
||||
AmountExecuted float64
|
||||
PriceExecuted float64
|
||||
OrderType string
|
||||
OrderPrice float64
|
||||
Maker bool
|
||||
Fee float64
|
||||
FeeCurrency string
|
||||
}
|
||||
@@ -468,21 +485,215 @@ type ErrorCapture struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// TimeInterval represents interval enum.
|
||||
type TimeInterval string
|
||||
// WebsocketHandshake defines the communication between the websocket API for
|
||||
// initial connection
|
||||
type WebsocketHandshake struct {
|
||||
Event string `json:"event"`
|
||||
Code int64 `json:"code"`
|
||||
Version float64 `json:"version"`
|
||||
}
|
||||
|
||||
// TimeInvterval vars
|
||||
var (
|
||||
TimeIntervalMinute = TimeInterval("1m")
|
||||
TimeIntervalFiveMinutes = TimeInterval("5m")
|
||||
TimeIntervalFifteenMinutes = TimeInterval("15m")
|
||||
TimeIntervalThirtyMinutes = TimeInterval("30m")
|
||||
TimeIntervalHour = TimeInterval("1h")
|
||||
TimeIntervalThreeHours = TimeInterval("3h")
|
||||
TimeIntervalSixHours = TimeInterval("6h")
|
||||
TimeIntervalTwelveHours = TimeInterval("12h")
|
||||
TimeIntervalDay = TimeInterval("1d")
|
||||
TimeIntervalSevenDays = TimeInterval("7d")
|
||||
TimeIntervalFourteenDays = TimeInterval("14d")
|
||||
TimeIntervalMonth = TimeInterval("1M")
|
||||
const (
|
||||
authenticatedBitfinexWebsocketEndpoint = "wss://api.bitfinex.com/ws/2"
|
||||
publicBitfinexWebsocketEndpoint = "wss://api-pub.bitfinex.com/ws/2"
|
||||
pong = "pong"
|
||||
wsHeartbeat = "hb"
|
||||
wsPositionSnapshot = "ps"
|
||||
wsPositionNew = "pn"
|
||||
wsPositionUpdate = "pu"
|
||||
wsPositionClose = "pc"
|
||||
wsWalletSnapshot = "ws"
|
||||
wsWalletUpdate = "wu"
|
||||
wsTradeExecutionUpdate = "tu"
|
||||
wsTradeExecuted = "te"
|
||||
wsFundingCreditSnapshot = "fcs"
|
||||
wsFundingCreditNew = "fcn"
|
||||
wsFundingCreditUpdate = "fcu"
|
||||
wsFundingCreditCancel = "fcc"
|
||||
wsFundingLoanSnapshot = "fls"
|
||||
wsFundingLoanNew = "fln"
|
||||
wsFundingLoanUpdate = "flu"
|
||||
wsFundingLoanCancel = "flc"
|
||||
wsFundingTradeExecuted = "fte"
|
||||
wsFundingTradeUpdate = "ftu"
|
||||
wsFundingInfoUpdate = "fiu"
|
||||
wsBalanceUpdate = "bu"
|
||||
wsMarginInfoUpdate = "miu"
|
||||
wsNotification = "n"
|
||||
wsOrderNew = "on"
|
||||
wsOrderUpdate = "ou"
|
||||
wsOrderCancel = "oc"
|
||||
wsFundingOrderSnapshot = "fos"
|
||||
wsFundingOrderNew = "fon"
|
||||
wsFundingOrderUpdate = "fou"
|
||||
wsFundingOrderCancel = "foc"
|
||||
wsCancelMultipleOrders = "oc_multi"
|
||||
wsBook = "book"
|
||||
wsCandles = "candles"
|
||||
wsTicker = "ticker"
|
||||
wsTrades = "trades"
|
||||
wsError = "error"
|
||||
)
|
||||
|
||||
// WsAuthRequest container for WS auth request
|
||||
type WsAuthRequest struct {
|
||||
Event string `json:"event"`
|
||||
APIKey string `json:"apiKey"`
|
||||
AuthPayload string `json:"authPayload"`
|
||||
AuthSig string `json:"authSig"`
|
||||
AuthNonce string `json:"authNonce"`
|
||||
DeadManSwitch int64 `json:"dms,omitempty"`
|
||||
}
|
||||
|
||||
// WsFundingOffer funding offer received via websocket
|
||||
type WsFundingOffer struct {
|
||||
ID int64
|
||||
Symbol string
|
||||
Created int64
|
||||
Updated int64
|
||||
Amount float64
|
||||
AmountOrig float64
|
||||
Type string
|
||||
Flags interface{}
|
||||
Status string
|
||||
Rate float64
|
||||
Period int64
|
||||
Notify bool
|
||||
Hidden bool
|
||||
Insure bool
|
||||
Renew bool
|
||||
RateReal float64
|
||||
}
|
||||
|
||||
// WsCredit credit details received via websocket
|
||||
type WsCredit struct {
|
||||
ID int64
|
||||
Symbol string
|
||||
Side string
|
||||
Created int64
|
||||
Updated int64
|
||||
Amount float64
|
||||
Flags interface{}
|
||||
Status string
|
||||
Rate float64
|
||||
Period int64
|
||||
Opened int64
|
||||
LastPayout int64
|
||||
Notify bool
|
||||
Hidden bool
|
||||
Insure bool
|
||||
Renew bool
|
||||
RateReal float64
|
||||
NoClose bool
|
||||
PositionPair string
|
||||
}
|
||||
|
||||
// WsWallet wallet update details received via websocket
|
||||
type WsWallet struct {
|
||||
Type string
|
||||
Currency string
|
||||
Balance float64
|
||||
UnsettledInterest float64
|
||||
BalanceAvailable float64
|
||||
}
|
||||
|
||||
// WsBalanceInfo the total and net assets in your account received via websocket
|
||||
type WsBalanceInfo struct {
|
||||
TotalAssetsUnderManagement float64
|
||||
NetAssetsUnderManagement float64
|
||||
}
|
||||
|
||||
// WsFundingInfo account funding info received via websocket
|
||||
type WsFundingInfo struct {
|
||||
Symbol string
|
||||
YieldLoan float64
|
||||
YieldLend float64
|
||||
DurationLoan float64
|
||||
DurationLend float64
|
||||
}
|
||||
|
||||
// WsMarginInfoBase account margin info received via websocket
|
||||
type WsMarginInfoBase struct {
|
||||
UserProfitLoss float64
|
||||
UserSwaps float64
|
||||
MarginBalance float64
|
||||
MarginNet float64
|
||||
}
|
||||
|
||||
// WsMarginInfoBase recent funding trades received via websocket
|
||||
type WsFundingTrade struct {
|
||||
ID int64
|
||||
Symbol string
|
||||
MTSCreated int64
|
||||
OfferID int64
|
||||
Amount float64
|
||||
Rate float64
|
||||
Period int64
|
||||
Maker bool
|
||||
}
|
||||
|
||||
// WsNewOrderRequest new order request...
|
||||
type WsNewOrderRequest struct {
|
||||
GroupID int64 `json:"gid,omitempty"`
|
||||
CustomID int64 `json:"cid,omitempty"`
|
||||
Type string `json:"type"`
|
||||
Symbol string `json:"symbol"`
|
||||
Amount float64 `json:"amount,string"`
|
||||
Price float64 `json:"price,string"`
|
||||
Leverage int64 `json:"lev,omitempty"`
|
||||
TrailingPrice float64 `json:"price_trailing,string,omitempty"`
|
||||
AuxiliaryLimitPrice float64 `json:"price_aux_limit,string,omitempty"`
|
||||
StopPrice float64 `json:"price_oco_stop,string,omitempty"`
|
||||
Flags int64 `json:"flags,omitempty"`
|
||||
TimeInForce string `json:"tif,omitempty"`
|
||||
}
|
||||
|
||||
// WsUpdateOrderRequest update order request...
|
||||
type WsUpdateOrderRequest struct {
|
||||
OrderID int64 `json:"id,omitempty"`
|
||||
CustomID int64 `json:"cid,omitempty"`
|
||||
CustomIDDate string `json:"cid_date,omitempty"`
|
||||
GroupID int64 `json:"gid,omitempty"`
|
||||
Price float64 `json:"price,string,omitempty"`
|
||||
Amount float64 `json:"amount,string,omitempty"`
|
||||
Leverage int64 `json:"lev,omitempty"`
|
||||
Delta float64 `json:"delta,string,omitempty"`
|
||||
AuxiliaryLimitPrice float64 `json:"price_aux_limit,string,omitempty"`
|
||||
TrailingPrice float64 `json:"price_trailing,string,omitempty"`
|
||||
Flags int64 `json:"flags,omitempty"`
|
||||
TimeInForce string `json:"tif,omitempty"`
|
||||
}
|
||||
|
||||
// WsCancelOrderRequest cancel order request...
|
||||
type WsCancelOrderRequest struct {
|
||||
OrderID int64 `json:"id,omitempty"`
|
||||
CustomID int64 `json:"cid,omitempty"`
|
||||
CustomIDDate string `json:"cid_date,omitempty"`
|
||||
}
|
||||
|
||||
// WsCancelGroupOrdersRequest cancel orders request...
|
||||
type WsCancelGroupOrdersRequest struct {
|
||||
OrderID []int64 `json:"id,omitempty"`
|
||||
CustomID [][]int64 `json:"cid,omitempty"`
|
||||
GroupOrderID []int64 `json:"gid,omitempty"`
|
||||
}
|
||||
|
||||
// WsNewOfferRequest new offer request
|
||||
type WsNewOfferRequest struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
Symbol string `json:"symbol,omitempty"`
|
||||
Amount float64 `json:"amount,string,omitempty"`
|
||||
Rate float64 `json:"rate,string,omitempty"`
|
||||
Period float64 `json:"period,omitempty"`
|
||||
Flags int64 `json:"flags,omitempty"`
|
||||
}
|
||||
|
||||
// WsCancelOfferRequest cancel offer request
|
||||
type WsCancelOfferRequest struct {
|
||||
OrderID int64 `json:"id"`
|
||||
}
|
||||
|
||||
// WsCancelAllOrdersRequest cancel all orders request
|
||||
type WsCancelAllOrdersRequest struct {
|
||||
All int64 `json:"all"`
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -87,7 +87,6 @@ func (b *Bitfinex) SetDefaults() {
|
||||
CancelOrder: true,
|
||||
SubmitOrder: true,
|
||||
SubmitOrders: true,
|
||||
ModifyOrder: true,
|
||||
DepositHistory: true,
|
||||
WithdrawalHistory: true,
|
||||
TradeFetching: true,
|
||||
@@ -99,12 +98,21 @@ func (b *Bitfinex) SetDefaults() {
|
||||
CryptoWithdrawalFee: true,
|
||||
},
|
||||
WebsocketCapabilities: protocol.Features{
|
||||
AccountBalance: true,
|
||||
CancelOrders: true,
|
||||
CancelOrder: true,
|
||||
SubmitOrder: true,
|
||||
ModifyOrder: true,
|
||||
TickerFetching: true,
|
||||
KlineFetching: true,
|
||||
TradeFetching: true,
|
||||
OrderbookFetching: true,
|
||||
AccountInfo: true,
|
||||
Subscribe: true,
|
||||
Unsubscribe: true,
|
||||
AuthenticatedEndpoints: true,
|
||||
MessageCorrelation: true,
|
||||
DeadMansSwitch: true,
|
||||
},
|
||||
WithdrawPermissions: exchange.AutoWithdrawCryptoWithAPIPermission |
|
||||
exchange.AutoWithdrawFiatWithAPIPermission,
|
||||
@@ -121,7 +129,7 @@ func (b *Bitfinex) SetDefaults() {
|
||||
|
||||
b.API.Endpoints.URLDefault = bitfinexAPIURLBase
|
||||
b.API.Endpoints.URL = b.API.Endpoints.URLDefault
|
||||
b.API.Endpoints.WebsocketURL = bitfinexWebsocket
|
||||
b.API.Endpoints.WebsocketURL = publicBitfinexWebsocketEndpoint
|
||||
b.Websocket = wshandler.New()
|
||||
b.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
|
||||
b.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
|
||||
@@ -146,7 +154,7 @@ func (b *Bitfinex) Setup(exch *config.ExchangeConfig) error {
|
||||
Verbose: exch.Verbose,
|
||||
AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
|
||||
WebsocketTimeout: exch.WebsocketTrafficTimeout,
|
||||
DefaultURL: bitfinexWebsocket,
|
||||
DefaultURL: publicBitfinexWebsocketEndpoint,
|
||||
ExchangeName: exch.Name,
|
||||
RunningURL: exch.API.Endpoints.WebsocketURL,
|
||||
Connector: b.WsConnect,
|
||||
@@ -166,6 +174,14 @@ func (b *Bitfinex) Setup(exch *config.ExchangeConfig) error {
|
||||
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
|
||||
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
|
||||
}
|
||||
b.AuthenticatedWebsocketConn = &wshandler.WebsocketConnection{
|
||||
ExchangeName: b.Name,
|
||||
URL: authenticatedBitfinexWebsocketEndpoint,
|
||||
ProxyURL: b.Websocket.GetProxyAddress(),
|
||||
Verbose: b.Verbose,
|
||||
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
|
||||
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
|
||||
}
|
||||
|
||||
b.Websocket.Orderbook.Setup(
|
||||
exch.WebsocketOrderbookBufferLimit,
|
||||
@@ -318,6 +334,7 @@ func (b *Bitfinex) UpdateOrderbook(p currency.Pair, assetType asset.Item) (order
|
||||
func (b *Bitfinex) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var response exchange.AccountInfo
|
||||
response.Exchange = b.Name
|
||||
|
||||
accountBalance, err := b.GetAccountBalance()
|
||||
if err != nil {
|
||||
return response, err
|
||||
@@ -358,39 +375,67 @@ func (b *Bitfinex) GetExchangeHistory(p currency.Pair, assetType asset.Item) ([]
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (b *Bitfinex) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
|
||||
func (b *Bitfinex) SubmitOrder(o *order.Submit) (order.SubmitResponse, error) {
|
||||
var submitOrderResponse order.SubmitResponse
|
||||
if err := s.Validate(); err != nil {
|
||||
err := o.Validate()
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
if b.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
submitOrderResponse.OrderID, err = b.WsNewOrder(&WsNewOrderRequest{
|
||||
CustomID: b.AuthenticatedWebsocketConn.GenerateMessageID(false),
|
||||
Type: o.OrderType.String(),
|
||||
Symbol: b.FormatExchangeCurrency(o.Pair, asset.Spot).String(),
|
||||
Amount: o.Amount,
|
||||
Price: o.Price,
|
||||
})
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
} else {
|
||||
var response Order
|
||||
isBuying := o.OrderSide == order.Buy
|
||||
b.appendOptionalDelimiter(&o.Pair)
|
||||
response, err = b.NewOrder(o.Pair.String(),
|
||||
o.Amount,
|
||||
o.Price,
|
||||
isBuying,
|
||||
o.OrderType.String(),
|
||||
false)
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
if response.OrderID > 0 {
|
||||
submitOrderResponse.OrderID = strconv.FormatInt(response.OrderID, 10)
|
||||
}
|
||||
if response.RemainingAmount == 0 {
|
||||
submitOrderResponse.FullyMatched = true
|
||||
}
|
||||
|
||||
var isBuying bool
|
||||
if s.OrderSide == order.Buy {
|
||||
isBuying = true
|
||||
}
|
||||
b.appendOptionalDelimiter(&s.Pair)
|
||||
response, err := b.NewOrder(s.Pair.String(),
|
||||
s.Amount,
|
||||
s.Price,
|
||||
isBuying,
|
||||
s.OrderType.String(),
|
||||
false)
|
||||
|
||||
if response.OrderID > 0 {
|
||||
submitOrderResponse.OrderID = strconv.FormatInt(response.OrderID, 10)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
}
|
||||
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
// ModifyOrder will allow of changing orderbook placement and limit to
|
||||
// market conversion
|
||||
func (b *Bitfinex) ModifyOrder(action *order.Modify) (string, error) {
|
||||
return "", common.ErrFunctionNotSupported
|
||||
orderIDInt, err := strconv.ParseInt(action.OrderID, 10, 64)
|
||||
if err != nil {
|
||||
return action.OrderID, err
|
||||
}
|
||||
if b.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
if action.Side == order.Sell && action.Amount > 0 {
|
||||
action.Amount = -1 * action.Amount
|
||||
}
|
||||
err = b.WsModifyOrder(&WsUpdateOrderRequest{
|
||||
OrderID: orderIDInt,
|
||||
Price: action.Price,
|
||||
Amount: action.Amount,
|
||||
})
|
||||
return action.OrderID, err
|
||||
}
|
||||
return "", common.ErrNotYetImplemented
|
||||
}
|
||||
|
||||
// CancelOrder cancels an order by its corresponding ID number
|
||||
@@ -399,13 +444,22 @@ func (b *Bitfinex) CancelOrder(order *order.Cancel) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = b.CancelExistingOrder(orderIDInt)
|
||||
if b.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
err = b.WsCancelOrder(orderIDInt)
|
||||
} else {
|
||||
_, err = b.CancelExistingOrder(orderIDInt)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// CancelAllOrders cancels all orders associated with a currency pair
|
||||
func (b *Bitfinex) CancelAllOrders(_ *order.Cancel) (order.CancelAllResponse, error) {
|
||||
_, err := b.CancelAllExistingOrders()
|
||||
var err error
|
||||
if b.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
err = b.WsCancelAllOrders()
|
||||
} else {
|
||||
_, err = b.CancelAllExistingOrders()
|
||||
}
|
||||
return order.CancelAllResponse{}, err
|
||||
}
|
||||
|
||||
@@ -422,7 +476,8 @@ func (b *Bitfinex) GetDepositAddress(cryptocurrency currency.Code, accountID str
|
||||
return "", err
|
||||
}
|
||||
|
||||
resp, err := b.NewDeposit(method, accountID, 0)
|
||||
var resp DepositResponse
|
||||
resp, err = b.NewDeposit(method, accountID, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -547,7 +602,7 @@ func (b *Bitfinex) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail,
|
||||
orderDetail.Status = order.UnknownStatus
|
||||
}
|
||||
|
||||
// API docs discrepency. Example contains prefixed "exchange "
|
||||
// API docs discrepancy. Example contains prefixed "exchange "
|
||||
// Return type suggests “market” / “limit” / “stop” / “trailing-stop”
|
||||
orderType := strings.Replace(resp[i].Type, "exchange ", "", 1)
|
||||
if orderType == "trailing-stop" {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package bitflyer
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
@@ -9,7 +11,6 @@ import (
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
// Please supply your own keys here for due diligence testing
|
||||
@@ -21,19 +22,16 @@ const (
|
||||
|
||||
var b Bitflyer
|
||||
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
func TestMain(m *testing.M) {
|
||||
b.SetDefaults()
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
cfg := config.GetConfig()
|
||||
err := cfg.LoadConfig("../../testdata/configtest.json", true)
|
||||
if err != nil {
|
||||
t.Fatal("Bitflyer load config error", err)
|
||||
log.Fatal("Bitflyer load config error", err)
|
||||
}
|
||||
bitflyerConfig, err := cfg.GetExchangeConfig("Bitflyer")
|
||||
if err != nil {
|
||||
t.Error("bitflyer Setup() init error")
|
||||
log.Fatal("bitflyer Setup() init error")
|
||||
}
|
||||
|
||||
bitflyerConfig.API.AuthenticatedSupport = true
|
||||
@@ -42,8 +40,10 @@ func TestSetup(t *testing.T) {
|
||||
|
||||
err = b.Setup(bitflyerConfig)
|
||||
if err != nil {
|
||||
t.Fatal("Bitflyer setup error", err)
|
||||
log.Fatal("Bitflyer setup error", err)
|
||||
}
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestGetLatestBlockCA(t *testing.T) {
|
||||
@@ -85,7 +85,7 @@ func TestGetAddressInfoCA(t *testing.T) {
|
||||
t.Error("Bitflyer - GetAddressInfoCA() error:", err)
|
||||
}
|
||||
if v.UnconfirmedBalance == 0 || v.ConfirmedBalance == 0 {
|
||||
log.Warn(log.ExchangeSys, "Donation wallet is empty :( - please consider donating")
|
||||
t.Log("Donation wallet is empty :( - please consider donating")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ func setFeeBuilder() *exchange.FeeBuilder {
|
||||
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
var feeBuilder = setFeeBuilder()
|
||||
b.GetFeeByType(feeBuilder)
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
if !areTestAPIKeysSet() {
|
||||
if feeBuilder.FeeType != exchange.OfflineTradeFee {
|
||||
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
|
||||
}
|
||||
@@ -183,11 +183,10 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetFee(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
t.Parallel()
|
||||
var feeBuilder = setFeeBuilder()
|
||||
|
||||
if apiKey != "" || apiSecret != "" {
|
||||
if areTestAPIKeysSet() {
|
||||
// CryptocurrencyTradeFee Basic
|
||||
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
|
||||
t.Error(err)
|
||||
@@ -256,20 +255,16 @@ func TestGetFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
t.Parallel()
|
||||
expectedResult := exchange.AutoWithdrawFiatText + " & " + exchange.WithdrawCryptoViaWebsiteOnlyText
|
||||
|
||||
withdrawPermissions := b.FormatWithdrawPermissions()
|
||||
|
||||
if withdrawPermissions != expectedResult {
|
||||
t.Errorf("Expected: %s, Received: %s", expectedResult, withdrawPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
t.Parallel()
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
}
|
||||
@@ -283,9 +278,7 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
t.Parallel()
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
}
|
||||
@@ -303,9 +296,7 @@ func areTestAPIKeysSet() bool {
|
||||
}
|
||||
|
||||
func TestSubmitOrder(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -328,9 +319,7 @@ func TestSubmitOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelExchangeOrder(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -351,9 +340,7 @@ func TestCancelExchangeOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -374,8 +361,11 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdraw(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
withdrawCryptoRequest := exchange.CryptoWithdrawRequest{
|
||||
GenericWithdrawRequestInfo: exchange.GenericWithdrawRequestInfo{
|
||||
Amount: -1,
|
||||
@@ -385,10 +375,6 @@ func TestWithdraw(t *testing.T) {
|
||||
Address: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
}
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
_, err := b.WithdrawCryptocurrencyFunds(&withdrawCryptoRequest)
|
||||
if err != common.ErrNotYetImplemented {
|
||||
t.Errorf("Expected 'Not Yet Implemented', received %v", err)
|
||||
@@ -396,6 +382,10 @@ func TestWithdraw(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestModifyOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
_, err := b.ModifyOrder(&order.Modify{})
|
||||
if err == nil {
|
||||
t.Error("ModifyOrder() Expected error")
|
||||
@@ -403,9 +393,7 @@ func TestModifyOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawFiat(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -419,9 +407,7 @@ func TestWithdrawFiat(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawInternationalBank(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package bithumb
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
@@ -20,19 +22,16 @@ const (
|
||||
|
||||
var b Bithumb
|
||||
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
func TestMain(m *testing.M) {
|
||||
b.SetDefaults()
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
cfg := config.GetConfig()
|
||||
err := cfg.LoadConfig("../../testdata/configtest.json", true)
|
||||
if err != nil {
|
||||
t.Fatal("Bithumb load config error", err)
|
||||
log.Fatal("Bithumb load config error", err)
|
||||
}
|
||||
bitConfig, err := cfg.GetExchangeConfig("Bithumb")
|
||||
if err != nil {
|
||||
t.Error("Bithumb Setup() init error")
|
||||
log.Fatal("Bithumb Setup() init error")
|
||||
}
|
||||
|
||||
bitConfig.API.AuthenticatedSupport = true
|
||||
@@ -41,8 +40,10 @@ func TestSetup(t *testing.T) {
|
||||
|
||||
err = b.Setup(bitConfig)
|
||||
if err != nil {
|
||||
t.Fatal("Bithumb setup error", err)
|
||||
log.Fatal("Bithumb setup error", err)
|
||||
}
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestGetTradablePairs(t *testing.T) {
|
||||
@@ -87,7 +88,7 @@ func TestGetTransactionHistory(t *testing.T) {
|
||||
|
||||
func TestGetAccountBalance(t *testing.T) {
|
||||
t.Parallel()
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
@@ -98,11 +99,11 @@ func TestGetAccountBalance(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetWalletAddress(t *testing.T) {
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
t.Parallel()
|
||||
_, err := b.GetWalletAddress("")
|
||||
if err == nil {
|
||||
t.Error("Bithumb GetWalletAddress() Expected error")
|
||||
@@ -167,7 +168,7 @@ func TestWithdrawCrypto(t *testing.T) {
|
||||
|
||||
func TestRequestKRWDepositDetails(t *testing.T) {
|
||||
t.Parallel()
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := b.RequestKRWDepositDetails()
|
||||
@@ -213,7 +214,7 @@ func setFeeBuilder() *exchange.FeeBuilder {
|
||||
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
var feeBuilder = setFeeBuilder()
|
||||
b.GetFeeByType(feeBuilder)
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
if !areTestAPIKeysSet() {
|
||||
if feeBuilder.FeeType != exchange.OfflineTradeFee {
|
||||
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
|
||||
}
|
||||
@@ -225,10 +226,7 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetFee(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
var feeBuilder = setFeeBuilder()
|
||||
|
||||
// CryptocurrencyTradeFee Basic
|
||||
if resp, err := b.GetFee(feeBuilder); resp != float64(0.0025) || err != nil {
|
||||
t.Error(err)
|
||||
@@ -296,20 +294,16 @@ func TestGetFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
t.Parallel()
|
||||
expectedResult := exchange.AutoWithdrawCryptoText + " & " + exchange.AutoWithdrawFiatText
|
||||
|
||||
withdrawPermissions := b.FormatWithdrawPermissions()
|
||||
|
||||
if withdrawPermissions != expectedResult {
|
||||
t.Errorf("Expected: %s, Received: %s", expectedResult, withdrawPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
t.Parallel()
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
OrderSide: order.Sell,
|
||||
@@ -324,9 +318,7 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
t.Parallel()
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
}
|
||||
@@ -346,9 +338,7 @@ func areTestAPIKeysSet() bool {
|
||||
}
|
||||
|
||||
func TestSubmitOrder(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -373,15 +363,12 @@ func TestSubmitOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelExchangeOrder(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -399,15 +386,12 @@ func TestCancelExchangeOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -431,7 +415,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
if apiKey != "" || apiSecret != "" {
|
||||
if areTestAPIKeysSet() {
|
||||
_, err := b.GetAccountInfo()
|
||||
if err != nil {
|
||||
t.Error("Bithumb GetAccountInfo() error", err)
|
||||
@@ -445,6 +429,7 @@ func TestGetAccountInfo(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestModifyOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
curr := currency.NewPairFromString("BTCUSD")
|
||||
_, err := b.ModifyOrder(&order.Modify{
|
||||
OrderID: "1337",
|
||||
@@ -458,8 +443,7 @@ func TestModifyOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdraw(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -483,9 +467,7 @@ func TestWithdraw(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawFiat(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -519,9 +501,7 @@ func TestWithdrawFiat(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawInternationalBank(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -534,7 +514,8 @@ func TestWithdrawInternationalBank(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetDepositAddress(t *testing.T) {
|
||||
if apiKey != "" && apiSecret != "" {
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() {
|
||||
_, err := b.GetDepositAddress(currency.BTC, "")
|
||||
if err != nil {
|
||||
t.Error("GetDepositAddress() error", err)
|
||||
|
||||
@@ -220,9 +220,9 @@ func (b *Bithumb) FetchOrderbook(p currency.Pair, assetType asset.Item) (orderbo
|
||||
// UpdateOrderbook updates and returns the orderbook for a currency pair
|
||||
func (b *Bithumb) UpdateOrderbook(p currency.Pair, assetType asset.Item) (orderbook.Base, error) {
|
||||
var orderBook orderbook.Base
|
||||
currency := p.Base.String()
|
||||
curr := p.Base.String()
|
||||
|
||||
orderbookNew, err := b.GetOrderBook(currency)
|
||||
orderbookNew, err := b.GetOrderBook(curr)
|
||||
if err != nil {
|
||||
return orderBook, err
|
||||
}
|
||||
@@ -311,20 +311,25 @@ func (b *Bithumb) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
|
||||
if s.OrderSide == order.Buy {
|
||||
var result MarketBuy
|
||||
result, err = b.MarketBuyOrder(s.Pair.Base.String(), s.Amount)
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
orderID = result.OrderID
|
||||
} else if s.OrderSide == order.Sell {
|
||||
var result MarketSell
|
||||
result, err = b.MarketSellOrder(s.Pair.Base.String(), s.Amount)
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
orderID = result.OrderID
|
||||
}
|
||||
|
||||
if orderID != "" {
|
||||
submitOrderResponse.OrderID = orderID
|
||||
submitOrderResponse.FullyMatched = true
|
||||
}
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
}
|
||||
return submitOrderResponse, err
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
|
||||
return submitOrderResponse, nil
|
||||
}
|
||||
|
||||
// ModifyOrder will allow of changing orderbook placement and limit to
|
||||
@@ -358,12 +363,13 @@ func (b *Bithumb) CancelAllOrders(orderCancellation *order.Cancel) (order.Cancel
|
||||
}
|
||||
|
||||
var allOrders []OrderData
|
||||
for _, currency := range b.GetEnabledPairs(asset.Spot) {
|
||||
currs := b.GetEnabledPairs(asset.Spot)
|
||||
for i := range currs {
|
||||
orders, err := b.GetOrders("",
|
||||
orderCancellation.Side.String(),
|
||||
"100",
|
||||
"",
|
||||
currency.Base.String())
|
||||
currs[i].Base.String())
|
||||
if err != nil {
|
||||
return cancelAllOrdersResponse, err
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package bitmex
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -25,19 +27,16 @@ const (
|
||||
|
||||
var b Bitmex
|
||||
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
func TestMain(m *testing.M) {
|
||||
b.SetDefaults()
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
cfg := config.GetConfig()
|
||||
err := cfg.LoadConfig("../../testdata/configtest.json", true)
|
||||
if err != nil {
|
||||
t.Fatal("Bitmex load config error", err)
|
||||
log.Fatal("Bitmex load config error", err)
|
||||
}
|
||||
bitmexConfig, err := cfg.GetExchangeConfig("Bitmex")
|
||||
if err != nil {
|
||||
t.Error("Bitmex Setup() init error")
|
||||
log.Fatal("Bitmex Setup() init error")
|
||||
}
|
||||
|
||||
bitmexConfig.API.AuthenticatedSupport = true
|
||||
@@ -47,8 +46,9 @@ func TestSetup(t *testing.T) {
|
||||
|
||||
err = b.Setup(bitmexConfig)
|
||||
if err != nil {
|
||||
t.Fatal("Bitmex setup error", err)
|
||||
log.Fatal("Bitmex setup error", err)
|
||||
}
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestStart(t *testing.T) {
|
||||
@@ -386,7 +386,7 @@ func setFeeBuilder() *exchange.FeeBuilder {
|
||||
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
var feeBuilder = setFeeBuilder()
|
||||
b.GetFeeByType(feeBuilder)
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
if !areTestAPIKeysSet() {
|
||||
if feeBuilder.FeeType != exchange.OfflineTradeFee {
|
||||
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
|
||||
}
|
||||
@@ -398,9 +398,6 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetFee(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var feeBuilder = setFeeBuilder()
|
||||
// CryptocurrencyTradeFee Basic
|
||||
if resp, err := b.GetFee(feeBuilder); resp != float64(0.00075) || err != nil {
|
||||
@@ -469,21 +466,15 @@ func TestGetFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
expectedResult := exchange.AutoWithdrawCryptoWithAPIPermissionText + " & " + exchange.WithdrawCryptoWith2FAText +
|
||||
" & " + exchange.WithdrawCryptoWithEmailText + " & " + exchange.NoFiatWithdrawalsText
|
||||
|
||||
withdrawPermissions := b.FormatWithdrawPermissions()
|
||||
|
||||
if withdrawPermissions != expectedResult {
|
||||
t.Errorf("Expected: %s, Received: %s", expectedResult, withdrawPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
}
|
||||
@@ -497,9 +488,6 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
Currencies: []currency.Pair{currency.NewPair(currency.LTC,
|
||||
@@ -521,9 +509,6 @@ func areTestAPIKeysSet() bool {
|
||||
}
|
||||
|
||||
func TestSubmitOrder(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -548,15 +533,11 @@ func TestSubmitOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelExchangeOrder(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "123456789012345678901234567890123456",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -574,15 +555,11 @@ func TestCancelExchangeOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "123456789012345678901234567890123456",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -605,7 +582,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
if apiKey != "" || apiSecret != "" {
|
||||
if areTestAPIKeysSet() {
|
||||
_, err := b.GetAccountInfo()
|
||||
if err != nil {
|
||||
t.Error("GetAccountInfo() error", err)
|
||||
@@ -619,6 +596,9 @@ func TestGetAccountInfo(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestModifyOrder(t *testing.T) {
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
_, err := b.ModifyOrder(&order.Modify{OrderID: "1337"})
|
||||
if err == nil {
|
||||
t.Error("ModifyOrder() error")
|
||||
@@ -626,9 +606,6 @@ func TestModifyOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdraw(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
withdrawCryptoRequest := exchange.CryptoWithdrawRequest{
|
||||
GenericWithdrawRequestInfo: exchange.GenericWithdrawRequestInfo{
|
||||
Amount: -1,
|
||||
@@ -653,9 +630,6 @@ func TestWithdraw(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawFiat(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -668,9 +642,6 @@ func TestWithdrawFiat(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawInternationalBank(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -698,8 +669,6 @@ func TestGetDepositAddress(t *testing.T) {
|
||||
|
||||
// TestWsAuth dials websocket, sends login request.
|
||||
func TestWsAuth(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
if !b.Websocket.IsEnabled() && !b.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
|
||||
@@ -432,15 +432,18 @@ func (b *Bitmex) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
|
||||
}
|
||||
|
||||
response, err := b.CreateOrder(&orderNewParams)
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
if response.OrderID != "" {
|
||||
submitOrderResponse.OrderID = response.OrderID
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
if s.OrderType == order.Market {
|
||||
submitOrderResponse.FullyMatched = true
|
||||
}
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
|
||||
return submitOrderResponse, err
|
||||
return submitOrderResponse, nil
|
||||
}
|
||||
|
||||
// ModifyOrder will allow of changing orderbook placement and limit to
|
||||
|
||||
@@ -38,7 +38,7 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
|
||||
var feeBuilder = setFeeBuilder()
|
||||
b.GetFeeByType(feeBuilder)
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
if !areTestAPIKeysSet() {
|
||||
if feeBuilder.FeeType != exchange.OfflineTradeFee {
|
||||
t.Errorf("Expected %v, received %v",
|
||||
exchange.OfflineTradeFee,
|
||||
@@ -319,7 +319,6 @@ func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
expectedResult := exchange.AutoWithdrawCryptoText +
|
||||
" & " +
|
||||
exchange.AutoWithdrawFiatText
|
||||
|
||||
withdrawPermissions := b.FormatWithdrawPermissions()
|
||||
if withdrawPermissions != expectedResult {
|
||||
t.Errorf("Expected: %s, Received: %s",
|
||||
|
||||
@@ -364,16 +364,18 @@ func (b *Bitstamp) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
|
||||
s.Amount,
|
||||
buy,
|
||||
market)
|
||||
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
if response.ID > 0 {
|
||||
submitOrderResponse.OrderID = strconv.FormatInt(response.ID, 10)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
if s.OrderType == order.Market {
|
||||
submitOrderResponse.FullyMatched = true
|
||||
}
|
||||
|
||||
return submitOrderResponse, err
|
||||
return submitOrderResponse, nil
|
||||
}
|
||||
|
||||
// ModifyOrder will allow of changing orderbook placement and limit to
|
||||
|
||||
@@ -329,7 +329,7 @@ func (b *Bittrex) Withdraw(currency, paymentID, address string, quantity float64
|
||||
var id UUID
|
||||
values := url.Values{}
|
||||
values.Set("currency", currency)
|
||||
values.Set("quantity", fmt.Sprintf("%v", quantity))
|
||||
values.Set("quantity", strconv.FormatFloat(quantity, 'f', -1, 64))
|
||||
values.Set("address", address)
|
||||
if len(paymentID) > 0 {
|
||||
values.Set("paymentid", paymentID)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package bittrex
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
@@ -19,22 +21,16 @@ const (
|
||||
|
||||
var b Bittrex
|
||||
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
func TestMain(m *testing.M) {
|
||||
b.SetDefaults()
|
||||
if b.Name != "Bittrex" {
|
||||
t.Error("Bittrex - SetDefaults() error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
cfg := config.GetConfig()
|
||||
err := cfg.LoadConfig("../../testdata/configtest.json", true)
|
||||
if err != nil {
|
||||
t.Fatal("Bittrex load config error", err)
|
||||
log.Fatal("Bittrex load config error", err)
|
||||
}
|
||||
bConfig, err := cfg.GetExchangeConfig("Bittrex")
|
||||
if err != nil {
|
||||
t.Error("Bittrex Setup() init error")
|
||||
log.Fatal("Bittrex Setup() init error")
|
||||
}
|
||||
bConfig.API.Credentials.Key = apiKey
|
||||
bConfig.API.Credentials.Secret = apiSecret
|
||||
@@ -42,13 +38,15 @@ func TestSetup(t *testing.T) {
|
||||
|
||||
err = b.Setup(bConfig)
|
||||
if err != nil {
|
||||
t.Fatal("Bittrex setup error", err)
|
||||
log.Fatal("Bittrex setup error", err)
|
||||
}
|
||||
|
||||
if !b.IsEnabled() || !b.API.AuthenticatedSupport ||
|
||||
b.Verbose || len(b.BaseCurrencies) < 1 {
|
||||
t.Error("Bittrex Setup values not set correctly")
|
||||
log.Fatal("Bittrex Setup values not set correctly")
|
||||
}
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestGetMarkets(t *testing.T) {
|
||||
@@ -236,7 +234,7 @@ func setFeeBuilder() *exchange.FeeBuilder {
|
||||
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
var feeBuilder = setFeeBuilder()
|
||||
b.GetFeeByType(feeBuilder)
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
if !areTestAPIKeysSet() {
|
||||
if feeBuilder.FeeType != exchange.OfflineTradeFee {
|
||||
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
|
||||
}
|
||||
@@ -248,11 +246,7 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetFee(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var feeBuilder = setFeeBuilder()
|
||||
|
||||
// CryptocurrencyTradeFee Basic
|
||||
if resp, err := b.GetFee(feeBuilder); resp != float64(0.0025) || err != nil {
|
||||
t.Error(err)
|
||||
@@ -320,20 +314,14 @@ func TestGetFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
expectedResult := exchange.AutoWithdrawCryptoWithAPIPermissionText + " & " + exchange.NoFiatWithdrawalsText
|
||||
|
||||
withdrawPermissions := b.FormatWithdrawPermissions()
|
||||
|
||||
if withdrawPermissions != expectedResult {
|
||||
t.Errorf("Expected: %s, Received: %s", expectedResult, withdrawPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
Currencies: []currency.Pair{currency.NewPair(currency.LTC,
|
||||
@@ -351,9 +339,6 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
}
|
||||
@@ -373,9 +358,6 @@ func areTestAPIKeysSet() bool {
|
||||
}
|
||||
|
||||
func TestSubmitOrder(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -401,15 +383,11 @@ func TestSubmitOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelExchangeOrder(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -427,15 +405,11 @@ func TestCancelExchangeOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -458,6 +432,9 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestModifyOrder(t *testing.T) {
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
_, err := b.ModifyOrder(&order.Modify{})
|
||||
if err == nil {
|
||||
t.Error("ModifyOrder() Expected error")
|
||||
@@ -465,8 +442,6 @@ func TestModifyOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdraw(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
withdrawCryptoRequest := exchange.CryptoWithdrawRequest{
|
||||
GenericWithdrawRequestInfo: exchange.GenericWithdrawRequestInfo{
|
||||
Amount: -1,
|
||||
@@ -490,9 +465,6 @@ func TestWithdraw(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawFiat(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -506,9 +478,6 @@ func TestWithdrawFiat(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawInternationalBank(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
@@ -329,7 +329,6 @@ func (b *Bittrex) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
|
||||
}
|
||||
|
||||
buy := s.OrderSide == order.Buy
|
||||
|
||||
if s.OrderType != order.Limit {
|
||||
return submitOrderResponse,
|
||||
errors.New("limit orders only supported on exchange")
|
||||
@@ -346,16 +345,16 @@ func (b *Bittrex) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
|
||||
s.Amount,
|
||||
s.Price)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
if response.Result.ID != "" {
|
||||
submitOrderResponse.OrderID = response.Result.ID
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
}
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
|
||||
return submitOrderResponse, err
|
||||
return submitOrderResponse, nil
|
||||
}
|
||||
|
||||
// ModifyOrder will allow of changing orderbook placement and limit to
|
||||
|
||||
@@ -205,7 +205,7 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
}
|
||||
|
||||
b.GetFeeByType(feeBuilder)
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
if !areTestAPIKeysSet() {
|
||||
if feeBuilder.FeeType != exchange.OfflineTradeFee {
|
||||
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
|
||||
}
|
||||
@@ -320,7 +320,6 @@ func TestCancelExchangeOrder(t *testing.T) {
|
||||
currencyPair := currency.NewPairWithDelimiter(currency.BTC.String(),
|
||||
currency.USD.String(),
|
||||
"-")
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "b334ecef-2b42-4998-b8a4-b6b14f6d2671",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -341,7 +340,6 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
currencyPair := currency.NewPairWithDelimiter(currency.BTC.String(),
|
||||
currency.USD.String(),
|
||||
"-")
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
|
||||
@@ -3,6 +3,7 @@ package btse
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -357,7 +358,9 @@ func (b *BTSE) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
|
||||
resp.IsOrderPlaced = true
|
||||
resp.OrderID = *r
|
||||
}
|
||||
|
||||
if s.OrderType == order.Market {
|
||||
resp.FullyMatched = true
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
@@ -475,7 +478,7 @@ func (b *BTSE) GetOrderInfo(orderID string) (order.Detail, error) {
|
||||
}
|
||||
od.Trades = append(od.Trades, order.TradeHistory{
|
||||
Timestamp: createdAt,
|
||||
TID: fills[i].ID,
|
||||
TID: strconv.FormatInt(fills[i].ID, 10),
|
||||
Price: fills[i].Price,
|
||||
Amount: fills[i].Amount,
|
||||
Exchange: b.Name,
|
||||
@@ -569,7 +572,7 @@ func (b *BTSE) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, err
|
||||
}
|
||||
openOrder.Trades = append(openOrder.Trades, order.TradeHistory{
|
||||
Timestamp: createdAt,
|
||||
TID: fills[i].ID,
|
||||
TID: strconv.FormatInt(fills[i].ID, 10),
|
||||
Price: fills[i].Price,
|
||||
Amount: fills[i].Amount,
|
||||
Exchange: b.Name,
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package coinbasepro
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -25,20 +27,18 @@ const (
|
||||
testPair = "BTC-USD"
|
||||
)
|
||||
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
func TestMain(m *testing.M) {
|
||||
c.SetDefaults()
|
||||
c.Requester.SetRateLimit(false, time.Second, 1)
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
cfg := config.GetConfig()
|
||||
err := cfg.LoadConfig("../../testdata/configtest.json", true)
|
||||
if err != nil {
|
||||
t.Fatal("coinbasepro load config error", err)
|
||||
log.Fatal("coinbasepro load config error", err)
|
||||
}
|
||||
gdxConfig, err := cfg.GetExchangeConfig("CoinbasePro")
|
||||
if err != nil {
|
||||
t.Error("coinbasepro Setup() init error")
|
||||
log.Fatal("coinbasepro Setup() init error")
|
||||
}
|
||||
gdxConfig.API.Credentials.Key = apiKey
|
||||
gdxConfig.API.Credentials.Secret = apiSecret
|
||||
@@ -47,8 +47,10 @@ func TestSetup(t *testing.T) {
|
||||
gdxConfig.API.AuthenticatedWebsocketSupport = true
|
||||
err = c.Setup(gdxConfig)
|
||||
if err != nil {
|
||||
t.Fatal("CoinbasePro setup error", err)
|
||||
log.Fatal("CoinbasePro setup error", err)
|
||||
}
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestGetProducts(t *testing.T) {
|
||||
@@ -198,7 +200,7 @@ func setFeeBuilder() *exchange.FeeBuilder {
|
||||
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
var feeBuilder = setFeeBuilder()
|
||||
c.GetFeeByType(feeBuilder)
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
if !areTestAPIKeysSet() {
|
||||
if feeBuilder.FeeType != exchange.OfflineTradeFee {
|
||||
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
|
||||
}
|
||||
@@ -210,12 +212,9 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetFee(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var feeBuilder = setFeeBuilder()
|
||||
|
||||
if apiKey != "" || apiSecret != "" {
|
||||
if areTestAPIKeysSet() {
|
||||
// CryptocurrencyTradeFee Basic
|
||||
if resp, err := c.GetFee(feeBuilder); resp != float64(0.003) || err != nil {
|
||||
t.Error(err)
|
||||
@@ -371,7 +370,6 @@ func TestCalculateTradingFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
expectedResult := exchange.AutoWithdrawCryptoWithAPIPermissionText + " & " + exchange.AutoWithdrawFiatWithAPIPermissionText
|
||||
withdrawPermissions := c.FormatWithdrawPermissions()
|
||||
if withdrawPermissions != expectedResult {
|
||||
@@ -380,9 +378,6 @@ func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
Currencies: []currency.Pair{currency.NewPair(currency.BTC,
|
||||
@@ -398,9 +393,6 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
Currencies: []currency.Pair{currency.NewPair(currency.BTC,
|
||||
@@ -422,9 +414,6 @@ func areTestAPIKeysSet() bool {
|
||||
}
|
||||
|
||||
func TestSubmitOrder(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -450,15 +439,11 @@ func TestSubmitOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelExchangeOrder(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -476,15 +461,11 @@ func TestCancelExchangeOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -507,6 +488,9 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestModifyOrder(t *testing.T) {
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
_, err := c.ModifyOrder(&order.Modify{})
|
||||
if err == nil {
|
||||
t.Error("ModifyOrder() Expected error")
|
||||
@@ -514,8 +498,6 @@ func TestModifyOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdraw(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
withdrawCryptoRequest := exchange.CryptoWithdrawRequest{
|
||||
GenericWithdrawRequestInfo: exchange.GenericWithdrawRequestInfo{
|
||||
Amount: -1,
|
||||
@@ -539,9 +521,6 @@ func TestWithdraw(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawFiat(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -564,9 +543,6 @@ func TestWithdrawFiat(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawInternationalBank(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -597,8 +573,6 @@ func TestGetDepositAddress(t *testing.T) {
|
||||
|
||||
// TestWsAuth dials websocket, sends login request.
|
||||
func TestWsAuth(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
if !c.Websocket.IsEnabled() && !c.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package coinbasepro
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
@@ -311,7 +310,7 @@ func (c *CoinbasePro) Subscribe(channelToSubscribe wshandler.WebsocketChannelSub
|
||||
},
|
||||
}
|
||||
if channelToSubscribe.Channel == "user" || channelToSubscribe.Channel == "full" {
|
||||
n := fmt.Sprintf("%v", time.Now().Unix())
|
||||
n := strconv.FormatInt(time.Now().Unix(), 10)
|
||||
message := n + "GET" + "/users/self/verify"
|
||||
hmac := crypto.GetHMAC(crypto.HashSHA256, []byte(message),
|
||||
[]byte(c.API.Credentials.Secret))
|
||||
|
||||
@@ -400,16 +400,19 @@ func (c *CoinbasePro) SubmitOrder(s *order.Submit) (order.SubmitResponse, error)
|
||||
default:
|
||||
err = errors.New("order type not supported")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
if s.OrderType == order.Market {
|
||||
submitOrderResponse.FullyMatched = true
|
||||
}
|
||||
if response != "" {
|
||||
submitOrderResponse.OrderID = response
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
}
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
|
||||
return submitOrderResponse, err
|
||||
return submitOrderResponse, nil
|
||||
}
|
||||
|
||||
// ModifyOrder will allow of changing orderbook placement and limit to
|
||||
@@ -509,7 +512,7 @@ func (c *CoinbasePro) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Deta
|
||||
|
||||
var orders []order.Detail
|
||||
for i := range respOrders {
|
||||
currency := currency.NewPairDelimiter(respOrders[i].ProductID,
|
||||
curr := currency.NewPairDelimiter(respOrders[i].ProductID,
|
||||
c.GetPairFormat(asset.Spot, false).Delimiter)
|
||||
orderSide := order.Side(strings.ToUpper(respOrders[i].Side))
|
||||
orderType := order.Type(strings.ToUpper(respOrders[i].Type))
|
||||
@@ -530,7 +533,7 @@ func (c *CoinbasePro) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Deta
|
||||
OrderType: orderType,
|
||||
OrderDate: orderDate,
|
||||
OrderSide: orderSide,
|
||||
CurrencyPair: currency,
|
||||
CurrencyPair: curr,
|
||||
Exchange: c.Name,
|
||||
})
|
||||
}
|
||||
@@ -545,9 +548,9 @@ func (c *CoinbasePro) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Deta
|
||||
// Can Limit response to specific order status
|
||||
func (c *CoinbasePro) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error) {
|
||||
var respOrders []GeneralizedOrderResponse
|
||||
for _, currency := range req.Currencies {
|
||||
for i := range req.Currencies {
|
||||
resp, err := c.GetOrders([]string{"done", "settled"},
|
||||
c.FormatExchangeCurrency(currency, asset.Spot).String())
|
||||
c.FormatExchangeCurrency(req.Currencies[i], asset.Spot).String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -556,7 +559,7 @@ func (c *CoinbasePro) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Deta
|
||||
|
||||
var orders []order.Detail
|
||||
for i := range respOrders {
|
||||
currency := currency.NewPairDelimiter(respOrders[i].ProductID,
|
||||
curr := currency.NewPairDelimiter(respOrders[i].ProductID,
|
||||
c.GetPairFormat(asset.Spot, false).Delimiter)
|
||||
orderSide := order.Side(strings.ToUpper(respOrders[i].Side))
|
||||
orderType := order.Type(strings.ToUpper(respOrders[i].Type))
|
||||
@@ -577,7 +580,7 @@ func (c *CoinbasePro) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Deta
|
||||
OrderType: orderType,
|
||||
OrderDate: orderDate,
|
||||
OrderSide: orderSide,
|
||||
CurrencyPair: currency,
|
||||
CurrencyPair: curr,
|
||||
Exchange: c.Name,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/crypto"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
|
||||
)
|
||||
|
||||
@@ -27,8 +28,6 @@ const (
|
||||
coinbeneAPIURL = "https://openapi-exchange.coinbene.com/api/exchange/"
|
||||
coinbeneAuthPath = "/api/exchange/v2"
|
||||
coinbeneAPIVersion = "v2"
|
||||
buy = "buy"
|
||||
sell = "sell"
|
||||
|
||||
// Public endpoints
|
||||
coinbeneFetchTicker = "/market/ticker/one"
|
||||
@@ -114,9 +113,9 @@ func (c *Coinbene) PlaceOrder(price, quantity float64, symbol, direction, client
|
||||
params := url.Values{}
|
||||
params.Set("symbol", symbol)
|
||||
switch direction {
|
||||
case sell:
|
||||
case order.Buy.Lower():
|
||||
params.Set("direction", "2")
|
||||
case buy:
|
||||
case order.Sell.Lower():
|
||||
params.Set("direction", "1")
|
||||
default:
|
||||
return resp,
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
)
|
||||
|
||||
// Please supply your own keys here for due diligence testing
|
||||
@@ -103,7 +104,7 @@ func TestPlaceOrder(t *testing.T) {
|
||||
if !areTestAPIKeysSet() || !canManipulateRealOrders {
|
||||
t.Skip("skipping test, either api keys or manipulaterealorders isnt set correctly")
|
||||
}
|
||||
_, err := c.PlaceOrder(140, 1, btcusdt, "buy", "")
|
||||
_, err := c.PlaceOrder(1, 1, btcusdt, order.Buy.Lower(), "")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package coinbene
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -504,9 +505,9 @@ func (c *Coinbene) GetActiveOrders(getOrdersRequest *order.GetOrdersRequest) ([]
|
||||
for y := range tempData.OpenOrders {
|
||||
tempResp.Exchange = c.Name
|
||||
tempResp.CurrencyPair = getOrdersRequest.Currencies[x]
|
||||
tempResp.OrderSide = buy
|
||||
if tempData.OpenOrders[y].OrderType == sell {
|
||||
tempResp.OrderSide = sell
|
||||
tempResp.OrderSide = order.Buy
|
||||
if strings.EqualFold(tempData.OpenOrders[y].OrderType, order.Sell.String()) {
|
||||
tempResp.OrderSide = order.Sell
|
||||
}
|
||||
t, err = time.Parse(time.RFC3339, tempData.OpenOrders[y].OrderTime)
|
||||
if err != nil {
|
||||
@@ -556,7 +557,7 @@ func (c *Coinbene) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest) ([]
|
||||
tempResp.Exchange = c.Name
|
||||
tempResp.CurrencyPair = getOrdersRequest.Currencies[x]
|
||||
tempResp.OrderSide = order.Buy
|
||||
if tempData.Data[y].OrderType == sell {
|
||||
if strings.EqualFold(tempData.Data[y].OrderType, order.Sell.String()) {
|
||||
tempResp.OrderSide = order.Sell
|
||||
}
|
||||
t, err = time.Parse(time.RFC3339, tempData.Data[y].OrderTime)
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common/crypto"
|
||||
@@ -105,9 +106,8 @@ func (c *COINUT) GetTrades(instrumentID int) (Trades, error) {
|
||||
}
|
||||
|
||||
// GetUserBalance returns the full user balance
|
||||
func (c *COINUT) GetUserBalance() (UserBalance, error) {
|
||||
result := UserBalance{}
|
||||
|
||||
func (c *COINUT) GetUserBalance() (*UserBalance, error) {
|
||||
var result *UserBalance
|
||||
return result, c.SendHTTPRequest(coinutBalance, nil, true, &result)
|
||||
}
|
||||
|
||||
@@ -117,26 +117,16 @@ func (c *COINUT) NewOrder(instrumentID int64, quantity, price float64, buy bool,
|
||||
params := make(map[string]interface{})
|
||||
params["inst_id"] = instrumentID
|
||||
if price > 0 {
|
||||
params["price"] = fmt.Sprintf("%v", price)
|
||||
params["price"] = strconv.FormatFloat(price, 'f', -1, 64)
|
||||
}
|
||||
params["qty"] = fmt.Sprintf("%v", quantity)
|
||||
params["qty"] = strconv.FormatFloat(quantity, 'f', -1, 64)
|
||||
params["side"] = order.Buy.String()
|
||||
if !buy {
|
||||
params["side"] = order.Sell.String()
|
||||
}
|
||||
params["client_ord_id"] = orderID
|
||||
|
||||
err := c.SendHTTPRequest(coinutOrder, params, true, &result)
|
||||
if _, ok := result.(OrderRejectResponse); ok {
|
||||
return result.(OrderRejectResponse), err
|
||||
}
|
||||
if _, ok := result.(OrderFilledResponse); ok {
|
||||
return result.(OrderFilledResponse), err
|
||||
}
|
||||
if _, ok := result.(OrdersBase); ok {
|
||||
return result.(OrdersBase), err
|
||||
}
|
||||
return result, err
|
||||
return result, c.SendHTTPRequest(coinutOrder, params, true, &result)
|
||||
}
|
||||
|
||||
// NewOrders places multiple orders on the exchange
|
||||
@@ -425,3 +415,77 @@ func getInternationalBankDepositFee(c currency.Code, amount float64) float64 {
|
||||
|
||||
return fee
|
||||
}
|
||||
|
||||
// IsLoaded returns whether or not the instrument map has been seeded
|
||||
func (i *instrumentMap) IsLoaded() bool {
|
||||
i.m.Lock()
|
||||
defer i.m.Unlock()
|
||||
return i.Loaded
|
||||
}
|
||||
|
||||
// Seed seeds the instrument map
|
||||
func (i *instrumentMap) Seed(curr string, id int64) {
|
||||
i.m.Lock()
|
||||
defer i.m.Unlock()
|
||||
|
||||
if !i.Loaded {
|
||||
i.Instruments = make(map[string]int64)
|
||||
}
|
||||
|
||||
// check to see if the instrument already exists
|
||||
_, ok := i.Instruments[curr]
|
||||
if ok {
|
||||
return
|
||||
}
|
||||
|
||||
i.Instruments[curr] = id
|
||||
i.Loaded = true
|
||||
}
|
||||
|
||||
// LookupInstrument looks up an instrument based on an id
|
||||
func (i *instrumentMap) LookupInstrument(id int64) string {
|
||||
i.m.Lock()
|
||||
defer i.m.Unlock()
|
||||
|
||||
if !i.Loaded {
|
||||
return ""
|
||||
}
|
||||
|
||||
for k, v := range i.Instruments {
|
||||
if v == id {
|
||||
return k
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// LookupID looks up an ID based on a string
|
||||
func (i *instrumentMap) LookupID(curr string) int64 {
|
||||
i.m.Lock()
|
||||
defer i.m.Unlock()
|
||||
|
||||
if !i.Loaded {
|
||||
return 0
|
||||
}
|
||||
|
||||
if ic, ok := i.Instruments[curr]; ok {
|
||||
return ic
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetInstrumentIDs returns a list of IDs
|
||||
func (i *instrumentMap) GetInstrumentIDs() []int64 {
|
||||
i.m.Lock()
|
||||
defer i.m.Unlock()
|
||||
|
||||
if !i.Loaded {
|
||||
return nil
|
||||
}
|
||||
|
||||
var instruments []int64
|
||||
for _, x := range i.Instruments {
|
||||
instruments = append(instruments, x)
|
||||
}
|
||||
return instruments
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package coinut
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
@@ -24,45 +26,42 @@ const (
|
||||
canManipulateRealOrders = false
|
||||
)
|
||||
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
func TestMain(m *testing.M) {
|
||||
c.SetDefaults()
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
cfg := config.GetConfig()
|
||||
err := cfg.LoadConfig("../../testdata/configtest.json", true)
|
||||
if err != nil {
|
||||
t.Fatal("Coinut load config error", err)
|
||||
log.Fatal("Coinut load config error", err)
|
||||
}
|
||||
bConfig, err := cfg.GetExchangeConfig("COINUT")
|
||||
if err != nil {
|
||||
t.Error("Coinut Setup() init error")
|
||||
log.Fatal("Coinut Setup() init error")
|
||||
}
|
||||
bConfig.API.AuthenticatedSupport = true
|
||||
bConfig.API.AuthenticatedWebsocketSupport = true
|
||||
bConfig.API.Credentials.Key = apiKey
|
||||
bConfig.API.Credentials.ClientID = clientID
|
||||
bConfig.Verbose = true
|
||||
err = c.Setup(bConfig)
|
||||
if err != nil {
|
||||
t.Fatal("Coinut setup error", err)
|
||||
log.Fatal("Coinut setup error", err)
|
||||
}
|
||||
|
||||
if !c.IsEnabled() || !c.Verbose ||
|
||||
c.Websocket.IsEnabled() || len(c.BaseCurrencies) < 1 {
|
||||
t.Error("Coinut Setup values not set correctly")
|
||||
}
|
||||
c.SeedInstruments()
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func setupWSTestAuth(t *testing.T) {
|
||||
if wsSetupRan {
|
||||
return
|
||||
}
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if !c.Websocket.IsEnabled() && !c.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
if areTestAPIKeysSet() {
|
||||
c.Websocket.SetCanUseAuthenticatedEndpoints(true)
|
||||
}
|
||||
c.WebsocketConn = &wshandler.WebsocketConnection{
|
||||
ExchangeName: c.Name,
|
||||
URL: coinutWebsocketURL,
|
||||
@@ -71,6 +70,7 @@ func setupWSTestAuth(t *testing.T) {
|
||||
ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
|
||||
ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
|
||||
}
|
||||
|
||||
var dialer websocket.Dialer
|
||||
err := c.WebsocketConn.Dial(&dialer, http.Header{})
|
||||
if err != nil {
|
||||
@@ -84,6 +84,10 @@ func setupWSTestAuth(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
wsSetupRan = true
|
||||
_, err = c.WsGetInstruments()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetInstruments(t *testing.T) {
|
||||
@@ -130,12 +134,8 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetFee(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
t.Parallel()
|
||||
|
||||
var feeBuilder = setFeeBuilder()
|
||||
|
||||
// CryptocurrencyTradeFee Basic
|
||||
if resp, err := c.GetFee(feeBuilder); resp != float64(0.001) || err != nil {
|
||||
t.Error(err)
|
||||
@@ -248,38 +248,29 @@ func TestGetFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
expectedResult := exchange.WithdrawCryptoViaWebsiteOnlyText + " & " + exchange.WithdrawFiatViaWebsiteOnlyText
|
||||
|
||||
withdrawPermissions := c.FormatWithdrawPermissions()
|
||||
|
||||
if withdrawPermissions != expectedResult {
|
||||
t.Errorf("Expected: %s, Received: %s", expectedResult, withdrawPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
}
|
||||
|
||||
_, err := c.GetActiveOrders(&getOrdersRequest)
|
||||
if areTestAPIKeysSet() && err != nil {
|
||||
t.Errorf("Could not get open orders: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
func TestGetOrderHistoryWrapper(t *testing.T) {
|
||||
setupWSTestAuth(t)
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
Currencies: []currency.Pair{currency.NewPair(currency.BTC,
|
||||
currency.LTC)},
|
||||
currency.USD)},
|
||||
}
|
||||
|
||||
_, err := c.GetOrderHistory(&getOrdersRequest)
|
||||
@@ -295,9 +286,6 @@ func areTestAPIKeysSet() bool {
|
||||
}
|
||||
|
||||
func TestSubmitOrder(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -311,7 +299,7 @@ func TestSubmitOrder(t *testing.T) {
|
||||
OrderType: order.Limit,
|
||||
Price: 1,
|
||||
Amount: 1,
|
||||
ClientID: "meowOrder",
|
||||
ClientID: "123",
|
||||
}
|
||||
response, err := c.SubmitOrder(orderSubmission)
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
@@ -322,15 +310,10 @@ func TestSubmitOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelExchangeOrder(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
|
||||
currencyPair := currency.NewPair(currency.BTC, currency.USD)
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -348,15 +331,11 @@ func TestCancelExchangeOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -393,6 +372,9 @@ func TestGetAccountInfo(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestModifyOrder(t *testing.T) {
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
_, err := c.ModifyOrder(&order.Modify{})
|
||||
if err == nil {
|
||||
t.Error("ModifyOrder() Expected error")
|
||||
@@ -400,8 +382,6 @@ func TestModifyOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdraw(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
withdrawCryptoRequest := exchange.CryptoWithdrawRequest{
|
||||
GenericWithdrawRequestInfo: exchange.GenericWithdrawRequestInfo{
|
||||
Amount: -1,
|
||||
@@ -422,9 +402,6 @@ func TestWithdraw(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawFiat(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -437,9 +414,6 @@ func TestWithdrawFiat(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawInternationalBank(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -473,14 +447,14 @@ func TestWsAuthSubmitOrder(t *testing.T) {
|
||||
if !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
order := WsSubmitOrderParameters{
|
||||
ord := WsSubmitOrderParameters{
|
||||
Amount: 1,
|
||||
Currency: currency.NewPair(currency.LTC, currency.BTC),
|
||||
OrderID: 1,
|
||||
Price: 1,
|
||||
Side: order.Buy,
|
||||
}
|
||||
_, err := c.wsSubmitOrder(&order)
|
||||
_, err := c.wsSubmitOrder(&ord)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -513,12 +487,13 @@ func TestWsAuthSubmitOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
// TestWsAuthCancelOrders dials websocket, cancels orders
|
||||
// doesn't care about if the order cancellations fail
|
||||
func TestWsAuthCancelOrders(t *testing.T) {
|
||||
setupWSTestAuth(t)
|
||||
if !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
order := WsCancelOrderParameters{
|
||||
ord := WsCancelOrderParameters{
|
||||
Currency: currency.NewPair(currency.LTC, currency.BTC),
|
||||
OrderID: 1,
|
||||
}
|
||||
@@ -526,9 +501,28 @@ func TestWsAuthCancelOrders(t *testing.T) {
|
||||
Currency: currency.NewPair(currency.LTC, currency.BTC),
|
||||
OrderID: 2,
|
||||
}
|
||||
_, errs := c.wsCancelOrders([]WsCancelOrderParameters{order, order2})
|
||||
if len(errs) > 0 {
|
||||
t.Error(errs)
|
||||
resp, err := c.wsCancelOrders([]WsCancelOrderParameters{ord, order2})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if resp.Status[0] != "OK" {
|
||||
t.Error("Order failed to cancel")
|
||||
}
|
||||
}
|
||||
|
||||
// TestWsAuthCancelOrders dials websocket, cancels orders
|
||||
// Checks that the wrapper oversight works
|
||||
func TestWsAuthCancelOrdersWrapper(t *testing.T) {
|
||||
setupWSTestAuth(t)
|
||||
if !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
orderDetails := order.Cancel{
|
||||
CurrencyPair: currency.NewPair(currency.LTC, currency.BTC),
|
||||
}
|
||||
_, err := c.CancelAllOrders(&orderDetails)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -538,20 +532,23 @@ func TestWsAuthCancelOrder(t *testing.T) {
|
||||
if !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
order := WsCancelOrderParameters{
|
||||
ord := &WsCancelOrderParameters{
|
||||
Currency: currency.NewPair(currency.LTC, currency.BTC),
|
||||
OrderID: 1,
|
||||
}
|
||||
err := c.wsCancelOrder(order)
|
||||
resp, err := c.wsCancelOrder(ord)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if len(resp.Status) >= 1 && resp.Status[0] != "OK" {
|
||||
t.Errorf("Failed to cancel order")
|
||||
}
|
||||
}
|
||||
|
||||
// TestWsAuthGetOpenOrders dials websocket, retrieves open orders
|
||||
func TestWsAuthGetOpenOrders(t *testing.T) {
|
||||
setupWSTestAuth(t)
|
||||
err := c.wsGetOpenOrders(currency.NewPair(currency.LTC, currency.BTC))
|
||||
_, err := c.wsGetOpenOrders(currency.NewPair(currency.LTC, currency.BTC).String())
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -573,7 +570,6 @@ func TestCurrencyMapIsLoaded(t *testing.T) {
|
||||
func TestCurrencyMapSeed(t *testing.T) {
|
||||
t.Parallel()
|
||||
var i instrumentMap
|
||||
|
||||
// Test non-seeded lookups
|
||||
if id := i.LookupInstrument(1234); id != "" {
|
||||
t.Error("unexpected result")
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package coinut
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
@@ -177,7 +176,7 @@ type CancelOrdersResponse struct {
|
||||
Results []struct {
|
||||
OrderID int64 `json:"order_id"`
|
||||
Status string `json:"status"`
|
||||
InstrumentID int `json:"inst_id"`
|
||||
InstrumentID int64 `json:"inst_id"`
|
||||
} `json:"results"`
|
||||
}
|
||||
|
||||
@@ -372,10 +371,10 @@ type WsTradeUpdate struct {
|
||||
|
||||
// WsInstrumentList defines instrument list
|
||||
type WsInstrumentList struct {
|
||||
Spot map[string][]WsSupportedCurrency `json:"SPOT"`
|
||||
Nonce int64 `json:"nonce"`
|
||||
Reply string `json:"inst_list"`
|
||||
Status []interface{} `json:"status"`
|
||||
Spot map[string][]InstrumentBase `json:"SPOT"`
|
||||
Nonce int64 `json:"nonce,omitempty"`
|
||||
Reply string `json:"inst_list,omitempty"`
|
||||
Status []interface{} `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// WsSupportedCurrency defines supported currency on the exchange
|
||||
@@ -536,14 +535,15 @@ type WsOrderFilledResponse struct {
|
||||
|
||||
// WsOrderData ws response data
|
||||
type WsOrderData struct {
|
||||
ClientOrdID int64 `json:"client_ord_id"`
|
||||
InstID int64 `json:"inst_id"`
|
||||
OpenQty float64 `json:"open_qty,string"`
|
||||
OrderID int64 `json:"order_id"`
|
||||
Price float64 `json:"price,string"`
|
||||
Qty float64 `json:"qty,string"`
|
||||
Side string `json:"side"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
ClientOrdID int64 `json:"client_ord_id"`
|
||||
InstID int64 `json:"inst_id"`
|
||||
OpenQty float64 `json:"open_qty,string"`
|
||||
OrderID int64 `json:"order_id"`
|
||||
Price float64 `json:"price,string"`
|
||||
Qty float64 `json:"qty,string"`
|
||||
Side string `json:"side"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
Status []string `json:"status"`
|
||||
}
|
||||
|
||||
// WsOrderFilledCommissionData ws response data
|
||||
@@ -656,20 +656,20 @@ type WsNewOrderResponse struct {
|
||||
|
||||
// WsGetAccountBalanceResponse contains values of each currency
|
||||
type WsGetAccountBalanceResponse struct {
|
||||
BCH string `json:"BCH"`
|
||||
BTC string `json:"BTC"`
|
||||
BTG string `json:"BTG"`
|
||||
CAD string `json:"CAD"`
|
||||
ETC string `json:"ETC"`
|
||||
ETH string `json:"ETH"`
|
||||
LCH string `json:"LCH"`
|
||||
LTC string `json:"LTC"`
|
||||
MYR string `json:"MYR"`
|
||||
SGD string `json:"SGD"`
|
||||
USD string `json:"USD"`
|
||||
USDT string `json:"USDT"`
|
||||
XMR string `json:"XMR"`
|
||||
ZEC string `json:"ZEC"`
|
||||
BCH float64 `json:"BCH,string"`
|
||||
BTC float64 `json:"BTC,string"`
|
||||
BTG float64 `json:"BTG,string"`
|
||||
CAD float64 `json:"CAD,string"`
|
||||
ETC float64 `json:"ETC,string"`
|
||||
ETH float64 `json:"ETH,string"`
|
||||
LCH float64 `json:"LCH,string"`
|
||||
LTC float64 `json:"LTC,string"`
|
||||
MYR float64 `json:"MYR,string"`
|
||||
SGD float64 `json:"SGD,string"`
|
||||
USD float64 `json:"USD,string"`
|
||||
USDT float64 `json:"USDT,string"`
|
||||
XMR float64 `json:"XMR,string"`
|
||||
ZEC float64 `json:"ZEC,string"`
|
||||
Nonce int64 `json:"nonce"`
|
||||
Reply string `json:"reply"`
|
||||
Status []string `json:"status"`
|
||||
@@ -681,79 +681,3 @@ type instrumentMap struct {
|
||||
Loaded bool
|
||||
m sync.Mutex
|
||||
}
|
||||
|
||||
// IsLoaded returns whether or not the instrument map has been seeded
|
||||
func (i *instrumentMap) IsLoaded() bool {
|
||||
i.m.Lock()
|
||||
defer i.m.Unlock()
|
||||
return i.Loaded
|
||||
}
|
||||
|
||||
// Seed seeds the instrument map
|
||||
func (i *instrumentMap) Seed(currency string, id int64) {
|
||||
i.m.Lock()
|
||||
defer i.m.Unlock()
|
||||
|
||||
if !i.Loaded {
|
||||
i.Instruments = make(map[string]int64)
|
||||
}
|
||||
|
||||
// check to see if the instrument already exists
|
||||
_, ok := i.Instruments[currency]
|
||||
if ok {
|
||||
return
|
||||
}
|
||||
|
||||
i.Instruments[currency] = id
|
||||
i.Loaded = true
|
||||
}
|
||||
|
||||
// LookupInstrument looks up an instrument based on an id
|
||||
func (i *instrumentMap) LookupInstrument(id int64) string {
|
||||
i.m.Lock()
|
||||
defer i.m.Unlock()
|
||||
|
||||
if !i.Loaded {
|
||||
return ""
|
||||
}
|
||||
|
||||
for k, v := range i.Instruments {
|
||||
if v == id {
|
||||
return k
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// LookupID looks up an ID based on a string
|
||||
func (i *instrumentMap) LookupID(currency string) int64 {
|
||||
i.m.Lock()
|
||||
defer i.m.Unlock()
|
||||
|
||||
if !i.Loaded {
|
||||
return 0
|
||||
}
|
||||
|
||||
for k, v := range i.Instruments {
|
||||
if strings.EqualFold(currency, k) {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetInstrumentIDs returns a list of IDs
|
||||
func (i *instrumentMap) GetInstrumentIDs() []int64 {
|
||||
i.m.Lock()
|
||||
defer i.m.Unlock()
|
||||
|
||||
if !i.Loaded {
|
||||
return nil
|
||||
}
|
||||
|
||||
var instruments []int64
|
||||
for _, x := range i.Instruments {
|
||||
instruments = append(instruments, x)
|
||||
}
|
||||
return instruments
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wsorderbook"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -25,8 +26,7 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
channels map[string]chan []byte
|
||||
wsInstrumentMap instrumentMap
|
||||
channels map[string]chan []byte
|
||||
)
|
||||
|
||||
// NOTE for speed considerations
|
||||
@@ -46,13 +46,17 @@ func (c *COINUT) WsConnect() error {
|
||||
}
|
||||
go c.WsHandleData()
|
||||
|
||||
if !wsInstrumentMap.IsLoaded() {
|
||||
err = c.WsSetInstrumentList()
|
||||
if !c.instrumentMap.IsLoaded() {
|
||||
_, err = c.WsGetInstruments()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
c.wsAuthenticate()
|
||||
err = c.wsAuthenticate()
|
||||
if err != nil {
|
||||
c.Websocket.SetCanUseAuthenticatedEndpoints(false)
|
||||
log.Error(log.WebsocketMgr, err)
|
||||
}
|
||||
c.GenerateDefaultSubscriptions()
|
||||
|
||||
// define bi-directional communication
|
||||
@@ -135,7 +139,7 @@ func (c *COINUT) wsProcessResponse(resp []byte) {
|
||||
return
|
||||
}
|
||||
|
||||
currencyPair := wsInstrumentMap.LookupInstrument(ticker.InstID)
|
||||
currencyPair := c.instrumentMap.LookupInstrument(ticker.InstID)
|
||||
c.Websocket.DataHandler <- wshandler.TickerData{
|
||||
Exchange: c.Name,
|
||||
Volume: ticker.Volume24,
|
||||
@@ -164,7 +168,7 @@ func (c *COINUT) wsProcessResponse(resp []byte) {
|
||||
c.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
currencyPair := wsInstrumentMap.LookupInstrument(orderbooksnapshot.InstID)
|
||||
currencyPair := c.instrumentMap.LookupInstrument(orderbooksnapshot.InstID)
|
||||
c.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
|
||||
Exchange: c.Name,
|
||||
Asset: asset.Spot,
|
||||
@@ -184,7 +188,7 @@ func (c *COINUT) wsProcessResponse(resp []byte) {
|
||||
c.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
currencyPair := wsInstrumentMap.LookupInstrument(orderbookUpdate.InstID)
|
||||
currencyPair := c.instrumentMap.LookupInstrument(orderbookUpdate.InstID)
|
||||
c.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
|
||||
Exchange: c.Name,
|
||||
Asset: asset.Spot,
|
||||
@@ -207,7 +211,7 @@ func (c *COINUT) wsProcessResponse(resp []byte) {
|
||||
c.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
currencyPair := wsInstrumentMap.LookupInstrument(tradeUpdate.InstID)
|
||||
currencyPair := c.instrumentMap.LookupInstrument(tradeUpdate.InstID)
|
||||
c.Websocket.DataHandler <- wshandler.TradeData{
|
||||
Timestamp: time.Unix(tradeUpdate.Timestamp, 0),
|
||||
CurrencyPair: currency.NewPairFromFormattedPairs(currencyPair,
|
||||
@@ -238,8 +242,9 @@ func (c *COINUT) GetNonce() int64 {
|
||||
return int64(c.Nonce.Get())
|
||||
}
|
||||
|
||||
// WsSetInstrumentList fetches instrument list and propagates a local cache
|
||||
func (c *COINUT) WsSetInstrumentList() error {
|
||||
// WsGetInstruments fetches instrument list and propagates a local cache
|
||||
func (c *COINUT) WsGetInstruments() (Instruments, error) {
|
||||
var list Instruments
|
||||
request := wsRequest{
|
||||
Request: "inst_list",
|
||||
SecType: strings.ToUpper(asset.Spot.String()),
|
||||
@@ -247,20 +252,19 @@ func (c *COINUT) WsSetInstrumentList() error {
|
||||
}
|
||||
resp, err := c.WebsocketConn.SendMessageReturnResponse(request.Nonce, request)
|
||||
if err != nil {
|
||||
return err
|
||||
return list, err
|
||||
}
|
||||
var list WsInstrumentList
|
||||
err = json.Unmarshal(resp, &list)
|
||||
if err != nil {
|
||||
return err
|
||||
return list, err
|
||||
}
|
||||
for curr, data := range list.Spot {
|
||||
wsInstrumentMap.Seed(curr, data[0].InstID)
|
||||
for curr, data := range list.Instruments {
|
||||
c.instrumentMap.Seed(curr, data[0].InstID)
|
||||
}
|
||||
if len(wsInstrumentMap.GetInstrumentIDs()) == 0 {
|
||||
return errors.New("instrument list failed to populate")
|
||||
if len(c.instrumentMap.GetInstrumentIDs()) == 0 {
|
||||
return list, errors.New("instrument list failed to populate")
|
||||
}
|
||||
return nil
|
||||
return list, nil
|
||||
}
|
||||
|
||||
// WsProcessOrderbookSnapshot processes the orderbook snapshot
|
||||
@@ -285,7 +289,7 @@ func (c *COINUT) WsProcessOrderbookSnapshot(ob *WsOrderbookSnapshot) error {
|
||||
newOrderBook.Asks = asks
|
||||
newOrderBook.Bids = bids
|
||||
newOrderBook.Pair = currency.NewPairFromFormattedPairs(
|
||||
wsInstrumentMap.LookupInstrument(ob.InstID),
|
||||
c.instrumentMap.LookupInstrument(ob.InstID),
|
||||
c.GetEnabledPairs(asset.Spot),
|
||||
c.GetPairFormat(asset.Spot, true),
|
||||
)
|
||||
@@ -298,7 +302,7 @@ func (c *COINUT) WsProcessOrderbookSnapshot(ob *WsOrderbookSnapshot) error {
|
||||
// WsProcessOrderbookUpdate process an orderbook update
|
||||
func (c *COINUT) WsProcessOrderbookUpdate(update *WsOrderbookUpdate) error {
|
||||
p := currency.NewPairFromFormattedPairs(
|
||||
wsInstrumentMap.LookupInstrument(update.InstID),
|
||||
c.instrumentMap.LookupInstrument(update.InstID),
|
||||
c.GetEnabledPairs(asset.Spot),
|
||||
c.GetPairFormat(asset.Spot, true),
|
||||
)
|
||||
@@ -335,7 +339,7 @@ func (c *COINUT) GenerateDefaultSubscriptions() {
|
||||
func (c *COINUT) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
|
||||
subscribe := wsRequest{
|
||||
Request: channelToSubscribe.Channel,
|
||||
InstID: wsInstrumentMap.LookupID(c.FormatExchangeCurrency(channelToSubscribe.Currency,
|
||||
InstID: c.instrumentMap.LookupID(c.FormatExchangeCurrency(channelToSubscribe.Currency,
|
||||
asset.Spot).String()),
|
||||
Subscribe: true,
|
||||
Nonce: c.WebsocketConn.GenerateMessageID(false),
|
||||
@@ -347,7 +351,7 @@ func (c *COINUT) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscrip
|
||||
func (c *COINUT) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
|
||||
subscribe := wsRequest{
|
||||
Request: channelToSubscribe.Channel,
|
||||
InstID: wsInstrumentMap.LookupID(c.FormatExchangeCurrency(channelToSubscribe.Currency,
|
||||
InstID: c.instrumentMap.LookupID(c.FormatExchangeCurrency(channelToSubscribe.Currency,
|
||||
asset.Spot).String()),
|
||||
Subscribe: false,
|
||||
Nonce: c.WebsocketConn.GenerateMessageID(false),
|
||||
@@ -406,7 +410,7 @@ func (c *COINUT) wsAuthenticate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *COINUT) wsGetAccountBalance() (*WsGetAccountBalanceResponse, error) {
|
||||
func (c *COINUT) wsGetAccountBalance() (*UserBalance, error) {
|
||||
if !c.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
return nil, fmt.Errorf("%v not authorised to submit order", c.Name)
|
||||
}
|
||||
@@ -418,7 +422,7 @@ func (c *COINUT) wsGetAccountBalance() (*WsGetAccountBalanceResponse, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var response WsGetAccountBalanceResponse
|
||||
var response UserBalance
|
||||
err = json.Unmarshal(resp, &response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -429,21 +433,21 @@ func (c *COINUT) wsGetAccountBalance() (*WsGetAccountBalanceResponse, error) {
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
func (c *COINUT) wsSubmitOrder(order *WsSubmitOrderParameters) (*WsStandardOrderResponse, error) {
|
||||
func (c *COINUT) wsSubmitOrder(o *WsSubmitOrderParameters) (*WsStandardOrderResponse, error) {
|
||||
if !c.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
return nil, fmt.Errorf("%v not authorised to submit order", c.Name)
|
||||
}
|
||||
curr := c.FormatExchangeCurrency(order.Currency, asset.Spot).String()
|
||||
curr := c.FormatExchangeCurrency(o.Currency, asset.Spot).String()
|
||||
var orderSubmissionRequest WsSubmitOrderRequest
|
||||
orderSubmissionRequest.Request = "new_order"
|
||||
orderSubmissionRequest.Nonce = c.WebsocketConn.GenerateMessageID(false)
|
||||
orderSubmissionRequest.InstID = wsInstrumentMap.LookupID(curr)
|
||||
orderSubmissionRequest.Qty = order.Amount
|
||||
orderSubmissionRequest.Price = order.Price
|
||||
orderSubmissionRequest.Side = string(order.Side)
|
||||
orderSubmissionRequest.InstID = c.instrumentMap.LookupID(curr)
|
||||
orderSubmissionRequest.Qty = o.Amount
|
||||
orderSubmissionRequest.Price = o.Price
|
||||
orderSubmissionRequest.Side = string(o.Side)
|
||||
|
||||
if order.OrderID > 0 {
|
||||
orderSubmissionRequest.OrderID = order.OrderID
|
||||
if o.OrderID > 0 {
|
||||
orderSubmissionRequest.OrderID = o.OrderID
|
||||
}
|
||||
resp, err := c.WebsocketConn.SendMessageReturnResponse(orderSubmissionRequest.Nonce, orderSubmissionRequest)
|
||||
if err != nil {
|
||||
@@ -548,7 +552,7 @@ func (c *COINUT) wsSubmitOrders(orders []WsSubmitOrderParameters) ([]WsStandardO
|
||||
Qty: orders[i].Amount,
|
||||
Price: orders[i].Price,
|
||||
Side: string(orders[i].Side),
|
||||
InstID: wsInstrumentMap.LookupID(curr),
|
||||
InstID: c.instrumentMap.LookupID(curr),
|
||||
ClientOrdID: i + 1,
|
||||
})
|
||||
}
|
||||
@@ -585,7 +589,7 @@ func (c *COINUT) wsSubmitOrders(orders []WsSubmitOrderParameters) ([]WsStandardO
|
||||
if len(standardOrder.Reasons) > 0 && standardOrder.Reasons[0] != "" {
|
||||
errors = append(errors, fmt.Errorf("%v order submission failed for currency %v and orderID %v, message %v ",
|
||||
c.Name,
|
||||
wsInstrumentMap.LookupInstrument(standardOrder.InstID),
|
||||
c.instrumentMap.LookupInstrument(standardOrder.InstID),
|
||||
standardOrder.OrderID,
|
||||
standardOrder.Reasons[0]))
|
||||
|
||||
@@ -597,73 +601,73 @@ func (c *COINUT) wsSubmitOrders(orders []WsSubmitOrderParameters) ([]WsStandardO
|
||||
return ordersResponse, errors
|
||||
}
|
||||
|
||||
func (c *COINUT) wsGetOpenOrders(p currency.Pair) error {
|
||||
func (c *COINUT) wsGetOpenOrders(curr string) (*WsUserOpenOrdersResponse, error) {
|
||||
var response *WsUserOpenOrdersResponse
|
||||
if !c.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
return fmt.Errorf("%v not authorised to get open orders", c.Name)
|
||||
return response, fmt.Errorf("%v not authorised to get open orders", c.Name)
|
||||
}
|
||||
curr := c.FormatExchangeCurrency(p, asset.Spot).String()
|
||||
var openOrdersRequest WsGetOpenOrdersRequest
|
||||
openOrdersRequest.Request = "user_open_orders"
|
||||
openOrdersRequest.Nonce = c.WebsocketConn.GenerateMessageID(false)
|
||||
openOrdersRequest.InstID = wsInstrumentMap.LookupID(curr)
|
||||
openOrdersRequest.InstID = c.instrumentMap.LookupID(curr)
|
||||
|
||||
resp, err := c.WebsocketConn.SendMessageReturnResponse(openOrdersRequest.Nonce, openOrdersRequest)
|
||||
if err != nil {
|
||||
return err
|
||||
return response, err
|
||||
}
|
||||
var response map[string]interface{}
|
||||
err = json.Unmarshal(resp, &response)
|
||||
if err != nil {
|
||||
return err
|
||||
return response, err
|
||||
}
|
||||
if response["status"].([]interface{})[0] != "OK" {
|
||||
return fmt.Errorf("%v get open orders failed for currency %v",
|
||||
if response.Status[0] != "OK" {
|
||||
return response, fmt.Errorf("%v get open orders failed for currency %v",
|
||||
c.Name,
|
||||
p)
|
||||
curr)
|
||||
}
|
||||
return nil
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (c *COINUT) wsCancelOrder(cancellation WsCancelOrderParameters) error {
|
||||
func (c *COINUT) wsCancelOrder(cancellation *WsCancelOrderParameters) (*CancelOrdersResponse, error) {
|
||||
var response *CancelOrdersResponse
|
||||
if !c.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
return fmt.Errorf("%v not authorised to cancel order", c.Name)
|
||||
return response, fmt.Errorf("%v not authorised to cancel order", c.Name)
|
||||
}
|
||||
currency := c.FormatExchangeCurrency(cancellation.Currency, asset.Spot).String()
|
||||
curr := c.FormatExchangeCurrency(cancellation.Currency, asset.Spot).String()
|
||||
var cancellationRequest WsCancelOrderRequest
|
||||
cancellationRequest.Request = "cancel_order"
|
||||
cancellationRequest.InstID = wsInstrumentMap.LookupID(currency)
|
||||
cancellationRequest.InstID = c.instrumentMap.LookupID(curr)
|
||||
cancellationRequest.OrderID = cancellation.OrderID
|
||||
cancellationRequest.Nonce = c.WebsocketConn.GenerateMessageID(false)
|
||||
|
||||
resp, err := c.WebsocketConn.SendMessageReturnResponse(cancellationRequest.Nonce, cancellationRequest)
|
||||
if err != nil {
|
||||
return err
|
||||
return response, err
|
||||
}
|
||||
var response map[string]interface{}
|
||||
err = json.Unmarshal(resp, &response)
|
||||
if err != nil {
|
||||
return err
|
||||
return response, err
|
||||
}
|
||||
if response["status"].([]interface{})[0] != "OK" {
|
||||
return fmt.Errorf("%v order cancellation failed for currency %v and orderID %v, message %v",
|
||||
if response.Status[0] != "OK" {
|
||||
return response, fmt.Errorf("%v order cancellation failed for currency %v and orderID %v, message %v",
|
||||
c.Name,
|
||||
cancellation.Currency,
|
||||
cancellation.OrderID,
|
||||
response["status"])
|
||||
response.Status[0])
|
||||
}
|
||||
return nil
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (c *COINUT) wsCancelOrders(cancellations []WsCancelOrderParameters) (*WsCancelOrdersResponse, []error) {
|
||||
var errors []error
|
||||
func (c *COINUT) wsCancelOrders(cancellations []WsCancelOrderParameters) (*CancelOrdersResponse, error) {
|
||||
var err error
|
||||
var response *CancelOrdersResponse
|
||||
if !c.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
return nil, errors
|
||||
return nil, err
|
||||
}
|
||||
cancelOrderRequest := WsCancelOrdersRequest{}
|
||||
var cancelOrderRequest WsCancelOrdersRequest
|
||||
for i := range cancellations {
|
||||
currency := c.FormatExchangeCurrency(cancellations[i].Currency, asset.Spot).String()
|
||||
curr := c.FormatExchangeCurrency(cancellations[i].Currency, asset.Spot).String()
|
||||
cancelOrderRequest.Entries = append(cancelOrderRequest.Entries, WsCancelOrdersRequestEntry{
|
||||
InstID: wsInstrumentMap.LookupID(currency),
|
||||
InstID: c.instrumentMap.LookupID(curr),
|
||||
OrderID: cancellations[i].OrderID,
|
||||
})
|
||||
}
|
||||
@@ -672,53 +676,40 @@ func (c *COINUT) wsCancelOrders(cancellations []WsCancelOrderParameters) (*WsCan
|
||||
cancelOrderRequest.Nonce = c.WebsocketConn.GenerateMessageID(false)
|
||||
resp, err := c.WebsocketConn.SendMessageReturnResponse(cancelOrderRequest.Nonce, cancelOrderRequest)
|
||||
if err != nil {
|
||||
return nil, []error{err}
|
||||
return response, err
|
||||
}
|
||||
var response WsCancelOrdersResponse
|
||||
err = json.Unmarshal(resp, &response)
|
||||
if err != nil {
|
||||
return nil, []error{err}
|
||||
return response, err
|
||||
}
|
||||
if response.Status[0] != "OK" {
|
||||
return &response, []error{err}
|
||||
}
|
||||
for i := range response.Results {
|
||||
if response.Results[i].Status != "OK" {
|
||||
errors = append(errors, fmt.Errorf("%v order cancellation failed for currency %v and orderID %v, message %v",
|
||||
c.Name,
|
||||
wsInstrumentMap.LookupInstrument(response.Results[i].InstID),
|
||||
response.Results[i].OrderID,
|
||||
response.Results[i].Status))
|
||||
}
|
||||
}
|
||||
return &response, errors
|
||||
return response, err
|
||||
}
|
||||
|
||||
func (c *COINUT) wsGetTradeHistory(p currency.Pair, start, limit int64) error {
|
||||
func (c *COINUT) wsGetTradeHistory(p currency.Pair, start, limit int64) (*WsTradeHistoryResponse, error) {
|
||||
var response *WsTradeHistoryResponse
|
||||
if !c.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
return fmt.Errorf("%v not authorised to get trade history", c.Name)
|
||||
return response, fmt.Errorf("%v not authorised to get trade history", c.Name)
|
||||
}
|
||||
curr := c.FormatExchangeCurrency(p, asset.Spot).String()
|
||||
var request WsTradeHistoryRequest
|
||||
request.Request = "trade_history"
|
||||
request.InstID = wsInstrumentMap.LookupID(curr)
|
||||
request.InstID = c.instrumentMap.LookupID(curr)
|
||||
request.Nonce = c.WebsocketConn.GenerateMessageID(false)
|
||||
request.Start = start
|
||||
request.Limit = limit
|
||||
|
||||
resp, err := c.WebsocketConn.SendMessageReturnResponse(request.Nonce, request)
|
||||
if err != nil {
|
||||
return err
|
||||
return response, err
|
||||
}
|
||||
var response map[string]interface{}
|
||||
err = json.Unmarshal(resp, &response)
|
||||
if err != nil {
|
||||
return err
|
||||
return response, err
|
||||
}
|
||||
if response["status"].([]interface{})[0] != "OK" {
|
||||
return fmt.Errorf("%v get trade history failed for %v",
|
||||
if response.Status[0] != "OK" {
|
||||
return response, fmt.Errorf("%v get trade history failed for %v",
|
||||
c.Name,
|
||||
request)
|
||||
}
|
||||
return nil
|
||||
return response, nil
|
||||
}
|
||||
|
||||
@@ -88,15 +88,20 @@ func (c *COINUT) SetDefaults() {
|
||||
FiatWithdrawalFee: true,
|
||||
},
|
||||
WebsocketCapabilities: protocol.Features{
|
||||
AccountBalance: true,
|
||||
GetOrders: true,
|
||||
CancelOrders: true,
|
||||
CancelOrder: true,
|
||||
SubmitOrder: true,
|
||||
SubmitOrders: true,
|
||||
UserTradeHistory: true,
|
||||
TickerFetching: true,
|
||||
OrderbookFetching: true,
|
||||
TradeFetching: true,
|
||||
OrderbookFetching: true,
|
||||
AccountInfo: true,
|
||||
Subscribe: true,
|
||||
Unsubscribe: true,
|
||||
AuthenticatedEndpoints: true,
|
||||
SubmitOrder: true,
|
||||
SubmitOrders: true,
|
||||
CancelOrder: true,
|
||||
MessageCorrelation: true,
|
||||
},
|
||||
WithdrawPermissions: exchange.WithdrawCryptoViaWebsiteOnly |
|
||||
@@ -217,15 +222,25 @@ func (c *COINUT) Run() {
|
||||
|
||||
// FetchTradablePairs returns a list of the exchanges tradable pairs
|
||||
func (c *COINUT) FetchTradablePairs(asset asset.Item) ([]string, error) {
|
||||
i, err := c.GetInstruments()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var instruments map[string][]InstrumentBase
|
||||
var resp Instruments
|
||||
var err error
|
||||
if c.Websocket.IsConnected() {
|
||||
resp, err = c.WsGetInstruments()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
resp, err = c.GetInstruments()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
instruments = resp.Instruments
|
||||
var pairs []string
|
||||
for _, y := range i.Instruments {
|
||||
c.instrumentMap.Seed(y[0].Base+y[0].Quote, y[0].InstID)
|
||||
p := y[0].Base + c.GetPairFormat(asset, false).Delimiter + y[0].Quote
|
||||
for i := range instruments {
|
||||
c.instrumentMap.Seed(instruments[i][0].Base+instruments[i][0].Quote, instruments[i][0].InstID)
|
||||
p := instruments[i][0].Base + c.GetPairFormat(asset, false).Delimiter + instruments[i][0].Quote
|
||||
pairs = append(pairs, p)
|
||||
}
|
||||
|
||||
@@ -248,9 +263,20 @@ func (c *COINUT) UpdateTradablePairs(forceUpdate bool) error {
|
||||
// COINUT exchange
|
||||
func (c *COINUT) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var info exchange.AccountInfo
|
||||
bal, err := c.GetUserBalance()
|
||||
if err != nil {
|
||||
return info, err
|
||||
var bal *UserBalance
|
||||
var err error
|
||||
if c.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
var resp *UserBalance
|
||||
resp, err = c.wsGetAccountBalance()
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
bal = resp
|
||||
} else {
|
||||
bal, err = c.GetUserBalance()
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
}
|
||||
|
||||
var balances = []exchange.AccountCurrencyInfo{
|
||||
@@ -322,12 +348,9 @@ func (c *COINUT) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (c *COINUT) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Price, error) {
|
||||
var tickerPrice ticker.Price
|
||||
|
||||
if !c.instrumentMap.IsLoaded() {
|
||||
err := c.SeedInstruments()
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
err := c.loadInstrumentsIfNotLoaded()
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
|
||||
instID := c.instrumentMap.LookupID(c.FormatExchangeCurrency(p,
|
||||
@@ -335,8 +358,8 @@ func (c *COINUT) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Pri
|
||||
if instID == 0 {
|
||||
return tickerPrice, errors.New("unable to lookup instrument ID")
|
||||
}
|
||||
|
||||
tick, err := c.GetInstrumentTicker(instID)
|
||||
var tick Ticker
|
||||
tick, err = c.GetInstrumentTicker(instID)
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
@@ -379,12 +402,9 @@ func (c *COINUT) FetchOrderbook(p currency.Pair, assetType asset.Item) (orderboo
|
||||
// UpdateOrderbook updates and returns the orderbook for a currency pair
|
||||
func (c *COINUT) UpdateOrderbook(p currency.Pair, assetType asset.Item) (orderbook.Base, error) {
|
||||
var orderBook orderbook.Base
|
||||
|
||||
if !c.instrumentMap.IsLoaded() {
|
||||
err := c.SeedInstruments()
|
||||
if err != nil {
|
||||
return orderBook, err
|
||||
}
|
||||
err := c.loadInstrumentsIfNotLoaded()
|
||||
if err != nil {
|
||||
return orderBook, err
|
||||
}
|
||||
|
||||
instID := c.instrumentMap.LookupID(c.FormatExchangeCurrency(p,
|
||||
@@ -430,69 +450,74 @@ func (c *COINUT) GetExchangeHistory(p currency.Pair, assetType asset.Item) ([]ex
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (c *COINUT) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
|
||||
func (c *COINUT) SubmitOrder(o *order.Submit) (order.SubmitResponse, error) {
|
||||
var submitOrderResponse order.SubmitResponse
|
||||
if err := s.Validate(); err != nil {
|
||||
return submitOrderResponse, err
|
||||
var err error
|
||||
if _, err = strconv.Atoi(o.ClientID); err != nil {
|
||||
return submitOrderResponse, fmt.Errorf("%s - ClientID must be a number, received: %s", c.Name, o.ClientID)
|
||||
}
|
||||
err = o.Validate()
|
||||
|
||||
var APIresponse interface{}
|
||||
isBuyOrder := s.OrderSide == order.Buy
|
||||
clientIDInt, err := strconv.ParseUint(s.ClientID, 0, 32)
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
clientIDUint := uint32(clientIDInt)
|
||||
|
||||
if !c.instrumentMap.IsLoaded() {
|
||||
err = c.SeedInstruments()
|
||||
if c.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
var response *WsStandardOrderResponse
|
||||
response, err = c.wsSubmitOrder(&WsSubmitOrderParameters{
|
||||
Currency: o.Pair,
|
||||
Side: o.OrderSide,
|
||||
Amount: o.Amount,
|
||||
Price: o.Price,
|
||||
})
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
}
|
||||
|
||||
currencyID := c.instrumentMap.LookupID(c.FormatExchangeCurrency(s.Pair,
|
||||
asset.Spot).String())
|
||||
if currencyID == 0 {
|
||||
return submitOrderResponse, errLookupInstrumentID
|
||||
}
|
||||
|
||||
switch s.OrderType {
|
||||
case order.Limit:
|
||||
APIresponse, err = c.NewOrder(currencyID,
|
||||
s.Amount,
|
||||
s.Price,
|
||||
isBuyOrder,
|
||||
clientIDUint)
|
||||
case order.Market:
|
||||
APIresponse, err = c.NewOrder(currencyID,
|
||||
s.Amount,
|
||||
0,
|
||||
isBuyOrder,
|
||||
clientIDUint)
|
||||
}
|
||||
|
||||
switch apiResp := APIresponse.(type) {
|
||||
case OrdersBase:
|
||||
orderResult := apiResp
|
||||
submitOrderResponse.OrderID = strconv.FormatInt(orderResult.OrderID, 10)
|
||||
case OrderFilledResponse:
|
||||
orderResult := apiResp
|
||||
submitOrderResponse.OrderID = strconv.FormatInt(orderResult.Order.OrderID, 10)
|
||||
case OrderRejectResponse:
|
||||
orderResult := apiResp
|
||||
submitOrderResponse.OrderID = strconv.FormatInt(orderResult.OrderID, 10)
|
||||
err = fmt.Errorf("orderID: %d was rejected: %v",
|
||||
orderResult.OrderID,
|
||||
orderResult.Reasons)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
submitOrderResponse.OrderID = strconv.FormatInt(response.OrderID, 10)
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
}
|
||||
} else {
|
||||
err = c.loadInstrumentsIfNotLoaded()
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
return submitOrderResponse, err
|
||||
currencyID := c.instrumentMap.LookupID(c.FormatExchangeCurrency(o.Pair,
|
||||
asset.Spot).String())
|
||||
if currencyID == 0 {
|
||||
return submitOrderResponse, errLookupInstrumentID
|
||||
}
|
||||
|
||||
var APIResponse interface{}
|
||||
var clientIDInt uint64
|
||||
isBuyOrder := o.OrderSide == order.Buy
|
||||
clientIDInt, err = strconv.ParseUint(o.ClientID, 0, 32)
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
clientIDUint := uint32(clientIDInt)
|
||||
APIResponse, err = c.NewOrder(currencyID, o.Amount, o.Price,
|
||||
isBuyOrder, clientIDUint)
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
responseMap := APIResponse.(map[string]interface{})
|
||||
switch responseMap["reply"].(string) {
|
||||
case "order_rejected":
|
||||
return submitOrderResponse, fmt.Errorf("clientOrderID: %v was rejected: %v", o.ClientID, responseMap["reasons"])
|
||||
case "order_filled":
|
||||
orderID := responseMap["order_id"].(float64)
|
||||
submitOrderResponse.OrderID = strconv.FormatFloat(orderID, 'f', -1, 64)
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
submitOrderResponse.FullyMatched = true
|
||||
return submitOrderResponse, nil
|
||||
case "order_accepted":
|
||||
orderID := responseMap["order_id"].(float64)
|
||||
submitOrderResponse.OrderID = strconv.FormatFloat(orderID, 'f', -1, 64)
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
return submitOrderResponse, nil
|
||||
}
|
||||
}
|
||||
return submitOrderResponse, nil
|
||||
}
|
||||
|
||||
// ModifyOrder will allow of changing orderbook placement and limit to
|
||||
@@ -502,76 +527,108 @@ func (c *COINUT) ModifyOrder(action *order.Modify) (string, error) {
|
||||
}
|
||||
|
||||
// CancelOrder cancels an order by its corresponding ID number
|
||||
func (c *COINUT) CancelOrder(order *order.Cancel) error {
|
||||
orderIDInt, err := strconv.ParseInt(order.OrderID, 10, 64)
|
||||
func (c *COINUT) CancelOrder(o *order.Cancel) error {
|
||||
err := c.loadInstrumentsIfNotLoaded()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
orderIDInt, err := strconv.ParseInt(o.OrderID, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !c.instrumentMap.IsLoaded() {
|
||||
err = c.SeedInstruments()
|
||||
currencyID := c.instrumentMap.LookupID(c.FormatExchangeCurrency(
|
||||
o.CurrencyPair,
|
||||
asset.Spot).String(),
|
||||
)
|
||||
if c.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
var resp *CancelOrdersResponse
|
||||
resp, err = c.wsCancelOrder(&WsCancelOrderParameters{
|
||||
Currency: o.CurrencyPair,
|
||||
OrderID: orderIDInt,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(resp.Status) >= 1 && resp.Status[0] != "OK" {
|
||||
return errors.New(c.Name + " - Failed to cancel order " + o.OrderID)
|
||||
}
|
||||
} else {
|
||||
if currencyID == 0 {
|
||||
return errLookupInstrumentID
|
||||
}
|
||||
_, err = c.CancelExistingOrder(currencyID, orderIDInt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
currencyID := c.instrumentMap.LookupID(c.FormatExchangeCurrency(
|
||||
order.CurrencyPair,
|
||||
asset.Spot).String(),
|
||||
)
|
||||
if currencyID == 0 {
|
||||
return errLookupInstrumentID
|
||||
}
|
||||
_, err = c.CancelExistingOrder(currencyID, orderIDInt)
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
// CancelAllOrders cancels all orders associated with a currency pair
|
||||
func (c *COINUT) CancelAllOrders(_ *order.Cancel) (order.CancelAllResponse, error) {
|
||||
// TODO, this is a terrible implementation. Requires DB to improve
|
||||
// Coinut provides no way of retrieving orders without a currency
|
||||
// So we need to retrieve all currencies, then retrieve orders for each
|
||||
// currency then cancel. Advisable to never use this until DB due to
|
||||
// performance.
|
||||
cancelAllOrdersResponse := order.CancelAllResponse{
|
||||
Status: make(map[string]string),
|
||||
func (c *COINUT) CancelAllOrders(details *order.Cancel) (order.CancelAllResponse, error) {
|
||||
var cancelAllOrdersResponse order.CancelAllResponse
|
||||
err := c.loadInstrumentsIfNotLoaded()
|
||||
if err != nil {
|
||||
return cancelAllOrdersResponse, err
|
||||
}
|
||||
|
||||
if !c.instrumentMap.IsLoaded() {
|
||||
err := c.SeedInstruments()
|
||||
cancelAllOrdersResponse.Status = make(map[string]string)
|
||||
if c.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
openOrders, err := c.wsGetOpenOrders(details.CurrencyPair.String())
|
||||
if err != nil {
|
||||
return cancelAllOrdersResponse, err
|
||||
}
|
||||
}
|
||||
|
||||
var allTheOrders []OrderResponse
|
||||
ids := c.instrumentMap.GetInstrumentIDs()
|
||||
for x := range ids {
|
||||
openOrders, err := c.GetOpenOrders(ids[x])
|
||||
var ordersToCancel []WsCancelOrderParameters
|
||||
for i := range openOrders.Orders {
|
||||
if openOrders.Orders[i].InstID == c.instrumentMap.LookupID(c.FormatExchangeCurrency(details.CurrencyPair, asset.Spot).String()) {
|
||||
ordersToCancel = append(ordersToCancel, WsCancelOrderParameters{
|
||||
Currency: details.CurrencyPair,
|
||||
OrderID: openOrders.Orders[i].OrderID,
|
||||
})
|
||||
}
|
||||
}
|
||||
resp, err := c.wsCancelOrders(ordersToCancel)
|
||||
if err != nil {
|
||||
return cancelAllOrdersResponse, err
|
||||
}
|
||||
allTheOrders = append(allTheOrders, openOrders.Orders...)
|
||||
}
|
||||
|
||||
var allTheOrdersToCancel []CancelOrders
|
||||
for _, orderToCancel := range allTheOrders {
|
||||
cancelOrder := CancelOrders{
|
||||
InstrumentID: orderToCancel.InstrumentID,
|
||||
OrderID: orderToCancel.OrderID,
|
||||
for i := range resp.Results {
|
||||
if openOrders.Orders[i].Status[0] != "OK" {
|
||||
cancelAllOrdersResponse.Status[strconv.FormatInt(openOrders.Orders[i].OrderID, 10)] = strings.Join(openOrders.Orders[i].Status, ",")
|
||||
}
|
||||
}
|
||||
allTheOrdersToCancel = append(allTheOrdersToCancel, cancelOrder)
|
||||
}
|
||||
|
||||
if len(allTheOrdersToCancel) > 0 {
|
||||
resp, err := c.CancelOrders(allTheOrdersToCancel)
|
||||
if err != nil {
|
||||
return cancelAllOrdersResponse, err
|
||||
} else {
|
||||
var allTheOrders []OrderResponse
|
||||
ids := c.instrumentMap.GetInstrumentIDs()
|
||||
for x := range ids {
|
||||
if ids[x] == c.instrumentMap.LookupID(c.FormatExchangeCurrency(details.CurrencyPair, asset.Spot).String()) {
|
||||
openOrders, err := c.GetOpenOrders(ids[x])
|
||||
if err != nil {
|
||||
return cancelAllOrdersResponse, err
|
||||
}
|
||||
allTheOrders = append(allTheOrders, openOrders.Orders...)
|
||||
}
|
||||
}
|
||||
|
||||
for _, order := range resp.Results {
|
||||
if order.Status != "OK" {
|
||||
cancelAllOrdersResponse.Status[strconv.FormatInt(order.OrderID, 10)] = order.Status
|
||||
var allTheOrdersToCancel []CancelOrders
|
||||
for i := range allTheOrders {
|
||||
cancelOrder := CancelOrders{
|
||||
InstrumentID: allTheOrders[i].InstrumentID,
|
||||
OrderID: allTheOrders[i].OrderID,
|
||||
}
|
||||
allTheOrdersToCancel = append(allTheOrdersToCancel, cancelOrder)
|
||||
}
|
||||
|
||||
if len(allTheOrdersToCancel) > 0 {
|
||||
resp, err := c.CancelOrders(allTheOrdersToCancel)
|
||||
if err != nil {
|
||||
return cancelAllOrdersResponse, err
|
||||
}
|
||||
|
||||
for i := range resp.Results {
|
||||
if resp.Results[i].Status != "OK" {
|
||||
cancelAllOrdersResponse.Status[strconv.FormatInt(resp.Results[i].OrderID, 10)] = resp.Results[i].Status
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -623,51 +680,81 @@ func (c *COINUT) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error)
|
||||
|
||||
// GetActiveOrders retrieves any orders that are active/open
|
||||
func (c *COINUT) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
|
||||
if !c.instrumentMap.IsLoaded() {
|
||||
err := c.SeedInstruments()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err := c.loadInstrumentsIfNotLoaded()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var instrumentsToUse []int64
|
||||
if len(req.Currencies) > 0 {
|
||||
for x := range req.Currencies {
|
||||
currency := c.FormatExchangeCurrency(req.Currencies[x],
|
||||
asset.Spot).String()
|
||||
instrumentsToUse = append(instrumentsToUse,
|
||||
c.instrumentMap.LookupID(currency))
|
||||
var orders []order.Detail
|
||||
var currenciesToCheck []string
|
||||
if len(req.Currencies) == 0 {
|
||||
for i := range req.Currencies {
|
||||
currenciesToCheck = append(currenciesToCheck, c.FormatExchangeCurrency(req.Currencies[i], asset.Spot).String())
|
||||
}
|
||||
} else {
|
||||
instrumentsToUse = c.instrumentMap.GetInstrumentIDs()
|
||||
}
|
||||
|
||||
if len(instrumentsToUse) == 0 {
|
||||
return nil, errors.New("no instrument IDs to use")
|
||||
}
|
||||
|
||||
var orders []order.Detail
|
||||
for x := range instrumentsToUse {
|
||||
openOrders, err := c.GetOpenOrders(instrumentsToUse[x])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
for k := range c.instrumentMap.Instruments {
|
||||
currenciesToCheck = append(currenciesToCheck, k)
|
||||
}
|
||||
for y := range openOrders.Orders {
|
||||
curr := c.instrumentMap.LookupInstrument(instrumentsToUse[x])
|
||||
p := currency.NewPairFromFormattedPairs(curr,
|
||||
c.GetEnabledPairs(asset.Spot),
|
||||
c.GetPairFormat(asset.Spot, true))
|
||||
orderSide := order.Side(strings.ToUpper(openOrders.Orders[y].Side))
|
||||
orderDate := time.Unix(openOrders.Orders[y].Timestamp, 0)
|
||||
orders = append(orders, order.Detail{
|
||||
ID: strconv.FormatInt(openOrders.Orders[y].OrderID, 10),
|
||||
Amount: openOrders.Orders[y].Quantity,
|
||||
Price: openOrders.Orders[y].Price,
|
||||
Exchange: c.Name,
|
||||
OrderSide: orderSide,
|
||||
OrderDate: orderDate,
|
||||
CurrencyPair: p,
|
||||
})
|
||||
}
|
||||
if c.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
for x := range currenciesToCheck {
|
||||
openOrders, err := c.wsGetOpenOrders(currenciesToCheck[x])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range openOrders.Orders {
|
||||
orders = append(orders, order.Detail{
|
||||
Exchange: c.Name,
|
||||
ID: strconv.FormatInt(openOrders.Orders[i].OrderID, 10),
|
||||
CurrencyPair: c.FormatExchangeCurrency(currency.NewPairFromString(currenciesToCheck[x]), asset.Spot),
|
||||
OrderSide: order.Side(openOrders.Orders[i].Side),
|
||||
OrderDate: time.Unix(0, openOrders.Orders[i].Timestamp),
|
||||
Status: order.Active,
|
||||
Price: openOrders.Orders[i].Price,
|
||||
Amount: openOrders.Orders[i].Qty,
|
||||
ExecutedAmount: openOrders.Orders[i].Qty - openOrders.Orders[i].OpenQty,
|
||||
RemainingAmount: openOrders.Orders[i].OpenQty,
|
||||
})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var instrumentsToUse []int64
|
||||
if len(req.Currencies) > 0 {
|
||||
for x := range req.Currencies {
|
||||
curr := c.FormatExchangeCurrency(req.Currencies[x],
|
||||
asset.Spot).String()
|
||||
instrumentsToUse = append(instrumentsToUse,
|
||||
c.instrumentMap.LookupID(curr))
|
||||
}
|
||||
} else {
|
||||
instrumentsToUse = c.instrumentMap.GetInstrumentIDs()
|
||||
}
|
||||
|
||||
if len(instrumentsToUse) == 0 {
|
||||
return nil, errors.New("no instrument IDs to use")
|
||||
}
|
||||
|
||||
for x := range instrumentsToUse {
|
||||
openOrders, err := c.GetOpenOrders(instrumentsToUse[x])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for y := range openOrders.Orders {
|
||||
curr := c.instrumentMap.LookupInstrument(instrumentsToUse[x])
|
||||
p := currency.NewPairFromFormattedPairs(curr,
|
||||
c.GetEnabledPairs(asset.Spot),
|
||||
c.GetPairFormat(asset.Spot, true))
|
||||
orderSide := order.Side(strings.ToUpper(openOrders.Orders[y].Side))
|
||||
orderDate := time.Unix(openOrders.Orders[y].Timestamp, 0)
|
||||
orders = append(orders, order.Detail{
|
||||
ID: strconv.FormatInt(openOrders.Orders[y].OrderID, 10),
|
||||
Amount: openOrders.Orders[y].Quantity,
|
||||
Price: openOrders.Orders[y].Price,
|
||||
Exchange: c.Name,
|
||||
OrderSide: orderSide,
|
||||
OrderDate: orderDate,
|
||||
CurrencyPair: p,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -679,51 +766,78 @@ func (c *COINUT) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
|
||||
// GetOrderHistory retrieves account order information
|
||||
// Can Limit response to specific order status
|
||||
func (c *COINUT) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error) {
|
||||
if !c.instrumentMap.IsLoaded() {
|
||||
err := c.SeedInstruments()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err := c.loadInstrumentsIfNotLoaded()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var instrumentsToUse []int64
|
||||
if len(req.Currencies) > 0 {
|
||||
for x := range req.Currencies {
|
||||
currency := c.FormatExchangeCurrency(req.Currencies[x],
|
||||
asset.Spot).String()
|
||||
instrumentsToUse = append(instrumentsToUse,
|
||||
c.instrumentMap.LookupID(currency))
|
||||
var allOrders []order.Detail
|
||||
if c.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
for i := range req.Currencies {
|
||||
for j := int64(0); ; j += 100 {
|
||||
trades, err := c.wsGetTradeHistory(req.Currencies[i], j, 100)
|
||||
if err != nil {
|
||||
return allOrders, err
|
||||
}
|
||||
for x := range trades.Trades {
|
||||
curr := c.instrumentMap.LookupInstrument(trades.Trades[x].InstID)
|
||||
allOrders = append(allOrders, order.Detail{
|
||||
Exchange: c.Name,
|
||||
ID: strconv.FormatInt(trades.Trades[x].OrderID, 10),
|
||||
CurrencyPair: currency.NewPairFromString(curr),
|
||||
OrderSide: order.Side(trades.Trades[x].Side),
|
||||
OrderDate: time.Unix(0, trades.Trades[x].Timestamp),
|
||||
Status: order.Filled,
|
||||
Price: trades.Trades[x].Price,
|
||||
Amount: trades.Trades[x].Qty,
|
||||
ExecutedAmount: trades.Trades[x].Qty,
|
||||
RemainingAmount: trades.Trades[x].OpenQty,
|
||||
})
|
||||
}
|
||||
if len(trades.Trades) < 100 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
instrumentsToUse = c.instrumentMap.GetInstrumentIDs()
|
||||
}
|
||||
|
||||
if len(instrumentsToUse) == 0 {
|
||||
return nil, errors.New("no instrument IDs to use")
|
||||
}
|
||||
|
||||
var allOrders []order.Detail
|
||||
for x := range instrumentsToUse {
|
||||
orders, err := c.GetTradeHistory(instrumentsToUse[x], -1, -1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var instrumentsToUse []int64
|
||||
if len(req.Currencies) > 0 {
|
||||
for x := range req.Currencies {
|
||||
curr := c.FormatExchangeCurrency(req.Currencies[x],
|
||||
asset.Spot).String()
|
||||
instrumentID := c.instrumentMap.LookupID(curr)
|
||||
if instrumentID > 0 {
|
||||
instrumentsToUse = append(instrumentsToUse, instrumentID)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
instrumentsToUse = c.instrumentMap.GetInstrumentIDs()
|
||||
}
|
||||
for y := range orders.Trades {
|
||||
curr := c.instrumentMap.LookupInstrument(instrumentsToUse[x])
|
||||
p := currency.NewPairFromFormattedPairs(curr,
|
||||
c.GetEnabledPairs(asset.Spot),
|
||||
c.GetPairFormat(asset.Spot, true))
|
||||
orderSide := order.Side(strings.ToUpper(orders.Trades[y].Order.Side))
|
||||
orderDate := time.Unix(orders.Trades[y].Order.Timestamp, 0)
|
||||
allOrders = append(allOrders, order.Detail{
|
||||
ID: strconv.FormatInt(orders.Trades[y].Order.OrderID, 10),
|
||||
Amount: orders.Trades[y].Order.Quantity,
|
||||
Price: orders.Trades[y].Order.Price,
|
||||
Exchange: c.Name,
|
||||
OrderSide: orderSide,
|
||||
OrderDate: orderDate,
|
||||
CurrencyPair: p,
|
||||
})
|
||||
|
||||
if len(instrumentsToUse) == 0 {
|
||||
return nil, errors.New("no instrument IDs to use")
|
||||
}
|
||||
for x := range instrumentsToUse {
|
||||
orders, err := c.GetTradeHistory(instrumentsToUse[x], -1, -1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for y := range orders.Trades {
|
||||
curr := c.instrumentMap.LookupInstrument(instrumentsToUse[x])
|
||||
p := currency.NewPairFromFormattedPairs(curr,
|
||||
c.GetEnabledPairs(asset.Spot),
|
||||
c.GetPairFormat(asset.Spot, true))
|
||||
orderSide := order.Side(strings.ToUpper(orders.Trades[y].Order.Side))
|
||||
orderDate := time.Unix(orders.Trades[y].Order.Timestamp, 0)
|
||||
allOrders = append(allOrders, order.Detail{
|
||||
ID: strconv.FormatInt(orders.Trades[y].Order.OrderID, 10),
|
||||
Amount: orders.Trades[y].Order.Quantity,
|
||||
Price: orders.Trades[y].Order.Price,
|
||||
Exchange: c.Name,
|
||||
OrderSide: orderSide,
|
||||
OrderDate: orderDate,
|
||||
CurrencyPair: p,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -755,3 +869,20 @@ func (c *COINUT) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, e
|
||||
func (c *COINUT) AuthenticateWebsocket() error {
|
||||
return c.wsAuthenticate()
|
||||
}
|
||||
|
||||
func (c *COINUT) loadInstrumentsIfNotLoaded() error {
|
||||
if !c.instrumentMap.IsLoaded() {
|
||||
if c.Websocket.IsConnected() {
|
||||
_, err := c.WsGetInstruments()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err := c.SeedInstruments()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -14,27 +14,8 @@ import (
|
||||
const (
|
||||
RestAuthentication uint8 = 0
|
||||
WebsocketAuthentication uint8 = 1
|
||||
)
|
||||
|
||||
// FeeType custom type for calculating fees based on method
|
||||
type FeeType uint8
|
||||
|
||||
// Const declarations for fee types
|
||||
const (
|
||||
BankFee FeeType = iota
|
||||
InternationalBankDepositFee
|
||||
InternationalBankWithdrawalFee
|
||||
CryptocurrencyTradeFee
|
||||
CyptocurrencyDepositFee
|
||||
CryptocurrencyWithdrawalFee
|
||||
OfflineTradeFee
|
||||
)
|
||||
|
||||
// InternationalBankTransactionType custom type for calculating fees based on fiat transaction types
|
||||
type InternationalBankTransactionType uint8
|
||||
|
||||
// Const declarations for international transaction types
|
||||
const (
|
||||
// Repeated exchange strings
|
||||
// FeeType custom type for calculating fees based on method
|
||||
WireTransfer InternationalBankTransactionType = iota
|
||||
PerfectMoney
|
||||
Neteller
|
||||
@@ -53,26 +34,15 @@ const (
|
||||
WesternUnion
|
||||
MoneyGram
|
||||
Contact
|
||||
)
|
||||
|
||||
// FeeBuilder is the type which holds all parameters required to calculate a fee
|
||||
// for an exchange
|
||||
type FeeBuilder struct {
|
||||
FeeType FeeType
|
||||
// Used for calculating crypto trading fees, deposits & withdrawals
|
||||
Pair currency.Pair
|
||||
IsMaker bool
|
||||
// Fiat currency used for bank deposits & withdrawals
|
||||
FiatCurrency currency.Code
|
||||
BankTransactionType InternationalBankTransactionType
|
||||
// Used to multiply for fee calculations
|
||||
PurchasePrice float64
|
||||
Amount float64
|
||||
}
|
||||
|
||||
// Definitions for each type of withdrawal method for a given exchange
|
||||
const (
|
||||
// No withdraw
|
||||
// Const declarations for fee types
|
||||
BankFee FeeType = iota
|
||||
InternationalBankDepositFee
|
||||
InternationalBankWithdrawalFee
|
||||
CryptocurrencyTradeFee
|
||||
CyptocurrencyDepositFee
|
||||
CryptocurrencyWithdrawalFee
|
||||
OfflineTradeFee
|
||||
// Definitions for each type of withdrawal method for a given exchange
|
||||
NoAPIWithdrawalMethods uint32 = 0
|
||||
NoAPIWithdrawalMethodsText string = "NONE, WEBSITE ONLY"
|
||||
AutoWithdrawCrypto uint32 = (1 << 0)
|
||||
@@ -113,10 +83,29 @@ const (
|
||||
WithdrawFiatViaWebsiteOnlyText string = "WITHDRAW FIAT VIA WEBSITE ONLY"
|
||||
NoFiatWithdrawals uint32 = (1 << 18)
|
||||
NoFiatWithdrawalsText string = "NO FIAT WITHDRAWAL"
|
||||
|
||||
UnknownWithdrawalTypeText string = "UNKNOWN"
|
||||
UnknownWithdrawalTypeText string = "UNKNOWN"
|
||||
)
|
||||
|
||||
type FeeType uint8
|
||||
|
||||
// InternationalBankTransactionType custom type for calculating fees based on fiat transaction types
|
||||
type InternationalBankTransactionType uint8
|
||||
|
||||
// FeeBuilder is the type which holds all parameters required to calculate a fee
|
||||
// for an exchange
|
||||
type FeeBuilder struct {
|
||||
FeeType FeeType
|
||||
// Used for calculating crypto trading fees, deposits & withdrawals
|
||||
Pair currency.Pair
|
||||
IsMaker bool
|
||||
// Fiat currency used for bank deposits & withdrawals
|
||||
FiatCurrency currency.Code
|
||||
BankTransactionType InternationalBankTransactionType
|
||||
// Used to multiply for fee calculations
|
||||
PurchasePrice float64
|
||||
Amount float64
|
||||
}
|
||||
|
||||
// AccountInfo is a Generic type to hold each exchange's holdings in
|
||||
// all enabled currencies
|
||||
type AccountInfo struct {
|
||||
|
||||
@@ -2,6 +2,7 @@ package exmo
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
@@ -21,11 +22,8 @@ var (
|
||||
e EXMO
|
||||
)
|
||||
|
||||
func TestDefault(t *testing.T) {
|
||||
func TestMain(m *testing.M) {
|
||||
e.SetDefaults()
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
cfg := config.GetConfig()
|
||||
err := cfg.LoadConfig("../../testdata/configtest.json", true)
|
||||
if err != nil {
|
||||
@@ -33,17 +31,19 @@ func TestSetup(t *testing.T) {
|
||||
}
|
||||
exmoConf, err := cfg.GetExchangeConfig("EXMO")
|
||||
if err != nil {
|
||||
t.Error("Exmo Setup() init error")
|
||||
log.Fatal("Exmo Setup() init error")
|
||||
}
|
||||
|
||||
err = e.Setup(exmoConf)
|
||||
if err != nil {
|
||||
t.Fatal("Exmo setup error", err)
|
||||
log.Fatal("Exmo setup error", err)
|
||||
}
|
||||
|
||||
e.API.AuthenticatedSupport = true
|
||||
e.API.Credentials.Key = APIKey
|
||||
e.API.Credentials.Secret = APISecret
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestGetTrades(t *testing.T) {
|
||||
@@ -88,10 +88,9 @@ func TestGetCurrency(t *testing.T) {
|
||||
|
||||
func TestGetUserInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
if APIKey == "" || APISecret == "" {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip()
|
||||
}
|
||||
TestSetup(t)
|
||||
_, err := e.GetUserInfo()
|
||||
if err != nil {
|
||||
t.Errorf("Err: %s", err)
|
||||
@@ -100,10 +99,9 @@ func TestGetUserInfo(t *testing.T) {
|
||||
|
||||
func TestGetRequiredAmount(t *testing.T) {
|
||||
t.Parallel()
|
||||
if APIKey == "" || APISecret == "" {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip()
|
||||
}
|
||||
TestSetup(t)
|
||||
_, err := e.GetRequiredAmount("BTC_USD", 100)
|
||||
if err != nil {
|
||||
t.Errorf("Err: %s", err)
|
||||
@@ -125,7 +123,7 @@ func setFeeBuilder() *exchange.FeeBuilder {
|
||||
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
var feeBuilder = setFeeBuilder()
|
||||
e.GetFeeByType(feeBuilder)
|
||||
if APIKey == "" || APISecret == "" {
|
||||
if !areTestAPIKeysSet() {
|
||||
if feeBuilder.FeeType != exchange.OfflineTradeFee {
|
||||
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
|
||||
}
|
||||
@@ -137,8 +135,6 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetFee(t *testing.T) {
|
||||
e.SetDefaults()
|
||||
TestSetup(t)
|
||||
t.Parallel()
|
||||
|
||||
var feeBuilder = setFeeBuilder()
|
||||
@@ -255,20 +251,14 @@ func TestGetFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
e.SetDefaults()
|
||||
expectedResult := exchange.AutoWithdrawCryptoWithSetupText + " & " + exchange.NoFiatWithdrawalsText
|
||||
|
||||
withdrawPermissions := e.FormatWithdrawPermissions()
|
||||
|
||||
if withdrawPermissions != expectedResult {
|
||||
t.Errorf("Expected: %s, Received: %s", expectedResult, withdrawPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
e.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
}
|
||||
@@ -282,9 +272,6 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
e.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
}
|
||||
@@ -307,8 +294,6 @@ func areTestAPIKeysSet() bool {
|
||||
}
|
||||
|
||||
func TestSubmitOrder(t *testing.T) {
|
||||
e.SetDefaults()
|
||||
TestSetup(t)
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -334,14 +319,11 @@ func TestSubmitOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelExchangeOrder(t *testing.T) {
|
||||
e.SetDefaults()
|
||||
TestSetup(t)
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -359,9 +341,6 @@ func TestCancelExchangeOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
e.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -389,6 +368,9 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestModifyOrder(t *testing.T) {
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
_, err := e.ModifyOrder(&order.Modify{})
|
||||
if err == nil {
|
||||
t.Error("ModifyOrder() Expected error")
|
||||
@@ -396,8 +378,10 @@ func TestModifyOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdraw(t *testing.T) {
|
||||
e.SetDefaults()
|
||||
TestSetup(t)
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
withdrawCryptoRequest := exchange.CryptoWithdrawRequest{
|
||||
GenericWithdrawRequestInfo: exchange.GenericWithdrawRequestInfo{
|
||||
Amount: -1,
|
||||
@@ -407,10 +391,6 @@ func TestWithdraw(t *testing.T) {
|
||||
Address: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
}
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
_, err := e.WithdrawCryptocurrencyFunds(&withdrawCryptoRequest)
|
||||
if !areTestAPIKeysSet() && err == nil {
|
||||
t.Error("Expecting an error when no keys are set")
|
||||
@@ -421,9 +401,6 @@ func TestWithdraw(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawFiat(t *testing.T) {
|
||||
e.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -436,9 +413,6 @@ func TestWithdrawFiat(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawInternationalBank(t *testing.T) {
|
||||
e.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
@@ -238,10 +238,10 @@ func (e *EXMO) UpdateOrderbook(p currency.Pair, assetType asset.Item) (orderbook
|
||||
if err != nil {
|
||||
return orderBook, err
|
||||
}
|
||||
|
||||
for _, x := range e.GetEnabledPairs(assetType) {
|
||||
currency := e.FormatExchangeCurrency(x, assetType)
|
||||
data, ok := result[currency.String()]
|
||||
enabledPairs := e.GetEnabledPairs(assetType)
|
||||
for i := range enabledPairs {
|
||||
curr := e.FormatExchangeCurrency(enabledPairs[i], assetType)
|
||||
data, ok := result[curr.String()]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
@@ -266,7 +266,7 @@ func (e *EXMO) UpdateOrderbook(p currency.Pair, assetType asset.Item) (orderbook
|
||||
}
|
||||
|
||||
orderBook.Bids = obItems
|
||||
orderBook.Pair = x
|
||||
orderBook.Pair = enabledPairs[i]
|
||||
orderBook.ExchangeName = e.Name
|
||||
orderBook.AssetType = assetType
|
||||
|
||||
@@ -344,15 +344,18 @@ func (e *EXMO) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
|
||||
oT,
|
||||
s.Price,
|
||||
s.Amount)
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
if response > 0 {
|
||||
submitOrderResponse.OrderID = strconv.FormatInt(response, 10)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
if s.OrderType == order.Market {
|
||||
submitOrderResponse.FullyMatched = true
|
||||
}
|
||||
|
||||
return submitOrderResponse, err
|
||||
return submitOrderResponse, nil
|
||||
}
|
||||
|
||||
// ModifyOrder will allow of changing orderbook placement and limit to
|
||||
@@ -382,10 +385,10 @@ func (e *EXMO) CancelAllOrders(_ *order.Cancel) (order.CancelAllResponse, error)
|
||||
return cancelAllOrdersResponse, err
|
||||
}
|
||||
|
||||
for _, order := range openOrders {
|
||||
err = e.CancelExistingOrder(order.OrderID)
|
||||
for i := range openOrders {
|
||||
err = e.CancelExistingOrder(openOrders[i].OrderID)
|
||||
if err != nil {
|
||||
cancelAllOrdersResponse.Status[strconv.FormatInt(order.OrderID, 10)] = err.Error()
|
||||
cancelAllOrdersResponse.Status[strconv.FormatInt(openOrders[i].OrderID, 10)] = err.Error()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -486,13 +489,13 @@ func (e *EXMO) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, err
|
||||
}
|
||||
|
||||
var allTrades []UserTrades
|
||||
for _, currency := range req.Currencies {
|
||||
resp, err := e.GetUserTrades(e.FormatExchangeCurrency(currency, asset.Spot).String(), "", "10000")
|
||||
for i := range req.Currencies {
|
||||
resp, err := e.GetUserTrades(e.FormatExchangeCurrency(req.Currencies[i], asset.Spot).String(), "", "10000")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, order := range resp {
|
||||
allTrades = append(allTrades, order...)
|
||||
for j := range resp {
|
||||
allTrades = append(allTrades, resp[j]...)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package gateio
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
@@ -25,29 +27,28 @@ const (
|
||||
var g Gateio
|
||||
var wsSetupRan bool
|
||||
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
func TestMain(m *testing.M) {
|
||||
g.SetDefaults()
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
cfg := config.GetConfig()
|
||||
err := cfg.LoadConfig("../../testdata/configtest.json", true)
|
||||
if err != nil {
|
||||
t.Fatal("GateIO load config error", err)
|
||||
log.Fatal("GateIO load config error", err)
|
||||
}
|
||||
gateioConfig, err := cfg.GetExchangeConfig("GateIO")
|
||||
gConf, err := cfg.GetExchangeConfig("GateIO")
|
||||
if err != nil {
|
||||
t.Error("GateIO Setup() init error")
|
||||
log.Fatal("GateIO Setup() init error")
|
||||
}
|
||||
gateioConfig.API.AuthenticatedSupport = true
|
||||
gateioConfig.API.AuthenticatedWebsocketSupport = true
|
||||
gateioConfig.API.Credentials.Key = apiKey
|
||||
gateioConfig.API.Credentials.Secret = apiSecret
|
||||
gConf.API.AuthenticatedSupport = true
|
||||
gConf.API.AuthenticatedWebsocketSupport = true
|
||||
gConf.API.Credentials.Key = apiKey
|
||||
gConf.API.Credentials.Secret = apiSecret
|
||||
|
||||
err = g.Setup(gateioConfig)
|
||||
err = g.Setup(gConf)
|
||||
if err != nil {
|
||||
t.Fatal("GateIO setup error", err)
|
||||
log.Fatal("GateIO setup error", err)
|
||||
}
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestGetSymbols(t *testing.T) {
|
||||
@@ -100,7 +101,7 @@ func TestCancelExistingOrder(t *testing.T) {
|
||||
func TestGetBalances(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
@@ -173,7 +174,7 @@ func setFeeBuilder() *exchange.FeeBuilder {
|
||||
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
var feeBuilder = setFeeBuilder()
|
||||
g.GetFeeByType(feeBuilder)
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
if !areTestAPIKeysSet() {
|
||||
if feeBuilder.FeeType != exchange.OfflineTradeFee {
|
||||
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
|
||||
}
|
||||
@@ -185,9 +186,6 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetFee(t *testing.T) {
|
||||
g.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var feeBuilder = setFeeBuilder()
|
||||
if areTestAPIKeysSet() {
|
||||
// CryptocurrencyTradeFee Basic
|
||||
@@ -265,20 +263,14 @@ func TestGetFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
g.SetDefaults()
|
||||
expectedResult := exchange.AutoWithdrawCryptoText + " & " + exchange.NoFiatWithdrawalsText
|
||||
|
||||
withdrawPermissions := g.FormatWithdrawPermissions()
|
||||
|
||||
if withdrawPermissions != expectedResult {
|
||||
t.Errorf("Expected: %s, Received: %s", expectedResult, withdrawPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
g.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
}
|
||||
@@ -292,9 +284,6 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
g.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
}
|
||||
@@ -318,9 +307,6 @@ func areTestAPIKeysSet() bool {
|
||||
}
|
||||
|
||||
func TestSubmitOrder(t *testing.T) {
|
||||
g.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip()
|
||||
}
|
||||
@@ -346,15 +332,11 @@ func TestSubmitOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelExchangeOrder(t *testing.T) {
|
||||
g.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -372,15 +354,11 @@ func TestCancelExchangeOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
g.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -417,6 +395,9 @@ func TestGetAccountInfo(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestModifyOrder(t *testing.T) {
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
_, err := g.ModifyOrder(&order.Modify{})
|
||||
if err == nil {
|
||||
t.Error("ModifyOrder() Expected error")
|
||||
@@ -424,8 +405,6 @@ func TestModifyOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdraw(t *testing.T) {
|
||||
g.SetDefaults()
|
||||
TestSetup(t)
|
||||
withdrawCryptoRequest := exchange.CryptoWithdrawRequest{
|
||||
GenericWithdrawRequestInfo: exchange.GenericWithdrawRequestInfo{
|
||||
Amount: -1,
|
||||
@@ -449,9 +428,6 @@ func TestWithdraw(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawFiat(t *testing.T) {
|
||||
g.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -464,9 +440,6 @@ func TestWithdrawFiat(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawInternationalBank(t *testing.T) {
|
||||
g.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -492,9 +465,6 @@ func TestGetDepositAddress(t *testing.T) {
|
||||
}
|
||||
}
|
||||
func TestGetOrderInfo(t *testing.T) {
|
||||
g.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("no API keys set skipping test")
|
||||
}
|
||||
@@ -509,8 +479,6 @@ func TestGetOrderInfo(t *testing.T) {
|
||||
|
||||
// TestWsGetBalance dials websocket, sends balance request.
|
||||
func TestWsGetBalance(t *testing.T) {
|
||||
g.SetDefaults()
|
||||
TestSetup(t)
|
||||
if !g.Websocket.IsEnabled() && !g.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
@@ -541,12 +509,14 @@ func TestWsGetBalance(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = g.wsGetBalance([]string{})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestWsGetOrderInfo dials websocket, sends order info request.
|
||||
func TestWsGetOrderInfo(t *testing.T) {
|
||||
g.SetDefaults()
|
||||
TestSetup(t)
|
||||
if !g.Websocket.IsEnabled() && !g.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
@@ -573,7 +543,7 @@ func TestWsGetOrderInfo(t *testing.T) {
|
||||
if resp.Result.Status != "success" {
|
||||
t.Fatal("Unsuccessful login")
|
||||
}
|
||||
_, err = g.wsGetOrderInfo("EOS_USDT", 0, 10)
|
||||
_, err = g.wsGetOrderInfo("EOS_USDT", 0, 1000)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -583,8 +553,6 @@ func setupWSTestAuth(t *testing.T) {
|
||||
if wsSetupRan {
|
||||
return
|
||||
}
|
||||
g.SetDefaults()
|
||||
TestSetup(t)
|
||||
if !g.Websocket.IsEnabled() && !g.API.AuthenticatedWebsocketSupport {
|
||||
t.Skip(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
|
||||
@@ -445,19 +445,19 @@ type WebSocketOrderQueryResult struct {
|
||||
|
||||
// WebSocketOrderQueryRecords contains order information from a order.query websocket request
|
||||
type WebSocketOrderQueryRecords struct {
|
||||
ID int `json:"id"`
|
||||
ID int64 `json:"id"`
|
||||
Market string `json:"market"`
|
||||
User int `json:"user"`
|
||||
User int64 `json:"user"`
|
||||
Ctime float64 `json:"ctime"`
|
||||
Mtime float64 `json:"mtime"`
|
||||
Price string `json:"price"`
|
||||
Amount string `json:"amount"`
|
||||
Left string `json:"left"`
|
||||
DealFee string `json:"dealFee"`
|
||||
OrderType int `json:"orderType"`
|
||||
Type int `json:"type"`
|
||||
FilledAmount string `json:"filledAmount"`
|
||||
FilledTotal string `json:"filledTotal"`
|
||||
Price float64 `json:"price,string"`
|
||||
Amount float64 `json:"amount,string"`
|
||||
Left float64 `json:"left,string"`
|
||||
DealFee float64 `json:"dealFee,string"`
|
||||
OrderType int64 `json:"orderType"`
|
||||
Type int64 `json:"type"`
|
||||
FilledAmount float64 `json:"filledAmount,string"`
|
||||
FilledTotal float64 `json:"filledTotal,string"`
|
||||
}
|
||||
|
||||
// WebsocketAuthenticationResponse contains the result of a login request
|
||||
@@ -473,14 +473,14 @@ type WebsocketAuthenticationResponse struct {
|
||||
type wsGetBalanceRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
Method string `json:"method"`
|
||||
Params []string `json:"params,omitempty"`
|
||||
Params []string `json:"params"`
|
||||
}
|
||||
|
||||
// WsGetBalanceResponse stores WS GetBalance response
|
||||
type WsGetBalanceResponse struct {
|
||||
Error interface{} `json:"error"`
|
||||
Result map[currency.Code]WsGetBalanceResponseData `json:"result,omitempty"`
|
||||
ID int64 `json:"id"`
|
||||
Error interface{} `json:"error"`
|
||||
Result map[string]WsGetBalanceResponseData `json:"result"`
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
|
||||
// WsGetBalanceResponseData contains currency data
|
||||
|
||||
@@ -40,6 +40,7 @@ func (g *Gateio) WsConnect() error {
|
||||
_, err = g.wsServerSignIn()
|
||||
if err != nil {
|
||||
log.Errorf(log.ExchangeSys, "%v - authentication failed: %v\n", g.Name, err)
|
||||
g.Websocket.SetCanUseAuthenticatedEndpoints(false)
|
||||
}
|
||||
g.GenerateAuthenticatedSubscriptions()
|
||||
g.GenerateDefaultSubscriptions()
|
||||
@@ -416,7 +417,7 @@ func (g *Gateio) wsGetOrderInfo(market string, offset, limit int) (*WebSocketOrd
|
||||
if !g.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
return nil, fmt.Errorf("%v not authorised to get order info", g.Name)
|
||||
}
|
||||
order := WebsocketRequest{
|
||||
ord := WebsocketRequest{
|
||||
ID: g.WebsocketConn.GenerateMessageID(true),
|
||||
Method: "order.query",
|
||||
Params: []interface{}{
|
||||
@@ -425,7 +426,7 @@ func (g *Gateio) wsGetOrderInfo(market string, offset, limit int) (*WebSocketOrd
|
||||
limit,
|
||||
},
|
||||
}
|
||||
resp, err := g.WebsocketConn.SendMessageReturnResponse(order.ID, order)
|
||||
resp, err := g.WebsocketConn.SendMessageReturnResponse(ord.ID, ord)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
@@ -99,6 +100,8 @@ func (g *Gateio) SetDefaults() {
|
||||
Unsubscribe: true,
|
||||
AuthenticatedEndpoints: true,
|
||||
MessageCorrelation: true,
|
||||
GetOrder: true,
|
||||
AccountBalance: true,
|
||||
},
|
||||
WithdrawPermissions: exchange.AutoWithdrawCrypto |
|
||||
exchange.NoFiatWithdrawals,
|
||||
@@ -269,9 +272,9 @@ func (g *Gateio) FetchOrderbook(p currency.Pair, assetType asset.Item) (orderboo
|
||||
// UpdateOrderbook updates and returns the orderbook for a currency pair
|
||||
func (g *Gateio) UpdateOrderbook(p currency.Pair, assetType asset.Item) (orderbook.Base, error) {
|
||||
var orderBook orderbook.Base
|
||||
currency := g.FormatExchangeCurrency(p, assetType).String()
|
||||
curr := g.FormatExchangeCurrency(p, assetType).String()
|
||||
|
||||
orderbookNew, err := g.GetOrderbook(currency)
|
||||
orderbookNew, err := g.GetOrderbook(curr)
|
||||
if err != nil {
|
||||
return orderBook, err
|
||||
}
|
||||
@@ -306,61 +309,78 @@ func (g *Gateio) UpdateOrderbook(p currency.Pair, assetType asset.Item) (orderbo
|
||||
// ZB exchange
|
||||
func (g *Gateio) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var info exchange.AccountInfo
|
||||
|
||||
balance, err := g.GetBalances()
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
var balances []exchange.AccountCurrencyInfo
|
||||
|
||||
switch l := balance.Locked.(type) {
|
||||
case map[string]interface{}:
|
||||
for x := range l {
|
||||
lockedF, err := strconv.ParseFloat(l[x].(string), 64)
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
balances = append(balances, exchange.AccountCurrencyInfo{
|
||||
CurrencyName: currency.NewCode(x),
|
||||
Hold: lockedF,
|
||||
if g.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
resp, err := g.wsGetBalance([]string{})
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
var currData []exchange.AccountCurrencyInfo
|
||||
for k := range resp.Result {
|
||||
currData = append(currData, exchange.AccountCurrencyInfo{
|
||||
CurrencyName: currency.NewCode(k),
|
||||
TotalValue: resp.Result[k].Available + resp.Result[k].Freeze,
|
||||
Hold: resp.Result[k].Freeze,
|
||||
})
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
info.Accounts = append(info.Accounts, exchange.Account{
|
||||
Currencies: currData,
|
||||
})
|
||||
} else {
|
||||
balance, err := g.GetBalances()
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
switch v := balance.Available.(type) {
|
||||
case map[string]interface{}:
|
||||
for x := range v {
|
||||
availAmount, err := strconv.ParseFloat(v[x].(string), 64)
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
var updated bool
|
||||
for i := range balances {
|
||||
if balances[i].CurrencyName == currency.NewCode(x) {
|
||||
balances[i].TotalValue = balances[i].Hold + availAmount
|
||||
updated = true
|
||||
break
|
||||
switch l := balance.Locked.(type) {
|
||||
case map[string]interface{}:
|
||||
for x := range l {
|
||||
lockedF, err := strconv.ParseFloat(l[x].(string), 64)
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
}
|
||||
if !updated {
|
||||
|
||||
balances = append(balances, exchange.AccountCurrencyInfo{
|
||||
CurrencyName: currency.NewCode(x),
|
||||
TotalValue: availAmount,
|
||||
Hold: lockedF,
|
||||
})
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
info.Accounts = append(info.Accounts, exchange.Account{
|
||||
Currencies: balances,
|
||||
})
|
||||
switch v := balance.Available.(type) {
|
||||
case map[string]interface{}:
|
||||
for x := range v {
|
||||
availAmount, err := strconv.ParseFloat(v[x].(string), 64)
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
var updated bool
|
||||
for i := range balances {
|
||||
if balances[i].CurrencyName == currency.NewCode(x) {
|
||||
balances[i].TotalValue = balances[i].Hold + availAmount
|
||||
updated = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !updated {
|
||||
balances = append(balances, exchange.AccountCurrencyInfo{
|
||||
CurrencyName: currency.NewCode(x),
|
||||
TotalValue: availAmount,
|
||||
})
|
||||
}
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
info.Accounts = append(info.Accounts, exchange.Account{
|
||||
Currencies: balances,
|
||||
})
|
||||
}
|
||||
|
||||
info.Exchange = g.Name
|
||||
|
||||
@@ -401,15 +421,18 @@ func (g *Gateio) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
|
||||
}
|
||||
|
||||
response, err := g.SpotNewOrder(spotNewOrderRequestParams)
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
if response.OrderNumber > 0 {
|
||||
submitOrderResponse.OrderID = strconv.FormatInt(response.OrderNumber, 10)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
if response.LeftAmount == 0 {
|
||||
submitOrderResponse.FullyMatched = true
|
||||
}
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
|
||||
return submitOrderResponse, err
|
||||
return submitOrderResponse, nil
|
||||
}
|
||||
|
||||
// ModifyOrder will allow of changing orderbook placement and limit to
|
||||
@@ -457,7 +480,6 @@ func (g *Gateio) CancelAllOrders(_ *order.Cancel) (order.CancelAllResponse, erro
|
||||
// GetOrderInfo returns information on a current open order
|
||||
func (g *Gateio) GetOrderInfo(orderID string) (order.Detail, error) {
|
||||
var orderDetail order.Detail
|
||||
|
||||
orders, err := g.GetOpenOrders("")
|
||||
if err != nil {
|
||||
return orderDetail, errors.New("failed to get open orders")
|
||||
@@ -534,40 +556,79 @@ func (g *Gateio) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error)
|
||||
|
||||
// GetActiveOrders retrieves any orders that are active/open
|
||||
func (g *Gateio) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
|
||||
var orders []order.Detail
|
||||
var currPair string
|
||||
if len(req.Currencies) == 1 {
|
||||
currPair = req.Currencies[0].String()
|
||||
}
|
||||
if g.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
for i := 0; ; i += 100 {
|
||||
resp, err := g.wsGetOrderInfo(req.OrderType.String(), i, 100)
|
||||
if err != nil {
|
||||
return orders, err
|
||||
}
|
||||
|
||||
resp, err := g.GetOpenOrders(currPair)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var orders []order.Detail
|
||||
for i := range resp.Orders {
|
||||
if resp.Orders[i].Status != "open" {
|
||||
continue
|
||||
for j := range resp.WebSocketOrderQueryRecords {
|
||||
orderSide := order.Buy
|
||||
if resp.WebSocketOrderQueryRecords[j].Type == 1 {
|
||||
orderSide = order.Sell
|
||||
}
|
||||
orderType := order.Market
|
||||
if resp.WebSocketOrderQueryRecords[j].OrderType == 1 {
|
||||
orderType = order.Limit
|
||||
}
|
||||
firstNum, decNum, err := convert.SplitFloatDecimals(resp.WebSocketOrderQueryRecords[j].Ctime)
|
||||
if err != nil {
|
||||
return orders, err
|
||||
}
|
||||
orderDate := time.Unix(firstNum, decNum)
|
||||
orders = append(orders, order.Detail{
|
||||
Exchange: g.Name,
|
||||
AccountID: strconv.FormatInt(resp.WebSocketOrderQueryRecords[j].User, 10),
|
||||
ID: strconv.FormatInt(resp.WebSocketOrderQueryRecords[j].ID, 10),
|
||||
CurrencyPair: currency.NewPairFromString(resp.WebSocketOrderQueryRecords[j].Market),
|
||||
OrderSide: orderSide,
|
||||
OrderType: orderType,
|
||||
OrderDate: orderDate,
|
||||
Price: resp.WebSocketOrderQueryRecords[j].Price,
|
||||
Amount: resp.WebSocketOrderQueryRecords[j].Amount,
|
||||
ExecutedAmount: resp.WebSocketOrderQueryRecords[j].FilledAmount,
|
||||
RemainingAmount: resp.WebSocketOrderQueryRecords[j].Left,
|
||||
Fee: resp.WebSocketOrderQueryRecords[j].DealFee,
|
||||
})
|
||||
}
|
||||
if len(resp.WebSocketOrderQueryRecords) < 100 {
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
resp, err := g.GetOpenOrders(currPair)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
symbol := currency.NewPairDelimiter(resp.Orders[i].CurrencyPair,
|
||||
g.GetPairFormat(asset.Spot, false).Delimiter)
|
||||
side := order.Side(strings.ToUpper(resp.Orders[i].Type))
|
||||
orderDate := time.Unix(resp.Orders[i].Timestamp, 0)
|
||||
for i := range resp.Orders {
|
||||
if resp.Orders[i].Status != "open" {
|
||||
continue
|
||||
}
|
||||
|
||||
orders = append(orders, order.Detail{
|
||||
ID: resp.Orders[i].OrderNumber,
|
||||
Amount: resp.Orders[i].Amount,
|
||||
Price: resp.Orders[i].Rate,
|
||||
RemainingAmount: resp.Orders[i].FilledAmount,
|
||||
OrderDate: orderDate,
|
||||
OrderSide: side,
|
||||
Exchange: g.Name,
|
||||
CurrencyPair: symbol,
|
||||
Status: order.Status(resp.Orders[i].Status),
|
||||
})
|
||||
symbol := currency.NewPairDelimiter(resp.Orders[i].CurrencyPair,
|
||||
g.GetPairFormat(asset.Spot, false).Delimiter)
|
||||
side := order.Side(strings.ToUpper(resp.Orders[i].Type))
|
||||
orderDate := time.Unix(resp.Orders[i].Timestamp, 0)
|
||||
orders = append(orders, order.Detail{
|
||||
ID: resp.Orders[i].OrderNumber,
|
||||
Amount: resp.Orders[i].Amount,
|
||||
Price: resp.Orders[i].Rate,
|
||||
RemainingAmount: resp.Orders[i].FilledAmount,
|
||||
OrderDate: orderDate,
|
||||
OrderSide: side,
|
||||
Exchange: g.Name,
|
||||
CurrencyPair: symbol,
|
||||
Status: order.Status(resp.Orders[i].Status),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
|
||||
order.FilterOrdersBySide(&orders, req.OrderSide)
|
||||
return orders, nil
|
||||
@@ -577,8 +638,8 @@ func (g *Gateio) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
|
||||
// Can Limit response to specific order status
|
||||
func (g *Gateio) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error) {
|
||||
var trades []TradesResponse
|
||||
for _, currency := range req.Currencies {
|
||||
resp, err := g.GetTradeHistory(currency.String())
|
||||
for i := range req.Currencies {
|
||||
resp, err := g.GetTradeHistory(req.Currencies[i].String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -336,9 +336,7 @@ func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
exchange.AutoWithdrawCryptoWithSetupText +
|
||||
" & " +
|
||||
exchange.WithdrawFiatViaWebsiteOnlyText
|
||||
|
||||
withdrawPermissions := g.FormatWithdrawPermissions()
|
||||
|
||||
if withdrawPermissions != expectedResult {
|
||||
t.Errorf("Expected: %s, Received: %s",
|
||||
expectedResult,
|
||||
@@ -425,7 +423,6 @@ func TestCancelExchangeOrder(t *testing.T) {
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders && !mockTests {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "266029865",
|
||||
}
|
||||
@@ -448,7 +445,6 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
|
||||
@@ -32,7 +32,7 @@ const (
|
||||
)
|
||||
|
||||
// Instantiates a communications channel between websocket connections
|
||||
var comms = make(chan ReadData, 1)
|
||||
var comms = make(chan ReadData)
|
||||
var responseMaxLimit time.Duration
|
||||
var responseCheckTimeout time.Duration
|
||||
|
||||
@@ -62,13 +62,13 @@ func (g *Gemini) WsConnect() error {
|
||||
// WsSubscribe subscribes to the full websocket suite on gemini exchange
|
||||
func (g *Gemini) WsSubscribe(dialer *websocket.Dialer) error {
|
||||
enabledCurrencies := g.GetEnabledPairs(asset.Spot)
|
||||
for i, c := range enabledCurrencies {
|
||||
for i := range enabledCurrencies {
|
||||
val := url.Values{}
|
||||
val.Set("heartbeat", "true")
|
||||
endpoint := fmt.Sprintf("%s%s/%s?%s",
|
||||
g.API.Endpoints.WebsocketURL,
|
||||
geminiWsMarketData,
|
||||
c.String(),
|
||||
enabledCurrencies[i].String(),
|
||||
val.Encode())
|
||||
connection := &wshandler.WebsocketConnection{
|
||||
ExchangeName: g.Name,
|
||||
@@ -82,7 +82,7 @@ func (g *Gemini) WsSubscribe(dialer *websocket.Dialer) error {
|
||||
return fmt.Errorf("%v Websocket connection %v error. Error %v",
|
||||
g.Name, endpoint, err)
|
||||
}
|
||||
go g.WsReadData(connection, c)
|
||||
go g.WsReadData(connection, enabledCurrencies[i])
|
||||
if len(enabledCurrencies)-1 == i {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -333,13 +333,16 @@ func (g *Gemini) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
|
||||
s.Price,
|
||||
s.OrderSide.String(),
|
||||
"exchange limit")
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
if response > 0 {
|
||||
submitOrderResponse.OrderID = strconv.FormatInt(response, 10)
|
||||
}
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
}
|
||||
return submitOrderResponse, err
|
||||
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
|
||||
return submitOrderResponse, nil
|
||||
}
|
||||
|
||||
// ModifyOrder will allow of changing orderbook placement and limit to
|
||||
@@ -369,8 +372,8 @@ func (g *Gemini) CancelAllOrders(_ *order.Cancel) (order.CancelAllResponse, erro
|
||||
return cancelAllOrdersResponse, err
|
||||
}
|
||||
|
||||
for _, order := range resp.Details.CancelRejects {
|
||||
cancelAllOrdersResponse.Status[order] = "Could not cancel order"
|
||||
for i := range resp.Details.CancelRejects {
|
||||
cancelAllOrdersResponse.Status[resp.Details.CancelRejects[i]] = "Could not cancel order"
|
||||
}
|
||||
|
||||
return cancelAllOrdersResponse, nil
|
||||
|
||||
@@ -315,7 +315,7 @@ func (h *HitBTC) GetOpenOrders(currency string) ([]OrderHistoryResponse, error)
|
||||
|
||||
// PlaceOrder places an order on the exchange
|
||||
func (h *HitBTC) PlaceOrder(currency string, rate, amount float64, orderType, side string) (OrderResponse, error) {
|
||||
result := OrderResponse{}
|
||||
var result OrderResponse
|
||||
values := url.Values{}
|
||||
|
||||
values.Set("symbol", currency)
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package hitbtc
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -26,19 +28,16 @@ const (
|
||||
canManipulateRealOrders = false
|
||||
)
|
||||
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
func TestMain(m *testing.M) {
|
||||
h.SetDefaults()
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
cfg := config.GetConfig()
|
||||
err := cfg.LoadConfig("../../testdata/configtest.json", true)
|
||||
if err != nil {
|
||||
t.Fatal("HitBTC load config error", err)
|
||||
log.Fatal("HitBTC load config error", err)
|
||||
}
|
||||
hitbtcConfig, err := cfg.GetExchangeConfig("HitBTC")
|
||||
if err != nil {
|
||||
t.Error("HitBTC Setup() init error")
|
||||
log.Fatal("HitBTC Setup() init error")
|
||||
}
|
||||
hitbtcConfig.API.AuthenticatedSupport = true
|
||||
hitbtcConfig.API.AuthenticatedWebsocketSupport = true
|
||||
@@ -47,8 +46,10 @@ func TestSetup(t *testing.T) {
|
||||
|
||||
err = h.Setup(hitbtcConfig)
|
||||
if err != nil {
|
||||
t.Fatal("HitBTC setup error", err)
|
||||
log.Fatal("HitBTC setup error", err)
|
||||
}
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestGetOrderbook(t *testing.T) {
|
||||
@@ -94,7 +95,7 @@ func setFeeBuilder() *exchange.FeeBuilder {
|
||||
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
var feeBuilder = setFeeBuilder()
|
||||
h.GetFeeByType(feeBuilder)
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
if !areTestAPIKeysSet() {
|
||||
if feeBuilder.FeeType != exchange.OfflineTradeFee {
|
||||
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
|
||||
}
|
||||
@@ -106,9 +107,6 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUpdateTicker(t *testing.T) {
|
||||
h.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
h.CurrencyPairs.StorePairs(asset.Spot, currency.NewPairsFromStrings([]string{"BTC-USD", "XRP-USD"}), true)
|
||||
_, err := h.UpdateTicker(currency.NewPair(currency.BTC, currency.USD), asset.Spot)
|
||||
if err != nil {
|
||||
@@ -136,9 +134,6 @@ func TestGetSingularTicker(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetFee(t *testing.T) {
|
||||
h.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var feeBuilder = setFeeBuilder()
|
||||
if areTestAPIKeysSet() {
|
||||
// CryptocurrencyTradeFee Basic
|
||||
@@ -219,20 +214,14 @@ func TestGetFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
h.SetDefaults()
|
||||
expectedResult := exchange.AutoWithdrawCryptoText + " & " + exchange.NoFiatWithdrawalsText
|
||||
|
||||
withdrawPermissions := h.FormatWithdrawPermissions()
|
||||
|
||||
if withdrawPermissions != expectedResult {
|
||||
t.Errorf("Expected: %s, Received: %s", expectedResult, withdrawPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
h.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
Currencies: []currency.Pair{currency.NewPair(currency.ETH, currency.BTC)},
|
||||
@@ -247,9 +236,6 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
h.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
Currencies: []currency.Pair{currency.NewPair(currency.ETH, currency.BTC)},
|
||||
@@ -270,9 +256,6 @@ func areTestAPIKeysSet() bool {
|
||||
}
|
||||
|
||||
func TestSubmitOrder(t *testing.T) {
|
||||
h.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -297,15 +280,11 @@ func TestSubmitOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelExchangeOrder(t *testing.T) {
|
||||
h.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -323,15 +302,11 @@ func TestCancelExchangeOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
h.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -354,6 +329,9 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestModifyOrder(t *testing.T) {
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
_, err := h.ModifyOrder(&order.Modify{})
|
||||
if err == nil {
|
||||
t.Error("ModifyOrder() Expected error")
|
||||
@@ -361,8 +339,6 @@ func TestModifyOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdraw(t *testing.T) {
|
||||
h.SetDefaults()
|
||||
TestSetup(t)
|
||||
withdrawCryptoRequest := exchange.CryptoWithdrawRequest{
|
||||
GenericWithdrawRequestInfo: exchange.GenericWithdrawRequestInfo{
|
||||
Amount: -1,
|
||||
@@ -386,9 +362,6 @@ func TestWithdraw(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawFiat(t *testing.T) {
|
||||
h.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -401,9 +374,6 @@ func TestWithdrawFiat(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawInternationalBank(t *testing.T) {
|
||||
h.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -432,8 +402,6 @@ func setupWsAuth(t *testing.T) {
|
||||
if wsSetupRan {
|
||||
return
|
||||
}
|
||||
TestSetDefaults(t)
|
||||
TestSetup(t)
|
||||
if !h.Websocket.IsEnabled() && !h.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -395,7 +396,7 @@ func (h *HitBTC) wsLogin() error {
|
||||
return fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", h.Name)
|
||||
}
|
||||
h.Websocket.SetCanUseAuthenticatedEndpoints(true)
|
||||
nonce := fmt.Sprintf("%v", time.Now().Unix())
|
||||
nonce := strconv.FormatInt(time.Now().Unix(), 10)
|
||||
hmac := crypto.GetHMAC(crypto.HashSHA256, []byte(nonce), []byte(h.API.Credentials.Secret))
|
||||
request := WsLoginRequest{
|
||||
Method: "login",
|
||||
@@ -483,7 +484,7 @@ func (h *HitBTC) wsReplaceOrder(clientOrderID string, quantity, price float64) (
|
||||
Method: "cancelReplaceOrder",
|
||||
Params: WsReplaceOrderRequestData{
|
||||
ClientOrderID: clientOrderID,
|
||||
RequestClientID: fmt.Sprintf("%v", time.Now().Unix()),
|
||||
RequestClientID: strconv.FormatInt(time.Now().Unix(), 10),
|
||||
Quantity: quantity,
|
||||
Price: price,
|
||||
},
|
||||
|
||||
@@ -373,24 +373,42 @@ func (h *HitBTC) GetExchangeHistory(p currency.Pair, assetType asset.Item) ([]ex
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (h *HitBTC) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
|
||||
func (h *HitBTC) SubmitOrder(o *order.Submit) (order.SubmitResponse, error) {
|
||||
var submitOrderResponse order.SubmitResponse
|
||||
if err := s.Validate(); err != nil {
|
||||
err := o.Validate()
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
if h.Websocket.IsConnected() && h.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
var response *WsSubmitOrderSuccessResponse
|
||||
response, err = h.wsPlaceOrder(o.Pair, o.OrderSide.String(), o.Amount, o.Price)
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
submitOrderResponse.OrderID = strconv.FormatInt(response.ID, 10)
|
||||
if response.Result.CumQuantity == o.Amount {
|
||||
submitOrderResponse.FullyMatched = true
|
||||
}
|
||||
} else {
|
||||
var response OrderResponse
|
||||
response, err = h.PlaceOrder(o.Pair.String(),
|
||||
o.Price,
|
||||
o.Amount,
|
||||
strings.ToLower(o.OrderType.String()),
|
||||
strings.ToLower(o.OrderSide.String()))
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
if response.OrderNumber > 0 {
|
||||
submitOrderResponse.OrderID = strconv.FormatInt(response.OrderNumber, 10)
|
||||
}
|
||||
if o.OrderType == order.Market {
|
||||
submitOrderResponse.FullyMatched = true
|
||||
}
|
||||
}
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
|
||||
response, err := h.PlaceOrder(s.Pair.String(),
|
||||
s.Price,
|
||||
s.Amount,
|
||||
s.OrderType.Lower(),
|
||||
s.OrderSide.Lower())
|
||||
if response.OrderNumber > 0 {
|
||||
submitOrderResponse.OrderID = strconv.FormatInt(response.OrderNumber, 10)
|
||||
}
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
}
|
||||
return submitOrderResponse, err
|
||||
return submitOrderResponse, nil
|
||||
}
|
||||
|
||||
// ModifyOrder will allow of changing orderbook placement and limit to
|
||||
|
||||
@@ -44,7 +44,7 @@ const (
|
||||
huobiOrderCancel = "order/orders/%s/submitcancel"
|
||||
huobiOrderCancelBatch = "order/orders/batchcancel"
|
||||
huobiBatchCancelOpenOrders = "order/orders/batchCancelOpenOrders"
|
||||
huobiGetOrder = "order/orders/%s"
|
||||
huobiGetOrder = "order/orders/getClientOrder"
|
||||
huobiGetOrderMatch = "order/orders/%s/matchresults"
|
||||
huobiGetOrders = "order/orders"
|
||||
huobiGetOpenOrders = "order/openOrders"
|
||||
@@ -443,8 +443,9 @@ func (h *HUOBI) GetOrder(orderID int64) (OrderInfo, error) {
|
||||
}
|
||||
|
||||
var result response
|
||||
endpoint := fmt.Sprintf(huobiGetOrder, strconv.FormatInt(orderID, 10))
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, endpoint, url.Values{}, nil, &result)
|
||||
urlVal := url.Values{}
|
||||
urlVal.Set("clientOrderId", strconv.FormatInt(orderID, 10))
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, huobiGetOrder, urlVal, nil, &result)
|
||||
|
||||
if result.ErrorMessage != "" {
|
||||
return result.Order, errors.New(result.ErrorMessage)
|
||||
@@ -514,7 +515,7 @@ func (h *HUOBI) GetOrders(symbol, types, start, end, states, from, direct, size
|
||||
}
|
||||
|
||||
// GetOpenOrders returns a list of orders
|
||||
func (h *HUOBI) GetOpenOrders(accountID, symbol, side string, size int) ([]OrderInfo, error) {
|
||||
func (h *HUOBI) GetOpenOrders(accountID, symbol, side string, size int64) ([]OrderInfo, error) {
|
||||
type response struct {
|
||||
Response
|
||||
Orders []OrderInfo `json:"data"`
|
||||
@@ -526,7 +527,7 @@ func (h *HUOBI) GetOpenOrders(accountID, symbol, side string, size int) ([]Order
|
||||
if len(side) > 0 {
|
||||
vals.Set("side", side)
|
||||
}
|
||||
vals.Set("size", fmt.Sprintf("%v", size))
|
||||
vals.Set("size", strconv.FormatInt(size, 10))
|
||||
|
||||
var result response
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, huobiGetOpenOrders, vals, nil, &result)
|
||||
@@ -855,8 +856,7 @@ func (h *HUOBI) SendAuthenticatedHTTPRequest(method, endpoint string, values url
|
||||
values.Set("PrivateSignature", crypto.Base64Encode(privSig))
|
||||
}
|
||||
|
||||
urlPath := fmt.Sprintf("%s%s", common.EncodeURLValues(h.API.Endpoints.URL, values),
|
||||
endpoint)
|
||||
urlPath := h.API.Endpoints.URL + common.EncodeURLValues(endpoint, values)
|
||||
|
||||
var body []byte
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"encoding/pem"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -33,11 +34,8 @@ const (
|
||||
var h HUOBI
|
||||
var wsSetupRan bool
|
||||
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
func TestMain(m *testing.M) {
|
||||
h.SetDefaults()
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
cfg := config.GetConfig()
|
||||
err := cfg.LoadConfig("../../testdata/configtest.json", true)
|
||||
if err != nil {
|
||||
@@ -45,7 +43,7 @@ func TestSetup(t *testing.T) {
|
||||
}
|
||||
hConfig, err := cfg.GetExchangeConfig("Huobi")
|
||||
if err != nil {
|
||||
t.Error("Huobi Setup() init error")
|
||||
log.Fatal("Huobi Setup() init error")
|
||||
}
|
||||
hConfig.API.AuthenticatedSupport = true
|
||||
hConfig.API.AuthenticatedWebsocketSupport = true
|
||||
@@ -54,16 +52,16 @@ func TestSetup(t *testing.T) {
|
||||
|
||||
err = h.Setup(hConfig)
|
||||
if err != nil {
|
||||
t.Fatal("Huobi setup error", err)
|
||||
log.Fatal("Huobi setup error", err)
|
||||
}
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func setupWsTests(t *testing.T) {
|
||||
if wsSetupRan {
|
||||
return
|
||||
}
|
||||
TestSetDefaults(t)
|
||||
TestSetup(t)
|
||||
if !h.Websocket.IsEnabled() && !h.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
@@ -195,8 +193,7 @@ func TestGetTimestamp(t *testing.T) {
|
||||
|
||||
func TestGetAccounts(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if !h.ValidateAPICredentials() {
|
||||
if !h.ValidateAPICredentials() || !canManipulateRealOrders {
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
@@ -208,8 +205,7 @@ func TestGetAccounts(t *testing.T) {
|
||||
|
||||
func TestGetAccountBalance(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if !h.ValidateAPICredentials() {
|
||||
if !h.ValidateAPICredentials() || !canManipulateRealOrders {
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
@@ -227,7 +223,6 @@ func TestGetAccountBalance(t *testing.T) {
|
||||
|
||||
func TestGetAggregatedBalance(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if !h.ValidateAPICredentials() {
|
||||
t.Skip()
|
||||
}
|
||||
@@ -240,8 +235,7 @@ func TestGetAggregatedBalance(t *testing.T) {
|
||||
|
||||
func TestSpotNewOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if !h.ValidateAPICredentials() {
|
||||
if !h.ValidateAPICredentials() || !canManipulateRealOrders {
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
@@ -261,7 +255,9 @@ func TestSpotNewOrder(t *testing.T) {
|
||||
|
||||
func TestCancelExistingOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if !h.ValidateAPICredentials() || !canManipulateRealOrders {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := h.CancelExistingOrder(1337)
|
||||
if err == nil {
|
||||
t.Error("Huobi TestCancelExistingOrder Expected error")
|
||||
@@ -270,16 +266,17 @@ func TestCancelExistingOrder(t *testing.T) {
|
||||
|
||||
func TestGetOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if !h.ValidateAPICredentials() || !canManipulateRealOrders {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := h.GetOrder(1337)
|
||||
if err == nil {
|
||||
t.Error("Huobi TestCancelOrder Expected error")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetMarginLoanOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if !h.ValidateAPICredentials() {
|
||||
t.Skip()
|
||||
}
|
||||
@@ -292,7 +289,6 @@ func TestGetMarginLoanOrders(t *testing.T) {
|
||||
|
||||
func TestGetMarginAccountBalance(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if !h.ValidateAPICredentials() {
|
||||
t.Skip()
|
||||
}
|
||||
@@ -305,7 +301,9 @@ func TestGetMarginAccountBalance(t *testing.T) {
|
||||
|
||||
func TestCancelWithdraw(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if !h.ValidateAPICredentials() || !canManipulateRealOrders {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := h.CancelWithdraw(1337)
|
||||
if err == nil {
|
||||
t.Error("Huobi TestCancelWithdraw Expected error")
|
||||
@@ -314,7 +312,6 @@ func TestCancelWithdraw(t *testing.T) {
|
||||
|
||||
func TestPEMLoadAndSign(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
pemKey := strings.NewReader(h.API.Credentials.PEMKey)
|
||||
pemBytes, err := ioutil.ReadAll(pemKey)
|
||||
if err != nil {
|
||||
@@ -355,7 +352,7 @@ func setFeeBuilder() *exchange.FeeBuilder {
|
||||
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
var feeBuilder = setFeeBuilder()
|
||||
h.GetFeeByType(feeBuilder)
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
if !areTestAPIKeysSet() {
|
||||
if feeBuilder.FeeType != exchange.OfflineTradeFee {
|
||||
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
|
||||
}
|
||||
@@ -443,20 +440,14 @@ func TestGetFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
h.SetDefaults()
|
||||
expectedResult := exchange.AutoWithdrawCryptoWithSetupText + " & " + exchange.NoFiatWithdrawalsText
|
||||
|
||||
withdrawPermissions := h.FormatWithdrawPermissions()
|
||||
|
||||
if withdrawPermissions != expectedResult {
|
||||
t.Errorf("Expected: %s, Received: %s", expectedResult, withdrawPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
h.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
Currencies: []currency.Pair{currency.NewPair(currency.BTC, currency.USDT)},
|
||||
@@ -471,9 +462,6 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
h.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
Currencies: []currency.Pair{currency.NewPair(currency.BTC, currency.USDT)},
|
||||
@@ -494,9 +482,6 @@ func areTestAPIKeysSet() bool {
|
||||
}
|
||||
|
||||
func TestSubmitOrder(t *testing.T) {
|
||||
h.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if !h.ValidateAPICredentials() {
|
||||
t.Skip()
|
||||
}
|
||||
@@ -528,15 +513,11 @@ func TestSubmitOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelExchangeOrder(t *testing.T) {
|
||||
h.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -555,8 +536,6 @@ func TestCancelExchangeOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
h.SetDefaults()
|
||||
TestSetup(t)
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -584,7 +563,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
if !areTestAPIKeysSet() {
|
||||
_, err := h.GetAccountInfo()
|
||||
if err == nil {
|
||||
t.Error("GetAccountInfo() Expected error")
|
||||
@@ -598,6 +577,9 @@ func TestGetAccountInfo(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestModifyOrder(t *testing.T) {
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
_, err := h.ModifyOrder(&order.Modify{})
|
||||
if err == nil {
|
||||
t.Error("ModifyOrder() Expected error")
|
||||
@@ -605,8 +587,6 @@ func TestModifyOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdraw(t *testing.T) {
|
||||
h.SetDefaults()
|
||||
TestSetup(t)
|
||||
withdrawCryptoRequest := exchange.CryptoWithdrawRequest{
|
||||
GenericWithdrawRequestInfo: exchange.GenericWithdrawRequestInfo{
|
||||
Amount: -1,
|
||||
@@ -630,9 +610,6 @@ func TestWithdraw(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawFiat(t *testing.T) {
|
||||
h.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -645,9 +622,6 @@ func TestWithdrawFiat(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawInternationalBank(t *testing.T) {
|
||||
h.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -669,7 +643,7 @@ func TestGetDepositAddress(t *testing.T) {
|
||||
// TestWsGetAccountsList connects to WS, logs in, gets account list
|
||||
func TestWsGetAccountsList(t *testing.T) {
|
||||
setupWsTests(t)
|
||||
resp, err := h.wsGetAccountsList(currency.NewPairFromString("ethbtc"))
|
||||
resp, err := h.wsGetAccountsList()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -170,24 +170,23 @@ type CancelOrderBatch struct {
|
||||
|
||||
// OrderInfo stores the order info
|
||||
type OrderInfo struct {
|
||||
ID int `json:"id"`
|
||||
ID int64 `json:"id"`
|
||||
Symbol string `json:"symbol"`
|
||||
AccountID float64 `json:"account-id"`
|
||||
AccountID int64 `json:"account-id"`
|
||||
Amount float64 `json:"amount,string"`
|
||||
Price float64 `json:"price,string"`
|
||||
CreatedAt int64 `json:"created-at"`
|
||||
Type string `json:"type"`
|
||||
FieldAmount float64 `json:"field-amount,string"`
|
||||
FieldCashAmount float64 `json:"field-cash-amount,string"`
|
||||
Fieldees float64 `json:"field-fees,string"`
|
||||
FilledAmount float64 `json:"filled-amount,string"`
|
||||
FilledCashAmount float64 `json:"filled-cash-amount,string"`
|
||||
FilledFees float64 `json:"filled-fees,string"`
|
||||
FinishedAt int64 `json:"finished-at"`
|
||||
UserID int `json:"user-id"`
|
||||
UserID int64 `json:"user-id"`
|
||||
Source string `json:"source"`
|
||||
State string `json:"state"`
|
||||
CanceledAt int `json:"canceled-at"`
|
||||
CanceledAt int64 `json:"canceled-at"`
|
||||
Exchange string `json:"exchange"`
|
||||
Batch string `json:"batch"`
|
||||
}
|
||||
@@ -547,31 +546,13 @@ type WsAuthenticatedAccountsListResponseDataList struct {
|
||||
// WsAuthenticatedOrdersListResponse response from OrdersList authenticated endpoint
|
||||
type WsAuthenticatedOrdersListResponse struct {
|
||||
WsAuthenticatedDataResponse
|
||||
Data []WsAuthenticatedOrdersListResponseData `json:"data"`
|
||||
}
|
||||
|
||||
// WsAuthenticatedOrdersListResponseData contains order details
|
||||
type WsAuthenticatedOrdersListResponseData struct {
|
||||
ID int64 `json:"id"`
|
||||
Symbol string `json:"symbol"`
|
||||
AccountID int64 `json:"account-id"`
|
||||
Amount float64 `json:"amount,string"`
|
||||
Price float64 `json:"price,string"`
|
||||
CreatedAt int64 `json:"created-at"`
|
||||
Type string `json:"type"`
|
||||
FilledAmount float64 `json:"filled-amount,string"`
|
||||
FilledCashAmount float64 `json:"filled-cash-amount,string"`
|
||||
FilledFees float64 `json:"filled-fees,string"`
|
||||
FinishedAt int64 `json:"finished-at"`
|
||||
Source string `json:"source"`
|
||||
State string `json:"state"`
|
||||
CanceledAt int64 `json:"canceled-at"`
|
||||
Data []OrderInfo `json:"data"`
|
||||
}
|
||||
|
||||
// WsAuthenticatedOrderDetailResponse response from OrderDetail authenticated endpoint
|
||||
type WsAuthenticatedOrderDetailResponse struct {
|
||||
WsAuthenticatedDataResponse
|
||||
Data WsAuthenticatedOrdersListResponseData `json:"data"`
|
||||
Data OrderInfo `json:"data"`
|
||||
}
|
||||
|
||||
// WsPong sent for pong messages
|
||||
|
||||
@@ -49,7 +49,7 @@ const (
|
||||
)
|
||||
|
||||
// Instantiates a communications channel between websocket connections
|
||||
var comms = make(chan WsMessage, 1)
|
||||
var comms = make(chan WsMessage)
|
||||
|
||||
// WsConnect initiates a new websocket connection
|
||||
func (h *HUOBI) WsConnect() error {
|
||||
@@ -68,6 +68,7 @@ func (h *HUOBI) WsConnect() error {
|
||||
err = h.wsLogin()
|
||||
if err != nil {
|
||||
log.Errorf(log.ExchangeSys, "%v - authentication failed: %v\n", h.Name, err)
|
||||
h.Websocket.SetCanUseAuthenticatedEndpoints(false)
|
||||
}
|
||||
|
||||
go h.WsHandleData()
|
||||
@@ -434,7 +435,7 @@ func (h *HUOBI) wsAuthenticatedSubscribe(operation, endpoint, topic string) erro
|
||||
return h.AuthenticatedWebsocketConn.SendMessage(request)
|
||||
}
|
||||
|
||||
func (h *HUOBI) wsGetAccountsList(pair currency.Pair) (*WsAuthenticatedAccountsListResponse, error) {
|
||||
func (h *HUOBI) wsGetAccountsList() (*WsAuthenticatedAccountsListResponse, error) {
|
||||
if !h.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
return nil, fmt.Errorf("%v not authenticated cannot get accounts list", h.Name)
|
||||
}
|
||||
@@ -446,7 +447,6 @@ func (h *HUOBI) wsGetAccountsList(pair currency.Pair) (*WsAuthenticatedAccountsL
|
||||
SignatureVersion: signatureVersion,
|
||||
Timestamp: timestamp,
|
||||
Topic: wsAccountsList,
|
||||
Symbol: h.FormatExchangeCurrency(pair, asset.Spot).String(),
|
||||
}
|
||||
hmac := h.wsGenerateSignature(timestamp, wsAccountListEndpoint)
|
||||
request.Signature = crypto.Base64Encode(hmac)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -96,6 +97,8 @@ func (h *HUOBI) SetDefaults() {
|
||||
AuthenticatedEndpoints: true,
|
||||
AccountInfo: true,
|
||||
MessageCorrelation: true,
|
||||
GetOrder: true,
|
||||
GetOrders: true,
|
||||
},
|
||||
WithdrawPermissions: exchange.AutoWithdrawCryptoWithSetup |
|
||||
exchange.NoFiatWithdrawals,
|
||||
@@ -393,62 +396,83 @@ func (h *HUOBI) GetAccountID() ([]Account, error) {
|
||||
func (h *HUOBI) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var info exchange.AccountInfo
|
||||
info.Exchange = h.Name
|
||||
|
||||
accounts, err := h.GetAccountID()
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
for i := range accounts {
|
||||
var acc exchange.Account
|
||||
acc.ID = strconv.FormatInt(accounts[i].ID, 10)
|
||||
balances, err := h.GetAccountBalance(acc.ID)
|
||||
if h.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
resp, err := h.wsGetAccountsList()
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
var currencyDetails []exchange.AccountCurrencyInfo
|
||||
for j := range balances {
|
||||
var frozen bool
|
||||
if balances[j].Type == "frozen" {
|
||||
frozen = true
|
||||
for i := range resp.Data {
|
||||
if len(resp.Data[i].List) == 0 {
|
||||
continue
|
||||
}
|
||||
currData := exchange.AccountCurrencyInfo{
|
||||
CurrencyName: currency.NewCode(resp.Data[i].List[0].Currency),
|
||||
TotalValue: resp.Data[i].List[0].Balance,
|
||||
}
|
||||
if len(resp.Data[i].List) > 1 && resp.Data[i].List[1].Type == "frozen" {
|
||||
currData.Hold = resp.Data[i].List[1].Balance
|
||||
}
|
||||
currencyDetails = append(currencyDetails, currData)
|
||||
}
|
||||
var acc exchange.Account
|
||||
acc.Currencies = currencyDetails
|
||||
info.Accounts = append(info.Accounts, acc)
|
||||
} else {
|
||||
accounts, err := h.GetAccountID()
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
for i := range accounts {
|
||||
var acc exchange.Account
|
||||
acc.ID = strconv.FormatInt(accounts[i].ID, 10)
|
||||
balances, err := h.GetAccountBalance(acc.ID)
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
var updated bool
|
||||
for i := range currencyDetails {
|
||||
if currencyDetails[i].CurrencyName == currency.NewCode(balances[j].Currency) {
|
||||
if frozen {
|
||||
currencyDetails[i].Hold = balances[j].Balance
|
||||
} else {
|
||||
currencyDetails[i].TotalValue = balances[j].Balance
|
||||
var currencyDetails []exchange.AccountCurrencyInfo
|
||||
for j := range balances {
|
||||
var frozen bool
|
||||
if balances[j].Type == "frozen" {
|
||||
frozen = true
|
||||
}
|
||||
|
||||
var updated bool
|
||||
for i := range currencyDetails {
|
||||
if currencyDetails[i].CurrencyName == currency.NewCode(balances[j].Currency) {
|
||||
if frozen {
|
||||
currencyDetails[i].Hold = balances[j].Balance
|
||||
} else {
|
||||
currencyDetails[i].TotalValue = balances[j].Balance
|
||||
}
|
||||
updated = true
|
||||
}
|
||||
updated = true
|
||||
}
|
||||
|
||||
if updated {
|
||||
continue
|
||||
}
|
||||
|
||||
if frozen {
|
||||
currencyDetails = append(currencyDetails,
|
||||
exchange.AccountCurrencyInfo{
|
||||
CurrencyName: currency.NewCode(balances[j].Currency),
|
||||
Hold: balances[j].Balance,
|
||||
})
|
||||
} else {
|
||||
currencyDetails = append(currencyDetails,
|
||||
exchange.AccountCurrencyInfo{
|
||||
CurrencyName: currency.NewCode(balances[j].Currency),
|
||||
TotalValue: balances[j].Balance,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if updated {
|
||||
continue
|
||||
}
|
||||
|
||||
if frozen {
|
||||
currencyDetails = append(currencyDetails,
|
||||
exchange.AccountCurrencyInfo{
|
||||
CurrencyName: currency.NewCode(balances[j].Currency),
|
||||
Hold: balances[j].Balance,
|
||||
})
|
||||
} else {
|
||||
currencyDetails = append(currencyDetails,
|
||||
exchange.AccountCurrencyInfo{
|
||||
CurrencyName: currency.NewCode(balances[j].Currency),
|
||||
TotalValue: balances[j].Balance,
|
||||
})
|
||||
}
|
||||
acc.Currencies = currencyDetails
|
||||
info.Accounts = append(info.Accounts, acc)
|
||||
}
|
||||
|
||||
acc.Currencies = currencyDetails
|
||||
info.Accounts = append(info.Accounts, acc)
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
@@ -498,13 +522,18 @@ func (h *HUOBI) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
|
||||
|
||||
params.Type = formattedType
|
||||
response, err := h.SpotNewOrder(params)
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
if response > 0 {
|
||||
submitOrderResponse.OrderID = strconv.FormatInt(response, 10)
|
||||
}
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
if s.OrderType == order.Market {
|
||||
submitOrderResponse.FullyMatched = true
|
||||
}
|
||||
return submitOrderResponse, err
|
||||
return submitOrderResponse, nil
|
||||
}
|
||||
|
||||
// ModifyOrder will allow of changing orderbook placement and limit to
|
||||
@@ -527,9 +556,10 @@ func (h *HUOBI) CancelOrder(order *order.Cancel) error {
|
||||
// CancelAllOrders cancels all orders associated with a currency pair
|
||||
func (h *HUOBI) CancelAllOrders(orderCancellation *order.Cancel) (order.CancelAllResponse, error) {
|
||||
var cancelAllOrdersResponse order.CancelAllResponse
|
||||
for _, currency := range h.GetEnabledPairs(asset.Spot) {
|
||||
enabledPairs := h.GetEnabledPairs(asset.Spot)
|
||||
for i := range enabledPairs {
|
||||
resp, err := h.CancelOpenOrdersBatch(orderCancellation.AccountID,
|
||||
h.FormatExchangeCurrency(currency, asset.Spot).String())
|
||||
h.FormatExchangeCurrency(enabledPairs[i], asset.Spot).String())
|
||||
if err != nil {
|
||||
return cancelAllOrdersResponse, err
|
||||
}
|
||||
@@ -551,7 +581,56 @@ func (h *HUOBI) CancelAllOrders(orderCancellation *order.Cancel) (order.CancelAl
|
||||
// GetOrderInfo returns information on a current open order
|
||||
func (h *HUOBI) GetOrderInfo(orderID string) (order.Detail, error) {
|
||||
var orderDetail order.Detail
|
||||
return orderDetail, common.ErrNotYetImplemented
|
||||
var respData *OrderInfo
|
||||
if h.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
resp, err := h.wsGetOrderDetails(orderID)
|
||||
if err != nil {
|
||||
return orderDetail, err
|
||||
}
|
||||
respData = &resp.Data
|
||||
} else {
|
||||
oID, err := strconv.ParseInt(orderID, 10, 64)
|
||||
if err != nil {
|
||||
return orderDetail, err
|
||||
}
|
||||
resp, err := h.GetOrder(oID)
|
||||
if err != nil {
|
||||
return orderDetail, err
|
||||
}
|
||||
respData = &resp
|
||||
}
|
||||
if respData.ID == 0 {
|
||||
return orderDetail, fmt.Errorf("%s - order not found for orderid %s", h.Name, orderID)
|
||||
}
|
||||
|
||||
typeDetails := strings.Split(respData.Type, "-")
|
||||
orderSide, err := order.StringToOrderSide(typeDetails[0])
|
||||
if err != nil {
|
||||
return orderDetail, err
|
||||
}
|
||||
orderType, err := order.StringToOrderType(typeDetails[1])
|
||||
if err != nil {
|
||||
return orderDetail, err
|
||||
}
|
||||
orderStatus, err := order.StringToOrderStatus(respData.State)
|
||||
if err != nil {
|
||||
return orderDetail, err
|
||||
}
|
||||
orderDetail = order.Detail{
|
||||
Exchange: h.Name,
|
||||
ID: strconv.FormatInt(respData.ID, 10),
|
||||
AccountID: strconv.FormatInt(respData.AccountID, 10),
|
||||
CurrencyPair: currency.NewPairFromString(respData.Symbol),
|
||||
OrderType: orderType,
|
||||
OrderSide: orderSide,
|
||||
OrderDate: time.Unix(respData.CreatedAt, 0),
|
||||
Status: orderStatus,
|
||||
Price: respData.Price,
|
||||
Amount: respData.Amount,
|
||||
ExecutedAmount: respData.FilledAmount,
|
||||
Fee: respData.FilledFees,
|
||||
}
|
||||
return orderDetail, nil
|
||||
}
|
||||
|
||||
// GetDepositAddress returns a deposit address for a specified currency
|
||||
@@ -607,32 +686,72 @@ func (h *HUOBI) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, er
|
||||
|
||||
var orders []order.Detail
|
||||
|
||||
for i := range req.Currencies {
|
||||
resp, err := h.GetOpenOrders(h.API.Credentials.ClientID,
|
||||
req.Currencies[i].Lower().String(),
|
||||
side,
|
||||
500)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if h.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
for i := range req.Currencies {
|
||||
resp, err := h.wsGetOrdersList(-1, req.Currencies[i])
|
||||
if err != nil {
|
||||
return orders, err
|
||||
}
|
||||
for j := range resp.Data {
|
||||
sideData := strings.Split(resp.Data[j].OrderState, "-")
|
||||
side = sideData[0]
|
||||
orderSide, err := order.StringToOrderSide(side)
|
||||
if err != nil {
|
||||
return orders, err
|
||||
}
|
||||
orderType, err := order.StringToOrderType(sideData[1])
|
||||
if err != nil {
|
||||
return orders, err
|
||||
}
|
||||
orderStatus, err := order.StringToOrderStatus(resp.Data[j].OrderState)
|
||||
if err != nil {
|
||||
return orders, err
|
||||
}
|
||||
orders = append(orders, order.Detail{
|
||||
Exchange: h.Name,
|
||||
AccountID: strconv.FormatInt(resp.Data[j].AccountID, 10),
|
||||
ID: strconv.FormatInt(resp.Data[j].OrderID, 10),
|
||||
CurrencyPair: req.Currencies[i],
|
||||
OrderType: orderType,
|
||||
OrderSide: orderSide,
|
||||
OrderDate: time.Unix(resp.Data[j].CreatedAt, 0),
|
||||
Status: orderStatus,
|
||||
Price: resp.Data[j].Price,
|
||||
Amount: resp.Data[j].OrderAmount,
|
||||
ExecutedAmount: resp.Data[j].FilledAmount,
|
||||
RemainingAmount: resp.Data[j].UnfilledAmount,
|
||||
Fee: resp.Data[j].FilledFees,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for i := range resp {
|
||||
orderDetail := order.Detail{
|
||||
ID: strconv.FormatInt(int64(resp[i].ID), 10),
|
||||
Price: resp[i].Price,
|
||||
Amount: resp[i].Amount,
|
||||
CurrencyPair: req.Currencies[i],
|
||||
Exchange: h.Name,
|
||||
ExecutedAmount: resp[i].FilledAmount,
|
||||
OrderDate: time.Unix(0, resp[i].CreatedAt*int64(time.Millisecond)),
|
||||
Status: order.Status(resp[i].State),
|
||||
AccountID: strconv.FormatFloat(resp[i].AccountID, 'f', -1, 64),
|
||||
Fee: resp[i].FilledFees,
|
||||
} else {
|
||||
for i := range req.Currencies {
|
||||
resp, err := h.GetOpenOrders(h.API.Credentials.ClientID,
|
||||
req.Currencies[i].Lower().String(),
|
||||
side,
|
||||
500)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
setOrderSideAndType(resp[i].Type, &orderDetail)
|
||||
for i := range resp {
|
||||
orderDetail := order.Detail{
|
||||
ID: strconv.FormatInt(resp[i].ID, 10),
|
||||
Price: resp[i].Price,
|
||||
Amount: resp[i].Amount,
|
||||
CurrencyPair: req.Currencies[i],
|
||||
Exchange: h.Name,
|
||||
ExecutedAmount: resp[i].FilledAmount,
|
||||
OrderDate: time.Unix(0, resp[i].CreatedAt*int64(time.Millisecond)),
|
||||
Status: order.Status(resp[i].State),
|
||||
AccountID: strconv.FormatInt(resp[i].AccountID, 10),
|
||||
Fee: resp[i].FilledFees,
|
||||
}
|
||||
|
||||
orders = append(orders, orderDetail)
|
||||
setOrderSideAndType(resp[i].Type, &orderDetail)
|
||||
|
||||
orders = append(orders, orderDetail)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -664,7 +783,7 @@ func (h *HUOBI) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, er
|
||||
|
||||
for i := range resp {
|
||||
orderDetail := order.Detail{
|
||||
ID: strconv.FormatInt(int64(resp[i].ID), 10),
|
||||
ID: strconv.FormatInt(resp[i].ID, 10),
|
||||
Price: resp[i].Price,
|
||||
Amount: resp[i].Amount,
|
||||
CurrencyPair: req.Currencies[i],
|
||||
@@ -672,7 +791,7 @@ func (h *HUOBI) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, er
|
||||
ExecutedAmount: resp[i].FilledAmount,
|
||||
OrderDate: time.Unix(0, resp[i].CreatedAt*int64(time.Millisecond)),
|
||||
Status: order.Status(resp[i].State),
|
||||
AccountID: strconv.FormatFloat(resp[i].AccountID, 'f', -1, 64),
|
||||
AccountID: strconv.FormatInt(resp[i].AccountID, 10),
|
||||
Fee: resp[i].FilledFees,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package itbit
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/url"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
@@ -21,19 +23,16 @@ const (
|
||||
canManipulateRealOrders = false
|
||||
)
|
||||
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
func TestMain(m *testing.M) {
|
||||
i.SetDefaults()
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
cfg := config.GetConfig()
|
||||
err := cfg.LoadConfig("../../testdata/configtest.json", true)
|
||||
if err != nil {
|
||||
t.Fatal("Itbit load config error", err)
|
||||
log.Fatal("Itbit load config error", err)
|
||||
}
|
||||
itbitConfig, err := cfg.GetExchangeConfig("ITBIT")
|
||||
if err != nil {
|
||||
t.Error("Itbit Setup() init error")
|
||||
log.Fatal("Itbit Setup() init error")
|
||||
}
|
||||
itbitConfig.API.AuthenticatedSupport = true
|
||||
itbitConfig.API.Credentials.Key = apiKey
|
||||
@@ -42,8 +41,10 @@ func TestSetup(t *testing.T) {
|
||||
|
||||
err = i.Setup(itbitConfig)
|
||||
if err != nil {
|
||||
t.Fatal("Itbit setup error", err)
|
||||
log.Fatal("Itbit setup error", err)
|
||||
}
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestGetTicker(t *testing.T) {
|
||||
@@ -167,7 +168,7 @@ func setFeeBuilder() *exchange.FeeBuilder {
|
||||
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
var feeBuilder = setFeeBuilder()
|
||||
i.GetFeeByType(feeBuilder)
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
if !areTestAPIKeysSet() {
|
||||
if feeBuilder.FeeType != exchange.OfflineTradeFee {
|
||||
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
|
||||
}
|
||||
@@ -255,20 +256,14 @@ func TestGetFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
i.SetDefaults()
|
||||
expectedResult := exchange.WithdrawCryptoViaWebsiteOnlyText + " & " + exchange.WithdrawFiatViaWebsiteOnlyText
|
||||
|
||||
withdrawPermissions := i.FormatWithdrawPermissions()
|
||||
|
||||
if withdrawPermissions != expectedResult {
|
||||
t.Errorf("Expected: %s, Received: %s", expectedResult, withdrawPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
i.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
}
|
||||
@@ -282,9 +277,6 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
i.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
}
|
||||
@@ -304,8 +296,6 @@ func areTestAPIKeysSet() bool {
|
||||
}
|
||||
|
||||
func TestSubmitOrder(t *testing.T) {
|
||||
i.SetDefaults()
|
||||
TestSetup(t)
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -330,15 +320,11 @@ func TestSubmitOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelExchangeOrder(t *testing.T) {
|
||||
i.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -357,15 +343,11 @@ func TestCancelExchangeOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
i.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -388,7 +370,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
if apiKey != "" || apiSecret != "" || clientID != "" {
|
||||
if areTestAPIKeysSet() {
|
||||
_, err := i.GetAccountInfo()
|
||||
if err == nil {
|
||||
t.Error("GetAccountInfo() Expected error")
|
||||
@@ -397,6 +379,9 @@ func TestGetAccountInfo(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestModifyOrder(t *testing.T) {
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
_, err := i.ModifyOrder(&order.Modify{})
|
||||
if err == nil {
|
||||
t.Error("ModifyOrder() Expected error")
|
||||
@@ -404,8 +389,6 @@ func TestModifyOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdraw(t *testing.T) {
|
||||
i.SetDefaults()
|
||||
TestSetup(t)
|
||||
withdrawCryptoRequest := exchange.CryptoWithdrawRequest{
|
||||
GenericWithdrawRequestInfo: exchange.GenericWithdrawRequestInfo{
|
||||
Amount: -1,
|
||||
@@ -426,9 +409,6 @@ func TestWithdraw(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawFiat(t *testing.T) {
|
||||
i.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -441,9 +421,6 @@ func TestWithdrawFiat(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawInternationalBank(t *testing.T) {
|
||||
i.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
@@ -331,14 +331,18 @@ func (i *ItBit) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
|
||||
s.Price,
|
||||
s.Pair.String(),
|
||||
"")
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
if response.ID != "" {
|
||||
submitOrderResponse.OrderID = response.ID
|
||||
}
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
}
|
||||
|
||||
return submitOrderResponse, err
|
||||
if response.AmountFilled == s.Amount {
|
||||
submitOrderResponse.FullyMatched = true
|
||||
}
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
return submitOrderResponse, nil
|
||||
}
|
||||
|
||||
// ModifyOrder will allow of changing orderbook placement and limit to
|
||||
|
||||
@@ -47,6 +47,7 @@ const (
|
||||
krakenDepositAddresses = "DepositAddresses"
|
||||
krakenWithdrawStatus = "WithdrawStatus"
|
||||
krakenWithdrawCancel = "WithdrawCancel"
|
||||
krakenWebsocketToken = "GetWebSocketsToken"
|
||||
|
||||
krakenAuthRate = 0
|
||||
krakenUnauthRate = 0
|
||||
@@ -57,8 +58,9 @@ var assetPairMap map[string]string
|
||||
// Kraken is the overarching type across the alphapoint package
|
||||
type Kraken struct {
|
||||
exchange.Base
|
||||
WebsocketConn *wshandler.WebsocketConnection
|
||||
wsRequestMtx sync.Mutex
|
||||
WebsocketConn *wshandler.WebsocketConnection
|
||||
AuthenticatedWebsocketConn *wshandler.WebsocketConnection
|
||||
wsRequestMtx sync.Mutex
|
||||
}
|
||||
|
||||
// GetServerTime returns current server time
|
||||
@@ -1036,3 +1038,14 @@ func (k *Kraken) WithdrawCancel(c currency.Code, refID string) (bool, error) {
|
||||
|
||||
return response.Result, GetError(response.Error)
|
||||
}
|
||||
|
||||
func (k *Kraken) GetWebsocketToken() (string, error) {
|
||||
var response WsTokenResponse
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenWebsocketToken, url.Values{}, &response); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(response.Error) > 0 {
|
||||
return "", fmt.Errorf("%s - %v", k.Name, response.Error)
|
||||
}
|
||||
return response.Result.Token, nil
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package kraken
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
@@ -25,13 +27,9 @@ const (
|
||||
canManipulateRealOrders = false
|
||||
)
|
||||
|
||||
// TestSetDefaults setup func
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
k.SetDefaults()
|
||||
}
|
||||
|
||||
// TestSetup setup func
|
||||
func TestSetup(t *testing.T) {
|
||||
func TestMain(m *testing.M) {
|
||||
k.SetDefaults()
|
||||
cfg := config.GetConfig()
|
||||
err := cfg.LoadConfig("../../testdata/configtest.json", true)
|
||||
if err != nil {
|
||||
@@ -39,19 +37,19 @@ func TestSetup(t *testing.T) {
|
||||
}
|
||||
krakenConfig, err := cfg.GetExchangeConfig("Kraken")
|
||||
if err != nil {
|
||||
t.Error("kraken Setup() init error", err)
|
||||
log.Fatal("kraken Setup() init error", err)
|
||||
}
|
||||
krakenConfig.API.AuthenticatedSupport = true
|
||||
krakenConfig.API.Credentials.Key = apiKey
|
||||
krakenConfig.API.Credentials.Secret = apiSecret
|
||||
krakenConfig.API.Credentials.ClientID = clientID
|
||||
krakenConfig.API.Endpoints.WebsocketURL = k.API.Endpoints.WebsocketURL
|
||||
subscribeToDefaultChannels = false
|
||||
|
||||
err = k.Setup(krakenConfig)
|
||||
if err != nil {
|
||||
t.Fatal("Kraken setup error", err)
|
||||
log.Fatal("Kraken setup error", err)
|
||||
}
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
// TestGetServerTime API endpoint test
|
||||
@@ -278,7 +276,7 @@ func setFeeBuilder() *exchange.FeeBuilder {
|
||||
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
var feeBuilder = setFeeBuilder()
|
||||
k.GetFeeByType(feeBuilder)
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
if !areTestAPIKeysSet() {
|
||||
if feeBuilder.FeeType != exchange.OfflineTradeFee {
|
||||
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
|
||||
}
|
||||
@@ -290,8 +288,6 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetFee(t *testing.T) {
|
||||
k.SetDefaults()
|
||||
TestSetup(t)
|
||||
var feeBuilder = setFeeBuilder()
|
||||
|
||||
if areTestAPIKeysSet() {
|
||||
@@ -373,11 +369,8 @@ func TestGetFee(t *testing.T) {
|
||||
|
||||
// TestFormatWithdrawPermissions logic test
|
||||
func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
k.SetDefaults()
|
||||
expectedResult := exchange.AutoWithdrawCryptoWithSetupText + " & " + exchange.WithdrawCryptoWith2FAText + " & " + exchange.AutoWithdrawFiatWithSetupText + " & " + exchange.WithdrawFiatWith2FAText
|
||||
|
||||
withdrawPermissions := k.FormatWithdrawPermissions()
|
||||
|
||||
if withdrawPermissions != expectedResult {
|
||||
t.Errorf("Expected: %s, Received: %s", expectedResult, withdrawPermissions)
|
||||
}
|
||||
@@ -385,9 +378,6 @@ func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
|
||||
// TestGetActiveOrders wrapper test
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
k.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
}
|
||||
@@ -402,9 +392,6 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
|
||||
// TestGetOrderHistory wrapper test
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
k.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
}
|
||||
@@ -417,6 +404,21 @@ func TestGetOrderHistory(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetOrderHistory wrapper test
|
||||
func TestGetOrderInfo(t *testing.T) {
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
_, err := k.GetOrderInfo("ImACoolOrderID")
|
||||
if !areTestAPIKeysSet() && err == nil {
|
||||
t.Error("Expecting error")
|
||||
}
|
||||
if areTestAPIKeysSet() && !strings.Contains(err.Error(), "- Order ID not found:") {
|
||||
t.Error("Expected Order ID not found error")
|
||||
}
|
||||
}
|
||||
|
||||
// Any tests below this line have the ability to impact your orders on the exchange. Enable canManipulateRealOrders to run them
|
||||
// ----------------------------------------------------------------------------------------------------------------------------
|
||||
func areTestAPIKeysSet() bool {
|
||||
@@ -425,9 +427,6 @@ func areTestAPIKeysSet() bool {
|
||||
|
||||
// TestSubmitOrder wrapper test
|
||||
func TestSubmitOrder(t *testing.T) {
|
||||
k.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -453,15 +452,11 @@ func TestSubmitOrder(t *testing.T) {
|
||||
|
||||
// TestCancelExchangeOrder wrapper test
|
||||
func TestCancelExchangeOrder(t *testing.T) {
|
||||
k.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -480,15 +475,11 @@ func TestCancelExchangeOrder(t *testing.T) {
|
||||
|
||||
// TestCancelAllExchangeOrders wrapper test
|
||||
func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
k.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -512,7 +503,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
|
||||
// TestGetAccountInfo wrapper test
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
if apiKey != "" || apiSecret != "" || clientID != "" {
|
||||
if areTestAPIKeysSet() || clientID != "" {
|
||||
_, err := k.GetAccountInfo()
|
||||
if err != nil {
|
||||
t.Error("GetAccountInfo() error", err)
|
||||
@@ -527,6 +518,9 @@ func TestGetAccountInfo(t *testing.T) {
|
||||
|
||||
// TestModifyOrder wrapper test
|
||||
func TestModifyOrder(t *testing.T) {
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
_, err := k.ModifyOrder(&order.Modify{})
|
||||
if err == nil {
|
||||
t.Error("ModifyOrder() Expected error")
|
||||
@@ -535,9 +529,6 @@ func TestModifyOrder(t *testing.T) {
|
||||
|
||||
// TestWithdraw wrapper test
|
||||
func TestWithdraw(t *testing.T) {
|
||||
k.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
withdrawCryptoRequest := exchange.CryptoWithdrawRequest{
|
||||
GenericWithdrawRequestInfo: exchange.GenericWithdrawRequestInfo{
|
||||
Amount: -1,
|
||||
@@ -563,9 +554,6 @@ func TestWithdraw(t *testing.T) {
|
||||
|
||||
// TestWithdrawFiat wrapper test
|
||||
func TestWithdrawFiat(t *testing.T) {
|
||||
k.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -590,9 +578,6 @@ func TestWithdrawFiat(t *testing.T) {
|
||||
|
||||
// TestWithdrawInternationalBank wrapper test
|
||||
func TestWithdrawInternationalBank(t *testing.T) {
|
||||
k.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -632,9 +617,6 @@ func TestGetDepositAddress(t *testing.T) {
|
||||
|
||||
// TestWithdrawStatus wrapper test
|
||||
func TestWithdrawStatus(t *testing.T) {
|
||||
k.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() {
|
||||
_, err := k.WithdrawStatus(currency.BTC, "")
|
||||
if err != nil {
|
||||
@@ -650,8 +632,6 @@ func TestWithdrawStatus(t *testing.T) {
|
||||
|
||||
// TestWithdrawCancel wrapper test
|
||||
func TestWithdrawCancel(t *testing.T) {
|
||||
k.SetDefaults()
|
||||
TestSetup(t)
|
||||
_, err := k.WithdrawCancel(currency.BTC, "")
|
||||
if areTestAPIKeysSet() && err == nil {
|
||||
t.Error("WithdrawCancel() error cannot be nil")
|
||||
@@ -666,12 +646,11 @@ func setupWsTests(t *testing.T) {
|
||||
if wsSetupRan {
|
||||
return
|
||||
}
|
||||
TestSetDefaults(t)
|
||||
TestSetup(t)
|
||||
if !k.Websocket.IsEnabled() && !k.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
k.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
|
||||
comms = make(chan wshandler.WebsocketResponse, sharedtestvalues.WebsocketChannelOverrideCapacity)
|
||||
k.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
|
||||
k.WebsocketConn = &wshandler.WebsocketConnection{
|
||||
ExchangeName: k.Name,
|
||||
@@ -680,12 +659,33 @@ func setupWsTests(t *testing.T) {
|
||||
ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
|
||||
ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
|
||||
}
|
||||
k.AuthenticatedWebsocketConn = &wshandler.WebsocketConnection{
|
||||
ExchangeName: k.Name,
|
||||
URL: krakenAuthWSURL,
|
||||
Verbose: k.Verbose,
|
||||
ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
|
||||
ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
|
||||
}
|
||||
var dialer websocket.Dialer
|
||||
err := k.WebsocketConn.Dial(&dialer, http.Header{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = k.AuthenticatedWebsocketConn.Dial(&dialer, http.Header{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
token, err := k.GetWebsocketToken()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
authToken = token
|
||||
|
||||
go k.WsReadData(k.WebsocketConn)
|
||||
go k.WsReadData(k.AuthenticatedWebsocketConn)
|
||||
go k.WsHandleData()
|
||||
go k.wsPingHandler()
|
||||
wsSetupRan = true
|
||||
}
|
||||
|
||||
@@ -700,3 +700,38 @@ func TestWebsocketSubscribe(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetWSToken(t *testing.T) {
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("API keys required, skipping")
|
||||
}
|
||||
resp, err := k.GetWebsocketToken()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if resp == "" {
|
||||
t.Error("Token not returned")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWsAddOrder(t *testing.T) {
|
||||
setupWsTests(t)
|
||||
_, err := k.wsAddOrder(&WsAddOrderRequest{
|
||||
OrderType: order.Limit.Lower(),
|
||||
OrderSide: order.Buy.Lower(),
|
||||
Pair: "XBT/USD",
|
||||
Price: -100,
|
||||
})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWsCancelOrder(t *testing.T) {
|
||||
setupWsTests(t)
|
||||
err := k.wsCancelOrders([]string{"1337"})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package kraken
|
||||
|
||||
import "github.com/thrasher-corp/gocryptotrader/currency"
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
)
|
||||
|
||||
// TimeResponse type
|
||||
type TimeResponse struct {
|
||||
@@ -391,7 +395,7 @@ type WithdrawStatusResponse struct {
|
||||
type WebsocketSubscriptionEventRequest struct {
|
||||
Event string `json:"event"` // subscribe
|
||||
RequestID int64 `json:"reqid,omitempty"` // Optional, client originated ID reflected in response message.
|
||||
Pairs []string `json:"pair"` // Array of currency pairs (pair1,pair2,pair3).
|
||||
Pairs []string `json:"pair,omitempty"` // Array of currency pairs (pair1,pair2,pair3).
|
||||
Subscription WebsocketSubscriptionData `json:"subscription,omitempty"`
|
||||
}
|
||||
|
||||
@@ -413,6 +417,8 @@ type WebsocketSubscriptionData struct {
|
||||
Name string `json:"name,omitempty"` // ticker|ohlc|trade|book|spread|*, * for all (ohlc interval value is 1 if all channels subscribed)
|
||||
Interval int64 `json:"interval,omitempty"` // Optional - Time interval associated with ohlc subscription in minutes. Default 1. Valid Interval values: 1|5|15|30|60|240|1440|10080|21600
|
||||
Depth int64 `json:"depth,omitempty"` // Optional - depth associated with book subscription in number of levels each side, default 10. Valid Options are: 10, 25, 100, 500, 1000
|
||||
Token string `json:"token,omitempty"` // Optional used for authenticated requests
|
||||
|
||||
}
|
||||
|
||||
// WebsocketEventResponse holds all data response types
|
||||
@@ -459,3 +465,103 @@ type WebsocketChannelData struct {
|
||||
Pair currency.Pair
|
||||
ChannelID int64
|
||||
}
|
||||
|
||||
// WsTokenResponse holds the WS auth token
|
||||
type WsTokenResponse struct {
|
||||
Error []string `json:"error"`
|
||||
Result struct {
|
||||
Expires int64 `json:"expires"`
|
||||
Token string `json:"token"`
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
// WsOwnTrade ws auth owntrade data
|
||||
type WsOwnTrade struct {
|
||||
Cost float64 `json:"cost,string"`
|
||||
Fee float64 `json:"fee,string"`
|
||||
Margin float64 `json:"margin,string"`
|
||||
OrderTransactionID string `json:"ordertxid"`
|
||||
OrderType string `json:"ordertype"`
|
||||
Pair string `json:"pair"`
|
||||
PostTransactionID string `json:"postxid"`
|
||||
Price float64 `json:"price,string"`
|
||||
Time time.Time `json:"time"`
|
||||
Type string `json:"type"`
|
||||
Vol float64 `json:"vol,string"`
|
||||
}
|
||||
|
||||
// WsOpenOrders ws auth open order data
|
||||
type WsOpenOrders struct {
|
||||
Cost float64 `json:"cost,string"`
|
||||
Description WsOpenOrderDescription `json:"descr"`
|
||||
ExpireTime time.Time `json:"expiretm"`
|
||||
Fee float64 `json:"fee,string"`
|
||||
LimitPrice float64 `json:"limitprice,string"`
|
||||
Misc string `json:"misc"`
|
||||
OFlags string `json:"oflags"`
|
||||
OpenTime time.Time `json:"opentm"`
|
||||
Price float64 `json:"price,string"`
|
||||
RefID string `json:"refid"`
|
||||
StartTime time.Time `json:"starttm"`
|
||||
Status string `json:"status"`
|
||||
StopPrice float64 `json:"stopprice,string"`
|
||||
UserReference float64 `json:"userref"`
|
||||
Volume float64 `json:"vol,string"`
|
||||
ExecutedVolume float64 `json:"vol_exec,string"`
|
||||
}
|
||||
|
||||
// WsOpenOrderDescription additional data for WsOpenOrders
|
||||
type WsOpenOrderDescription struct {
|
||||
Close string `json:"close"`
|
||||
Leverage string `json:"leverage"`
|
||||
Order string `json:"order"`
|
||||
OrderType string `json:"ordertype"`
|
||||
Pair string `json:"pair"`
|
||||
Price float64 `json:"price,string"`
|
||||
Price2 float64 `json:"price2,string"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
// WsAddOrderRequest request type for ws adding order
|
||||
type WsAddOrderRequest struct {
|
||||
Event string `json:"event"`
|
||||
Token string `json:"token"`
|
||||
OrderType string `json:"ordertype"`
|
||||
OrderSide string `json:"type"`
|
||||
Pair string `json:"pair"`
|
||||
Price float64 `json:"price,omitempty"` // optional
|
||||
Price2 float64 `json:"price2,omitempty"` // optional
|
||||
Volume float64 `json:"volume,omitempty"`
|
||||
Leverage float64 `json:"leverage,omitempty"` // optional
|
||||
OFlags string `json:"oflags,omitempty"` // optional
|
||||
StartTime string `json:"starttm,omitempty"` // optional
|
||||
ExpireTime string `json:"expiretm,omitempty"` // optional
|
||||
UserReferenceID string `json:"userref,omitempty"` // optional
|
||||
Validate string `json:"validate,omitempty"` // optional
|
||||
CloseOrderType string `json:"close[ordertype],omitempty"` // optional
|
||||
ClosePrice float64 `json:"close[price],omitempty"` // optional
|
||||
ClosePrice2 float64 `json:"close[price2],omitempty"` // optional
|
||||
}
|
||||
|
||||
// WsAddOrderResponse response data for ws order
|
||||
type WsAddOrderResponse struct {
|
||||
Description string `json:"descr"`
|
||||
Event string `json:"event"`
|
||||
Status string `json:"status"`
|
||||
TransactionID string `json:"txid"`
|
||||
ErrorMessage string `json:"errorMessage"`
|
||||
}
|
||||
|
||||
// WsCancelOrderRequest request for ws cancel order
|
||||
type WsCancelOrderRequest struct {
|
||||
Event string `json:"event"`
|
||||
Token string `json:"token"`
|
||||
TransactionIDs []string `json:"txid"`
|
||||
}
|
||||
|
||||
// WsCancelOrderResponse response data for ws cancel order
|
||||
type WsCancelOrderResponse struct {
|
||||
Event string `json:"event"`
|
||||
Status string `json:"status"`
|
||||
ErrorMessage string `json:"errorMessage"`
|
||||
}
|
||||
|
||||
@@ -10,7 +10,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
|
||||
@@ -21,11 +23,9 @@ import (
|
||||
// List of all websocket channels to subscribe to
|
||||
const (
|
||||
krakenWSURL = "wss://ws.kraken.com"
|
||||
krakenAuthWSURL = "wss://ws-auth.kraken.com"
|
||||
krakenWSSandboxURL = "wss://sandbox.kraken.com"
|
||||
krakenWSSupportedVersion = "0.2.0"
|
||||
// If a checksum fails, then resubscribing to the channel fails, fatal after these attempts
|
||||
krakenWsResubscribeFailureLimit = 3
|
||||
krakenWsResubscribeDelayInSeconds = 3
|
||||
krakenWSSupportedVersion = "0.3.0"
|
||||
// WS endpoints
|
||||
krakenWsHeartbeat = "heartbeat"
|
||||
krakenWsPing = "ping"
|
||||
@@ -39,18 +39,22 @@ const (
|
||||
krakenWsTrade = "trade"
|
||||
krakenWsSpread = "spread"
|
||||
krakenWsOrderbook = "book"
|
||||
|
||||
orderbookBufferLimit = 3
|
||||
krakenWsRateLimit = 50
|
||||
krakenWsOwnTrades = "ownTrades"
|
||||
krakenWsOpenOrders = "openOrders"
|
||||
krakenWsAddOrder = "addOrder"
|
||||
krakenWsCancelOrder = "cancelOrder"
|
||||
krakenWsRateLimit = 50
|
||||
)
|
||||
|
||||
// orderbookMutex Ensures if two entries arrive at once, only one can be processed at a time
|
||||
var subscriptionChannelPair []WebsocketChannelData
|
||||
var subscribeToDefaultChannels = true
|
||||
var comms = make(chan wshandler.WebsocketResponse)
|
||||
var authToken string
|
||||
|
||||
// Channels require a topic and a currency
|
||||
// Format [[ticker,but-t4u],[orderbook,nce-btt]]
|
||||
var defaultSubscribedChannels = []string{krakenWsTicker, krakenWsTrade, krakenWsOrderbook, krakenWsOHLC, krakenWsSpread}
|
||||
var authenticatedChannels = []string{krakenWsOwnTrades, krakenWsOpenOrders}
|
||||
|
||||
// WsConnect initiates a websocket connection
|
||||
func (k *Kraken) WsConnect() error {
|
||||
@@ -62,15 +66,86 @@ func (k *Kraken) WsConnect() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go k.WsHandleData()
|
||||
go k.wsPingHandler()
|
||||
if subscribeToDefaultChannels {
|
||||
k.GenerateDefaultSubscriptions()
|
||||
if k.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
|
||||
authToken, err = k.GetWebsocketToken()
|
||||
if err != nil {
|
||||
k.Websocket.SetCanUseAuthenticatedEndpoints(false)
|
||||
log.Errorf(log.ExchangeSys, "%v - authentication failed: %v\n", k.Name, err)
|
||||
}
|
||||
err = k.AuthenticatedWebsocketConn.Dial(&dialer, http.Header{})
|
||||
if err != nil {
|
||||
k.Websocket.SetCanUseAuthenticatedEndpoints(false)
|
||||
log.Errorf(log.ExchangeSys, "%v - failed to connect to authenticated endpoint: %v\n", k.Name, err)
|
||||
}
|
||||
go k.WsReadData(k.AuthenticatedWebsocketConn)
|
||||
k.GenerateAuthenticatedSubscriptions()
|
||||
}
|
||||
|
||||
go k.WsReadData(k.WebsocketConn)
|
||||
go k.WsHandleData()
|
||||
go k.wsPingHandler()
|
||||
k.GenerateDefaultSubscriptions()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WsReadData funnels both auth and public ws data into one manageable place
|
||||
func (k *Kraken) WsReadData(ws *wshandler.WebsocketConnection) {
|
||||
k.Websocket.Wg.Add(1)
|
||||
defer k.Websocket.Wg.Done()
|
||||
for {
|
||||
select {
|
||||
case <-k.Websocket.ShutdownC:
|
||||
return
|
||||
default:
|
||||
resp, err := ws.ReadMessage()
|
||||
if err != nil {
|
||||
k.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
k.Websocket.TrafficAlert <- struct{}{}
|
||||
comms <- resp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WsHandleData handles the read data from the websocket connection
|
||||
func (k *Kraken) WsHandleData() {
|
||||
k.Websocket.Wg.Add(1)
|
||||
defer func() {
|
||||
k.Websocket.Wg.Done()
|
||||
}()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-k.Websocket.ShutdownC:
|
||||
return
|
||||
default:
|
||||
resp := <-comms
|
||||
// event response handling
|
||||
var eventResponse WebsocketEventResponse
|
||||
err := json.Unmarshal(resp.Raw, &eventResponse)
|
||||
if err == nil && eventResponse.Event != "" {
|
||||
k.WsHandleEventResponse(&eventResponse, resp.Raw)
|
||||
continue
|
||||
}
|
||||
// Data response handling
|
||||
var dataResponse WebsocketDataResponse
|
||||
err = json.Unmarshal(resp.Raw, &dataResponse)
|
||||
if err != nil {
|
||||
log.Error(log.WebsocketMgr, fmt.Errorf("%s - unhandled websocket data: %v", k.Name, err))
|
||||
continue
|
||||
}
|
||||
if _, ok := dataResponse[0].(float64); ok {
|
||||
k.WsHandleDataResponse(dataResponse)
|
||||
}
|
||||
if _, ok := dataResponse[1].(string); ok {
|
||||
k.wsHandleAuthDataResponse(dataResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// wsPingHandler sends a message "ping" every 27 to maintain the connection to the websocket
|
||||
func (k *Kraken) wsPingHandler() {
|
||||
k.Websocket.Wg.Add(1)
|
||||
@@ -96,82 +171,47 @@ func (k *Kraken) wsPingHandler() {
|
||||
}
|
||||
}
|
||||
|
||||
// WsHandleData handles the read data from the websocket connection
|
||||
func (k *Kraken) WsHandleData() {
|
||||
k.Websocket.Wg.Add(1)
|
||||
defer func() {
|
||||
k.Websocket.Wg.Done()
|
||||
}()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-k.Websocket.ShutdownC:
|
||||
return
|
||||
default:
|
||||
resp, err := k.WebsocketConn.ReadMessage()
|
||||
if err != nil {
|
||||
k.Websocket.ReadMessageErrors <- err
|
||||
return
|
||||
}
|
||||
k.Websocket.TrafficAlert <- struct{}{}
|
||||
// event response handling
|
||||
var eventResponse WebsocketEventResponse
|
||||
err = json.Unmarshal(resp.Raw, &eventResponse)
|
||||
if err == nil && eventResponse.Event != "" {
|
||||
k.WsHandleEventResponse(&eventResponse, resp.Raw)
|
||||
continue
|
||||
}
|
||||
// Data response handling
|
||||
var dataResponse WebsocketDataResponse
|
||||
err = json.Unmarshal(resp.Raw, &dataResponse)
|
||||
if err == nil && dataResponse[0].(float64) >= 0 {
|
||||
k.WsHandleDataResponse(dataResponse)
|
||||
continue
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WsHandleDataResponse classifies the WS response and sends to appropriate handler
|
||||
func (k *Kraken) WsHandleDataResponse(response WebsocketDataResponse) {
|
||||
channelID := int64(response[0].(float64))
|
||||
channelData := getSubscriptionChannelData(channelID)
|
||||
switch channelData.Subscription {
|
||||
case krakenWsTicker:
|
||||
if k.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%v Websocket ticker data received",
|
||||
k.Name)
|
||||
if cID, ok := response[0].(float64); ok {
|
||||
channelID := int64(cID)
|
||||
channelData := getSubscriptionChannelData(channelID)
|
||||
switch channelData.Subscription {
|
||||
case krakenWsTicker:
|
||||
if k.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%v Websocket ticker data received",
|
||||
k.Name)
|
||||
}
|
||||
k.wsProcessTickers(&channelData, response[1].(map[string]interface{}))
|
||||
case krakenWsOHLC:
|
||||
if k.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%v Websocket OHLC data received",
|
||||
k.Name)
|
||||
}
|
||||
k.wsProcessCandles(&channelData, response[1].([]interface{}))
|
||||
case krakenWsOrderbook:
|
||||
if k.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%v Websocket Orderbook data received",
|
||||
k.Name)
|
||||
}
|
||||
k.wsProcessOrderBook(&channelData, response[1].(map[string]interface{}))
|
||||
case krakenWsSpread:
|
||||
if k.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%v Websocket Spread data received",
|
||||
k.Name)
|
||||
}
|
||||
k.wsProcessSpread(&channelData, response[1].([]interface{}))
|
||||
case krakenWsTrade:
|
||||
if k.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%v Websocket Trade data received",
|
||||
k.Name)
|
||||
}
|
||||
k.wsProcessTrades(&channelData, response[1].([]interface{}))
|
||||
default:
|
||||
log.Errorf(log.ExchangeSys, "%v Unidentified websocket data received: %v",
|
||||
k.Name,
|
||||
response)
|
||||
}
|
||||
k.wsProcessTickers(&channelData, response[1].(map[string]interface{}))
|
||||
case krakenWsOHLC:
|
||||
if k.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%v Websocket OHLC data received",
|
||||
k.Name)
|
||||
}
|
||||
k.wsProcessCandles(&channelData, response[1].([]interface{}))
|
||||
case krakenWsOrderbook:
|
||||
if k.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%v Websocket Orderbook data received",
|
||||
k.Name)
|
||||
}
|
||||
k.wsProcessOrderBook(&channelData, response[1].(map[string]interface{}))
|
||||
case krakenWsSpread:
|
||||
if k.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%v Websocket Spread data received",
|
||||
k.Name)
|
||||
}
|
||||
k.wsProcessSpread(&channelData, response[1].([]interface{}))
|
||||
case krakenWsTrade:
|
||||
if k.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%v Websocket Trade data received",
|
||||
k.Name)
|
||||
}
|
||||
k.wsProcessTrades(&channelData, response[1].([]interface{}))
|
||||
default:
|
||||
log.Errorf(log.ExchangeSys, "%v Unidentified websocket data received: %v",
|
||||
k.Name,
|
||||
response)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,7 +237,7 @@ func (k *Kraken) WsHandleEventResponse(response *WebsocketEventResponse, rawResp
|
||||
k.Websocket.DataHandler <- fmt.Errorf("%v Websocket status '%v'",
|
||||
k.Name, response.Status)
|
||||
}
|
||||
if response.WebsocketStatusResponse.Version != krakenWSSupportedVersion {
|
||||
if response.WebsocketStatusResponse.Version > krakenWSSupportedVersion {
|
||||
log.Warnf(log.ExchangeSys, "%v New version of Websocket API released. Was %v Now %v",
|
||||
k.Name, krakenWSSupportedVersion, response.WebsocketStatusResponse.Version)
|
||||
}
|
||||
@@ -214,6 +254,192 @@ func (k *Kraken) WsHandleEventResponse(response *WebsocketEventResponse, rawResp
|
||||
}
|
||||
}
|
||||
|
||||
func (k *Kraken) wsHandleAuthDataResponse(response WebsocketDataResponse) {
|
||||
if chName, ok := response[1].(string); ok {
|
||||
switch chName {
|
||||
case krakenWsOwnTrades:
|
||||
if k.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%v Websocket auth own trade data received",
|
||||
k.Name)
|
||||
}
|
||||
k.wsProcessOwnTrades(&response[0])
|
||||
case krakenWsOpenOrders:
|
||||
if k.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%v Websocket auth open order data received",
|
||||
k.Name)
|
||||
}
|
||||
k.wsProcessOpenOrders(&response[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (k *Kraken) wsProcessOwnTrades(ownOrders interface{}) {
|
||||
if data, ok := ownOrders.([]interface{}); ok {
|
||||
for i := range data {
|
||||
ownTrade := data[i].(map[string]interface{})
|
||||
for _, val := range ownTrade {
|
||||
tradeData := val.(map[string]interface{})
|
||||
cost, err := strconv.ParseFloat(tradeData["cost"].(string), 64)
|
||||
if err != nil {
|
||||
k.Websocket.DataHandler <- err
|
||||
}
|
||||
fee, err := strconv.ParseFloat(tradeData["fee"].(string), 64)
|
||||
if err != nil {
|
||||
k.Websocket.DataHandler <- err
|
||||
}
|
||||
margin, err := strconv.ParseFloat(tradeData["margin"].(string), 64)
|
||||
if err != nil {
|
||||
k.Websocket.DataHandler <- err
|
||||
}
|
||||
vol, err := strconv.ParseFloat(tradeData["vol"].(string), 64)
|
||||
if err != nil {
|
||||
k.Websocket.DataHandler <- err
|
||||
}
|
||||
price, err := strconv.ParseFloat(tradeData["price"].(string), 64)
|
||||
if err != nil {
|
||||
k.Websocket.DataHandler <- err
|
||||
}
|
||||
timeTogether, err := strconv.ParseFloat(tradeData["time"].(string), 64)
|
||||
if err != nil {
|
||||
k.Websocket.DataHandler <- err
|
||||
}
|
||||
first, second, err := convert.SplitFloatDecimals(timeTogether)
|
||||
if err != nil {
|
||||
k.Websocket.DataHandler <- err
|
||||
}
|
||||
k.Websocket.DataHandler <- WsOwnTrade{
|
||||
Cost: cost,
|
||||
Fee: fee,
|
||||
Margin: margin,
|
||||
OrderTransactionID: tradeData["ordertxid"].(string),
|
||||
OrderType: tradeData["ordertype"].(string),
|
||||
Pair: tradeData["pair"].(string),
|
||||
PostTransactionID: tradeData["postxid"].(string),
|
||||
Price: price,
|
||||
Time: time.Unix(first, second),
|
||||
Type: tradeData["type"].(string),
|
||||
Vol: vol,
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
k.Websocket.DataHandler <- errors.New(k.Name + " - Invalid own trades data")
|
||||
}
|
||||
}
|
||||
|
||||
func (k *Kraken) wsProcessOpenOrders(ownOrders interface{}) {
|
||||
if data, ok := ownOrders.([]interface{}); ok {
|
||||
for i := range data {
|
||||
ownTrade := data[i].(map[string]interface{})
|
||||
for key, val := range ownTrade {
|
||||
tradeData := val.(map[string]interface{})
|
||||
if len(tradeData) == 1 {
|
||||
// just a status update
|
||||
if status, ok := tradeData["status"].(string); ok {
|
||||
k.Websocket.DataHandler <- k.Name + " - Order " + key + " " + status
|
||||
}
|
||||
}
|
||||
startTimeConv, err := strconv.ParseFloat(tradeData["starttm"].(string), 64)
|
||||
if err != nil {
|
||||
k.Websocket.DataHandler <- err
|
||||
}
|
||||
startTime, startTimeNano, err := convert.SplitFloatDecimals(startTimeConv)
|
||||
if err != nil {
|
||||
k.Websocket.DataHandler <- err
|
||||
}
|
||||
openTimeConv, err := strconv.ParseFloat(tradeData["opentm"].(string), 64)
|
||||
if err != nil {
|
||||
k.Websocket.DataHandler <- err
|
||||
}
|
||||
openTime, openTimeNano, err := convert.SplitFloatDecimals(openTimeConv)
|
||||
if err != nil {
|
||||
k.Websocket.DataHandler <- err
|
||||
}
|
||||
expireTimeConv, err := strconv.ParseFloat(tradeData["expiretm"].(string), 64)
|
||||
if err != nil {
|
||||
k.Websocket.DataHandler <- err
|
||||
}
|
||||
expireTime, expireTimeNano, err := convert.SplitFloatDecimals(expireTimeConv)
|
||||
if err != nil {
|
||||
k.Websocket.DataHandler <- err
|
||||
}
|
||||
cost, err := strconv.ParseFloat(tradeData["cost"].(string), 64)
|
||||
if err != nil {
|
||||
k.Websocket.DataHandler <- err
|
||||
}
|
||||
executedVolume, err := strconv.ParseFloat(tradeData["vol_exec"].(string), 64)
|
||||
if err != nil {
|
||||
k.Websocket.DataHandler <- err
|
||||
}
|
||||
volume, err := strconv.ParseFloat(tradeData["vol"].(string), 64)
|
||||
if err != nil {
|
||||
k.Websocket.DataHandler <- err
|
||||
}
|
||||
userReference, err := strconv.ParseFloat(tradeData["userref"].(string), 64)
|
||||
if err != nil {
|
||||
k.Websocket.DataHandler <- err
|
||||
}
|
||||
stopPrice, err := strconv.ParseFloat(tradeData["stopprice"].(string), 64)
|
||||
if err != nil {
|
||||
k.Websocket.DataHandler <- err
|
||||
}
|
||||
price, err := strconv.ParseFloat(tradeData["price"].(string), 64)
|
||||
if err != nil {
|
||||
k.Websocket.DataHandler <- err
|
||||
}
|
||||
limitPrice, err := strconv.ParseFloat(tradeData["limitprice"].(string), 64)
|
||||
if err != nil {
|
||||
k.Websocket.DataHandler <- err
|
||||
}
|
||||
fee, err := strconv.ParseFloat(tradeData["fee"].(string), 64)
|
||||
if err != nil {
|
||||
k.Websocket.DataHandler <- err
|
||||
}
|
||||
descriptionSubData := tradeData["description"].(map[string]interface{})
|
||||
descriptionPrice, err := strconv.ParseFloat(descriptionSubData["price"].(string), 64)
|
||||
if err != nil {
|
||||
k.Websocket.DataHandler <- err
|
||||
}
|
||||
descriptionPrice2, err := strconv.ParseFloat(descriptionSubData["price2"].(string), 64)
|
||||
if err != nil {
|
||||
k.Websocket.DataHandler <- err
|
||||
}
|
||||
description := WsOpenOrderDescription{
|
||||
Close: descriptionSubData["close"].(string),
|
||||
Leverage: descriptionSubData["leverage"].(string),
|
||||
Order: descriptionSubData["order"].(string),
|
||||
OrderType: descriptionSubData["ordertype"].(string),
|
||||
Pair: descriptionSubData["pair"].(string),
|
||||
Price: descriptionPrice,
|
||||
Price2: descriptionPrice2,
|
||||
Type: descriptionSubData["type"].(string),
|
||||
}
|
||||
|
||||
k.Websocket.DataHandler <- WsOpenOrders{
|
||||
Cost: cost,
|
||||
ExpireTime: time.Unix(expireTime, expireTimeNano),
|
||||
Description: description,
|
||||
Fee: fee,
|
||||
LimitPrice: limitPrice,
|
||||
Misc: tradeData["misc"].(string),
|
||||
OFlags: tradeData["oflags"].(string),
|
||||
OpenTime: time.Unix(openTime, openTimeNano),
|
||||
Price: price,
|
||||
RefID: tradeData["refid"].(string),
|
||||
StartTime: time.Unix(startTime, startTimeNano),
|
||||
Status: tradeData["status"].(string),
|
||||
StopPrice: stopPrice,
|
||||
UserReference: userReference,
|
||||
Volume: volume,
|
||||
ExecutedVolume: executedVolume,
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
k.Websocket.DataHandler <- errors.New(k.Name + " - Invalid own trades data")
|
||||
}
|
||||
}
|
||||
|
||||
// addNewSubscriptionChannelData stores channel ids, pairs and subscription types to an array
|
||||
// allowing correlation between subscriptions and returned data
|
||||
func addNewSubscriptionChannelData(response *WebsocketEventResponse) {
|
||||
@@ -623,22 +849,39 @@ func (k *Kraken) GenerateDefaultSubscriptions() {
|
||||
k.Websocket.SubscribeToChannels(subscriptions)
|
||||
}
|
||||
|
||||
// GenerateDefaultSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions()
|
||||
func (k *Kraken) GenerateAuthenticatedSubscriptions() {
|
||||
var subscriptions []wshandler.WebsocketChannelSubscription
|
||||
for i := range authenticatedChannels {
|
||||
params := make(map[string]interface{})
|
||||
subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
|
||||
Channel: authenticatedChannels[i],
|
||||
Params: params,
|
||||
})
|
||||
}
|
||||
k.Websocket.SubscribeToChannels(subscriptions)
|
||||
}
|
||||
|
||||
// Subscribe sends a websocket message to receive data from the channel
|
||||
func (k *Kraken) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
|
||||
var depth int64
|
||||
if channelToSubscribe.Channel == "book" {
|
||||
depth = 1000
|
||||
}
|
||||
|
||||
resp := WebsocketSubscriptionEventRequest{
|
||||
Event: krakenWsSubscribe,
|
||||
Pairs: []string{channelToSubscribe.Currency.String()},
|
||||
Subscription: WebsocketSubscriptionData{
|
||||
Name: channelToSubscribe.Channel,
|
||||
Depth: depth,
|
||||
Name: channelToSubscribe.Channel,
|
||||
},
|
||||
RequestID: k.WebsocketConn.GenerateMessageID(false),
|
||||
}
|
||||
if channelToSubscribe.Channel == "book" {
|
||||
// TODO: Add ability to make depth customisable
|
||||
resp.Subscription.Depth = 1000
|
||||
}
|
||||
if !channelToSubscribe.Currency.IsEmpty() {
|
||||
resp.Pairs = []string{channelToSubscribe.Currency.String()}
|
||||
}
|
||||
if channelToSubscribe.Params != nil {
|
||||
resp.Subscription.Token = authToken
|
||||
}
|
||||
|
||||
_, err := k.WebsocketConn.SendMessageReturnResponse(resp.RequestID, resp)
|
||||
return err
|
||||
}
|
||||
@@ -656,3 +899,32 @@ func (k *Kraken) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscr
|
||||
_, err := k.WebsocketConn.SendMessageReturnResponse(resp.RequestID, resp)
|
||||
return err
|
||||
}
|
||||
|
||||
func (k *Kraken) wsAddOrder(request *WsAddOrderRequest) (string, error) {
|
||||
id := k.AuthenticatedWebsocketConn.GenerateMessageID(false)
|
||||
request.UserReferenceID = strconv.FormatInt(id, 10)
|
||||
request.Event = krakenWsAddOrder
|
||||
request.Token = authToken
|
||||
jsonResp, err := k.AuthenticatedWebsocketConn.SendMessageReturnResponse(id, request)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var resp WsAddOrderResponse
|
||||
err = json.Unmarshal(jsonResp, &resp)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if resp.ErrorMessage != "" {
|
||||
return "", fmt.Errorf(k.Name + " - " + resp.ErrorMessage)
|
||||
}
|
||||
return resp.TransactionID, nil
|
||||
}
|
||||
|
||||
func (k *Kraken) wsCancelOrders(orderIDs []string) error {
|
||||
request := WsCancelOrderRequest{
|
||||
Event: krakenWsCancelOrder,
|
||||
Token: authToken,
|
||||
TransactionIDs: orderIDs,
|
||||
}
|
||||
return k.AuthenticatedWebsocketConn.SendMessage(request)
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
@@ -106,6 +107,9 @@ func (k *Kraken) SetDefaults() {
|
||||
Subscribe: true,
|
||||
Unsubscribe: true,
|
||||
MessageCorrelation: true,
|
||||
SubmitOrder: true,
|
||||
CancelOrder: true,
|
||||
CancelOrders: true,
|
||||
},
|
||||
WithdrawPermissions: exchange.AutoWithdrawCryptoWithSetup |
|
||||
exchange.WithdrawCryptoWith2FA |
|
||||
@@ -171,6 +175,16 @@ func (k *Kraken) Setup(exch *config.ExchangeConfig) error {
|
||||
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
|
||||
}
|
||||
|
||||
k.AuthenticatedWebsocketConn = &wshandler.WebsocketConnection{
|
||||
ExchangeName: k.Name,
|
||||
URL: krakenAuthWSURL,
|
||||
ProxyURL: k.Websocket.GetProxyAddress(),
|
||||
Verbose: k.Verbose,
|
||||
RateLimit: krakenWsRateLimit,
|
||||
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
|
||||
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
|
||||
}
|
||||
|
||||
k.Websocket.Orderbook.Setup(
|
||||
exch.WebsocketOrderbookBufferLimit,
|
||||
true,
|
||||
@@ -397,25 +411,47 @@ func (k *Kraken) GetExchangeHistory(p currency.Pair, assetType asset.Item) ([]ex
|
||||
// SubmitOrder submits a new order
|
||||
func (k *Kraken) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
|
||||
var submitOrderResponse order.SubmitResponse
|
||||
if err := s.Validate(); err != nil {
|
||||
err := s.Validate()
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
response, err := k.AddOrder(s.Pair.String(),
|
||||
s.OrderSide.String(),
|
||||
s.OrderType.String(),
|
||||
s.Amount,
|
||||
s.Price,
|
||||
0,
|
||||
0,
|
||||
&AddOrderOptions{})
|
||||
if len(response.TransactionIds) > 0 {
|
||||
submitOrderResponse.OrderID = strings.Join(response.TransactionIds, ", ")
|
||||
}
|
||||
if err == nil {
|
||||
if k.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
var resp string
|
||||
resp, err = k.wsAddOrder(&WsAddOrderRequest{
|
||||
OrderType: s.OrderType.String(),
|
||||
OrderSide: s.OrderSide.String(),
|
||||
Pair: s.Pair.String(),
|
||||
Price: s.Price,
|
||||
Volume: s.Amount,
|
||||
})
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
submitOrderResponse.OrderID = resp
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
} else {
|
||||
var response AddOrderResponse
|
||||
response, err = k.AddOrder(s.Pair.String(),
|
||||
s.OrderSide.String(),
|
||||
s.OrderType.String(),
|
||||
s.Amount,
|
||||
s.Price,
|
||||
0,
|
||||
0,
|
||||
&AddOrderOptions{})
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
if len(response.TransactionIds) > 0 {
|
||||
submitOrderResponse.OrderID = strings.Join(response.TransactionIds, ", ")
|
||||
}
|
||||
}
|
||||
return submitOrderResponse, err
|
||||
if s.OrderType == order.Market {
|
||||
submitOrderResponse.FullyMatched = true
|
||||
}
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
return submitOrderResponse, nil
|
||||
}
|
||||
|
||||
// ModifyOrder will allow of changing orderbook placement and limit to
|
||||
@@ -426,6 +462,9 @@ func (k *Kraken) ModifyOrder(action *order.Modify) (string, error) {
|
||||
|
||||
// CancelOrder cancels an order by its corresponding ID number
|
||||
func (k *Kraken) CancelOrder(order *order.Cancel) error {
|
||||
if k.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
return k.wsCancelOrders([]string{order.OrderID})
|
||||
}
|
||||
_, err := k.CancelExistingOrder(order.OrderID)
|
||||
|
||||
return err
|
||||
@@ -436,26 +475,78 @@ func (k *Kraken) CancelAllOrders(_ *order.Cancel) (order.CancelAllResponse, erro
|
||||
cancelAllOrdersResponse := order.CancelAllResponse{
|
||||
Status: make(map[string]string),
|
||||
}
|
||||
|
||||
var emptyOrderOptions OrderInfoOptions
|
||||
openOrders, err := k.GetOpenOrders(emptyOrderOptions)
|
||||
if err != nil {
|
||||
return cancelAllOrdersResponse, err
|
||||
}
|
||||
|
||||
for orderID := range openOrders.Open {
|
||||
_, err = k.CancelExistingOrder(orderID)
|
||||
var err error
|
||||
if k.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
err = k.wsCancelOrders([]string{orderID})
|
||||
} else {
|
||||
_, err = k.CancelExistingOrder(orderID)
|
||||
}
|
||||
if err != nil {
|
||||
cancelAllOrdersResponse.Status[orderID] = err.Error()
|
||||
}
|
||||
}
|
||||
|
||||
return cancelAllOrdersResponse, nil
|
||||
}
|
||||
|
||||
// GetOrderInfo returns information on a current open order
|
||||
func (k *Kraken) GetOrderInfo(orderID string) (order.Detail, error) {
|
||||
var orderDetail order.Detail
|
||||
return orderDetail, common.ErrNotYetImplemented
|
||||
var emptyOrderOptions OrderInfoOptions
|
||||
openOrders, err := k.GetOpenOrders(emptyOrderOptions)
|
||||
if err != nil {
|
||||
return orderDetail, err
|
||||
}
|
||||
if orderInfo, ok := openOrders.Open[orderID]; ok {
|
||||
var trades []order.TradeHistory
|
||||
for i := range orderInfo.Trades {
|
||||
trades = append(trades, order.TradeHistory{
|
||||
TID: orderInfo.Trades[i],
|
||||
})
|
||||
}
|
||||
firstNum, decNum, err := convert.SplitFloatDecimals(orderInfo.StartTime)
|
||||
if err != nil {
|
||||
return orderDetail, err
|
||||
}
|
||||
side, err := order.StringToOrderSide(orderInfo.Description.Type)
|
||||
if err != nil {
|
||||
return orderDetail, err
|
||||
}
|
||||
status, err := order.StringToOrderStatus(orderInfo.Status)
|
||||
if err != nil {
|
||||
return orderDetail, err
|
||||
}
|
||||
oType, err := order.StringToOrderType(orderInfo.Description.OrderType)
|
||||
if err != nil {
|
||||
return orderDetail, err
|
||||
}
|
||||
|
||||
orderDetail = order.Detail{
|
||||
Exchange: k.Name,
|
||||
ID: orderID,
|
||||
CurrencyPair: currency.NewPairFromString(orderInfo.Description.Pair),
|
||||
OrderSide: side,
|
||||
OrderType: oType,
|
||||
OrderDate: time.Unix(firstNum, decNum),
|
||||
Status: status,
|
||||
Price: orderInfo.Price,
|
||||
Amount: orderInfo.Volume,
|
||||
ExecutedAmount: orderInfo.VolumeExecuted,
|
||||
RemainingAmount: orderInfo.Volume - orderInfo.VolumeExecuted,
|
||||
Fee: orderInfo.Fee,
|
||||
Trades: trades,
|
||||
}
|
||||
} else {
|
||||
return orderDetail, errors.New(k.Name + " - Order ID not found: " + orderID)
|
||||
}
|
||||
|
||||
return orderDetail, nil
|
||||
}
|
||||
|
||||
// GetDepositAddress returns a deposit address for a specified currency
|
||||
@@ -606,5 +697,9 @@ func (k *Kraken) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, e
|
||||
|
||||
// AuthenticateWebsocket sends an authentication message to the websocket
|
||||
func (k *Kraken) AuthenticateWebsocket() error {
|
||||
return common.ErrFunctionNotSupported
|
||||
resp, err := k.GetWebsocketToken()
|
||||
if resp != "" {
|
||||
authToken = resp
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package lakebtc
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
@@ -16,7 +17,6 @@ import (
|
||||
)
|
||||
|
||||
var l LakeBTC
|
||||
var setupRan bool
|
||||
|
||||
// Please add your own APIkeys to do correct due diligence testing.
|
||||
const (
|
||||
@@ -25,34 +25,28 @@ const (
|
||||
canManipulateRealOrders = false
|
||||
)
|
||||
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
if !setupRan {
|
||||
l.SetDefaults()
|
||||
func TestMain(m *testing.M) {
|
||||
l.SetDefaults()
|
||||
cfg := config.GetConfig()
|
||||
err := cfg.LoadConfig("../../testdata/configtest.json", true)
|
||||
if err != nil {
|
||||
log.Fatal("LakeBTC load config error", err)
|
||||
}
|
||||
}
|
||||
lakebtcConfig, err := cfg.GetExchangeConfig("LakeBTC")
|
||||
if err != nil {
|
||||
log.Fatal("LakeBTC Setup() init error")
|
||||
}
|
||||
lakebtcConfig.API.AuthenticatedSupport = true
|
||||
lakebtcConfig.API.Credentials.Key = apiKey
|
||||
lakebtcConfig.API.Credentials.Secret = apiSecret
|
||||
lakebtcConfig.Features.Enabled.Websocket = true
|
||||
err = l.Setup(lakebtcConfig)
|
||||
if err != nil {
|
||||
log.Fatal("LakeBTC setup error", err)
|
||||
}
|
||||
l.API.Endpoints.WebsocketURL = lakeBTCWSURL
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
if !setupRan {
|
||||
cfg := config.GetConfig()
|
||||
err := cfg.LoadConfig("../../testdata/configtest.json", true)
|
||||
if err != nil {
|
||||
log.Fatal("LakeBTC load config error", err)
|
||||
}
|
||||
lakebtcConfig, err := cfg.GetExchangeConfig("LakeBTC")
|
||||
if err != nil {
|
||||
t.Error("LakeBTC Setup() init error")
|
||||
}
|
||||
lakebtcConfig.API.AuthenticatedSupport = true
|
||||
lakebtcConfig.API.Credentials.Key = apiKey
|
||||
lakebtcConfig.API.Credentials.Secret = apiSecret
|
||||
lakebtcConfig.Features.Enabled.Websocket = true
|
||||
err = l.Setup(lakebtcConfig)
|
||||
if err != nil {
|
||||
t.Fatal("LakeBTC setup error", err)
|
||||
}
|
||||
l.API.Endpoints.WebsocketURL = lakeBTCWSURL
|
||||
setupRan = true
|
||||
}
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestFetchTradablePairs(t *testing.T) {
|
||||
@@ -171,7 +165,7 @@ func setFeeBuilder() *exchange.FeeBuilder {
|
||||
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
var feeBuilder = setFeeBuilder()
|
||||
l.GetFeeByType(feeBuilder)
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
if !areTestAPIKeysSet() {
|
||||
if feeBuilder.FeeType != exchange.OfflineTradeFee {
|
||||
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
|
||||
}
|
||||
@@ -259,20 +253,14 @@ func TestGetFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
l.SetDefaults()
|
||||
expectedResult := exchange.AutoWithdrawCryptoText + " & " + exchange.WithdrawFiatViaWebsiteOnlyText
|
||||
|
||||
withdrawPermissions := l.FormatWithdrawPermissions()
|
||||
|
||||
if withdrawPermissions != expectedResult {
|
||||
t.Errorf("Expected: %s, Received: %s", expectedResult, withdrawPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
l.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
}
|
||||
@@ -286,9 +274,6 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
l.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
}
|
||||
@@ -308,9 +293,6 @@ func areTestAPIKeysSet() bool {
|
||||
}
|
||||
|
||||
func TestSubmitOrder(t *testing.T) {
|
||||
l.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -335,15 +317,11 @@ func TestSubmitOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelExchangeOrder(t *testing.T) {
|
||||
l.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -361,15 +339,11 @@ func TestCancelExchangeOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
l.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -392,6 +366,9 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestModifyOrder(t *testing.T) {
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
_, err := l.ModifyOrder(&order.Modify{})
|
||||
if err == nil {
|
||||
t.Error("ModifyOrder() Expected error")
|
||||
@@ -399,8 +376,6 @@ func TestModifyOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdraw(t *testing.T) {
|
||||
l.SetDefaults()
|
||||
TestSetup(t)
|
||||
withdrawCryptoRequest := exchange.CryptoWithdrawRequest{
|
||||
GenericWithdrawRequestInfo: exchange.GenericWithdrawRequestInfo{
|
||||
Amount: -1,
|
||||
@@ -424,9 +399,6 @@ func TestWithdraw(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawFiat(t *testing.T) {
|
||||
l.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -439,9 +411,6 @@ func TestWithdrawFiat(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawInternationalBank(t *testing.T) {
|
||||
l.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -469,8 +438,6 @@ func TestGetDepositAddress(t *testing.T) {
|
||||
|
||||
// TestWsConn websocket connection test
|
||||
func TestWsConn(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
TestSetup(t)
|
||||
if !l.Websocket.IsEnabled() {
|
||||
t.Skip(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
@@ -484,8 +451,6 @@ func TestWsConn(t *testing.T) {
|
||||
|
||||
// TestWsTradeProcessing logic test
|
||||
func TestWsTradeProcessing(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
TestSetup(t)
|
||||
l.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
|
||||
l.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
|
||||
json := `{"trades":[{"type":"sell","date":1564985787,"price":"11913.02","amount":"0.49"}]}`
|
||||
@@ -497,8 +462,6 @@ func TestWsTradeProcessing(t *testing.T) {
|
||||
|
||||
// TestWsTickerProcessing logic test
|
||||
func TestWsTickerProcessing(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
TestSetup(t)
|
||||
const testChanSize = 26
|
||||
l.Websocket.DataHandler = make(chan interface{}, testChanSize)
|
||||
l.Websocket.TrafficAlert = make(chan struct{}, testChanSize)
|
||||
@@ -519,8 +482,6 @@ func TestGetCurrencyFromChannel(t *testing.T) {
|
||||
|
||||
// TestWsOrderbookProcessing logic test
|
||||
func TestWsOrderbookProcessing(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
TestSetup(t)
|
||||
l.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
|
||||
l.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
|
||||
json := `{"asks":[["11905.66","0.0019"],["11905.73","0.0015"],["11906.43","0.0013"],["11906.62","0.0019"],["11907.25","11.087"],["11907.66","0.0006"],["11907.73","0.3113"],["11907.84","0.0006"],["11908.37","0.0016"],["11908.86","10.3786"],["11909.54","4.2955"],["11910.15","0.0012"],["11910.56","13.5505"],["11911.06","0.0011"],["11911.37","0.0023"]],"bids":[["11905.55","0.0171"],["11904.43","0.0225"],["11903.31","0.0223"],["11902.2","0.0027"],["11901.92","1.002"],["11901.6","0.0015"],["11901.49","0.0012"],["11901.08","0.0227"],["11900.93","0.0009"],["11900.53","1.662"],["11900.08","0.001"],["11900.01","3.6745"],["11899.96","0.003"],["11899.91","0.0006"],["11899.44","0.0013"]]}`
|
||||
|
||||
@@ -334,13 +334,18 @@ func (l *LakeBTC) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
|
||||
isBuyOrder := s.OrderSide == order.Buy
|
||||
response, err := l.Trade(isBuyOrder, s.Amount, s.Price,
|
||||
s.Pair.Lower().String())
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
if response.ID > 0 {
|
||||
submitOrderResponse.OrderID = strconv.FormatInt(response.ID, 10)
|
||||
}
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
if s.OrderType == order.Market {
|
||||
submitOrderResponse.FullyMatched = true
|
||||
}
|
||||
return submitOrderResponse, err
|
||||
return submitOrderResponse, nil
|
||||
}
|
||||
|
||||
// ModifyOrder will allow of changing orderbook placement and limit to
|
||||
@@ -369,8 +374,8 @@ func (l *LakeBTC) CancelAllOrders(_ *order.Cancel) (order.CancelAllResponse, err
|
||||
}
|
||||
|
||||
var ordersToCancel []string
|
||||
for _, order := range openOrders {
|
||||
ordersToCancel = append(ordersToCancel, strconv.FormatInt(order.ID, 10))
|
||||
for i := range openOrders {
|
||||
ordersToCancel = append(ordersToCancel, strconv.FormatInt(openOrders[i].ID, 10))
|
||||
}
|
||||
|
||||
return cancelAllOrdersResponse, l.CancelExistingOrders(ordersToCancel)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package lbank
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -91,7 +91,7 @@ func TestGetMarketDepths(t *testing.T) {
|
||||
func TestGetTrades(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := l.GetTrades(testCurrencyPair, "600",
|
||||
fmt.Sprintf("%v", time.Now().Unix()))
|
||||
strconv.FormatInt(time.Now().Unix(), 10))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -104,7 +104,7 @@ func TestGetTrades(t *testing.T) {
|
||||
func TestGetKlines(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := l.GetKlines(testCurrencyPair, "600", "minute1",
|
||||
fmt.Sprintf("%v", time.Now().Unix()))
|
||||
strconv.FormatInt(time.Now().Unix(), 10))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
@@ -315,6 +315,9 @@ func (l *Lbank) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
|
||||
}
|
||||
resp.IsOrderPlaced = true
|
||||
resp.OrderID = tempResp.OrderID
|
||||
if s.OrderType == order.Market {
|
||||
resp.FullyMatched = true
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -579,7 +579,7 @@ func (l *LocalBitcoins) WalletSend(address string, amount float64, pin int64) er
|
||||
path := localbitcoinsAPIWalletSend
|
||||
|
||||
if pin > 0 {
|
||||
values.Set("pincode", fmt.Sprintf("%v", pin))
|
||||
values.Set("pincode", strconv.FormatInt(pin, 10))
|
||||
path = localbitcoinsAPIWalletSendPin
|
||||
}
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
t.Parallel()
|
||||
var feeBuilder = setFeeBuilder()
|
||||
l.GetFeeByType(feeBuilder)
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
if !areTestAPIKeysSet() {
|
||||
if feeBuilder.FeeType != exchange.OfflineTradeFee {
|
||||
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
|
||||
}
|
||||
@@ -189,7 +189,6 @@ func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
expectedResult := exchange.AutoWithdrawCryptoText +
|
||||
" & " +
|
||||
exchange.WithdrawFiatViaWebsiteOnlyText
|
||||
|
||||
withdrawPermissions := l.FormatWithdrawPermissions()
|
||||
if withdrawPermissions != expectedResult {
|
||||
t.Errorf("Expected: %s, Received: %s",
|
||||
@@ -275,7 +274,6 @@ func TestCancelExchangeOrder(t *testing.T) {
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders && !mockTests {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -300,7 +298,6 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders && !mockTests {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
|
||||
@@ -2,7 +2,9 @@ package okcoin
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
@@ -34,43 +36,25 @@ var testSetupRan bool
|
||||
var spotCurrency = currency.NewPairWithDelimiter(currency.BTC.String(), currency.USD.String(), "-").Lower().String()
|
||||
var websocketEnabled bool
|
||||
|
||||
// TestSetDefaults Sets standard default settings for running a test
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
if o.Name != OKGroupExchange {
|
||||
o.SetDefaults()
|
||||
}
|
||||
if o.Name != OKGroupExchange {
|
||||
t.Errorf("%v - SetDefaults() error", OKGroupExchange)
|
||||
}
|
||||
TestSetup(t)
|
||||
}
|
||||
|
||||
// TestSetRealOrderDefaults Sets test defaults when test can impact real money/orders
|
||||
func TestSetRealOrderDefaults(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
if !areTestAPIKeysSet() || !canManipulateRealOrders {
|
||||
t.Skip("Ensure canManipulateRealOrders is true and your API keys are set")
|
||||
}
|
||||
}
|
||||
|
||||
// TestSetup Sets defaults for test environment
|
||||
func TestSetup(t *testing.T) {
|
||||
if testSetupRan {
|
||||
return
|
||||
}
|
||||
if o.API.Credentials.Key == apiKey && o.API.Credentials.Secret == apiSecret &&
|
||||
o.API.Credentials.ClientID == passphrase && apiKey != "" && apiSecret != "" && passphrase != "" {
|
||||
return
|
||||
}
|
||||
func TestMain(m *testing.M) {
|
||||
o.SetDefaults()
|
||||
o.ExchangeName = OKGroupExchange
|
||||
cfg := config.GetConfig()
|
||||
err := cfg.LoadConfig("../../testdata/configtest.json", true)
|
||||
if err != nil {
|
||||
t.Fatal("Okcoin load config error", err)
|
||||
log.Fatal("Okcoin load config error", err)
|
||||
}
|
||||
okcoinConfig, err := cfg.GetExchangeConfig(OKGroupExchange)
|
||||
if err != nil {
|
||||
t.Fatalf("%v Setup() init error", OKGroupExchange)
|
||||
log.Fatalf("%v Setup() init error", OKGroupExchange)
|
||||
}
|
||||
if okcoinConfig.Features.Enabled.Websocket {
|
||||
websocketEnabled = true
|
||||
@@ -84,11 +68,13 @@ func TestSetup(t *testing.T) {
|
||||
okcoinConfig.API.Endpoints.WebsocketURL = o.API.Endpoints.WebsocketURL
|
||||
err = o.Setup(okcoinConfig)
|
||||
if err != nil {
|
||||
t.Fatal("OKCoin setup error", err)
|
||||
log.Fatal("OKCoin setup error", err)
|
||||
}
|
||||
testSetupRan = true
|
||||
o.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
|
||||
o.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func areTestAPIKeysSet() bool {
|
||||
@@ -106,14 +92,12 @@ func testStandardErrorHandling(t *testing.T, err error) {
|
||||
|
||||
// TestGetAccountCurrencies API endpoint test
|
||||
func TestGetAccountCurrencies(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
_, err := o.GetAccountCurrencies()
|
||||
testStandardErrorHandling(t, err)
|
||||
}
|
||||
|
||||
// TestGetAccountWalletInformation API endpoint test
|
||||
func TestGetAccountWalletInformation(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
resp, err := o.GetAccountWalletInformation("")
|
||||
if areTestAPIKeysSet() {
|
||||
if err != nil {
|
||||
@@ -129,7 +113,6 @@ func TestGetAccountWalletInformation(t *testing.T) {
|
||||
|
||||
// TestGetAccountWalletInformationForCurrency API endpoint test
|
||||
func TestGetAccountWalletInformationForCurrency(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
resp, err := o.GetAccountWalletInformation(currency.BTC.String())
|
||||
if areTestAPIKeysSet() {
|
||||
if err != nil {
|
||||
@@ -173,7 +156,6 @@ func TestAccountWithdrawRequest(t *testing.T) {
|
||||
|
||||
// TestGetAccountWithdrawalFee API endpoint test
|
||||
func TestGetAccountWithdrawalFee(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
resp, err := o.GetAccountWithdrawalFee("")
|
||||
if areTestAPIKeysSet() {
|
||||
if err != nil {
|
||||
@@ -189,7 +171,6 @@ func TestGetAccountWithdrawalFee(t *testing.T) {
|
||||
|
||||
// TestGetWithdrawalFeeForCurrency API endpoint test
|
||||
func TestGetAccountWithdrawalFeeForCurrency(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
resp, err := o.GetAccountWithdrawalFee(currency.BTC.String())
|
||||
if areTestAPIKeysSet() {
|
||||
if err != nil {
|
||||
@@ -205,63 +186,54 @@ func TestGetAccountWithdrawalFeeForCurrency(t *testing.T) {
|
||||
|
||||
// TestGetAccountWithdrawalHistory API endpoint test
|
||||
func TestGetAccountWithdrawalHistory(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
_, err := o.GetAccountWithdrawalHistory("")
|
||||
testStandardErrorHandling(t, err)
|
||||
}
|
||||
|
||||
// TestGetAccountWithdrawalHistoryForCurrency API endpoint test
|
||||
func TestGetAccountWithdrawalHistoryForCurrency(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
_, err := o.GetAccountWithdrawalHistory(currency.BTC.String())
|
||||
testStandardErrorHandling(t, err)
|
||||
}
|
||||
|
||||
// TestGetAccountBillDetails API endpoint test
|
||||
func TestGetAccountBillDetails(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
_, err := o.GetAccountBillDetails(okgroup.GetAccountBillDetailsRequest{})
|
||||
testStandardErrorHandling(t, err)
|
||||
}
|
||||
|
||||
// TestGetAccountDepositAddressForCurrency API endpoint test
|
||||
func TestGetAccountDepositAddressForCurrency(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
_, err := o.GetAccountDepositAddressForCurrency(currency.BTC.String())
|
||||
testStandardErrorHandling(t, err)
|
||||
}
|
||||
|
||||
// TestGetAccountDepositHistory API endpoint test
|
||||
func TestGetAccountDepositHistory(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
_, err := o.GetAccountDepositHistory("")
|
||||
testStandardErrorHandling(t, err)
|
||||
}
|
||||
|
||||
// TestGetAccountDepositHistoryForCurrency API endpoint test
|
||||
func TestGetAccountDepositHistoryForCurrency(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
_, err := o.GetAccountDepositHistory(currency.BTC.String())
|
||||
testStandardErrorHandling(t, err)
|
||||
}
|
||||
|
||||
// TestGetSpotTradingAccounts API endpoint test
|
||||
func TestGetSpotTradingAccounts(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
_, err := o.GetSpotTradingAccounts()
|
||||
testStandardErrorHandling(t, err)
|
||||
}
|
||||
|
||||
// TestGetSpotTradingAccountsForCurrency API endpoint test
|
||||
func TestGetSpotTradingAccountsForCurrency(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
_, err := o.GetSpotTradingAccountForCurrency(currency.BTC.String())
|
||||
testStandardErrorHandling(t, err)
|
||||
}
|
||||
|
||||
// TestGetSpotBillDetailsForCurrency API endpoint test
|
||||
func TestGetSpotBillDetailsForCurrency(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
request := okgroup.GetSpotBillDetailsForCurrencyRequest{
|
||||
Currency: currency.BTC.String(),
|
||||
Limit: 100,
|
||||
@@ -272,7 +244,6 @@ func TestGetSpotBillDetailsForCurrency(t *testing.T) {
|
||||
|
||||
// TestGetSpotBillDetailsForCurrencyBadLimit API logic test
|
||||
func TestGetSpotBillDetailsForCurrencyBadLimit(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
request := okgroup.GetSpotBillDetailsForCurrencyRequest{
|
||||
Currency: currency.BTC.String(),
|
||||
Limit: -1,
|
||||
@@ -316,7 +287,7 @@ func TestPlaceSpotOrderMarket(t *testing.T) {
|
||||
// TestPlaceMultipleSpotOrders API endpoint test
|
||||
func TestPlaceMultipleSpotOrders(t *testing.T) {
|
||||
TestSetRealOrderDefaults(t)
|
||||
order := okgroup.PlaceOrderRequest{
|
||||
ord := okgroup.PlaceOrderRequest{
|
||||
InstrumentID: spotCurrency,
|
||||
Type: order.Limit.Lower(),
|
||||
Side: order.Buy.Lower(),
|
||||
@@ -325,7 +296,7 @@ func TestPlaceMultipleSpotOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
request := []okgroup.PlaceOrderRequest{
|
||||
order,
|
||||
ord,
|
||||
}
|
||||
|
||||
_, errs := o.PlaceMultipleSpotOrders(request)
|
||||
@@ -336,8 +307,7 @@ func TestPlaceMultipleSpotOrders(t *testing.T) {
|
||||
|
||||
// TestPlaceMultipleSpotOrdersOverCurrencyLimits API logic test
|
||||
func TestPlaceMultipleSpotOrdersOverCurrencyLimits(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
order := okgroup.PlaceOrderRequest{
|
||||
ord := okgroup.PlaceOrderRequest{
|
||||
InstrumentID: spotCurrency,
|
||||
Type: order.Limit.Lower(),
|
||||
Side: order.Buy.Lower(),
|
||||
@@ -346,11 +316,11 @@ func TestPlaceMultipleSpotOrdersOverCurrencyLimits(t *testing.T) {
|
||||
}
|
||||
|
||||
request := []okgroup.PlaceOrderRequest{
|
||||
order,
|
||||
order,
|
||||
order,
|
||||
order,
|
||||
order,
|
||||
ord,
|
||||
ord,
|
||||
ord,
|
||||
ord,
|
||||
ord,
|
||||
}
|
||||
|
||||
_, errs := o.PlaceMultipleSpotOrders(request)
|
||||
@@ -361,8 +331,7 @@ func TestPlaceMultipleSpotOrdersOverCurrencyLimits(t *testing.T) {
|
||||
|
||||
// TestPlaceMultipleSpotOrdersOverPairLimits API logic test
|
||||
func TestPlaceMultipleSpotOrdersOverPairLimits(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
order := okgroup.PlaceOrderRequest{
|
||||
ord := okgroup.PlaceOrderRequest{
|
||||
InstrumentID: spotCurrency,
|
||||
Type: order.Limit.Lower(),
|
||||
Side: order.Buy.Lower(),
|
||||
@@ -371,7 +340,7 @@ func TestPlaceMultipleSpotOrdersOverPairLimits(t *testing.T) {
|
||||
}
|
||||
|
||||
request := []okgroup.PlaceOrderRequest{
|
||||
order,
|
||||
ord,
|
||||
}
|
||||
|
||||
pairs := currency.Pairs{
|
||||
@@ -382,8 +351,8 @@ func TestPlaceMultipleSpotOrdersOverPairLimits(t *testing.T) {
|
||||
}
|
||||
|
||||
for x := range pairs {
|
||||
order.InstrumentID = pairs[x].Format("-", false).String()
|
||||
request = append(request, order)
|
||||
ord.InstrumentID = pairs[x].Format("-", false).String()
|
||||
request = append(request, ord)
|
||||
}
|
||||
|
||||
_, errs := o.PlaceMultipleSpotOrders(request)
|
||||
@@ -439,7 +408,6 @@ func TestCancelMultipleSpotOrdersOverCurrencyLimits(t *testing.T) {
|
||||
|
||||
// TestGetSpotOrders API endpoint test
|
||||
func TestGetSpotOrders(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
request := okgroup.GetSpotOrdersRequest{
|
||||
InstrumentID: spotCurrency,
|
||||
Status: "all",
|
||||
@@ -450,7 +418,6 @@ func TestGetSpotOrders(t *testing.T) {
|
||||
|
||||
// TestGetSpotOpenOrders API endpoint test
|
||||
func TestGetSpotOpenOrders(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
request := okgroup.GetSpotOpenOrdersRequest{}
|
||||
_, err := o.GetSpotOpenOrders(request)
|
||||
testStandardErrorHandling(t, err)
|
||||
@@ -458,7 +425,6 @@ func TestGetSpotOpenOrders(t *testing.T) {
|
||||
|
||||
// TestGetSpotOrder API endpoint test
|
||||
func TestGetSpotOrder(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
request := okgroup.GetSpotOrderRequest{
|
||||
OrderID: "-1234",
|
||||
InstrumentID: currency.NewPairWithDelimiter(currency.BTC.String(), currency.USD.String(), "-").Upper().String(),
|
||||
@@ -469,7 +435,6 @@ func TestGetSpotOrder(t *testing.T) {
|
||||
|
||||
// TestGetSpotTransactionDetails API endpoint test
|
||||
func TestGetSpotTransactionDetails(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
request := okgroup.GetSpotTransactionDetailsRequest{
|
||||
OrderID: 1234,
|
||||
InstrumentID: spotCurrency,
|
||||
@@ -480,7 +445,6 @@ func TestGetSpotTransactionDetails(t *testing.T) {
|
||||
|
||||
// TestGetSpotTokenPairDetails API endpoint test
|
||||
func TestGetSpotTokenPairDetails(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
_, err := o.GetSpotTokenPairDetails()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
@@ -489,7 +453,6 @@ func TestGetSpotTokenPairDetails(t *testing.T) {
|
||||
|
||||
// TestGetSpotAllTokenPairsInformation API endpoint test
|
||||
func TestGetSpotAllTokenPairsInformation(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
_, err := o.GetSpotAllTokenPairsInformation()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
@@ -498,7 +461,6 @@ func TestGetSpotAllTokenPairsInformation(t *testing.T) {
|
||||
|
||||
// TestGetSpotAllTokenPairsInformationForCurrency API endpoint test
|
||||
func TestGetSpotAllTokenPairsInformationForCurrency(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
_, err := o.GetSpotAllTokenPairsInformationForCurrency(spotCurrency)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
@@ -507,7 +469,6 @@ func TestGetSpotAllTokenPairsInformationForCurrency(t *testing.T) {
|
||||
|
||||
// TestGetSpotFilledOrdersInformation API endpoint test
|
||||
func TestGetSpotFilledOrdersInformation(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
request := okgroup.GetSpotFilledOrdersInformationRequest{
|
||||
InstrumentID: spotCurrency,
|
||||
}
|
||||
@@ -519,7 +480,6 @@ func TestGetSpotFilledOrdersInformation(t *testing.T) {
|
||||
|
||||
// TestGetSpotMarketData API endpoint test
|
||||
func TestGetSpotMarketData(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
request := okgroup.GetSpotMarketDataRequest{
|
||||
InstrumentID: spotCurrency,
|
||||
Granularity: 604800,
|
||||
@@ -532,21 +492,18 @@ func TestGetSpotMarketData(t *testing.T) {
|
||||
|
||||
// TestGetMarginTradingAccounts API endpoint test
|
||||
func TestGetMarginTradingAccounts(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
_, err := o.GetMarginTradingAccounts()
|
||||
testStandardErrorHandling(t, err)
|
||||
}
|
||||
|
||||
// TestGetMarginTradingAccountsForCurrency API endpoint test
|
||||
func TestGetMarginTradingAccountsForCurrency(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
_, err := o.GetMarginTradingAccountsForCurrency(spotCurrency)
|
||||
testStandardErrorHandling(t, err)
|
||||
}
|
||||
|
||||
// TestGetMarginBillDetails API endpoint test
|
||||
func TestGetMarginBillDetails(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
request := okgroup.GetMarginBillDetailsRequest{
|
||||
InstrumentID: spotCurrency,
|
||||
Limit: 100,
|
||||
@@ -557,14 +514,12 @@ func TestGetMarginBillDetails(t *testing.T) {
|
||||
|
||||
// TestGetMarginAccountSettings API endpoint test
|
||||
func TestGetMarginAccountSettings(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
_, err := o.GetMarginAccountSettings("")
|
||||
testStandardErrorHandling(t, err)
|
||||
}
|
||||
|
||||
// TestGetMarginAccountSettingsForCurrency API endpoint test
|
||||
func TestGetMarginAccountSettingsForCurrency(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
_, err := o.GetMarginAccountSettings(spotCurrency)
|
||||
testStandardErrorHandling(t, err)
|
||||
}
|
||||
@@ -631,7 +586,7 @@ func TestPlaceMarginOrderMarket(t *testing.T) {
|
||||
// TestPlaceMultipleMarginOrders API endpoint test
|
||||
func TestPlaceMultipleMarginOrders(t *testing.T) {
|
||||
TestSetRealOrderDefaults(t)
|
||||
order := okgroup.PlaceOrderRequest{
|
||||
ord := okgroup.PlaceOrderRequest{
|
||||
InstrumentID: spotCurrency,
|
||||
Type: order.Limit.Lower(),
|
||||
Side: order.Buy.Lower(),
|
||||
@@ -641,7 +596,7 @@ func TestPlaceMultipleMarginOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
request := []okgroup.PlaceOrderRequest{
|
||||
order,
|
||||
ord,
|
||||
}
|
||||
|
||||
_, errs := o.PlaceMultipleMarginOrders(request)
|
||||
@@ -652,8 +607,7 @@ func TestPlaceMultipleMarginOrders(t *testing.T) {
|
||||
|
||||
// TestPlaceMultipleMarginOrdersOverCurrencyLimits API logic test
|
||||
func TestPlaceMultipleMarginOrdersOverCurrencyLimits(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
order := okgroup.PlaceOrderRequest{
|
||||
ord := okgroup.PlaceOrderRequest{
|
||||
InstrumentID: spotCurrency,
|
||||
Type: order.Limit.Lower(),
|
||||
Side: order.Buy.Lower(),
|
||||
@@ -663,11 +617,11 @@ func TestPlaceMultipleMarginOrdersOverCurrencyLimits(t *testing.T) {
|
||||
}
|
||||
|
||||
request := []okgroup.PlaceOrderRequest{
|
||||
order,
|
||||
order,
|
||||
order,
|
||||
order,
|
||||
order,
|
||||
ord,
|
||||
ord,
|
||||
ord,
|
||||
ord,
|
||||
ord,
|
||||
}
|
||||
|
||||
_, errs := o.PlaceMultipleMarginOrders(request)
|
||||
@@ -678,8 +632,7 @@ func TestPlaceMultipleMarginOrdersOverCurrencyLimits(t *testing.T) {
|
||||
|
||||
// TestPlaceMultipleMarginOrdersOverPairLimits API logic test
|
||||
func TestPlaceMultipleMarginOrdersOverPairLimits(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
order := okgroup.PlaceOrderRequest{
|
||||
ord := okgroup.PlaceOrderRequest{
|
||||
InstrumentID: spotCurrency,
|
||||
Type: order.Limit.Lower(),
|
||||
Side: order.Buy.Lower(),
|
||||
@@ -689,7 +642,7 @@ func TestPlaceMultipleMarginOrdersOverPairLimits(t *testing.T) {
|
||||
}
|
||||
|
||||
request := []okgroup.PlaceOrderRequest{
|
||||
order,
|
||||
ord,
|
||||
}
|
||||
|
||||
pairs := currency.Pairs{
|
||||
@@ -700,8 +653,8 @@ func TestPlaceMultipleMarginOrdersOverPairLimits(t *testing.T) {
|
||||
}
|
||||
|
||||
for x := range pairs {
|
||||
order.InstrumentID = pairs[x].Format("-", false).String()
|
||||
request = append(request, order)
|
||||
ord.InstrumentID = pairs[x].Format("-", false).String()
|
||||
request = append(request, ord)
|
||||
}
|
||||
|
||||
_, errs := o.PlaceMultipleMarginOrders(request)
|
||||
@@ -752,7 +705,6 @@ func TestCancelMultipleMarginOrdersOverCurrencyLimits(t *testing.T) {
|
||||
|
||||
// TestGetMarginOrders API endpoint test
|
||||
func TestGetMarginOrders(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
request := okgroup.GetSpotOrdersRequest{
|
||||
InstrumentID: spotCurrency,
|
||||
Status: "all",
|
||||
@@ -763,7 +715,6 @@ func TestGetMarginOrders(t *testing.T) {
|
||||
|
||||
// TestGetMarginOpenOrders API endpoint test
|
||||
func TestGetMarginOpenOrders(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
request := okgroup.GetSpotOpenOrdersRequest{}
|
||||
_, err := o.GetMarginOpenOrders(request)
|
||||
testStandardErrorHandling(t, err)
|
||||
@@ -771,7 +722,6 @@ func TestGetMarginOpenOrders(t *testing.T) {
|
||||
|
||||
// TestGetMarginOrder API endpoint test
|
||||
func TestGetMarginOrder(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
request := okgroup.GetSpotOrderRequest{
|
||||
OrderID: "1234",
|
||||
InstrumentID: currency.NewPairWithDelimiter(currency.BTC.String(), currency.USD.String(), "-").Upper().String(),
|
||||
@@ -782,7 +732,6 @@ func TestGetMarginOrder(t *testing.T) {
|
||||
|
||||
// TestGetMarginTransactionDetails API endpoint test
|
||||
func TestGetMarginTransactionDetails(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
request := okgroup.GetSpotTransactionDetailsRequest{
|
||||
OrderID: 1234,
|
||||
InstrumentID: spotCurrency,
|
||||
@@ -797,7 +746,6 @@ func TestGetMarginTransactionDetails(t *testing.T) {
|
||||
// Attempts to subscribe to a channel that doesn't exist
|
||||
// Will log in if credentials are present
|
||||
func TestSendWsMessages(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
if !o.Websocket.IsEnabled() && !o.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
@@ -850,7 +798,6 @@ func TestGetAssetTypeFromTableName(t *testing.T) {
|
||||
|
||||
// TestGetWsChannelWithoutOrderType logic test
|
||||
func TestGetWsChannelWithoutOrderType(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
str := "spot/depth5:BTC-USDT"
|
||||
expected := "depth5"
|
||||
resp := o.GetWsChannelWithoutOrderType(str)
|
||||
@@ -872,7 +819,6 @@ func TestGetWsChannelWithoutOrderType(t *testing.T) {
|
||||
|
||||
// TestOrderBookUpdateChecksumCalculator logic test
|
||||
func TestOrderBookUpdateChecksumCalculator(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
if !websocketEnabled {
|
||||
t.Skip("Websocket not enabled, skipping")
|
||||
}
|
||||
@@ -902,7 +848,6 @@ func TestOrderBookUpdateChecksumCalculator(t *testing.T) {
|
||||
|
||||
// TestOrderBookUpdateChecksumCalculatorWithDash logic test
|
||||
func TestOrderBookUpdateChecksumCalculatorWith8DecimalPlaces(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
if !websocketEnabled {
|
||||
t.Skip("Websocket not enabled, skipping")
|
||||
}
|
||||
@@ -964,7 +909,7 @@ func setFeeBuilder() *exchange.FeeBuilder {
|
||||
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
var feeBuilder = setFeeBuilder()
|
||||
o.GetFeeByType(feeBuilder)
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
if !areTestAPIKeysSet() {
|
||||
if feeBuilder.FeeType != exchange.OfflineTradeFee {
|
||||
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
|
||||
}
|
||||
@@ -976,7 +921,6 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetFee(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
var feeBuilder = setFeeBuilder()
|
||||
// CryptocurrencyTradeFee Basic
|
||||
if resp, err := o.GetFee(feeBuilder); resp != float64(0.0015) || err != nil {
|
||||
@@ -1031,7 +975,6 @@ func TestGetFee(t *testing.T) {
|
||||
|
||||
// TestFormatWithdrawPermissions helper test
|
||||
func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
TestSetDefaults(t)
|
||||
expectedResult := exchange.AutoWithdrawCryptoText + " & " + exchange.NoFiatWithdrawalsText
|
||||
withdrawPermissions := o.FormatWithdrawPermissions()
|
||||
if withdrawPermissions != expectedResult {
|
||||
@@ -1149,3 +1092,25 @@ func TestWithdrawInternationalBank(t *testing.T) {
|
||||
t.Errorf("Expected '%v', received: '%v'", common.ErrFunctionNotSupported, err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetOrderbook logic test
|
||||
func TestGetOrderbook(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := o.GetOrderBook(okgroup.GetOrderBookRequest{InstrumentID: "BTC-USDT"},
|
||||
asset.Spot)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
_, err = o.GetOrderBook(okgroup.GetOrderBookRequest{InstrumentID: "Payload"},
|
||||
asset.Futures)
|
||||
if err == nil {
|
||||
t.Error("error cannot be nil")
|
||||
}
|
||||
|
||||
_, err = o.GetOrderBook(okgroup.GetOrderBookRequest{InstrumentID: "BTC-USD-SWAP"},
|
||||
asset.PerpetualSwap)
|
||||
if err == nil {
|
||||
t.Error("error cannot be nil")
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -233,8 +233,8 @@ func (o *OKGroup) PlaceMultipleSpotOrders(request []PlaceOrderRequest) (map[stri
|
||||
|
||||
var orderErrors []error
|
||||
for currency, orderResponse := range resp {
|
||||
for _, order := range orderResponse {
|
||||
if !order.Result {
|
||||
for i := range orderResponse {
|
||||
if !orderResponse[i].Result {
|
||||
orderErrors = append(orderErrors, fmt.Errorf("order for currency %v failed to be placed", currency))
|
||||
}
|
||||
}
|
||||
@@ -262,15 +262,15 @@ func (o *OKGroup) CancelMultipleSpotOrders(request CancelMultipleSpotOrdersReque
|
||||
}
|
||||
|
||||
for currency, orderResponse := range resp {
|
||||
for _, order := range orderResponse {
|
||||
for i := range orderResponse {
|
||||
cancellationResponse := CancelMultipleSpotOrdersResponse{
|
||||
OrderID: order.OrderID,
|
||||
Result: order.Result,
|
||||
ClientOID: order.ClientOID,
|
||||
OrderID: orderResponse[i].OrderID,
|
||||
Result: orderResponse[i].Result,
|
||||
ClientOID: orderResponse[i].ClientOID,
|
||||
}
|
||||
|
||||
if !order.Result {
|
||||
cancellationResponse.Error = fmt.Errorf("order %v for currency %v failed to be cancelled", order.OrderID, currency)
|
||||
if !orderResponse[i].Result {
|
||||
cancellationResponse.Error = fmt.Errorf("order %v for currency %v failed to be cancelled", orderResponse[i].OrderID, currency)
|
||||
}
|
||||
|
||||
resp[currency] = append(resp[currency], cancellationResponse)
|
||||
@@ -454,8 +454,8 @@ func (o *OKGroup) PlaceMultipleMarginOrders(request []PlaceOrderRequest) (map[st
|
||||
|
||||
var orderErrors []error
|
||||
for currency, orderResponse := range resp {
|
||||
for _, order := range orderResponse {
|
||||
if !order.Result {
|
||||
for i := range orderResponse {
|
||||
if !orderResponse[i].Result {
|
||||
orderErrors = append(orderErrors, fmt.Errorf("order for currency %v failed to be placed", currency))
|
||||
}
|
||||
}
|
||||
@@ -484,9 +484,9 @@ func (o *OKGroup) CancelMultipleMarginOrders(request CancelMultipleSpotOrdersReq
|
||||
|
||||
var orderErrors []error
|
||||
for currency, orderResponse := range resp {
|
||||
for _, order := range orderResponse {
|
||||
if !order.Result {
|
||||
orderErrors = append(orderErrors, fmt.Errorf("order %v for currency %v failed to be cancelled", order.OrderID, currency))
|
||||
for i := range orderResponse {
|
||||
if !orderResponse[i].Result {
|
||||
orderErrors = append(orderErrors, fmt.Errorf("order %v for currency %v failed to be cancelled", orderResponse[i].OrderID, currency))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
package okgroup
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
|
||||
)
|
||||
|
||||
const (
|
||||
apiKey = ""
|
||||
apiSecret = ""
|
||||
|
||||
testAPIURL = "https://www.okex.com/api/"
|
||||
testAPIVersion = "/v3/"
|
||||
)
|
||||
|
||||
var o OKGroup
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
cfg := config.GetConfig()
|
||||
err := cfg.LoadConfig("../../testdata/configtest.json", true)
|
||||
if err != nil {
|
||||
log.Fatal("okgroup load config error", err)
|
||||
}
|
||||
okgroup, err := cfg.GetExchangeConfig("Okex")
|
||||
if err != nil {
|
||||
log.Fatal("okgroup Setup() init error", err)
|
||||
}
|
||||
|
||||
okgroup.API.AuthenticatedSupport = true
|
||||
okgroup.API.Credentials.Key = apiKey
|
||||
okgroup.API.Credentials.Secret = apiSecret
|
||||
o.API.Endpoints.URL = testAPIURL
|
||||
o.APIVersion = testAPIVersion
|
||||
|
||||
o.Requester = request.New("okgroup_test_things",
|
||||
request.NewRateLimit(time.Second, 10),
|
||||
request.NewRateLimit(time.Second, 10),
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
||||
)
|
||||
o.Websocket = wshandler.New()
|
||||
|
||||
err = o.Setup(okgroup)
|
||||
if err != nil {
|
||||
log.Fatal("okgroup setup error", err)
|
||||
}
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestGetOrderbook(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := o.GetOrderBook(GetOrderBookRequest{InstrumentID: "BTC-USDT"},
|
||||
asset.Spot)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// futures expire and break test, will need to mock this in the future
|
||||
_, err = o.GetOrderBook(GetOrderBookRequest{InstrumentID: "Payload"},
|
||||
asset.Futures)
|
||||
if err == nil {
|
||||
t.Error("error cannot be nil")
|
||||
}
|
||||
|
||||
_, err = o.GetOrderBook(GetOrderBookRequest{InstrumentID: "BTC-USD-SWAP"},
|
||||
asset.PerpetualSwap)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -273,6 +273,9 @@ func (o *OKGroup) SubmitOrder(s *order.Submit) (resp order.SubmitResponse, err e
|
||||
|
||||
resp.IsOrderPlaced = orderResponse.Result
|
||||
resp.OrderID = orderResponse.OrderID
|
||||
if s.OrderType == order.Market {
|
||||
resp.FullyMatched = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -398,3 +399,138 @@ func TestSortOrdersByOrderType(t *testing.T) {
|
||||
orders[0].OrderType)
|
||||
}
|
||||
}
|
||||
|
||||
var stringsToOrderSide = []struct {
|
||||
in string
|
||||
out Side
|
||||
err error
|
||||
}{
|
||||
{"buy", Buy, nil},
|
||||
{"BUY", Buy, nil},
|
||||
{"bUy", Buy, nil},
|
||||
{"sell", Sell, nil},
|
||||
{"SELL", Sell, nil},
|
||||
{"sElL", Sell, nil},
|
||||
{"bid", Bid, nil},
|
||||
{"BID", Bid, nil},
|
||||
{"bId", Bid, nil},
|
||||
{"ask", Ask, nil},
|
||||
{"ASK", Ask, nil},
|
||||
{"aSk", Ask, nil},
|
||||
{"any", AnySide, nil},
|
||||
{"ANY", AnySide, nil},
|
||||
{"aNy", AnySide, nil},
|
||||
{"woahMan", Buy, errors.New("woahMan not recognised as side type")},
|
||||
}
|
||||
|
||||
func TestStringToOrderSide(t *testing.T) {
|
||||
for i := 0; i < len(stringsToOrderSide); i++ {
|
||||
testData := &stringsToOrderSide[i]
|
||||
t.Run(testData.in, func(t *testing.T) {
|
||||
out, err := StringToOrderSide(testData.in)
|
||||
if err != nil {
|
||||
if err.Error() != testData.err.Error() {
|
||||
t.Error("Unexpected error", err)
|
||||
}
|
||||
} else if out != testData.out {
|
||||
t.Errorf("Unexpected output %v. Expected %v", out, testData.out)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var stringsToOrderType = []struct {
|
||||
in string
|
||||
out Type
|
||||
err error
|
||||
}{
|
||||
{"limit", Limit, nil},
|
||||
{"LIMIT", Limit, nil},
|
||||
{"lImIt", Limit, nil},
|
||||
{"market", Market, nil},
|
||||
{"MARKET", Market, nil},
|
||||
{"mArKeT", Market, nil},
|
||||
{"immediate_or_cancel", ImmediateOrCancel, nil},
|
||||
{"IMMEDIATE_OR_CANCEL", ImmediateOrCancel, nil},
|
||||
{"iMmEdIaTe_Or_CaNcEl", ImmediateOrCancel, nil},
|
||||
{"stop", Stop, nil},
|
||||
{"STOP", Stop, nil},
|
||||
{"sToP", Stop, nil},
|
||||
{"trailingstop", TrailingStop, nil},
|
||||
{"TRAILINGSTOP", TrailingStop, nil},
|
||||
{"tRaIlInGsToP", TrailingStop, nil},
|
||||
{"any", AnyType, nil},
|
||||
{"ANY", AnyType, nil},
|
||||
{"aNy", AnyType, nil},
|
||||
{"woahMan", Unknown, errors.New("woahMan not recognised as order type")},
|
||||
}
|
||||
|
||||
func TestStringToOrderType(t *testing.T) {
|
||||
for i := 0; i < len(stringsToOrderType); i++ {
|
||||
testData := &stringsToOrderType[i]
|
||||
t.Run(testData.in, func(t *testing.T) {
|
||||
out, err := StringToOrderType(testData.in)
|
||||
if err != nil {
|
||||
if err.Error() != testData.err.Error() {
|
||||
t.Error("Unexpected error", err)
|
||||
}
|
||||
} else if out != testData.out {
|
||||
t.Errorf("Unexpected output %v. Expected %v", out, testData.out)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var stringsToOrderStatus = []struct {
|
||||
in string
|
||||
out Status
|
||||
err error
|
||||
}{
|
||||
{"any", AnyStatus, nil},
|
||||
{"ANY", AnyStatus, nil},
|
||||
{"aNy", AnyStatus, nil},
|
||||
{"new", New, nil},
|
||||
{"NEW", New, nil},
|
||||
{"nEw", New, nil},
|
||||
{"active", Active, nil},
|
||||
{"ACTIVE", Active, nil},
|
||||
{"aCtIvE", Active, nil},
|
||||
{"partially_filled", PartiallyFilled, nil},
|
||||
{"PARTIALLY_FILLED", PartiallyFilled, nil},
|
||||
{"pArTiAlLy_FiLlEd", PartiallyFilled, nil},
|
||||
{"filled", Filled, nil},
|
||||
{"FILLED", Filled, nil},
|
||||
{"fIlLeD", Filled, nil},
|
||||
{"canceled", Cancelled, nil},
|
||||
{"CANCELED", Cancelled, nil},
|
||||
{"cAnCelEd", Cancelled, nil},
|
||||
{"pending_cancel", PendingCancel, nil},
|
||||
{"PENDING_CANCEL", PendingCancel, nil},
|
||||
{"pENdInG_cAnCeL", PendingCancel, nil},
|
||||
{"rejected", Rejected, nil},
|
||||
{"REJECTED", Rejected, nil},
|
||||
{"rEjEcTeD", Rejected, nil},
|
||||
{"expired", Expired, nil},
|
||||
{"EXPIRED", Expired, nil},
|
||||
{"eXpIrEd", Expired, nil},
|
||||
{"hidden", Hidden, nil},
|
||||
{"HIDDEN", Hidden, nil},
|
||||
{"hIdDeN", Hidden, nil},
|
||||
{"woahMan", UnknownStatus, errors.New("woahMan not recognised as order STATUS")},
|
||||
}
|
||||
|
||||
func TestStringToOrderStatus(t *testing.T) {
|
||||
for i := 0; i < len(stringsToOrderStatus); i++ {
|
||||
testData := &stringsToOrderStatus[i]
|
||||
t.Run(testData.in, func(t *testing.T) {
|
||||
out, err := StringToOrderStatus(testData.in)
|
||||
if err != nil {
|
||||
if err.Error() != testData.err.Error() {
|
||||
t.Error("Unexpected error", err)
|
||||
}
|
||||
} else if out != testData.out {
|
||||
t.Errorf("Unexpected output %v. Expected %v", out, testData.out)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ type Submit struct {
|
||||
// SubmitResponse is what is returned after submitting an order to an exchange
|
||||
type SubmitResponse struct {
|
||||
IsOrderPlaced bool
|
||||
FullyMatched bool
|
||||
OrderID string
|
||||
}
|
||||
|
||||
@@ -127,7 +128,7 @@ type Detail struct {
|
||||
// TradeHistory holds exchange history data
|
||||
type TradeHistory struct {
|
||||
Timestamp time.Time
|
||||
TID int64
|
||||
TID string
|
||||
Price float64
|
||||
Amount float64
|
||||
Exchange string
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -10,18 +11,18 @@ import (
|
||||
|
||||
// NewOrder creates a new order and returns a an orderID
|
||||
func NewOrder(exchangeName string, amount, price float64) int {
|
||||
order := &Order{}
|
||||
ord := &Order{}
|
||||
if len(Orders) == 0 {
|
||||
order.OrderID = 0
|
||||
ord.OrderID = 0
|
||||
} else {
|
||||
order.OrderID = len(Orders)
|
||||
ord.OrderID = len(Orders)
|
||||
}
|
||||
|
||||
order.Exchange = exchangeName
|
||||
order.Amount = amount
|
||||
order.Price = price
|
||||
Orders = append(Orders, order)
|
||||
return order.OrderID
|
||||
ord.Exchange = exchangeName
|
||||
ord.Amount = amount
|
||||
ord.Price = price
|
||||
Orders = append(Orders, ord)
|
||||
return ord.OrderID
|
||||
}
|
||||
|
||||
// DeleteOrder deletes orders by ID and returns state
|
||||
@@ -300,3 +301,72 @@ func SortOrdersBySide(orders *[]Detail, reverse bool) {
|
||||
sort.Sort(ByOrderSide(*orders))
|
||||
}
|
||||
}
|
||||
|
||||
// StringToOrderSide for converting case insensitive order side
|
||||
// and returning a real Side
|
||||
func StringToOrderSide(side string) (Side, error) {
|
||||
switch {
|
||||
case strings.EqualFold(side, Buy.String()):
|
||||
return Buy, nil
|
||||
case strings.EqualFold(side, Sell.String()):
|
||||
return Sell, nil
|
||||
case strings.EqualFold(side, Bid.String()):
|
||||
return Bid, nil
|
||||
case strings.EqualFold(side, Ask.String()):
|
||||
return Ask, nil
|
||||
case strings.EqualFold(side, AnySide.String()):
|
||||
return AnySide, nil
|
||||
default:
|
||||
return Side(""), fmt.Errorf("%s not recognised as side type", side)
|
||||
}
|
||||
}
|
||||
|
||||
// StringToOrderType for converting case insensitive order type
|
||||
// and returning a real Type
|
||||
func StringToOrderType(oType string) (Type, error) {
|
||||
switch {
|
||||
case strings.EqualFold(oType, Limit.String()):
|
||||
return Limit, nil
|
||||
case strings.EqualFold(oType, Market.String()):
|
||||
return Market, nil
|
||||
case strings.EqualFold(oType, ImmediateOrCancel.String()):
|
||||
return ImmediateOrCancel, nil
|
||||
case strings.EqualFold(oType, Stop.String()):
|
||||
return Stop, nil
|
||||
case strings.EqualFold(oType, TrailingStop.String()):
|
||||
return TrailingStop, nil
|
||||
case strings.EqualFold(oType, AnyType.String()):
|
||||
return AnyType, nil
|
||||
default:
|
||||
return Unknown, fmt.Errorf("%s not recognised as order type", oType)
|
||||
}
|
||||
}
|
||||
|
||||
// StringToOrderStatus for converting case insensitive order status
|
||||
// and returning a real Status
|
||||
func StringToOrderStatus(status string) (Status, error) {
|
||||
switch {
|
||||
case strings.EqualFold(status, AnyStatus.String()):
|
||||
return AnyStatus, nil
|
||||
case strings.EqualFold(status, New.String()):
|
||||
return New, nil
|
||||
case strings.EqualFold(status, Active.String()):
|
||||
return Active, nil
|
||||
case strings.EqualFold(status, PartiallyFilled.String()):
|
||||
return PartiallyFilled, nil
|
||||
case strings.EqualFold(status, Filled.String()):
|
||||
return Filled, nil
|
||||
case strings.EqualFold(status, Cancelled.String()):
|
||||
return Cancelled, nil
|
||||
case strings.EqualFold(status, PendingCancel.String()):
|
||||
return PendingCancel, nil
|
||||
case strings.EqualFold(status, Rejected.String()):
|
||||
return Rejected, nil
|
||||
case strings.EqualFold(status, Expired.String()):
|
||||
return Expired, nil
|
||||
case strings.EqualFold(status, Hidden.String()):
|
||||
return Hidden, nil
|
||||
default:
|
||||
return UnknownStatus, fmt.Errorf("%s not recognised as order STATUS", status)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,9 +158,9 @@ func TestVerify(t *testing.T) {
|
||||
|
||||
func TestCalculateTotalBids(t *testing.T) {
|
||||
t.Parallel()
|
||||
currency := currency.NewPairFromStrings("BTC", "USD")
|
||||
curr := currency.NewPairFromStrings("BTC", "USD")
|
||||
base := Base{
|
||||
Pair: currency,
|
||||
Pair: curr,
|
||||
Bids: []Item{{Price: 100, Amount: 10}},
|
||||
LastUpdated: time.Now(),
|
||||
}
|
||||
@@ -173,9 +173,9 @@ func TestCalculateTotalBids(t *testing.T) {
|
||||
|
||||
func TestCalculateTotaAsks(t *testing.T) {
|
||||
t.Parallel()
|
||||
currency := currency.NewPairFromStrings("BTC", "USD")
|
||||
curr := currency.NewPairFromStrings("BTC", "USD")
|
||||
base := Base{
|
||||
Pair: currency,
|
||||
Pair: curr,
|
||||
Asks: []Item{{Price: 100, Amount: 10}},
|
||||
}
|
||||
|
||||
@@ -187,10 +187,10 @@ func TestCalculateTotaAsks(t *testing.T) {
|
||||
|
||||
func TestUpdate(t *testing.T) {
|
||||
t.Parallel()
|
||||
currency := currency.NewPairFromStrings("BTC", "USD")
|
||||
curr := currency.NewPairFromStrings("BTC", "USD")
|
||||
timeNow := time.Now()
|
||||
base := Base{
|
||||
Pair: currency,
|
||||
Pair: curr,
|
||||
Asks: []Item{{Price: 100, Amount: 10}},
|
||||
Bids: []Item{{Price: 200, Amount: 10}},
|
||||
LastUpdated: timeNow,
|
||||
|
||||
@@ -103,7 +103,7 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
|
||||
var feeBuilder = setFeeBuilder()
|
||||
p.GetFeeByType(feeBuilder)
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
if !areTestAPIKeysSet() {
|
||||
if feeBuilder.FeeType != exchange.OfflineTradeFee {
|
||||
t.Errorf("Expected %v, received %v",
|
||||
exchange.OfflineTradeFee,
|
||||
@@ -202,9 +202,7 @@ func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
expectedResult := exchange.AutoWithdrawCryptoWithAPIPermissionText +
|
||||
" & " +
|
||||
exchange.NoFiatWithdrawalsText
|
||||
|
||||
withdrawPermissions := p.FormatWithdrawPermissions()
|
||||
|
||||
if withdrawPermissions != expectedResult {
|
||||
t.Errorf("Expected: %s, Received: %s",
|
||||
expectedResult,
|
||||
@@ -284,7 +282,6 @@ func TestCancelExchangeOrder(t *testing.T) {
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders && !mockTests {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -310,7 +307,6 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
|
||||
@@ -469,12 +469,12 @@ func (p *Poloniex) WsProcessOrderbookUpdate(sequenceNumber int64, target []inter
|
||||
func (p *Poloniex) GenerateDefaultSubscriptions() {
|
||||
var subscriptions []wshandler.WebsocketChannelSubscription
|
||||
subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
|
||||
Channel: fmt.Sprintf("%v", wsTickerDataID),
|
||||
Channel: strconv.FormatInt(wsTickerDataID, 10),
|
||||
})
|
||||
|
||||
if p.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
|
||||
subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
|
||||
Channel: fmt.Sprintf("%v", wsAccountNotificationID),
|
||||
Channel: strconv.FormatInt(wsAccountNotificationID, 10),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -495,9 +495,9 @@ func (p *Poloniex) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscr
|
||||
Command: "subscribe",
|
||||
}
|
||||
switch {
|
||||
case strings.EqualFold(fmt.Sprintf("%v", wsAccountNotificationID), channelToSubscribe.Channel):
|
||||
case strings.EqualFold(strconv.FormatInt(wsAccountNotificationID, 10), channelToSubscribe.Channel):
|
||||
return p.wsSendAuthorisedCommand("subscribe")
|
||||
case strings.EqualFold(fmt.Sprintf("%v", wsTickerDataID), channelToSubscribe.Channel):
|
||||
case strings.EqualFold(strconv.FormatInt(wsTickerDataID, 10), channelToSubscribe.Channel):
|
||||
subscriptionRequest.Channel = wsTickerDataID
|
||||
default:
|
||||
subscriptionRequest.Channel = channelToSubscribe.Currency.String()
|
||||
@@ -511,9 +511,9 @@ func (p *Poloniex) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubs
|
||||
Command: "unsubscribe",
|
||||
}
|
||||
switch {
|
||||
case strings.EqualFold(fmt.Sprintf("%v", wsAccountNotificationID), channelToSubscribe.Channel):
|
||||
case strings.EqualFold(strconv.FormatInt(wsAccountNotificationID, 10), channelToSubscribe.Channel):
|
||||
return p.wsSendAuthorisedCommand("unsubscribe")
|
||||
case strings.EqualFold(fmt.Sprintf("%v", wsTickerDataID), channelToSubscribe.Channel):
|
||||
case strings.EqualFold(strconv.FormatInt(wsTickerDataID, 10), channelToSubscribe.Channel):
|
||||
unsubscriptionRequest.Channel = wsTickerDataID
|
||||
default:
|
||||
unsubscriptionRequest.Channel = channelToSubscribe.Currency.String()
|
||||
|
||||
@@ -238,13 +238,14 @@ func (p *Poloniex) UpdateTicker(currencyPair currency.Pair, assetType asset.Item
|
||||
return tickerPrice, err
|
||||
}
|
||||
|
||||
for _, x := range p.GetEnabledPairs(assetType) {
|
||||
enabledPairs := p.GetEnabledPairs(assetType)
|
||||
for i := range enabledPairs {
|
||||
var tp ticker.Price
|
||||
curr := p.FormatExchangeCurrency(x, assetType).String()
|
||||
curr := p.FormatExchangeCurrency(enabledPairs[i], assetType).String()
|
||||
if _, ok := tick[curr]; !ok {
|
||||
continue
|
||||
}
|
||||
tp.Pair = x
|
||||
tp.Pair = enabledPairs[i]
|
||||
tp.Ask = tick[curr].LowestAsk
|
||||
tp.Bid = tick[curr].HighestBid
|
||||
tp.High = tick[curr].High24Hr
|
||||
@@ -287,9 +288,9 @@ func (p *Poloniex) UpdateOrderbook(currencyPair currency.Pair, assetType asset.I
|
||||
return orderBook, err
|
||||
}
|
||||
|
||||
for _, x := range p.GetEnabledPairs(assetType) {
|
||||
currency := p.FormatExchangeCurrency(x, assetType).String()
|
||||
data, ok := orderbookNew.Data[currency]
|
||||
enabledPairs := p.GetEnabledPairs(assetType)
|
||||
for i := range enabledPairs {
|
||||
data, ok := orderbookNew.Data[p.FormatExchangeCurrency(enabledPairs[i], assetType).String()]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
@@ -307,7 +308,7 @@ func (p *Poloniex) UpdateOrderbook(currencyPair currency.Pair, assetType asset.I
|
||||
Amount: data.Asks[y].Amount, Price: data.Asks[y].Price})
|
||||
}
|
||||
orderBook.Asks = obItems
|
||||
orderBook.Pair = x
|
||||
orderBook.Pair = enabledPairs[i]
|
||||
orderBook.ExchangeName = p.Name
|
||||
orderBook.AssetType = assetType
|
||||
|
||||
@@ -370,13 +371,18 @@ func (p *Poloniex) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
|
||||
false,
|
||||
fillOrKill,
|
||||
isBuyOrder)
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
if response.OrderNumber > 0 {
|
||||
submitOrderResponse.OrderID = strconv.FormatInt(response.OrderNumber, 10)
|
||||
}
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
if s.OrderType == order.Market {
|
||||
submitOrderResponse.FullyMatched = true
|
||||
}
|
||||
return submitOrderResponse, err
|
||||
return submitOrderResponse, nil
|
||||
}
|
||||
|
||||
// ModifyOrder will allow of changing orderbook placement and limit to
|
||||
|
||||
@@ -327,6 +327,17 @@ func (w *Websocket) IsConnectionMonitorRunning() bool {
|
||||
return w.connectionMonitorRunning
|
||||
}
|
||||
|
||||
// CanUseAuthenticatedWebsocketForWrapper Handles a common check to
|
||||
// verify whether a wrapper can use an authenticated websocket endpoint
|
||||
func (w *Websocket) CanUseAuthenticatedWebsocketForWrapper() bool {
|
||||
if w.IsConnected() && w.CanUseAuthenticatedEndpoints() {
|
||||
return true
|
||||
} else if w.IsConnected() && !w.CanUseAuthenticatedEndpoints() {
|
||||
log.Infof(log.WebsocketMgr, WebsocketNotAuthenticatedUsingRest, w.exchangeName)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// SetWebsocketURL sets websocket URL
|
||||
func (w *Websocket) SetWebsocketURL(websocketURL string) {
|
||||
if websocketURL == "" || websocketURL == config.WebsocketURLNonDefaultMessage {
|
||||
@@ -629,7 +640,6 @@ func (w *WebsocketConnection) Dial(dialer *websocket.Dialer, headers http.Header
|
||||
}
|
||||
dialer.Proxy = http.ProxyURL(proxy)
|
||||
}
|
||||
|
||||
var err error
|
||||
var conStatus *http.Response
|
||||
w.Connection, conStatus, err = dialer.Dial(w.URL, headers)
|
||||
@@ -640,7 +650,7 @@ func (w *WebsocketConnection) Dial(dialer *websocket.Dialer, headers http.Header
|
||||
return fmt.Errorf("%v Error: %v", w.URL, err)
|
||||
}
|
||||
if w.Verbose {
|
||||
log.Infof(log.WebsocketMgr, "%v Websocket connected", w.ExchangeName)
|
||||
log.Infof(log.WebsocketMgr, "%v Websocket connected to %s", w.ExchangeName, w.URL)
|
||||
}
|
||||
w.setConnectedStatus(true)
|
||||
return nil
|
||||
@@ -703,6 +713,12 @@ func (w *WebsocketConnection) WaitForResult(id int64, wg *sync.WaitGroup) {
|
||||
for k := range w.IDResponses {
|
||||
if k == id {
|
||||
w.Unlock()
|
||||
if !timer.Stop() {
|
||||
select {
|
||||
case <-timer.C:
|
||||
default:
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -678,3 +678,22 @@ func readMessages(wc *WebsocketConnection, t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestCanUseAuthenticatedWebsocketForWrapper logic test
|
||||
func TestCanUseAuthenticatedWebsocketForWrapper(t *testing.T) {
|
||||
ws := &Websocket{}
|
||||
resp := ws.CanUseAuthenticatedWebsocketForWrapper()
|
||||
if resp {
|
||||
t.Error("Expected false, `connected` is false")
|
||||
}
|
||||
ws.setConnectedStatus(true)
|
||||
resp = ws.CanUseAuthenticatedWebsocketForWrapper()
|
||||
if resp {
|
||||
t.Error("Expected false, `connected` is true and `CanUseAuthenticatedEndpoints` is false")
|
||||
}
|
||||
ws.canUseAuthenticatedEndpoints = true
|
||||
resp = ws.CanUseAuthenticatedWebsocketForWrapper()
|
||||
if !resp {
|
||||
t.Error("Expected true, `connected` and `CanUseAuthenticatedEndpoints` is true")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,8 @@ const (
|
||||
WebsocketNotEnabled = "exchange_websocket_not_enabled"
|
||||
manageSubscriptionsDelay = 5 * time.Second
|
||||
// connection monitor time delays and limits
|
||||
connectionMonitorDelay = 2 * time.Second
|
||||
connectionMonitorDelay = 2 * time.Second
|
||||
WebsocketNotAuthenticatedUsingRest = "%v - Websocket not authenticated, using REST"
|
||||
)
|
||||
|
||||
// Websocket defines a return type for websocket connections via the interface
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package yobit
|
||||
|
||||
import (
|
||||
"log"
|
||||
"math"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -22,19 +24,16 @@ const (
|
||||
canManipulateRealOrders = false
|
||||
)
|
||||
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
func TestMain(m *testing.M) {
|
||||
y.SetDefaults()
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
yobitConfig := config.GetConfig()
|
||||
err := yobitConfig.LoadConfig("../../testdata/configtest.json", true)
|
||||
if err != nil {
|
||||
t.Fatal("Yobit load config error", err)
|
||||
log.Fatal("Yobit load config error", err)
|
||||
}
|
||||
conf, err := yobitConfig.GetExchangeConfig("Yobit")
|
||||
if err != nil {
|
||||
t.Fatal("Yobit init error", err)
|
||||
log.Fatal("Yobit init error", err)
|
||||
}
|
||||
conf.API.Credentials.Key = apiKey
|
||||
conf.API.Credentials.Secret = apiSecret
|
||||
@@ -42,8 +41,9 @@ func TestSetup(t *testing.T) {
|
||||
|
||||
err = y.Setup(conf)
|
||||
if err != nil {
|
||||
t.Fatal("Yobit setup error", err)
|
||||
log.Fatal("Yobit setup error", err)
|
||||
}
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestFetchTradablePairs(t *testing.T) {
|
||||
@@ -167,7 +167,7 @@ func setFeeBuilder() *exchange.FeeBuilder {
|
||||
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
var feeBuilder = setFeeBuilder()
|
||||
y.GetFeeByType(feeBuilder)
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
if !areTestAPIKeysSet() {
|
||||
if feeBuilder.FeeType != exchange.OfflineTradeFee {
|
||||
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
|
||||
}
|
||||
@@ -179,8 +179,6 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetFee(t *testing.T) {
|
||||
y.SetDefaults()
|
||||
TestSetup(t)
|
||||
var feeBuilder = setFeeBuilder()
|
||||
|
||||
// CryptocurrencyTradeFee Basic
|
||||
@@ -317,20 +315,14 @@ func TestGetFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
y.SetDefaults()
|
||||
expectedResult := exchange.AutoWithdrawCryptoWithAPIPermissionText + " & " + exchange.WithdrawFiatViaWebsiteOnlyText
|
||||
|
||||
withdrawPermissions := y.FormatWithdrawPermissions()
|
||||
|
||||
if withdrawPermissions != expectedResult {
|
||||
t.Errorf("Expected: %s, Received: %s", expectedResult, withdrawPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
y.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
Currencies: []currency.Pair{currency.NewPair(currency.LTC,
|
||||
@@ -346,9 +338,6 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
y.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
Currencies: []currency.Pair{currency.NewPair(currency.LTC,
|
||||
@@ -372,9 +361,6 @@ func areTestAPIKeysSet() bool {
|
||||
}
|
||||
|
||||
func TestSubmitOrder(t *testing.T) {
|
||||
y.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -400,15 +386,11 @@ func TestSubmitOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelExchangeOrder(t *testing.T) {
|
||||
y.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -426,15 +408,11 @@ func TestCancelExchangeOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
y.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -457,6 +435,9 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestModifyOrder(t *testing.T) {
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
_, err := y.ModifyOrder(&order.Modify{})
|
||||
if err == nil {
|
||||
t.Error("ModifyOrder() Expected error")
|
||||
@@ -464,8 +445,6 @@ func TestModifyOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdraw(t *testing.T) {
|
||||
y.SetDefaults()
|
||||
TestSetup(t)
|
||||
withdrawCryptoRequest := exchange.CryptoWithdrawRequest{
|
||||
GenericWithdrawRequestInfo: exchange.GenericWithdrawRequestInfo{
|
||||
Amount: -1,
|
||||
@@ -489,9 +468,6 @@ func TestWithdraw(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawFiat(t *testing.T) {
|
||||
y.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -506,9 +482,6 @@ func TestWithdrawFiat(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawInternationalBank(t *testing.T) {
|
||||
y.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -523,7 +496,7 @@ func TestWithdrawInternationalBank(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetDepositAddress(t *testing.T) {
|
||||
if apiKey != "" || apiSecret != "" {
|
||||
if areTestAPIKeysSet() {
|
||||
_, err := y.GetDepositAddress(currency.BTC, "")
|
||||
if err != nil {
|
||||
t.Error("GetDepositAddress() Expected error")
|
||||
|
||||
@@ -187,20 +187,22 @@ func (y *Yobit) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Pric
|
||||
return tickerPrice, err
|
||||
}
|
||||
|
||||
for _, x := range y.GetEnabledPairs(assetType) {
|
||||
curr := y.FormatExchangeCurrency(x, assetType).Lower().String()
|
||||
enabledPairs := y.GetEnabledPairs(assetType)
|
||||
for i := range enabledPairs {
|
||||
curr := y.FormatExchangeCurrency(enabledPairs[i], assetType).Lower().String()
|
||||
if _, ok := result[curr]; !ok {
|
||||
continue
|
||||
}
|
||||
resultCurr := result[curr]
|
||||
var tickerPrice ticker.Price
|
||||
tickerPrice.Pair = x
|
||||
tickerPrice.Last = result[curr].Last
|
||||
tickerPrice.Ask = result[curr].Sell
|
||||
tickerPrice.Bid = result[curr].Buy
|
||||
tickerPrice.Last = result[curr].Last
|
||||
tickerPrice.Low = result[curr].Low
|
||||
tickerPrice.QuoteVolume = result[curr].VolumeCurrent
|
||||
tickerPrice.Volume = result[curr].Vol
|
||||
tickerPrice.Pair = enabledPairs[i]
|
||||
tickerPrice.Last = resultCurr.Last
|
||||
tickerPrice.Ask = resultCurr.Sell
|
||||
tickerPrice.Bid = resultCurr.Buy
|
||||
tickerPrice.Last = resultCurr.Last
|
||||
tickerPrice.Low = resultCurr.Low
|
||||
tickerPrice.QuoteVolume = resultCurr.VolumeCurrent
|
||||
tickerPrice.Volume = resultCurr.Vol
|
||||
|
||||
err = ticker.ProcessTicker(y.Name, &tickerPrice, assetType)
|
||||
if err != nil {
|
||||
@@ -323,13 +325,15 @@ func (y *Yobit) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
|
||||
s.OrderSide.String(),
|
||||
s.Amount,
|
||||
s.Price)
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
if response > 0 {
|
||||
submitOrderResponse.OrderID = strconv.FormatInt(response, 10)
|
||||
}
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
}
|
||||
return submitOrderResponse, err
|
||||
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
return submitOrderResponse, nil
|
||||
}
|
||||
|
||||
// ModifyOrder will allow of changing orderbook placement and limit to
|
||||
|
||||
@@ -423,10 +423,10 @@ func (z *ZB) Withdraw(currency, address, safepassword string, amount, fees float
|
||||
|
||||
vals := url.Values{}
|
||||
vals.Set("accesskey", z.API.Credentials.Key)
|
||||
vals.Set("amount", fmt.Sprintf("%v", amount))
|
||||
vals.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64))
|
||||
vals.Set("currency", currency)
|
||||
vals.Set("fees", fmt.Sprintf("%v", fees))
|
||||
vals.Set("itransfer", fmt.Sprintf("%v", itransfer))
|
||||
vals.Set("fees", strconv.FormatFloat(fees, 'f', -1, 64))
|
||||
vals.Set("itransfer", strconv.FormatBool(itransfer))
|
||||
vals.Set("method", "withdraw")
|
||||
vals.Set("recieveAddr", address)
|
||||
vals.Set("safePwd", safepassword)
|
||||
|
||||
@@ -3,7 +3,10 @@ package zb
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
@@ -25,19 +28,16 @@ const (
|
||||
var z ZB
|
||||
var wsSetupRan bool
|
||||
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
func TestMain(m *testing.M) {
|
||||
z.SetDefaults()
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
cfg := config.GetConfig()
|
||||
err := cfg.LoadConfig("../../testdata/configtest.json", true)
|
||||
if err != nil {
|
||||
t.Fatal("ZB load config error", err)
|
||||
log.Fatal("ZB load config error", err)
|
||||
}
|
||||
zbConfig, err := cfg.GetExchangeConfig("ZB")
|
||||
if err != nil {
|
||||
t.Fatal("ZB Setup() init error", err)
|
||||
log.Fatal("ZB Setup() init error", err)
|
||||
}
|
||||
zbConfig.API.AuthenticatedSupport = true
|
||||
zbConfig.API.AuthenticatedWebsocketSupport = true
|
||||
@@ -46,16 +46,16 @@ func TestSetup(t *testing.T) {
|
||||
|
||||
err = z.Setup(zbConfig)
|
||||
if err != nil {
|
||||
t.Fatal("ZB setup error", err)
|
||||
log.Fatal("ZB setup error", err)
|
||||
}
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func setupWsAuth(t *testing.T) {
|
||||
if wsSetupRan {
|
||||
return
|
||||
}
|
||||
z.SetDefaults()
|
||||
TestSetup(t)
|
||||
if !z.Websocket.IsEnabled() && !z.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() || !canManipulateRealOrders {
|
||||
t.Skip(wshandler.WebsocketNotEnabled)
|
||||
}
|
||||
@@ -90,11 +90,9 @@ func TestSpotNewOrder(t *testing.T) {
|
||||
Amount: 0.01,
|
||||
Price: 10246.1,
|
||||
}
|
||||
orderid, err := z.SpotNewOrder(arg)
|
||||
_, err := z.SpotNewOrder(arg)
|
||||
if err != nil {
|
||||
t.Errorf("ZB SpotNewOrder: %s", err)
|
||||
} else {
|
||||
t.Log(orderid)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,7 +180,7 @@ func setFeeBuilder() *exchange.FeeBuilder {
|
||||
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
var feeBuilder = setFeeBuilder()
|
||||
z.GetFeeByType(feeBuilder)
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
if !areTestAPIKeysSet() {
|
||||
if feeBuilder.FeeType != exchange.OfflineTradeFee {
|
||||
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
|
||||
}
|
||||
@@ -194,8 +192,6 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetFee(t *testing.T) {
|
||||
z.SetDefaults()
|
||||
TestSetup(t)
|
||||
var feeBuilder = setFeeBuilder()
|
||||
|
||||
// CryptocurrencyTradeFee Basic
|
||||
@@ -272,20 +268,14 @@ func TestGetFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
z.SetDefaults()
|
||||
expectedResult := exchange.AutoWithdrawCryptoText + " & " + exchange.NoFiatWithdrawalsText
|
||||
|
||||
withdrawPermissions := z.FormatWithdrawPermissions()
|
||||
|
||||
if withdrawPermissions != expectedResult {
|
||||
t.Errorf("Expected: %s, Received: %s", expectedResult, withdrawPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
z.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
Currencies: []currency.Pair{currency.NewPair(currency.XRP,
|
||||
@@ -301,9 +291,6 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
z.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
OrderType: order.AnyType,
|
||||
OrderSide: order.Buy,
|
||||
@@ -326,9 +313,6 @@ func areTestAPIKeysSet() bool {
|
||||
}
|
||||
|
||||
func TestSubmitOrder(t *testing.T) {
|
||||
z.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip(fmt.Sprintf("ApiKey: %s. Can place orders: %v",
|
||||
z.API.Credentials.Key,
|
||||
@@ -356,15 +340,11 @@ func TestSubmitOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelExchangeOrder(t *testing.T) {
|
||||
z.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.XRP, currency.USDT)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -382,15 +362,11 @@ func TestCancelExchangeOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
z.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := currency.NewPair(currency.XRP, currency.USDT)
|
||||
|
||||
var orderCancellation = &order.Cancel{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
@@ -427,6 +403,9 @@ func TestGetAccountInfo(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestModifyOrder(t *testing.T) {
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
_, err := z.ModifyOrder(&order.Modify{})
|
||||
if err == nil {
|
||||
t.Error("ModifyOrder() Expected error")
|
||||
@@ -434,8 +413,6 @@ func TestModifyOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdraw(t *testing.T) {
|
||||
z.SetDefaults()
|
||||
TestSetup(t)
|
||||
withdrawCryptoRequest := exchange.CryptoWithdrawRequest{
|
||||
GenericWithdrawRequestInfo: exchange.GenericWithdrawRequestInfo{
|
||||
Amount: -1,
|
||||
@@ -460,9 +437,6 @@ func TestWithdraw(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawFiat(t *testing.T) {
|
||||
z.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -475,9 +449,6 @@ func TestWithdrawFiat(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawInternationalBank(t *testing.T) {
|
||||
z.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -490,7 +461,7 @@ func TestWithdrawInternationalBank(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetDepositAddress(t *testing.T) {
|
||||
if apiKey != "" || apiSecret != "" {
|
||||
if areTestAPIKeysSet() {
|
||||
_, err := z.GetDepositAddress(currency.BTC, "")
|
||||
if err != nil {
|
||||
t.Error("GetDepositAddress() error PLEASE MAKE SURE YOU CREATE DEPOSIT ADDRESSES VIA ZB.COM",
|
||||
@@ -548,7 +519,7 @@ func TestWsCreateSuUserKey(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
userID := subUsers.Message[0].UserID
|
||||
_, err = z.wsCreateSubUserKey(true, true, true, true, "subu", fmt.Sprintf("%v", userID))
|
||||
_, err = z.wsCreateSubUserKey(true, true, true, true, "subu", strconv.FormatInt(userID, 10))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ type OrderbookResponse struct {
|
||||
|
||||
// AccountsResponseCoin holds the accounts coin details
|
||||
type AccountsResponseCoin struct {
|
||||
Freez string `json:"freez"` // 冻结资产
|
||||
Freeze string `json:"freez"` // 冻结资产
|
||||
EnName string `json:"enName"` // 币种英文名
|
||||
UnitDecimal int `json:"unitDecimal"` // 保留小数位
|
||||
UnName string `json:"cnName"` // 币种中文名
|
||||
@@ -44,6 +44,9 @@ type Order struct {
|
||||
TradeDate int `json:"trade_date"`
|
||||
TradeMoney float64 `json:"trade_money"`
|
||||
Type int64 `json:"type"`
|
||||
Fees float64 `json:"fees,omitempty"`
|
||||
TradePrice float64 `json:"trade_price,omitempty"`
|
||||
No int64 `json:"no,string,omitempty"`
|
||||
}
|
||||
|
||||
// AccountsResponse 用户基本信息
|
||||
|
||||
@@ -187,40 +187,6 @@ func (z *ZB) WsHandleData() {
|
||||
}
|
||||
}
|
||||
|
||||
var wsErrCodes = map[int64]string{
|
||||
1000: "Successful call",
|
||||
1001: "General error message",
|
||||
1002: "internal error",
|
||||
1003: "Verification failed",
|
||||
1004: "Financial security password lock",
|
||||
1005: "The fund security password is incorrect. Please confirm and re-enter.",
|
||||
1006: "Real-name certification is awaiting review or review",
|
||||
1007: "Channel is empty",
|
||||
1008: "Event is empty",
|
||||
1009: "This interface is being maintained",
|
||||
1011: "Not open yet",
|
||||
1012: "Insufficient permissions",
|
||||
1013: "Can not trade, if you have any questions, please contact online customer service",
|
||||
1014: "Cannot be sold during the pre-sale period",
|
||||
2002: "Insufficient balance in Bitcoin account",
|
||||
2003: "Insufficient balance of Litecoin account",
|
||||
2005: "Insufficient balance in Ethereum account",
|
||||
2006: "Insufficient balance in ETC currency account",
|
||||
2007: "Insufficient balance of BTS currency account",
|
||||
2008: "Insufficient balance in EOS currency account",
|
||||
2009: "Insufficient account balance",
|
||||
3001: "Pending order not found",
|
||||
3002: "Invalid amount",
|
||||
3003: "Invalid quantity",
|
||||
3004: "User does not exist",
|
||||
3005: "Invalid parameter",
|
||||
3006: "Invalid IP or inconsistent with the bound IP",
|
||||
3007: "Request time has expired",
|
||||
3008: "Transaction history not found",
|
||||
4001: "API interface is locked",
|
||||
4002: "Request too frequently",
|
||||
}
|
||||
|
||||
// GenerateDefaultSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions()
|
||||
func (z *ZB) GenerateDefaultSubscriptions() {
|
||||
var subscriptions []wshandler.WebsocketChannelSubscription
|
||||
|
||||
@@ -191,28 +191,12 @@ type WsGetOrderRequest struct {
|
||||
|
||||
// WsGetOrderResponse contains order data
|
||||
type WsGetOrderResponse struct {
|
||||
Message string `json:"message"`
|
||||
No int64 `json:"no,string"`
|
||||
Code int64 `json:"code"`
|
||||
Channel string `json:"channel"`
|
||||
Success bool `json:"success"`
|
||||
Data WsGetOrderResponseData `json:"data"`
|
||||
}
|
||||
|
||||
// WsGetOrderResponseData Detailed order data
|
||||
type WsGetOrderResponseData struct {
|
||||
Currency string `json:"currency"`
|
||||
Fees float64 `json:"fees"`
|
||||
ID string `json:"id"`
|
||||
Price float64 `json:"price"`
|
||||
Status int64 `json:"status"`
|
||||
TotalAmount float64 `json:"total_amount"`
|
||||
TradeAmount float64 `json:"trade_amount"`
|
||||
TradePrice float64 `json:"trade_price"`
|
||||
TradeDate int64 `json:"trade_date"`
|
||||
TradeMoney float64 `json:"trade_money"`
|
||||
Type int64 `json:"type"`
|
||||
No int64 `json:"no,string"`
|
||||
Message string `json:"message"`
|
||||
No int64 `json:"no,string"`
|
||||
Code int64 `json:"code"`
|
||||
Channel string `json:"channel"`
|
||||
Success bool `json:"success"`
|
||||
Data []Order `json:"data"`
|
||||
}
|
||||
|
||||
// WsGetOrdersRequest get more orders, with no orderID filtering
|
||||
@@ -228,12 +212,12 @@ type WsGetOrdersRequest struct {
|
||||
|
||||
// WsGetOrdersResponse contains orders data
|
||||
type WsGetOrdersResponse struct {
|
||||
Message string `json:"message"`
|
||||
No int64 `json:"no,string"`
|
||||
Code int64 `json:"code"`
|
||||
Channel string `json:"channel"`
|
||||
Success bool `json:"success"`
|
||||
Data []WsGetOrderResponseData `json:"data"`
|
||||
Message string `json:"message"`
|
||||
No int64 `json:"no,string"`
|
||||
Code int64 `json:"code"`
|
||||
Channel string `json:"channel"`
|
||||
Success bool `json:"success"`
|
||||
Data []Order `json:"data"`
|
||||
}
|
||||
|
||||
// WsGetOrdersIgnoreTradeTypeRequest ws request
|
||||
@@ -249,12 +233,12 @@ type WsGetOrdersIgnoreTradeTypeRequest struct {
|
||||
|
||||
// WsGetOrdersIgnoreTradeTypeResponse contains orders data
|
||||
type WsGetOrdersIgnoreTradeTypeResponse struct {
|
||||
Message string `json:"message"`
|
||||
No int64 `json:"no,string"`
|
||||
Code int64 `json:"code"`
|
||||
Channel string `json:"channel"`
|
||||
Success bool `json:"success"`
|
||||
Data []WsGetOrderResponseData `json:"data"`
|
||||
Message string `json:"message"`
|
||||
No int64 `json:"no,string"`
|
||||
Code int64 `json:"code"`
|
||||
Channel string `json:"channel"`
|
||||
Success bool `json:"success"`
|
||||
Data []Order `json:"data"`
|
||||
}
|
||||
|
||||
// WsGetAccountInfoResponse contains account data
|
||||
@@ -262,23 +246,44 @@ type WsGetAccountInfoResponse struct {
|
||||
Message string `json:"message"`
|
||||
No int64 `json:"no,string"`
|
||||
Data struct {
|
||||
Coins []struct {
|
||||
Freez float64 `json:"freez,string"`
|
||||
EnName string `json:"enName"`
|
||||
UnitDecimal int64 `json:"unitDecimal"`
|
||||
CnName string `json:"cnName"`
|
||||
UnitTag string `json:"unitTag"`
|
||||
Available float64 `json:"available,string"`
|
||||
Key string `json:"key"`
|
||||
} `json:"coins"`
|
||||
Base struct {
|
||||
Username string `json:"username"`
|
||||
TradePasswordEnabled bool `json:"trade_password_enabled"`
|
||||
AuthGoogleEnabled bool `json:"auth_google_enabled"`
|
||||
AuthMobileEnabled bool `json:"auth_mobile_enabled"`
|
||||
} `json:"base"`
|
||||
Coins []AccountsResponseCoin `json:"coins"`
|
||||
Base AccountsBaseResponse `json:"base"`
|
||||
} `json:"data"`
|
||||
Code int64 `json:"code"`
|
||||
Channel string `json:"channel"`
|
||||
Success bool `json:"success"`
|
||||
}
|
||||
|
||||
var wsErrCodes = map[int64]string{
|
||||
1000: "Successful call",
|
||||
1001: "General error message",
|
||||
1002: "internal error",
|
||||
1003: "Verification failed",
|
||||
1004: "Financial security password lock",
|
||||
1005: "The fund security password is incorrect. Please confirm and re-enter.",
|
||||
1006: "Real-name certification is awaiting review or review",
|
||||
1007: "Channel is empty",
|
||||
1008: "Event is empty",
|
||||
1009: "This interface is being maintained",
|
||||
1011: "Not open yet",
|
||||
1012: "Insufficient permissions",
|
||||
1013: "Can not trade, if you have any questions, please contact online customer service",
|
||||
1014: "Cannot be sold during the pre-sale period",
|
||||
2002: "Insufficient balance in Bitcoin account",
|
||||
2003: "Insufficient balance of Litecoin account",
|
||||
2005: "Insufficient balance in Ethereum account",
|
||||
2006: "Insufficient balance in ETC currency account",
|
||||
2007: "Insufficient balance of BTS currency account",
|
||||
2008: "Insufficient balance in EOS currency account",
|
||||
2009: "Insufficient account balance",
|
||||
3001: "Pending order not found",
|
||||
3002: "Invalid amount",
|
||||
3003: "Invalid quantity",
|
||||
3004: "User does not exist",
|
||||
3005: "Invalid parameter",
|
||||
3006: "Invalid IP or inconsistent with the bound IP",
|
||||
3007: "Request time has expired",
|
||||
3008: "Transaction history not found",
|
||||
4001: "API interface is locked",
|
||||
4002: "Request too frequently",
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package zb
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -268,8 +269,9 @@ func (z *ZB) FetchOrderbook(p currency.Pair, assetType asset.Item) (orderbook.Ba
|
||||
// UpdateOrderbook updates and returns the orderbook for a currency pair
|
||||
func (z *ZB) UpdateOrderbook(p currency.Pair, assetType asset.Item) (orderbook.Base, error) {
|
||||
var orderBook orderbook.Base
|
||||
orderbookNew, err := z.GetOrderbook(z.FormatExchangeCurrency(p,
|
||||
assetType).String())
|
||||
curr := z.FormatExchangeCurrency(p, assetType).String()
|
||||
|
||||
orderbookNew, err := z.GetOrderbook(curr)
|
||||
if err != nil {
|
||||
return orderBook, err
|
||||
}
|
||||
@@ -304,25 +306,35 @@ func (z *ZB) UpdateOrderbook(p currency.Pair, assetType asset.Item) (orderbook.B
|
||||
// ZB exchange
|
||||
func (z *ZB) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var info exchange.AccountInfo
|
||||
bal, err := z.GetAccountInformation()
|
||||
if err != nil {
|
||||
return info, err
|
||||
var balances []exchange.AccountCurrencyInfo
|
||||
var coins []AccountsResponseCoin
|
||||
if z.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
resp, err := z.wsGetAccountInfoRequest()
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
coins = resp.Data.Coins
|
||||
} else {
|
||||
bal, err := z.GetAccountInformation()
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
coins = bal.Result.Coins
|
||||
}
|
||||
|
||||
var balances []exchange.AccountCurrencyInfo
|
||||
for _, data := range bal.Result.Coins {
|
||||
hold, err := strconv.ParseFloat(data.Freez, 64)
|
||||
for i := range coins {
|
||||
hold, err := strconv.ParseFloat(coins[i].Freeze, 64)
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
avail, err := strconv.ParseFloat(data.Available, 64)
|
||||
avail, err := strconv.ParseFloat(coins[i].Available, 64)
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
balances = append(balances, exchange.AccountCurrencyInfo{
|
||||
CurrencyName: currency.NewCode(data.EnName),
|
||||
CurrencyName: currency.NewCode(coins[i].EnName),
|
||||
TotalValue: hold + avail,
|
||||
Hold: hold,
|
||||
})
|
||||
@@ -348,33 +360,53 @@ func (z *ZB) GetExchangeHistory(p currency.Pair, assetType asset.Item) ([]exchan
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (z *ZB) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
|
||||
func (z *ZB) SubmitOrder(o *order.Submit) (order.SubmitResponse, error) {
|
||||
var submitOrderResponse order.SubmitResponse
|
||||
if err := s.Validate(); err != nil {
|
||||
err := o.Validate()
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
var oT SpotNewOrderRequestParamsType
|
||||
if s.OrderSide == order.Buy {
|
||||
oT = SpotNewOrderRequestParamsTypeBuy
|
||||
if z.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
var isBuyOrder int64
|
||||
if o.OrderSide == order.Buy {
|
||||
isBuyOrder = 1
|
||||
} else {
|
||||
isBuyOrder = 0
|
||||
}
|
||||
var response *WsSubmitOrderResponse
|
||||
response, err = z.wsSubmitOrder(o.Pair, o.Amount, o.Price, isBuyOrder)
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
submitOrderResponse.OrderID = strconv.FormatInt(response.Data.EntrustID, 10)
|
||||
} else {
|
||||
oT = SpotNewOrderRequestParamsTypeSell
|
||||
}
|
||||
var oT SpotNewOrderRequestParamsType
|
||||
if o.OrderSide == order.Buy {
|
||||
oT = SpotNewOrderRequestParamsTypeBuy
|
||||
} else {
|
||||
oT = SpotNewOrderRequestParamsTypeSell
|
||||
}
|
||||
|
||||
var params = SpotNewOrderRequestParams{
|
||||
Amount: s.Amount,
|
||||
Price: s.Price,
|
||||
Symbol: s.Pair.Lower().String(),
|
||||
Type: oT,
|
||||
var params = SpotNewOrderRequestParams{
|
||||
Amount: o.Amount,
|
||||
Price: o.Price,
|
||||
Symbol: o.Pair.Lower().String(),
|
||||
Type: oT,
|
||||
}
|
||||
var response int64
|
||||
response, err = z.SpotNewOrder(params)
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
if response > 0 {
|
||||
submitOrderResponse.OrderID = strconv.FormatInt(response, 10)
|
||||
}
|
||||
}
|
||||
response, err := z.SpotNewOrder(params)
|
||||
if response > 0 {
|
||||
submitOrderResponse.OrderID = strconv.FormatInt(response, 10)
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
if o.OrderType == order.Market {
|
||||
submitOrderResponse.FullyMatched = true
|
||||
}
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
}
|
||||
return submitOrderResponse, err
|
||||
return submitOrderResponse, nil
|
||||
}
|
||||
|
||||
// ModifyOrder will allow of changing orderbook placement and limit to
|
||||
@@ -389,8 +421,20 @@ func (z *ZB) CancelOrder(o *order.Cancel) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
curr := z.FormatExchangeCurrency(o.CurrencyPair, o.AssetType).String()
|
||||
return z.CancelExistingOrder(orderIDInt, curr)
|
||||
|
||||
if z.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
var response *WsCancelOrderResponse
|
||||
response, err = z.wsCancelOrder(o.CurrencyPair, orderIDInt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !response.Success {
|
||||
return fmt.Errorf("%v - Could not cancel order %v", z.Name, o.OrderID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return z.CancelExistingOrder(orderIDInt, z.FormatExchangeCurrency(o.CurrencyPair,
|
||||
o.AssetType).String())
|
||||
}
|
||||
|
||||
// CancelAllOrders cancels all orders associated with a currency pair
|
||||
@@ -424,11 +468,12 @@ func (z *ZB) CancelAllOrders(_ *order.Cancel) (order.CancelAllResponse, error) {
|
||||
}
|
||||
|
||||
for i := range allOpenOrders {
|
||||
err := z.CancelExistingOrder(allOpenOrders[i].ID,
|
||||
allOpenOrders[i].Currency)
|
||||
err := z.CancelOrder(&order.Cancel{
|
||||
OrderID: strconv.FormatInt(allOpenOrders[i].ID, 10),
|
||||
CurrencyPair: currency.NewPairFromString(allOpenOrders[i].Currency),
|
||||
})
|
||||
if err != nil {
|
||||
ID := strconv.FormatInt(allOpenOrders[i].ID, 10)
|
||||
cancelAllOrdersResponse.Status[ID] = err.Error()
|
||||
cancelAllOrdersResponse.Status[strconv.FormatInt(allOpenOrders[i].ID, 10)] = err.Error()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -539,35 +584,45 @@ func (z *ZB) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error
|
||||
if req.OrderSide == order.AnySide || req.OrderSide == "" {
|
||||
return nil, errors.New("specific order side is required")
|
||||
}
|
||||
|
||||
var allOrders []Order
|
||||
|
||||
var orders []order.Detail
|
||||
var side int64
|
||||
if req.OrderSide == order.Buy {
|
||||
side = 1
|
||||
}
|
||||
|
||||
for x := range req.Currencies {
|
||||
for y := int64(1); ; y++ {
|
||||
fPair := z.FormatExchangeCurrency(req.Currencies[x], asset.Spot).String()
|
||||
resp, err := z.GetOrders(fPair, y, side)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if z.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
for x := range req.Currencies {
|
||||
for y := int64(1); ; y++ {
|
||||
resp, err := z.wsGetOrdersIgnoreTradeType(req.Currencies[x], y, 10)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
allOrders = append(allOrders, resp.Data...)
|
||||
if len(resp.Data) != 10 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if len(resp) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
allOrders = append(allOrders, resp...)
|
||||
|
||||
if len(resp) != 10 {
|
||||
break
|
||||
}
|
||||
} else {
|
||||
if req.OrderSide == order.Buy {
|
||||
side = 1
|
||||
}
|
||||
for x := range req.Currencies {
|
||||
for y := int64(1); ; y++ {
|
||||
fPair := z.FormatExchangeCurrency(req.Currencies[x], asset.Spot).String()
|
||||
resp, err := z.GetOrders(fPair, y, side)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(resp) == 0 {
|
||||
break
|
||||
}
|
||||
allOrders = append(allOrders, resp...)
|
||||
if len(resp) != 10 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var orders []order.Detail
|
||||
for i := range allOrders {
|
||||
symbol := currency.NewPairDelimiter(allOrders[i].Currency,
|
||||
z.GetPairFormat(asset.Spot, false).Delimiter)
|
||||
|
||||
Reference in New Issue
Block a user