Files
gocryptotrader/exchanges/kucoin/kucoin_test.go
Ryan O'Hara-Reid 6ccb0e0c2f gateio/kucoin: assortment of fixes (#1404)
* gateio: fix unmarshal bug and update fields

* gateio: fix wrapper function function, add helper methods

* update order types and add kucoin wrapper fix

* currency pairs

* Add tests

* gateio; inspect error and continue for no funds in account, kucoin: fetch all settlement amounts

* futures: order fixit

* finish off gateio updates for market orders

* cute line

* Update exchanges/kucoin/kucoin_wrapper.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* Update exchanges/kucoin/kucoin_wrapper.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* Update exchanges/gateio/gateio.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* Update exchanges/gateio/gateio_wrapper.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* Update exchanges/gateio/gateio_wrapper.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* glorious: nits

* glorious: nits - filter by pair match and fix bug where the endpoint returns details instead of message

* Add fix for leverage check (non-merge) my ip has been blocked from gateio still... scammmmmmmm

* glorious: nitters

* Update exchanges/gateio/gateio_test.go

Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io>

* Update exchanges/gateio/gateio_test.go

Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io>

* Update exchanges/gateio/gateio_test.go

Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io>

---------

Co-authored-by: Ryan O'Hara-Reid <ryan.oharareid@thrasher.io>
Co-authored-by: Scott <gloriousCode@users.noreply.github.com>
Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io>
2024-03-06 13:06:13 +11:00

2777 lines
98 KiB
Go

package kucoin
import (
"context"
"encoding/json"
"errors"
"log"
"os"
"strings"
"testing"
"time"
"github.com/gofrs/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/thrasher-corp/gocryptotrader/common"
"github.com/thrasher-corp/gocryptotrader/common/key"
"github.com/thrasher-corp/gocryptotrader/config"
"github.com/thrasher-corp/gocryptotrader/core"
"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/fundingrate"
"github.com/thrasher-corp/gocryptotrader/exchanges/futures"
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
"github.com/thrasher-corp/gocryptotrader/exchanges/margin"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
"github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer"
"github.com/thrasher-corp/gocryptotrader/exchanges/subscription"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
testexch "github.com/thrasher-corp/gocryptotrader/internal/testing/exchange"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
// Please supply your own keys here to do authenticated endpoint testing
const (
apiKey = ""
apiSecret = ""
passPhrase = ""
canManipulateRealOrders = false
)
var (
ku = &Kucoin{}
spotTradablePair, marginTradablePair, futuresTradablePair currency.Pair
)
func TestMain(m *testing.M) {
ku.SetDefaults()
cfg := config.GetConfig()
err := cfg.LoadConfig("../../testdata/configtest.json", true)
if err != nil {
log.Fatal(err)
}
exchCfg, err := cfg.GetExchangeConfig("Kucoin")
if err != nil {
log.Fatal(err)
}
exchCfg.API.AuthenticatedSupport = true
exchCfg.API.AuthenticatedWebsocketSupport = true
exchCfg.API.Credentials.Key = apiKey
exchCfg.API.Credentials.Secret = apiSecret
exchCfg.API.Credentials.ClientID = passPhrase
if apiKey != "" && apiSecret != "" && passPhrase != "" {
ku.Websocket.SetCanUseAuthenticatedEndpoints(true)
}
ku.SetDefaults()
ku.Websocket = sharedtestvalues.NewTestWebsocket()
ku.Websocket.Orderbook = buffer.Orderbook{}
err = ku.Setup(exchCfg)
if err != nil {
log.Fatal(err)
}
ku.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
ku.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
setupWS()
getFirstTradablePairOfAssets()
os.Exit(m.Run())
}
// Spot asset test cases starts from here
func TestGetSymbols(t *testing.T) {
t.Parallel()
symbols, err := ku.GetSymbols(context.Background(), "")
if err != nil {
t.Error("GetSymbols() error", err)
}
assert.NotEmpty(t, symbols, "should return all available spot/margin symbols")
// Using market string reduces the scope of what is returned.
symbols, err = ku.GetSymbols(context.Background(), "ETF")
if err != nil {
t.Error("GetSymbols() error", err)
}
assert.NotEmpty(t, symbols, "should return all available ETF symbols")
}
func TestGetTicker(t *testing.T) {
t.Parallel()
_, err := ku.GetTicker(context.Background(), "BTC-USDT")
if err != nil {
t.Error("GetTicker() error", err)
}
}
func TestGetAllTickers(t *testing.T) {
t.Parallel()
_, err := ku.GetTickers(context.Background())
if err != nil {
t.Error("GetAllTickers() error", err)
}
}
func TestGetFuturesTickers(t *testing.T) {
t.Parallel()
tickers, err := ku.GetFuturesTickers(context.Background())
assert.NoError(t, err, "GetFuturesTickers should not error")
for i := range tickers {
assert.Positive(t, tickers[i].Last, "Last should be positive")
assert.Positive(t, tickers[i].Bid, "Bid should be positive")
assert.Positive(t, tickers[i].Ask, "Ask should be positive")
assert.NotEmpty(t, tickers[i].Pair, "Pair should not be empty")
assert.NotEmpty(t, tickers[i].LastUpdated, "LastUpdated should not be empty")
assert.Equal(t, ku.Name, tickers[i].ExchangeName, "Exchange name should be correct")
assert.Equal(t, asset.Futures, tickers[i].AssetType, "Asset type should be correct")
}
}
func TestGet24hrStats(t *testing.T) {
t.Parallel()
_, err := ku.Get24hrStats(context.Background(), "BTC-USDT")
if err != nil {
t.Error("Get24hrStats() error", err)
}
}
func TestGetMarketList(t *testing.T) {
t.Parallel()
_, err := ku.GetMarketList(context.Background())
if err != nil {
t.Error("GetMarketList() error", err)
}
}
func TestGetPartOrderbook20(t *testing.T) {
t.Parallel()
_, err := ku.GetPartOrderbook20(context.Background(), "BTC-USDT")
if err != nil {
t.Error("GetPartOrderbook20() error", err)
}
}
func TestGetPartOrderbook100(t *testing.T) {
t.Parallel()
_, err := ku.GetPartOrderbook100(context.Background(), "BTC-USDT")
if err != nil {
t.Error("GetPartOrderbook100() error", err)
}
}
func TestGetOrderbook(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetOrderbook(context.Background(), "BTC-USDT")
if err != nil {
t.Error("GetOrderbook() error", err)
}
}
func TestGetTradeHistory(t *testing.T) {
t.Parallel()
_, err := ku.GetTradeHistory(context.Background(), "BTC-USDT")
if err != nil {
t.Error("GetTradeHistory() error", err)
}
}
func TestGetKlines(t *testing.T) {
t.Parallel()
_, err := ku.GetKlines(context.Background(), "BTC-USDT", "1week", time.Time{}, time.Time{})
if err != nil {
t.Error("GetKlines() error", err)
}
_, err = ku.GetKlines(context.Background(), "BTC-USDT", "5min", time.Now().Add(-time.Hour*1), time.Now())
if err != nil {
t.Error("GetKlines() error", err)
}
}
func TestGetCurrencies(t *testing.T) {
t.Parallel()
_, err := ku.GetCurrencies(context.Background())
if err != nil {
t.Error("GetCurrencies() error", err)
}
}
func TestGetCurrency(t *testing.T) {
t.Parallel()
_, err := ku.GetCurrencyDetail(context.Background(), "BTC", "")
if err != nil {
t.Error("GetCurrency() error", err)
}
_, err = ku.GetCurrencyDetail(context.Background(), "BTC", "ETH")
if err != nil {
t.Error("GetCurrency() error", err)
}
}
func TestGetFiatPrice(t *testing.T) {
t.Parallel()
_, err := ku.GetFiatPrice(context.Background(), "", "")
if err != nil {
t.Error("GetFiatPrice() error", err)
}
_, err = ku.GetFiatPrice(context.Background(), "EUR", "ETH,BTC")
if err != nil {
t.Error("GetFiatPrice() error", err)
}
}
func TestGetMarkPrice(t *testing.T) {
t.Parallel()
_, err := ku.GetMarkPrice(context.Background(), "USDT-BTC")
if err != nil {
t.Error("GetMarkPrice() error", err)
}
}
func TestGetMarginConfiguration(t *testing.T) {
t.Parallel()
_, err := ku.GetMarginConfiguration(context.Background())
if err != nil {
t.Error("GetMarginConfiguration() error", err)
}
}
func TestGetMarginAccount(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetMarginAccount(context.Background())
if err != nil {
t.Error("GetMarginAccount() error", err)
}
}
func TestGetMarginRiskLimit(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetMarginRiskLimit(context.Background(), "cross")
if err != nil {
t.Error("GetMarginRiskLimit() error", err)
}
_, err = ku.GetMarginRiskLimit(context.Background(), "isolated")
if err != nil {
t.Error("GetMarginRiskLimit() error", err)
}
}
func TestPostBorrowOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
_, err := ku.PostBorrowOrder(context.Background(), "USDT", "FOK", "", 10, 0)
if err != nil {
t.Error("PostBorrowOrder() error", err)
}
_, err = ku.PostBorrowOrder(context.Background(), "USDT", "IOC", "7,14,28", 10, 0.05)
if err != nil {
t.Error("PostBorrowOrder() error", err)
}
}
const borrowOrderJSON = `{"orderId": "a2111213","currency": "USDT","size": "1.009","filled": 1.009,"matchList": [{"currency": "USDT","dailyIntRate": "0.001","size": "12.9","term": 7,"timestamp": "1544657947759","tradeId": "1212331"}],"status": "DONE"}`
func TestGetBorrowOrder(t *testing.T) {
t.Parallel()
var resp *BorrowOrder
err := json.Unmarshal([]byte(borrowOrderJSON), &resp)
if err != nil {
t.Fatal(err)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err = ku.GetBorrowOrder(context.Background(), "orderID")
if err != nil {
t.Error("GetBorrowOrder() error", err)
}
}
const outstandingRecordResponseJSON = `{"currentPage": 0, "pageSize": 0, "totalNum": 0, "totalPage": 0, "items": [ { "tradeId": "1231141", "currency": "USDT", "accruedInterest": "0.22121", "dailyIntRate": "0.0021", "liability": "1.32121", "maturityTime": "1544657947759", "principal": "1.22121", "repaidSize": "0", "term": 7, "createdAt": "1544657947759" } ] }`
func TestGetOutstandingRecord(t *testing.T) {
t.Parallel()
var resp *OutstandingRecordResponse
err := json.Unmarshal([]byte(outstandingRecordResponseJSON), &resp)
if err != nil {
t.Error(err)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err = ku.GetOutstandingRecord(context.Background(), "BTC")
if err != nil {
t.Error("GetOutstandingRecord() error", err)
}
}
const repaidRecordJSON = `{"pageSize": 0, "totalNum": 0, "totalPage": 0, "currentPage": 0, "items": [ { "tradeId": "1231141", "currency": "USDT", "dailyIntRate": "0.0021", "interest": "0.22121", "principal": "1.22121", "repaidSize": "0", "repayTime": "1544657947759", "term": 7 } ] }`
func TestGetRepaidRecord(t *testing.T) {
t.Parallel()
var resp *RepaidRecordsResponse
err := json.Unmarshal([]byte(repaidRecordJSON), &resp)
if err != nil {
t.Error(err)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err = ku.GetRepaidRecord(context.Background(), "BTC")
if err != nil {
t.Error("GetRepaidRecord() error", err)
}
}
func TestOneClickRepayment(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
err := ku.OneClickRepayment(context.Background(), "BTC", "RECENTLY_EXPIRE_FIRST", 2.5)
if err != nil {
t.Error("OneClickRepayment() error", err)
}
}
func TestSingleOrderRepayment(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
err := ku.SingleOrderRepayment(context.Background(), "BTC", "fa3e34c980062c10dad74016", 2.5)
if err != nil {
t.Error("SingleOrderRepayment() error", err)
}
}
func TestPostLendOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
_, err := ku.PostLendOrder(context.Background(), "BTC", 0.0001, 5, 7)
if err != nil {
t.Error("PostLendOrder() error", err)
}
}
func TestCancelLendOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
err := ku.CancelLendOrder(context.Background(), "OrderID")
if err != nil {
t.Error("CancelLendOrder() error", err)
}
}
func TestSetAutoLend(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
err := ku.SetAutoLend(context.Background(), "BTC", 0.0002, 0.005, 7, true)
if err != nil {
t.Error("SetAutoLend() error", err)
}
}
const activeOrderResponseJSON = `[ { "orderId": "5da59f5ef943c033b2b643e4", "currency": "BTC", "size": "0.51", "filledSize": "0", "dailyIntRate": "0.0001", "term": 7, "createdAt": 1571135326913 } ]`
func TestGetActiveOrder(t *testing.T) {
t.Parallel()
var resp []LendOrder
err := json.Unmarshal([]byte(activeOrderResponseJSON), &resp)
if err != nil {
t.Fatal(err)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err = ku.GetActiveOrder(context.Background(), "")
if err != nil {
t.Error("GetActiveOrder() error", err)
}
_, err = ku.GetActiveOrder(context.Background(), "BTC")
if err != nil {
t.Error("GetActiveOrder() error", err)
}
}
func TestGetLendHistory(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetLendHistory(context.Background(), "")
if err != nil {
t.Error("GetLendHistory() error", err)
}
_, err = ku.GetLendHistory(context.Background(), "BTC")
if err != nil {
t.Error("GetLendHistory() error", err)
}
}
const activeLentOrderResponseJSON = `[ { "tradeId": "5da6dba0f943c0c81f5d5db5", "currency": "BTC", "size": "0.51", "accruedInterest": "0", "repaid": "0.10999968", "dailyIntRate": "0.0001", "term": 14, "maturityTime": 1572425888958 } ]`
func TestGetUnsettleLendOrder(t *testing.T) {
t.Parallel()
var resp []UnsettleLendOrder
err := json.Unmarshal([]byte(activeLentOrderResponseJSON), &resp)
if err != nil {
t.Fatal(err)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err = ku.GetUnsettledLendOrder(context.Background(), "")
if err != nil {
t.Error("GetUnsettledLendOrder() error", err)
}
_, err = ku.GetUnsettledLendOrder(context.Background(), "BTC")
if err != nil {
t.Error("GetUnsettledLendOrder() error", err)
}
}
const settledLendOrderResponseJSON = `[{ "tradeId": "5da59fe6f943c033b2b6440b", "currency": "BTC", "size": "0.51", "interest": "0.00004899", "repaid": "0.510041641", "dailyIntRate": "0.0001", "term": 7, "settledAt": 1571216254767, "note": "The account of the borrowers reached a negative balance, and the system has supplemented the loss via the insurance fund. Deposit funds: 0.51." } ]`
func TestGetSettleLendOrder(t *testing.T) {
t.Parallel()
var resp []SettleLendOrder
err := json.Unmarshal([]byte(settledLendOrderResponseJSON), &resp)
if err != nil {
t.Fatal(err)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err = ku.GetSettledLendOrder(context.Background(), "")
if err != nil {
t.Error("GetSettledLendOrder() error", err)
}
_, err = ku.GetSettledLendOrder(context.Background(), "BTC")
if err != nil {
t.Error("GetSettledLendOrder() error", err)
}
}
func TestGetAccountLendRecord(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetAccountLendRecord(context.Background(), "")
if err != nil {
t.Error("GetAccountLendRecord() error", err)
}
_, err = ku.GetAccountLendRecord(context.Background(), "BTC")
if err != nil {
t.Error("GetAccountLendRecord() error", err)
}
}
func TestGetLendingMarketData(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetLendingMarketData(context.Background(), "BTC", 0)
if err != nil {
t.Error("GetLendingMarketData() error", err)
}
_, err = ku.GetLendingMarketData(context.Background(), "BTC", 7)
if err != nil {
t.Error("GetLendingMarketData() error", err)
}
}
func TestGetMarginTradeData(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetMarginTradeData(context.Background(), "BTC")
if err != nil {
t.Error("GetMarginTradeData() error", err)
}
}
func TestGetIsolatedMarginPairConfig(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetIsolatedMarginPairConfig(context.Background())
if err != nil {
t.Error("GetIsolatedMarginPairConfig() error", err)
}
}
func TestGetIsolatedMarginAccountInfo(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetIsolatedMarginAccountInfo(context.Background(), "")
if err != nil {
t.Error("GetIsolatedMarginAccountInfo() error", err)
}
_, err = ku.GetIsolatedMarginAccountInfo(context.Background(), "USDT")
if err != nil {
t.Error("GetIsolatedMarginAccountInfo() error", err)
}
}
func TestGetSingleIsolatedMarginAccountInfo(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetSingleIsolatedMarginAccountInfo(context.Background(), "BTC-USDT")
if err != nil {
t.Error("GetSingleIsolatedMarginAccountInfo() error", err)
}
}
func TestInitiateIsolateMarginBorrowing(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
_, err := ku.InitiateIsolatedMarginBorrowing(context.Background(), "BTC-USDT", "USDT", "FOK", "", 10, 0)
if err != nil {
t.Error("InitiateIsolateMarginBorrowing() error", err)
}
}
func TestGetIsolatedOutstandingRepaymentRecords(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetIsolatedOutstandingRepaymentRecords(context.Background(), "", "", 0, 0)
if err != nil {
t.Error("GetIsolatedOutstandingRepaymentRecords() error", err)
}
_, err = ku.GetIsolatedOutstandingRepaymentRecords(context.Background(), "BTC-USDT", "USDT", 0, 0)
if err != nil {
t.Error("GetIsolatedOutstandingRepaymentRecords() error", err)
}
}
func TestGetIsolatedMarginRepaymentRecords(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetIsolatedMarginRepaymentRecords(context.Background(), "", "", 0, 0)
if err != nil {
t.Error("GetIsolatedMarginRepaymentRecords() error", err)
}
_, err = ku.GetIsolatedMarginRepaymentRecords(context.Background(), "BTC-USDT", "USDT", 0, 0)
if err != nil {
t.Error("GetIsolatedMarginRepaymentRecords() error", err)
}
}
func TestInitiateIsolatedMarginQuickRepayment(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
err := ku.InitiateIsolatedMarginQuickRepayment(context.Background(), "BTC-USDT", "USDT", "RECENTLY_EXPIRE_FIRST", 10)
if err != nil {
t.Error("InitiateIsolatedMarginQuickRepayment() error", err)
}
}
func TestInitiateIsolatedMarginSingleRepayment(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
err := ku.InitiateIsolatedMarginSingleRepayment(context.Background(), "BTC-USDT", "USDT", "628c570f7818320001d52b69", 10)
if err != nil {
t.Error("InitiateIsolatedMarginSingleRepayment() error", err)
}
}
func TestGetCurrentServerTime(t *testing.T) {
t.Parallel()
_, err := ku.GetCurrentServerTime(context.Background())
if err != nil {
t.Error("GetCurrentServerTime() error", err)
}
}
func TestGetServiceStatus(t *testing.T) {
t.Parallel()
_, err := ku.GetServiceStatus(context.Background())
if err != nil {
t.Error("GetServiceStatus() error", err)
}
}
func TestPostOrder(t *testing.T) {
t.Parallel()
// default order type is limit
_, err := ku.PostOrder(context.Background(), &SpotOrderParam{
ClientOrderID: ""})
if !errors.Is(err, errInvalidClientOrderID) {
t.Errorf("PostOrder() expected %v, but found %v", errInvalidClientOrderID, err)
}
customID, err := uuid.NewV4()
if err != nil {
t.Fatal(err)
}
_, err = ku.PostOrder(context.Background(), &SpotOrderParam{
ClientOrderID: customID.String(), Symbol: spotTradablePair,
OrderType: ""})
if !errors.Is(err, order.ErrSideIsInvalid) {
t.Errorf("PostOrder() expected %v, but found %v", order.ErrSideIsInvalid, err)
}
_, err = ku.PostOrder(context.Background(), &SpotOrderParam{
ClientOrderID: customID.String(), Symbol: currency.EMPTYPAIR,
Size: 0.1, Side: "buy", Price: 234565})
if !errors.Is(err, currency.ErrCurrencyPairEmpty) {
t.Errorf("PostOrder() expected %v, but found %v", currency.ErrCurrencyPairEmpty, err)
}
_, err = ku.PostOrder(context.Background(), &SpotOrderParam{
ClientOrderID: customID.String(), Side: "buy",
Symbol: spotTradablePair,
OrderType: "limit", Size: 0.1})
if !errors.Is(err, errInvalidPrice) {
t.Errorf("PostOrder() expected %v, but found %v", errInvalidPrice, err)
}
_, err = ku.PostOrder(context.Background(), &SpotOrderParam{
ClientOrderID: customID.String(), Symbol: spotTradablePair, Side: "buy",
OrderType: "limit", Price: 234565})
if !errors.Is(err, errInvalidSize) {
t.Errorf("PostOrder() expected %v, but found %v", errInvalidSize, err)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
_, err = ku.PostOrder(context.Background(), &SpotOrderParam{
ClientOrderID: customID.String(),
Side: "buy",
Symbol: spotTradablePair,
OrderType: "limit",
Size: 0.005,
Price: 1000})
if err != nil {
t.Error("PostOrder() error", err)
}
}
func TestPostMarginOrder(t *testing.T) {
t.Parallel()
// default order type is limit
_, err := ku.PostMarginOrder(context.Background(), &MarginOrderParam{
ClientOrderID: ""})
if !errors.Is(err, errInvalidClientOrderID) {
t.Errorf("PostMarginOrder() expected %v, but found %v", errInvalidClientOrderID, err)
}
_, err = ku.PostMarginOrder(context.Background(), &MarginOrderParam{
ClientOrderID: "5bd6e9286d99522a52e458de", Symbol: marginTradablePair,
OrderType: ""})
if !errors.Is(err, order.ErrSideIsInvalid) {
t.Errorf("PostMarginOrder() expected %v, but found %v", order.ErrSideIsInvalid, err)
}
_, err = ku.PostMarginOrder(context.Background(), &MarginOrderParam{
ClientOrderID: "5bd6e9286d99522a52e458de", Symbol: currency.EMPTYPAIR,
Size: 0.1, Side: "buy", Price: 234565})
if !errors.Is(err, currency.ErrCurrencyPairEmpty) {
t.Errorf("PostMarginOrder() expected %v, but found %v", currency.ErrCurrencyPairEmpty, err)
}
_, err = ku.PostMarginOrder(context.Background(), &MarginOrderParam{
ClientOrderID: "5bd6e9286d99522a52e458de", Side: "buy",
Symbol: marginTradablePair,
OrderType: "limit", Size: 0.1})
if !errors.Is(err, errInvalidPrice) {
t.Errorf("PostMarginOrder() expected %v, but found %v", errInvalidPrice, err)
}
_, err = ku.PostMarginOrder(context.Background(), &MarginOrderParam{
ClientOrderID: "5bd6e9286d99522a52e458de", Symbol: marginTradablePair, Side: "buy",
OrderType: "limit", Price: 234565})
if !errors.Is(err, errInvalidSize) {
t.Errorf("PostMarginOrder() expected %v, but found %v", errInvalidSize, err)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
// default order type is limit and margin mode is cross
_, err = ku.PostMarginOrder(context.Background(),
&MarginOrderParam{
ClientOrderID: "5bd6e9286d99522a52e458de",
Side: "buy", Symbol: marginTradablePair,
Price: 1000, Size: 0.1, PostOnly: true})
if err != nil {
t.Error("PostMarginOrder() error", err)
}
// market isolated order
_, err = ku.PostMarginOrder(context.Background(),
&MarginOrderParam{
ClientOrderID: "5bd6e9286d99522a52e458de",
Side: "buy", Symbol: marginTradablePair,
OrderType: "market", Funds: 1234,
Remark: "remark", MarginMode: "cross", Price: 1000, PostOnly: true, AutoBorrow: true})
if err != nil {
t.Error("PostMarginOrder() error", err)
}
}
func TestPostBulkOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
req := []OrderRequest{
{
ClientOID: "3d07008668054da6b3cb12e432c2b13a",
Side: "buy",
Type: "limit",
Price: 1000,
Size: 0.01,
},
{
ClientOID: "37245dbe6e134b5c97732bfb36cd4a9d",
Side: "buy",
Type: "limit",
Price: 1000,
Size: 0.01,
},
}
_, err := ku.PostBulkOrder(context.Background(), "BTC-USDT", req)
if err != nil {
t.Error("PostBulkOrder() error", err)
}
}
func TestCancelSingleOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
_, err := ku.CancelSingleOrder(context.Background(), "5bd6e9286d99522a52e458de")
if err != nil {
t.Error("CancelSingleOrder() error", err)
}
}
func TestCancelOrderByClientOID(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
_, err := ku.CancelOrderByClientOID(context.Background(), "5bd6e9286d99522a52e458de")
if err != nil {
t.Error("CancelOrderByClientOID() error", err)
}
}
func TestCancelAllOpenOrders(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
_, err := ku.CancelAllOpenOrders(context.Background(), "", "")
if err != nil {
t.Error("CancelAllOpenOrders() error", err)
}
}
const ordersListResponseJSON = `{"currentPage": 1, "pageSize": 1, "totalNum": 153408, "totalPage": 153408, "items": [ { "id": "5c35c02703aa673ceec2a168", "symbol": "BTC-USDT", "opType": "DEAL", "type": "limit", "side": "buy", "price": "10", "size": "2", "funds": "0", "dealFunds": "0.166", "dealSize": "2", "fee": "0", "feeCurrency": "USDT", "stp": "", "stop": "", "stopTriggered": false, "stopPrice": "0", "timeInForce": "GTC", "postOnly": false, "hidden": false, "iceberg": false, "visibleSize": "0", "cancelAfter": 0, "channel": "IOS", "clientOid": "", "remark": "", "tags": "", "isActive": false, "cancelExist": false, "createdAt": 1547026471000, "tradeType": "TRADE" } ] }`
func TestGetOrders(t *testing.T) {
t.Parallel()
var resp *OrdersListResponse
err := json.Unmarshal([]byte(ordersListResponseJSON), &resp)
if err != nil {
t.Error(err)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err = ku.ListOrders(context.Background(), "", "", "", "", "", time.Time{}, time.Time{})
if err != nil {
t.Error("GetOrders() error", err)
}
}
func TestGetRecentOrders(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetRecentOrders(context.Background())
if err != nil {
t.Error("GetRecentOrders() error", err)
}
}
func TestGetOrderByID(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetOrderByID(context.Background(), "5c35c02703aa673ceec2a168")
if err != nil {
t.Error("GetOrderByID() error", err)
}
}
func TestGetOrderByClientOID(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetOrderByClientSuppliedOrderID(context.Background(), "6d539dc614db312")
if err != nil {
t.Error("GetOrderByClientOID() error", err)
}
}
func TestGetFills(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetFills(context.Background(), "", "", "", "", "", time.Time{}, time.Time{})
if err != nil {
t.Error("GetFills() error", err)
}
_, err = ku.GetFills(context.Background(), "5c35c02703aa673ceec2a168", "BTC-USDT", "buy", "limit", "TRADE", time.Now().Add(-time.Hour*12), time.Now())
if err != nil {
t.Error("GetFills() error", err)
}
}
const limitFillsResponseJSON = `[{ "counterOrderId":"5db7ee769797cf0008e3beea", "createdAt":1572335233000, "fee":"0.946357371456", "feeCurrency":"USDT", "feeRate":"0.001", "forceTaker":true, "funds":"946.357371456", "liquidity":"taker", "orderId":"5db7ee805d53620008dce1ba", "price":"9466.8", "side":"buy", "size":"0.09996592", "stop":"", "symbol":"BTC-USDT", "tradeId":"5db7ee8054c05c0008069e21", "tradeType":"MARGIN_TRADE", "type":"market" }, { "counterOrderId":"5db7ee4b5d53620008dcde8e", "createdAt":1572335207000, "fee":"0.94625", "feeCurrency":"USDT", "feeRate":"0.001", "forceTaker":true, "funds":"946.25", "liquidity":"taker", "orderId":"5db7ee675d53620008dce01e", "price":"9462.5", "side":"sell", "size":"0.1", "stop":"", "symbol":"BTC-USDT", "tradeId":"5db7ee6754c05c0008069e03", "tradeType":"MARGIN_TRADE", "type":"market" }]`
func TestGetRecentFills(t *testing.T) {
t.Parallel()
var resp []Fill
err := json.Unmarshal([]byte(limitFillsResponseJSON), &resp)
if err != nil {
t.Fatal(err)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err = ku.GetRecentFills(context.Background())
if err != nil {
t.Error("GetRecentFills() error", err)
}
}
func TestPostStopOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
_, err := ku.PostStopOrder(context.Background(), "5bd6e9286d99522a52e458de", "buy", "BTC-USDT", "", "", "entry", "CO", "TRADE", "", 0.1, 1, 10, 0, 0, 0, true, false, false)
if err != nil {
t.Error("PostStopOrder() error", err)
}
}
func TestCancelStopOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
_, err := ku.CancelStopOrder(context.Background(), "5bd6e9286d99522a52e458de")
if err != nil {
t.Error("CancelStopOrder() error", err)
}
}
func TestCancelAllStopOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
_, err := ku.CancelStopOrders(context.Background(), "", "", "")
if err != nil {
t.Error("CancelAllStopOrder() error", err)
}
}
const stopOrderResponseJSON = `{"id": "vs8hoo8q2ceshiue003b67c0", "symbol": "KCS-USDT", "userId": "60fe4956c43cbc0006562c2c", "status": "NEW", "type": "limit", "side": "buy", "price": "0.01000000000000000000", "size": "0.01000000000000000000", "funds": null, "stp": null, "timeInForce": "GTC", "cancelAfter": -1, "postOnly": false, "hidden": false, "iceberg": false, "visibleSize": null, "channel": "API", "clientOid": "40e0eb9efe6311eb8e58acde48001122", "remark": null, "tags": null, "orderTime": 1629098781127530345, "domainId": "kucoin", "tradeSource": "USER", "tradeType": "TRADE", "feeCurrency": "USDT", "takerFeeRate": "0.00200000000000000000", "makerFeeRate": "0.00200000000000000000", "createdAt": 1629098781128, "stop": "loss", "stopTriggerTime": null, "stopPrice": "10.00000000000000000000" }`
func TestGetStopOrder(t *testing.T) {
t.Parallel()
var resp *StopOrder
err := json.Unmarshal([]byte(stopOrderResponseJSON), &resp)
if err != nil {
t.Fatal(err)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err = ku.GetStopOrder(context.Background(), "5bd6e9286d99522a52e458de")
if err != nil {
t.Error("GetStopOrder() error", err)
}
}
func TestGetAllStopOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.ListStopOrders(context.Background(), "", "", "", "", "", time.Time{}, time.Time{}, 0, 0)
if err != nil {
t.Error("GetAllStopOrder() error", err)
}
}
func TestGetStopOrderByClientID(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetStopOrderByClientID(context.Background(), "", "5bd6e9286d99522a52e458de")
if err != nil {
t.Error("GetStopOrderByClientID() error", err)
}
}
func TestCancelStopOrderByClientID(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
_, err := ku.CancelStopOrderByClientID(context.Background(), "", "5bd6e9286d99522a52e458de")
if err != nil {
t.Error("CancelStopOrderByClientID() error", err)
}
}
func TestGetAllAccounts(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetAllAccounts(context.Background(), "", "")
if err != nil {
t.Error("GetAllAccounts() error", err)
}
}
func TestGetAccount(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetAccount(context.Background(), "62fcd1969474ea0001fd20e4")
if err != nil {
t.Error("GetAccount() error", err)
}
}
const accountLedgerResponseJSON = `{"currentPage": 1, "pageSize": 50, "totalNum": 2, "totalPage": 1, "items": [ { "id": "611a1e7c6a053300067a88d9", "currency": "USDT", "amount": "10.00059547", "fee": "0", "balance": "0", "accountType": "MAIN", "bizType": "Loans Repaid", "direction": "in", "createdAt": 1629101692950, "context": "{\"borrowerUserId\":\"601ad03e50dc810006d242ea\",\"loanRepayDetailNo\":\"611a1e7cc913d000066cf7ec\"}" }, { "id": "611a18bc6a0533000671e1bf", "currency": "USDT", "amount": "10.00059547", "fee": "0", "balance": "0", "accountType": "MAIN", "bizType": "Loans Repaid", "direction": "in", "createdAt": 1629100220843, "context": "{\"borrowerUserId\":\"5e3f4623dbf52d000800292f\",\"loanRepayDetailNo\":\"611a18bc7255c200063ea545\"}" } ] }`
func TestGetAccountLedgers(t *testing.T) {
t.Parallel()
var resp *AccountLedgerResponse
err := json.Unmarshal([]byte(accountLedgerResponseJSON), &resp)
if err != nil {
t.Fatal(err)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err = ku.GetAccountLedgers(context.Background(), "", "", "", time.Time{}, time.Time{})
if err != nil {
t.Error("GetAccountLedgers() error", err)
}
}
func TestGetAccountSummaryInformation(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
if _, err := ku.GetAccountSummaryInformation(context.Background()); err != nil {
t.Error(err)
}
}
func TestGetSubAccountBalance(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetSubAccountBalance(context.Background(), "62fcd1969474ea0001fd20e4", false)
if err != nil {
t.Error("GetSubAccountBalance() error", err)
}
}
func TestGetAggregatedSubAccountBalance(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetAggregatedSubAccountBalance(context.Background())
if err != nil {
t.Error("GetAggregatedSubAccountBalance() error", err)
}
}
func TestGetPaginatedSubAccountInformation(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetPaginatedSubAccountInformation(context.Background(), 0, 10)
if err != nil {
t.Error("GetPaginatedSubAccountInformation() error", err)
}
}
func TestGetTransferableBalance(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetTransferableBalance(context.Background(), "BTC", "MAIN", "")
if err != nil {
t.Error("GetTransferableBalance() error", err)
}
}
func TestTransferMainToSubAccount(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
_, err := ku.TransferMainToSubAccount(context.Background(), "62fcd1969474ea0001fd20e4", "BTC", "1", "OUT", "", "", "5caefba7d9575a0688f83c45")
if err != nil {
t.Error("TransferMainToSubAccount() error", err)
}
}
func TestMakeInnerTransfer(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
_, err := ku.MakeInnerTransfer(context.Background(), "62fcd1969474ea0001fd20e4", "BTC", "trade", "main", "1", "", "")
if err != nil {
t.Error("MakeInnerTransfer() error", err)
}
}
func TestCreateDepositAddress(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
_, err := ku.CreateDepositAddress(context.Background(), "BTC", "")
if err != nil {
t.Error("CreateDepositAddress() error", err)
}
_, err = ku.CreateDepositAddress(context.Background(), "USDT", "TRC20")
if err != nil {
t.Error("CreateDepositAddress() error", err)
}
}
func TestGetDepositAddressV2(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetDepositAddressesV2(context.Background(), "BTC")
if err != nil {
t.Error("GetDepositAddressV2() error", err)
}
}
func TestGetDepositAddressesV1(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetDepositAddressV1(context.Background(), "BTC", "")
if err != nil {
t.Error("GetDepositAddressV1() error", err)
}
}
const depositResponseJSON = `{"currentPage": 1, "pageSize": 50, "totalNum": 1, "totalPage": 1, "items": [ { "currency": "XRP", "chain": "xrp", "status": "SUCCESS", "address": "rNFugeoj3ZN8Wv6xhuLegUBBPXKCyWLRkB", "memo": "1919537769", "isInner": false, "amount": "20.50000000", "fee": "0.00000000", "walletTxId": "2C24A6D5B3E7D5B6AA6534025B9B107AC910309A98825BF5581E25BEC94AD83B@e8902757998fc352e6c9d8890d18a71c", "createdAt": 1666600519000, "updatedAt": 1666600549000, "remark": "Deposit" } ] }`
func TestGetDepositList(t *testing.T) {
t.Parallel()
var resp DepositResponse
err := json.Unmarshal([]byte(depositResponseJSON), &resp)
if err != nil {
t.Fatal(err)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err = ku.GetDepositList(context.Background(), "", "", time.Time{}, time.Time{})
if err != nil {
t.Error("GetDepositList() error", err)
}
}
const historicalDepositResponseJSON = `{"currentPage":1, "pageSize":1, "totalNum":9, "totalPage":9, "items":[ { "currency":"BTC", "createAt":1528536998, "amount":"0.03266638", "walletTxId":"55c643bc2c68d6f17266383ac1be9e454038864b929ae7cee0bc408cc5c869e8@12ffGWmMMD1zA1WbFm7Ho3JZ1w6NYXjpFk@234", "isInner":false, "status":"SUCCESS" } ] }`
func TestGetHistoricalDepositList(t *testing.T) {
t.Parallel()
var resp *HistoricalDepositWithdrawalResponse
err := json.Unmarshal([]byte(historicalDepositResponseJSON), &resp)
if err != nil {
t.Fatal(err)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err = ku.GetHistoricalDepositList(context.Background(), "", "", time.Time{}, time.Time{})
if err != nil {
t.Error("GetHistoricalDepositList() error", err)
}
}
func TestGetWithdrawalList(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetWithdrawalList(context.Background(), "", "", time.Time{}, time.Time{})
if err != nil {
t.Error("GetWithdrawalList() error", err)
}
}
func TestGetHistoricalWithdrawalList(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetHistoricalWithdrawalList(context.Background(), "", "", time.Time{}, time.Time{}, 0, 0)
if err != nil {
t.Error("GetHistoricalWithdrawalList() error", err)
}
}
func TestGetWithdrawalQuotas(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetWithdrawalQuotas(context.Background(), "BTC", "")
if err != nil {
t.Error("GetWithdrawalQuotas() error", err)
}
}
func TestApplyWithdrawal(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
_, err := ku.ApplyWithdrawal(context.Background(), "ETH", "0x597873884BC3a6C10cB6Eb7C69172028Fa85B25A", "", "", "", "", false, 1)
if err != nil {
t.Error("ApplyWithdrawal() error", err)
}
}
func TestCancelWithdrawal(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
err := ku.CancelWithdrawal(context.Background(), "5bffb63303aa675e8bbe18f9")
if err != nil {
t.Error("CancelWithdrawal() error", err)
}
}
func TestGetBasicFee(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetBasicFee(context.Background(), "1")
if err != nil {
t.Error("GetBasicFee() error", err)
}
}
func TestGetTradingFee(t *testing.T) {
t.Parallel()
_, err := ku.GetTradingFee(context.Background(), nil)
if !errors.Is(err, currency.ErrCurrencyPairsEmpty) {
t.Fatalf("received %v, expected %v", err, currency.ErrCurrencyPairsEmpty)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
avail, err := ku.GetAvailablePairs(asset.Spot)
if err != nil {
t.Fatal(err)
}
pairs := currency.Pairs{avail[0]}
btcusdTradingFee, err := ku.GetTradingFee(context.Background(), pairs)
if !errors.Is(err, nil) {
t.Fatalf("received %v, expected %v", err, nil)
}
if len(btcusdTradingFee) != 1 {
t.Error("GetTradingFee() error, expected 1 pair")
}
// NOTE: Test below will error out from an external call as this will exceed
// the allowed pairs. If this does not error then this endpoint will allow
// more items to be requested.
pairs = append(pairs, avail[1:11]...)
_, err = ku.GetTradingFee(context.Background(), pairs)
if errors.Is(err, nil) {
t.Fatalf("received %v, expected %v", err, "code: 200000 message: symbols size invalid.")
}
got, err := ku.GetTradingFee(context.Background(), pairs[:10])
if !errors.Is(err, nil) {
t.Fatalf("received %v, expected %v", err, nil)
}
if len(got) != 10 {
t.Error("GetTradingFee() error, expected 10 pairs")
}
}
// futures
func TestGetFuturesOpenContracts(t *testing.T) {
t.Parallel()
_, err := ku.GetFuturesOpenContracts(context.Background())
if err != nil {
t.Error("GetFuturesOpenContracts() error", err)
}
}
func TestGetFuturesContract(t *testing.T) {
t.Parallel()
_, err := ku.GetFuturesContract(context.Background(), "XBTUSDTM")
if err != nil {
t.Error("GetFuturesContract() error", err)
}
}
func TestGetFuturesTicker(t *testing.T) {
t.Parallel()
tick, err := ku.GetFuturesTicker(context.Background(), "XBTUSDTM")
if assert.NoError(t, err, "GetFuturesTicker should not error") {
assert.Positive(t, tick.Sequence, "Sequence should be positive")
assert.Equal(t, "XBTUSDTM", tick.Symbol, "Symbol should be correct")
assert.Contains(t, []order.Side{order.Buy, order.Sell}, tick.Side, "Side should be a side")
assert.Positive(t, tick.Size, "Size should be positive")
assert.Positive(t, tick.Price.Float64(), "Price should be positive")
assert.Positive(t, tick.BestBidPrice.Float64(), "BestBidPrice should be positive")
assert.Positive(t, tick.BestBidSize, "BestBidSize should be positive")
assert.Positive(t, tick.BestAskPrice.Float64(), "BestAskPrice should be positive")
assert.Positive(t, tick.BestAskSize, "BestAskSize should be positive")
assert.NotEmpty(t, tick.TradeID, "TradeID should not be empty")
assert.WithinRange(t, tick.FilledTime.Time(), time.Now().Add(time.Hour*-24), time.Now(), "FilledTime should be within last 24 hours")
}
}
func TestGetFuturesOrderbook(t *testing.T) {
t.Parallel()
_, err := ku.GetFuturesOrderbook(context.Background(), futuresTradablePair.String())
if err != nil {
t.Error("GetFuturesOrderbook() error", err)
}
}
func TestGetFuturesPartOrderbook20(t *testing.T) {
t.Parallel()
_, err := ku.GetFuturesPartOrderbook20(context.Background(), "XBTUSDTM")
if err != nil {
t.Error("GetFuturesPartOrderbook20() error", err)
}
}
func TestGetFuturesPartOrderbook100(t *testing.T) {
t.Parallel()
_, err := ku.GetFuturesPartOrderbook100(context.Background(), "XBTUSDTM")
if err != nil {
t.Error("GetFuturesPartOrderbook100() error", err)
}
}
func TestGetFuturesTradeHistory(t *testing.T) {
t.Parallel()
_, err := ku.GetFuturesTradeHistory(context.Background(), "XBTUSDTM")
if err != nil {
t.Error("GetFuturesTradeHistory() error", err)
}
}
func TestGetFuturesInterestRate(t *testing.T) {
t.Parallel()
_, err := ku.GetFuturesInterestRate(context.Background(), "XBTUSDTM", time.Time{}, time.Time{}, false, false, 0, 0)
if err != nil {
t.Error("GetFuturesInterestRate() error", err)
}
}
func TestGetFuturesIndexList(t *testing.T) {
t.Parallel()
_, err := ku.GetFuturesIndexList(context.Background(), futuresTradablePair.String(), time.Time{}, time.Time{}, false, false, 0, 10)
if err != nil {
t.Error(err)
}
}
func TestGetFuturesCurrentMarkPrice(t *testing.T) {
t.Parallel()
_, err := ku.GetFuturesCurrentMarkPrice(context.Background(), "XBTUSDTM")
if err != nil {
t.Error("GetFuturesCurrentMarkPrice() error", err)
}
}
func TestGetFuturesPremiumIndex(t *testing.T) {
t.Parallel()
_, err := ku.GetFuturesPremiumIndex(context.Background(), "XBTUSDTM", time.Time{}, time.Time{}, false, false, 0, 0)
if err != nil {
t.Error("GetFuturesPremiumIndex() error", err)
}
}
func TestGetFuturesCurrentFundingRate(t *testing.T) {
t.Parallel()
_, err := ku.GetFuturesCurrentFundingRate(context.Background(), "XBTUSDTM")
if err != nil {
t.Error("GetFuturesCurrentFundingRate() error", err)
}
}
func TestGetFuturesServerTime(t *testing.T) {
t.Parallel()
_, err := ku.GetFuturesServerTime(context.Background())
if err != nil {
t.Error("GetFuturesServerTime() error", err)
}
}
func TestGetFuturesServiceStatus(t *testing.T) {
t.Parallel()
_, err := ku.GetFuturesServiceStatus(context.Background())
if err != nil {
t.Error("GetFuturesServiceStatus() error", err)
}
}
func TestGetFuturesKline(t *testing.T) {
t.Parallel()
_, err := ku.GetFuturesKline(context.Background(), int64(kline.ThirtyMin.Duration().Minutes()), "XBTUSDTM", time.Time{}, time.Time{})
if err != nil {
t.Error("GetFuturesKline() error", err)
}
}
func TestPostFuturesOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
_, err := ku.PostFuturesOrder(context.Background(), &FuturesOrderParam{ClientOrderID: "5bd6e9286d99522a52e458de"})
if !errors.Is(err, errInvalidLeverage) {
t.Errorf("PostFuturesOrder expected %v, but found %v", errInvalidLeverage, err)
}
_, err = ku.PostFuturesOrder(context.Background(), &FuturesOrderParam{Side: "buy", Leverage: 0.02})
if !errors.Is(err, errInvalidClientOrderID) {
t.Errorf("PostFuturesOrder expected %v, but found %v", errInvalidClientOrderID, err)
}
_, err = ku.PostFuturesOrder(context.Background(), &FuturesOrderParam{ClientOrderID: "5bd6e9286d99522a52e458de", Leverage: 0.02})
if !errors.Is(err, order.ErrSideIsInvalid) {
t.Errorf("PostFuturesOrder expected %v, but found %v", order.ErrSideIsInvalid, err)
}
_, err = ku.PostFuturesOrder(context.Background(), &FuturesOrderParam{ClientOrderID: "5bd6e9286d99522a52e458de", Side: "buy", Leverage: 0.02})
if !errors.Is(err, currency.ErrCurrencyPairEmpty) {
t.Errorf("PostFuturesOrder expected %v, but found %v", currency.ErrCurrencyPairEmpty, err)
}
// With Stop order configuration
_, err = ku.PostFuturesOrder(context.Background(), &FuturesOrderParam{ClientOrderID: "5bd6e9286d99522a52e458de", Side: "buy", Symbol: futuresTradablePair, OrderType: "limit", Remark: "10",
Stop: "up", StopPriceType: "", TimeInForce: "", Size: 1, Price: 1000, StopPrice: 0, Leverage: 0.02, VisibleSize: 0})
if !errors.Is(err, errInvalidStopPriceType) {
t.Errorf("PostFuturesOrder expected %v, but found %v", errInvalidStopPriceType, err)
}
_, err = ku.PostFuturesOrder(context.Background(), &FuturesOrderParam{ClientOrderID: "5bd6e9286d99522a52e458de", Side: "buy", Symbol: futuresTradablePair, OrderType: "limit", Remark: "10",
Stop: "up", StopPriceType: "TP", TimeInForce: "", Size: 1, Price: 1000, StopPrice: 0, Leverage: 0.02, VisibleSize: 0})
if !errors.Is(err, errInvalidPrice) {
t.Errorf("PostFuturesOrder expected %v, but found %v", errInvalidPrice, err)
}
_, err = ku.PostFuturesOrder(context.Background(), &FuturesOrderParam{ClientOrderID: "5bd6e9286d99522a52e458de", Side: "buy", Symbol: futuresTradablePair, OrderType: "limit", Remark: "10",
Stop: "up", StopPriceType: "TP", StopPrice: 123456, TimeInForce: "", Size: 1, Price: 1000, Leverage: 0.02, VisibleSize: 0})
if err != nil {
t.Errorf("PostFuturesOrder expected %v", err)
}
// Limit Orders
_, err = ku.PostFuturesOrder(context.Background(), &FuturesOrderParam{ClientOrderID: "5bd6e9286d99522a52e458de", Side: "buy", Symbol: futuresTradablePair,
OrderType: "limit", Remark: "10", Leverage: 0.02})
if !errors.Is(err, errInvalidPrice) {
t.Errorf("PostFuturesOrder expected %v, but found %v", errInvalidPrice, err)
}
_, err = ku.PostFuturesOrder(context.Background(), &FuturesOrderParam{ClientOrderID: "5bd6e9286d99522a52e458de", Side: "buy", Symbol: futuresTradablePair, OrderType: "limit", Remark: "10", Price: 1000, Leverage: 0.02, VisibleSize: 0})
if !errors.Is(err, errInvalidSize) {
t.Errorf("PostFuturesOrder expected %v, but found %v", errInvalidSize, err)
}
_, err = ku.PostFuturesOrder(context.Background(), &FuturesOrderParam{ClientOrderID: "5bd6e9286d99522a52e458de", Side: "buy", Symbol: futuresTradablePair, OrderType: "limit", Remark: "10",
Size: 1, Price: 1000, Leverage: 0.02, VisibleSize: 0})
if err != nil {
t.Error(err)
}
// Market Orders
_, err = ku.PostFuturesOrder(context.Background(), &FuturesOrderParam{ClientOrderID: "5bd6e9286d99522a52e458de", Side: "buy", Symbol: futuresTradablePair,
OrderType: "market", Remark: "10", Leverage: 0.02})
if !errors.Is(err, errInvalidSize) {
t.Errorf("PostFuturesOrder expected %v, but found %v", errInvalidSize, err)
}
_, err = ku.PostFuturesOrder(context.Background(), &FuturesOrderParam{ClientOrderID: "5bd6e9286d99522a52e458de", Side: "buy", Symbol: futuresTradablePair, OrderType: "market", Remark: "10",
Size: 1, Leverage: 0.02, VisibleSize: 0})
if !errors.Is(err, errInvalidSize) {
t.Errorf("PostFuturesOrder expected %v, but found %v", errInvalidSize, err)
}
_, err = ku.PostFuturesOrder(context.Background(), &FuturesOrderParam{
ClientOrderID: "5bd6e9286d99522a52e458de",
Side: "buy",
Symbol: futuresTradablePair,
OrderType: "limit",
Remark: "10",
Stop: "",
StopPriceType: "",
TimeInForce: "",
Size: 1,
Price: 1000,
StopPrice: 0,
Leverage: 0.02,
VisibleSize: 0})
if err != nil {
t.Error("PostFuturesOrder() error", err)
}
}
func TestCancelFuturesOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
_, err := ku.CancelFuturesOrder(context.Background(), "5bd6e9286d99522a52e458de")
if err != nil {
t.Error("CancelFuturesOrder() error", err)
}
}
func TestCancelAllFuturesOpenOrders(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
_, err := ku.CancelAllFuturesOpenOrders(context.Background(), "XBTUSDM")
if err != nil {
t.Error("CancelAllFuturesOpenOrders() error", err)
}
}
func TestCancelAllFuturesStopOrders(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
_, err := ku.CancelAllFuturesStopOrders(context.Background(), "XBTUSDM")
if err != nil {
t.Error("CancelAllFuturesStopOrders() error", err)
}
}
func TestGetFuturesOrders(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetFuturesOrders(context.Background(), "", "", "", "", time.Time{}, time.Time{})
if err != nil {
t.Error("GetFuturesOrders() error", err)
}
}
func TestGetUntriggeredFuturesStopOrders(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetUntriggeredFuturesStopOrders(context.Background(), "", "", "", time.Time{}, time.Time{})
if err != nil {
t.Error("GetUntriggeredFuturesStopOrders() error", err)
}
}
func TestGetFuturesRecentCompletedOrders(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetFuturesRecentCompletedOrders(context.Background())
if err != nil {
t.Error("GetFuturesRecentCompletedOrders() error", err)
}
}
func TestGetFuturesOrderDetails(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetFuturesOrderDetails(context.Background(), "5cdfc138b21023a909e5ad55")
if err != nil {
t.Error("GetFuturesOrderDetails() error", err)
}
}
func TestGetFuturesOrderDetailsByClientID(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetFuturesOrderDetailsByClientID(context.Background(), "eresc138b21023a909e5ad59")
if err != nil {
t.Error("GetFuturesOrderDetailsByClientID() error", err)
}
}
func TestGetFuturesFills(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetFuturesFills(context.Background(), "", "", "", "", time.Time{}, time.Time{})
if err != nil {
t.Error("GetFuturesFills() error", err)
}
}
func TestGetFuturesRecentFills(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetFuturesRecentFills(context.Background())
if err != nil {
t.Error("GetFuturesRecentFills() error", err)
}
}
func TestGetFuturesOpenOrderStats(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetFuturesOpenOrderStats(context.Background(), "XBTUSDM")
if err != nil {
t.Error("GetFuturesOpenOrderStats() error", err)
}
}
func TestGetFuturesPosition(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetFuturesPosition(context.Background(), "XBTUSDM")
if err != nil {
t.Error("GetFuturesPosition() error", err)
}
}
func TestGetFuturesPositionList(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetFuturesPositionList(context.Background())
if err != nil {
t.Error("GetFuturesPositionList() error", err)
}
}
func TestSetAutoDepositMargin(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
_, err := ku.SetAutoDepositMargin(context.Background(), "ADAUSDTM", true)
if err != nil {
t.Error("SetAutoDepositMargin() error", err)
}
}
func TestAddMargin(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
_, err := ku.AddMargin(context.Background(), "XBTUSDTM", "6200c9b83aecfb000152dasfdee", 1)
if err != nil {
t.Error("AddMargin() error", err)
}
}
func TestGetFuturesRiskLimitLevel(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetFuturesRiskLimitLevel(context.Background(), "ADAUSDTM")
if err != nil {
t.Error("GetFuturesRiskLimitLevel() error", err)
}
}
func TestUpdateRiskLmitLevel(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
_, err := ku.FuturesUpdateRiskLmitLevel(context.Background(), "ADASUDTM", 2)
if err != nil {
t.Error("UpdateRiskLmitLevel() error", err)
}
}
func TestGetFuturesFundingHistory(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetFuturesFundingHistory(context.Background(), futuresTradablePair.String(), 0, 0, true, true, time.Time{}, time.Time{})
if err != nil {
t.Error("GetFuturesFundingHistory() error", err)
}
}
func TestGetFuturesAccountOverview(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetFuturesAccountOverview(context.Background(), "")
if err != nil {
t.Error("GetFuturesAccountOverview() error", err)
}
}
func TestGetFuturesTransactionHistory(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetFuturesTransactionHistory(context.Background(), "", "", 0, 0, true, time.Time{}, time.Time{})
if err != nil {
t.Error("GetFuturesTransactionHistory() error", err)
}
}
func TestCreateFuturesSubAccountAPIKey(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
_, err := ku.CreateFuturesSubAccountAPIKey(context.Background(), "", "passphrase", "", "remark", "subAccName")
if err != nil {
t.Error("CreateFuturesSubAccountAPIKey() error", err)
}
}
func TestGetFuturesDepositAddress(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetFuturesDepositAddress(context.Background(), "XBT")
if err != nil {
t.Error("GetFuturesDepositAddress() error", err)
}
}
func TestGetFuturesDepositsList(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetFuturesDepositsList(context.Background(), "", "", time.Time{}, time.Time{})
if err != nil {
t.Error("GetFuturesDepositsList() error", err)
}
}
func TestGetFuturesWithdrawalLimit(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetFuturesWithdrawalLimit(context.Background(), "XBT")
if err != nil {
t.Error("GetFuturesWithdrawalLimit() error", err)
}
}
func TestGetFuturesWithdrawalList(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetFuturesWithdrawalList(context.Background(), "", "", time.Time{}, time.Time{})
if err != nil {
t.Error("GetFuturesWithdrawalList() error", err)
}
}
func TestCancelFuturesWithdrawal(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
_, err := ku.CancelFuturesWithdrawal(context.Background(), "5cda659603aa67131f305f7e")
if err != nil {
t.Error("CancelFuturesWithdrawal() error", err)
}
}
func TestTransferFuturesFundsToMainAccount(t *testing.T) {
t.Parallel()
var resp *TransferRes
err := json.Unmarshal([]byte(transferFuturesFundsResponseJSON), &resp)
if err != nil {
t.Fatal(err)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
_, err = ku.TransferFuturesFundsToMainAccount(context.Background(), 1, "USDT", "MAIN")
if err != nil {
t.Error("TransferFuturesFundsToMainAccount() error", err)
}
}
func TestTransferFundsToFuturesAccount(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
err := ku.TransferFundsToFuturesAccount(context.Background(), 1, "USDT", "MAIN")
if err != nil {
t.Error("TransferFundsToFuturesAccount() error", err)
}
}
func TestGetFuturesTransferOutList(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetFuturesTransferOutList(context.Background(), "USDT", "", time.Time{}, time.Time{})
if err != nil {
t.Error("GetFuturesTransferOutList() error", err)
}
}
func TestCancelFuturesTransferOut(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
err := ku.CancelFuturesTransferOut(context.Background(), "5cd53be30c19fc3754b60928")
if err != nil {
t.Error("CancelFuturesTransferOut() error", err)
}
}
func TestFetchTradablePairs(t *testing.T) {
t.Parallel()
_, err := ku.FetchTradablePairs(context.Background(), asset.Futures)
if err != nil {
t.Error(err)
}
_, err = ku.FetchTradablePairs(context.Background(), asset.Spot)
if err != nil {
t.Error(err)
}
_, err = ku.FetchTradablePairs(context.Background(), asset.Margin)
if err != nil {
t.Error(err)
}
}
func TestUpdateOrderbook(t *testing.T) {
t.Parallel()
if _, err := ku.UpdateOrderbook(context.Background(), futuresTradablePair, asset.Futures); err != nil {
t.Error(err)
}
if _, err := ku.UpdateOrderbook(context.Background(), marginTradablePair, asset.Margin); err != nil {
t.Error(err)
}
if _, err := ku.UpdateOrderbook(context.Background(), spotTradablePair, asset.Spot); err != nil {
t.Error(err)
}
}
func TestUpdateTickers(t *testing.T) {
t.Parallel()
for _, a := range ku.GetAssetTypes(true) {
err := ku.UpdateTickers(context.Background(), a)
assert.NoError(t, err, "UpdateTickers should not error")
pairs, err := ku.GetEnabledPairs(a)
assert.NoError(t, err, "GetEnabledPairs should not error")
for _, p := range pairs {
tick, err := ticker.GetTicker(ku.Name, p, a)
if assert.NoError(t, err, "GetTicker %s %s should not error", a, p) {
assert.Positive(t, tick.Last, "%s %s Tick Last should be positive", a, p)
assert.NotEmpty(t, tick.Pair, "%s %s Tick Pair should not be empty", a, p)
assert.Equal(t, ku.Name, tick.ExchangeName, "ExchangeName should be correct")
assert.Equal(t, a, tick.AssetType, "AssetType should be correct")
assert.NotEmpty(t, tick.LastUpdated, "%s %s Tick LastUpdated should not be empty", a, p)
}
}
}
}
func TestUpdateTicker(t *testing.T) {
t.Parallel()
var err error
_, err = ku.UpdateTicker(context.Background(), spotTradablePair, asset.Spot)
if err != nil {
t.Fatal(err)
}
_, err = ku.UpdateTicker(context.Background(), marginTradablePair, asset.Margin)
if err != nil {
t.Fatal(err)
}
_, err = ku.UpdateTicker(context.Background(), futuresTradablePair, asset.Futures)
if err != nil {
t.Fatal(err)
}
}
func TestFetchTicker(t *testing.T) {
t.Parallel()
_, err := ku.FetchTicker(context.Background(), spotTradablePair, asset.Spot)
if err != nil {
t.Fatal(err)
}
if _, err = ku.FetchTicker(context.Background(), marginTradablePair, asset.Margin); err != nil {
t.Error(err)
}
if _, err = ku.FetchTicker(context.Background(), futuresTradablePair, asset.Futures); err != nil {
t.Error(err)
}
}
func TestFetchOrderbook(t *testing.T) {
t.Parallel()
if _, err := ku.FetchOrderbook(context.Background(), spotTradablePair, asset.Spot); err != nil {
t.Error(err)
}
if _, err := ku.FetchOrderbook(context.Background(), marginTradablePair, asset.Margin); err != nil {
t.Error(err)
}
if _, err := ku.FetchOrderbook(context.Background(), futuresTradablePair, asset.Futures); err != nil {
t.Error(err)
}
}
func TestGetHistoricCandles(t *testing.T) {
startTime := time.Now().Add(-time.Hour * 48)
endTime := time.Now().Add(-time.Hour * 3)
var err error
_, err = ku.GetHistoricCandles(context.Background(), futuresTradablePair, asset.Futures, kline.OneHour, startTime, endTime)
if err != nil {
t.Fatal(err)
}
_, err = ku.GetHistoricCandles(context.Background(), spotTradablePair, asset.Spot, kline.OneHour, startTime, time.Now())
if err != nil {
t.Fatal(err)
}
_, err = ku.GetHistoricCandles(context.Background(), marginTradablePair, asset.Margin, kline.OneHour, startTime, time.Now())
if err != nil {
t.Fatal(err)
}
}
func TestGetHistoricCandlesExtended(t *testing.T) {
startTime := time.Now().Add(-time.Hour * 48)
endTime := time.Now().Add(-time.Hour * 1)
var err error
_, err = ku.GetHistoricCandlesExtended(context.Background(), spotTradablePair, asset.Spot, kline.OneHour, startTime, endTime)
if err != nil {
t.Fatal(err)
}
_, err = ku.GetHistoricCandlesExtended(context.Background(), spotTradablePair, asset.Spot, kline.FiveMin, startTime, endTime)
if err != nil {
t.Error(err)
}
_, err = ku.GetHistoricCandlesExtended(context.Background(), marginTradablePair, asset.Margin, kline.OneHour, startTime, endTime)
if err != nil {
t.Fatal(err)
}
_, err = ku.GetHistoricCandlesExtended(context.Background(), futuresTradablePair, asset.Futures, kline.FiveMin, startTime, endTime)
if err != nil {
t.Error(err)
}
}
func TestGetServerTime(t *testing.T) {
t.Parallel()
_, err := ku.GetServerTime(context.Background(), asset.Spot)
if err != nil {
t.Error(err)
}
_, err = ku.GetServerTime(context.Background(), asset.Futures)
if err != nil {
t.Error(err)
}
_, err = ku.GetServerTime(context.Background(), asset.Margin)
if err != nil {
t.Error(err)
}
}
func TestGetRecentTrades(t *testing.T) {
t.Parallel()
_, err := ku.GetRecentTrades(context.Background(), futuresTradablePair, asset.Futures)
if err != nil {
t.Error(err)
}
_, err = ku.GetRecentTrades(context.Background(), spotTradablePair, asset.Spot)
if err != nil {
t.Error(err)
}
_, err = ku.GetRecentTrades(context.Background(), marginTradablePair, asset.Margin)
if err != nil {
t.Error(err)
}
}
func TestGetOrderHistory(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
var enabledPairs currency.Pairs
var getOrdersRequest order.MultiOrderRequest
var err error
enabledPairs, err = ku.GetEnabledPairs(asset.Futures)
if err != nil {
t.Fatal(err)
}
getOrdersRequest = order.MultiOrderRequest{
Type: order.Limit,
Pairs: append([]currency.Pair{currency.NewPair(currency.BTC, currency.USDT)}, enabledPairs[:3]...),
AssetType: asset.Futures,
Side: order.AnySide,
}
_, err = ku.GetOrderHistory(context.Background(), &getOrdersRequest)
if err != nil {
t.Error(err)
}
getOrdersRequest.Pairs = []currency.Pair{}
_, err = ku.GetOrderHistory(context.Background(), &getOrdersRequest)
if err != nil {
t.Error(err)
}
getOrdersRequest = order.MultiOrderRequest{
Type: order.Limit,
Pairs: []currency.Pair{spotTradablePair},
AssetType: asset.Spot,
Side: order.Sell,
}
_, err = ku.GetOrderHistory(context.Background(), &getOrdersRequest)
if err != nil {
t.Error(err)
}
getOrdersRequest.Pairs = []currency.Pair{}
_, err = ku.GetOrderHistory(context.Background(), &getOrdersRequest)
if err != nil {
t.Error(err)
}
getOrdersRequest.AssetType = asset.Margin
getOrdersRequest.Pairs = currency.Pairs{marginTradablePair}
_, err = ku.GetOrderHistory(context.Background(), &getOrdersRequest)
if err != nil {
t.Error(err)
}
}
func TestGetActiveOrders(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
var getOrdersRequest order.MultiOrderRequest
var enabledPairs currency.Pairs
var err error
enabledPairs, err = ku.GetEnabledPairs(asset.Spot)
if err != nil {
t.Fatal(err)
}
getOrdersRequest = order.MultiOrderRequest{
Type: order.Limit,
Pairs: enabledPairs,
AssetType: asset.Spot,
Side: order.Buy,
}
if _, err = ku.GetActiveOrders(context.Background(), &getOrdersRequest); err != nil {
t.Error("Kucoin GetActiveOrders() error", err)
}
getOrdersRequest.Pairs = []currency.Pair{}
if _, err = ku.GetActiveOrders(context.Background(), &getOrdersRequest); err != nil {
t.Error("Kucoin GetActiveOrders() error", err)
}
getOrdersRequest.Type = order.Market
if _, err = ku.GetActiveOrders(context.Background(), &getOrdersRequest); err != nil {
t.Error("Kucoin GetActiveOrders() error", err)
}
getOrdersRequest.Type = order.OCO
if _, err = ku.GetActiveOrders(context.Background(), &getOrdersRequest); !errors.Is(err, order.ErrUnsupportedOrderType) {
t.Error("Kucoin GetActiveOrders() error", err)
}
enabledPairs, err = ku.GetEnabledPairs(asset.Spot)
if err != nil {
t.Fatal(err)
}
getOrdersRequest = order.MultiOrderRequest{
Type: order.Limit,
Pairs: enabledPairs,
AssetType: asset.Margin,
Side: order.Buy,
}
if _, err = ku.GetActiveOrders(context.Background(), &getOrdersRequest); err != nil {
t.Error("Kucoin GetActiveOrders() error", err)
}
getOrdersRequest.Pairs = []currency.Pair{}
if _, err = ku.GetActiveOrders(context.Background(), &getOrdersRequest); err != nil {
t.Error("Kucoin GetActiveOrders() error", err)
}
getOrdersRequest.Type = order.Market
if _, err = ku.GetActiveOrders(context.Background(), &getOrdersRequest); err != nil {
t.Error("Kucoin GetActiveOrders() error", err)
}
getOrdersRequest.Type = order.OCO
if _, err = ku.GetActiveOrders(context.Background(), &getOrdersRequest); !errors.Is(err, order.ErrUnsupportedOrderType) {
t.Errorf("expected %v, but found %v", order.ErrUnsupportedOrderType, err)
}
enabledPairs, err = ku.GetEnabledPairs(asset.Futures)
if err != nil {
t.Fatal(err)
}
getOrdersRequest = order.MultiOrderRequest{
Type: order.Limit,
Pairs: enabledPairs,
AssetType: asset.Futures,
Side: order.Buy,
}
if _, err = ku.GetActiveOrders(context.Background(), &getOrdersRequest); err != nil {
t.Error("Kucoin GetActiveOrders() error", err)
}
getOrdersRequest.Pairs = []currency.Pair{}
if _, err = ku.GetActiveOrders(context.Background(), &getOrdersRequest); err != nil {
t.Error("Kucoin GetActiveOrders() error", err)
}
getOrdersRequest.Type = order.StopLimit
if _, err = ku.GetActiveOrders(context.Background(), &getOrdersRequest); err != nil {
t.Error("Kucoin GetActiveOrders() error", err)
}
getOrdersRequest.Type = order.OCO
if _, err = ku.GetActiveOrders(context.Background(), &getOrdersRequest); !errors.Is(err, order.ErrUnsupportedOrderType) {
t.Errorf("expected %v, but found %v", order.ErrUnsupportedOrderType, err)
}
}
func TestGetFeeByType(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
if _, err := ku.GetFeeByType(context.Background(), &exchange.FeeBuilder{
Amount: 1,
FeeType: exchange.CryptocurrencyTradeFee,
Pair: currency.NewPairWithDelimiter(currency.BTC.String(), currency.USDT.String(), currency.DashDelimiter),
PurchasePrice: 1,
FiatCurrency: currency.USD,
BankTransactionType: exchange.WireTransfer,
}); err != nil {
t.Error(err)
}
}
func TestValidateCredentials(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
assetTypes := ku.CurrencyPairs.GetAssetTypes(true)
for _, at := range assetTypes {
if err := ku.ValidateCredentials(context.Background(), at); err != nil {
t.Error(err)
}
}
}
func TestGetInstanceServers(t *testing.T) {
t.Parallel()
if _, err := ku.GetInstanceServers(context.Background()); err != nil {
t.Error(err)
}
}
func TestGetAuthenticatedServersInstances(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetAuthenticatedInstanceServers(context.Background())
if err != nil {
t.Error(err)
}
}
func TestPushData(t *testing.T) {
n := new(Kucoin)
sharedtestvalues.TestFixtureToDataHandler(t, ku, n, "testdata/wsHandleData.json", ku.wsHandleData)
}
func verifySubs(tb testing.TB, subs []subscription.Subscription, a asset.Item, prefix string, expected ...string) {
tb.Helper()
var sub *subscription.Subscription
for i, s := range subs { //nolint:gocritic // prefer convenience over performance here for tests
if s.Asset == a && strings.HasPrefix(s.Channel, prefix) {
if len(expected) == 1 && !strings.Contains(s.Channel, expected[0]) {
continue
}
if sub != nil {
assert.Failf(tb, "Too many subs with prefix", "Asset %s; Prefix %s", a.String(), prefix)
return
}
sub = &subs[i]
}
}
if assert.NotNil(tb, sub, "Should find a sub for asset %s with prefix %s for %s", a.String(), prefix, strings.Join(expected, ", ")) {
suffix := strings.TrimPrefix(sub.Channel, prefix)
if len(expected) == 0 {
assert.Empty(tb, suffix, "Sub for asset %s with prefix %s should have no symbol suffix", a.String(), prefix)
} else {
currs := strings.Split(suffix, ",")
assert.ElementsMatch(tb, currs, expected, "Currencies should match in sub for asset %s with prefix %s", a.String(), prefix)
}
}
}
// Pairs for Subscription tests:
// Only in Spot: BTC-USDT, ETH-USDT
// In Both: ETH-BTC, LTC-USDT
// Only in Margin: TRX-BTC, SOL-USDC
func TestGenerateDefaultSubscriptions(t *testing.T) {
t.Parallel()
subs, err := ku.GenerateDefaultSubscriptions()
assert.NoError(t, err, "GenerateDefaultSubscriptions should not error")
assert.Len(t, subs, 11, "Should generate the correct number of subs when not logged in")
verifySubs(t, subs, asset.Spot, "/market/ticker:all") // This takes care of margin as well.
verifySubs(t, subs, asset.Spot, "/market/match:", "BTC-USDT", "ETH-USDT", "LTC-USDT", "ETH-BTC")
verifySubs(t, subs, asset.Margin, "/market/match:", "SOL-USDC", "TRX-BTC")
verifySubs(t, subs, asset.Spot, "/spotMarket/level2Depth5:", "BTC-USDT", "ETH-USDT", "LTC-USDT", "ETH-BTC")
verifySubs(t, subs, asset.Margin, "/spotMarket/level2Depth5:", "SOL-USDC", "TRX-BTC")
for _, c := range []string{"ETHUSDCM", "XBTUSDCM", "SOLUSDTM"} {
verifySubs(t, subs, asset.Futures, "/contractMarket/tickerV2:", c)
verifySubs(t, subs, asset.Futures, "/contractMarket/level2Depth50:", c)
}
}
func TestGenerateAuthSubscriptions(t *testing.T) {
t.Parallel()
// Create a parallel safe Kucoin to mess with
nu := new(Kucoin)
nu.Base.Features = ku.Base.Features
assert.NoError(t, nu.CurrencyPairs.Load(&ku.CurrencyPairs), "Loading Pairs should not error")
nu.Websocket = sharedtestvalues.NewTestWebsocket()
nu.Websocket.SetCanUseAuthenticatedEndpoints(true)
subs, err := nu.GenerateDefaultSubscriptions()
assert.NoError(t, err, "GenerateDefaultSubscriptions with Auth should not error")
assert.Len(t, subs, 24, "Should generate the correct number of subs when logged in")
verifySubs(t, subs, asset.Spot, "/market/ticker:all") // This takes care of margin as well.
verifySubs(t, subs, asset.Spot, "/market/match:", "BTC-USDT", "ETH-USDT", "LTC-USDT", "ETH-BTC")
verifySubs(t, subs, asset.Margin, "/market/match:", "SOL-USDC", "TRX-BTC")
verifySubs(t, subs, asset.Spot, "/spotMarket/level2Depth5:", "BTC-USDT", "ETH-USDT", "LTC-USDT", "ETH-BTC")
verifySubs(t, subs, asset.Margin, "/spotMarket/level2Depth5:", "SOL-USDC", "TRX-BTC")
for _, c := range []string{"ETHUSDCM", "XBTUSDCM", "SOLUSDTM"} {
verifySubs(t, subs, asset.Futures, "/contractMarket/tickerV2:", c)
verifySubs(t, subs, asset.Futures, "/contractMarket/level2Depth50:", c)
}
for _, c := range []string{"SOL", "BTC", "TRX", "LTC", "USDC", "USDT", "ETH"} {
verifySubs(t, subs, asset.Margin, "/margin/loan:", c)
}
verifySubs(t, subs, asset.Spot, "/account/balance")
verifySubs(t, subs, asset.Margin, "/margin/position")
verifySubs(t, subs, asset.Margin, "/margin/fundingBook:", "SOL", "BTC", "TRX", "LTC", "USDT", "USDC", "ETH")
verifySubs(t, subs, asset.Futures, "/contractAccount/wallet")
verifySubs(t, subs, asset.Futures, "/contractMarket/advancedOrders")
verifySubs(t, subs, asset.Futures, "/contractMarket/tradeOrders")
}
func TestGenerateCandleSubscription(t *testing.T) {
t.Parallel()
// Create a parallel safe Kucoin to mess with
nu := new(Kucoin)
nu.Base.Features = ku.Base.Features
nu.Websocket = sharedtestvalues.NewTestWebsocket()
assert.NoError(t, nu.CurrencyPairs.Load(&ku.CurrencyPairs), "Loading Pairs should not error")
nu.Features.Subscriptions = []*subscription.Subscription{
{Channel: subscription.CandlesChannel, Interval: kline.FourHour},
}
subs, err := nu.GenerateDefaultSubscriptions()
assert.NoError(t, err, "GenerateDefaultSubscriptions with Candles should not error")
assert.Len(t, subs, 6, "Should generate the correct number of subs for candles")
for _, c := range []string{"BTC-USDT", "ETH-USDT", "LTC-USDT", "ETH-BTC"} {
verifySubs(t, subs, asset.Spot, "/market/candles:", c+"_4hour")
}
for _, c := range []string{"SOL-USDC", "TRX-BTC"} {
verifySubs(t, subs, asset.Margin, "/market/candles:", c+"_4hour")
}
}
func TestGenerateMarketSubscription(t *testing.T) {
t.Parallel()
// Create a parallel safe Kucoin to mess with
nu := new(Kucoin)
nu.Base.Features = ku.Base.Features
nu.Websocket = sharedtestvalues.NewTestWebsocket()
assert.NoError(t, nu.CurrencyPairs.Load(&ku.CurrencyPairs), "Loading Pairs should not error")
nu.Features.Subscriptions = []*subscription.Subscription{
{Channel: marketSnapshotChannel},
}
subs, err := nu.GenerateDefaultSubscriptions()
assert.NoError(t, err, "GenerateDefaultSubscriptions with MarketSnapshot should not error")
assert.Len(t, subs, 7, "Should generate the correct number of subs for snapshot")
for _, c := range []string{"BTC", "ETH", "LTC", "USDT"} {
verifySubs(t, subs, asset.Spot, "/market/snapshot:", c)
}
for _, c := range []string{"SOL", "USDC", "TRX"} {
verifySubs(t, subs, asset.Margin, "/market/snapshot:", c)
}
}
func TestGetAvailableTransferChains(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
if _, err := ku.GetAvailableTransferChains(context.Background(), currency.BTC); err != nil {
t.Error(err)
}
}
func TestGetWithdrawalsHistory(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
if _, err := ku.GetWithdrawalsHistory(context.Background(), currency.BTC, asset.Futures); err != nil {
t.Error(err)
}
if _, err := ku.GetWithdrawalsHistory(context.Background(), currency.BTC, asset.Spot); err != nil {
t.Error(err)
}
if _, err := ku.GetWithdrawalsHistory(context.Background(), currency.BTC, asset.Margin); !errors.Is(err, asset.ErrNotSupported) {
t.Error(err)
}
}
func TestGetOrderInfo(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
var err error
_, err = ku.GetOrderInfo(context.Background(), "123", futuresTradablePair, asset.Futures)
if err != nil {
t.Errorf("expected %s, but found %v", "Order does not exist", err)
}
_, err = ku.GetOrderInfo(context.Background(), "123", futuresTradablePair, asset.Spot)
if err != nil {
t.Errorf("expected %s, but found %v", "Order does not exist", err)
}
_, err = ku.GetOrderInfo(context.Background(), "123", futuresTradablePair, asset.Margin)
if err != nil {
t.Errorf("expected %s, but found %v", "Order does not exist", err)
}
}
func TestGetDepositAddress(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
if _, err := ku.GetDepositAddress(context.Background(), currency.BTC, "", ""); err != nil && !errors.Is(err, errNoDepositAddress) {
t.Error(err)
}
}
func TestWithdrawCryptocurrencyFunds(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
withdrawCryptoRequest := withdraw.Request{
Exchange: ku.Name,
Amount: 0.00000000001,
Currency: currency.BTC,
Crypto: withdraw.CryptoRequest{
Address: core.BitcoinDonationAddress,
},
}
if _, err := ku.WithdrawCryptocurrencyFunds(context.Background(), &withdrawCryptoRequest); err != nil {
t.Error(err)
}
}
func TestSubmitOrder(t *testing.T) {
t.Parallel()
orderSubmission := &order.Submit{
Pair: spotTradablePair,
Exchange: ku.Name,
Side: order.Bid,
Type: order.Limit,
Price: 1,
Amount: 100000,
ClientOrderID: "myOrder",
AssetType: asset.Spot,
}
orderSubmission.AssetType = asset.Options
_, err := ku.SubmitOrder(context.Background(), orderSubmission)
if !errors.Is(err, asset.ErrNotSupported) {
t.Errorf("expected %v, but found %v", asset.ErrNotSupported, err)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
orderSubmission.AssetType = asset.Spot
orderSubmission.Side = order.Buy
orderSubmission.Pair = spotTradablePair
_, err = ku.SubmitOrder(context.Background(), orderSubmission)
if err != order.ErrTypeIsInvalid {
t.Errorf("expected %v, but found %v", order.ErrTypeIsInvalid, err)
}
orderSubmission.AssetType = asset.Spot
orderSubmission.Pair = spotTradablePair
_, err = ku.SubmitOrder(context.Background(), orderSubmission)
if err != nil {
t.Error(err)
}
orderSubmission.AssetType = asset.Margin
orderSubmission.Pair = marginTradablePair
_, err = ku.SubmitOrder(context.Background(), orderSubmission)
if err != nil {
t.Error(err)
}
orderSubmission.AssetType = asset.Margin
orderSubmission.Pair = marginTradablePair
orderSubmission.MarginType = margin.Isolated
_, err = ku.SubmitOrder(context.Background(), orderSubmission)
if err != nil {
t.Error(err)
}
orderSubmission.AssetType = asset.Futures
orderSubmission.Pair = futuresTradablePair
_, err = ku.SubmitOrder(context.Background(), orderSubmission)
if !errors.Is(err, errInvalidLeverage) {
t.Error(err)
}
orderSubmission.Leverage = 0.01
_, err = ku.SubmitOrder(context.Background(), orderSubmission)
if err != nil {
t.Error(err)
}
}
func TestCancelOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
var orderCancellation = &order.Cancel{
OrderID: "1",
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: spotTradablePair,
AssetType: asset.Spot,
}
if err := ku.CancelOrder(context.Background(), orderCancellation); err != nil {
t.Error(err)
}
orderCancellation.Pair = marginTradablePair
orderCancellation.AssetType = asset.Margin
if err := ku.CancelOrder(context.Background(), orderCancellation); err != nil {
t.Error(err)
}
orderCancellation.Pair = futuresTradablePair
orderCancellation.AssetType = asset.Futures
if err := ku.CancelOrder(context.Background(), orderCancellation); err != nil {
t.Error(err)
}
}
func TestCancelAllOrders(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
if _, err := ku.CancelAllOrders(context.Background(), &order.Cancel{
AssetType: asset.Futures,
MarginType: margin.Isolated,
}); err != nil {
t.Error(err)
}
if _, err := ku.CancelAllOrders(context.Background(), &order.Cancel{
AssetType: asset.Margin,
MarginType: margin.Isolated,
}); err != nil {
t.Error(err)
}
if _, err := ku.CancelAllOrders(context.Background(), &order.Cancel{
AssetType: asset.Spot,
MarginType: margin.Isolated,
}); err != nil {
t.Error(err)
}
}
const (
subUserResponseJSON = `{"userId":"635002438793b80001dcc8b3", "uid":62356, "subName":"margin01", "status":2, "type":4, "access":"Margin", "createdAt":1666187844000, "remarks":null }`
positionSettlementPushData = `{"userId": "xbc453tg732eba53a88ggyt8c", "topic": "/contract/position:XBTUSDM", "subject": "position.settlement", "data": { "fundingTime": 1551770400000, "qty": 100, "markPrice": 3610.85, "fundingRate": -0.002966, "fundingFee": -296, "ts": 1547697294838004923, "settleCurrency": "XBT" } }`
transferFuturesFundsResponseJSON = `{"applyId": "620a0bbefeaa6a000110e833", "bizNo": "620a0bbefeaa6a000110e832", "payAccountType": "CONTRACT", "payTag": "DEFAULT", "remark": "", "recAccountType": "MAIN", "recTag": "DEFAULT", "recRemark": "", "recSystem": "KUCOIN", "status": "PROCESSING", "currency": "USDT", "amount": "0.001", "fee": "0", "sn": 889048787670001, "reason": "", "createdAt": 1644825534000, "updatedAt": 1644825534000 }`
modifySubAccountSpotAPIs = `{"subName": "AAAAAAAAAA0007", "remark": "remark", "apiKey": "630325e0e750870001829864", "apiSecret": "110f31fc-61c5-4baf-a29f-3f19a62bbf5d", "passphrase": "passphrase", "permission": "General", "ipWhitelist": "", "createdAt": 1661150688000 }`
)
func TestCreateSubUser(t *testing.T) {
t.Parallel()
var resp *SubAccount
err := json.Unmarshal([]byte(subUserResponseJSON), &resp)
if err != nil {
t.Fatal(err)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
if _, err := ku.CreateSubUser(context.Background(), "SamuaelTee1", "sdfajdlkad", "", ""); err != nil {
t.Error(err)
}
}
func TestGetSubAccountSpotAPIList(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
if _, err := ku.GetSubAccountSpotAPIList(context.Background(), "sam", ""); err != nil {
t.Error(err)
}
}
func TestCreateSpotAPIsForSubAccount(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
if _, err := ku.CreateSpotAPIsForSubAccount(context.Background(), &SpotAPISubAccountParams{
SubAccountName: "gocryptoTrader1",
Passphrase: "mysecretPassphrase123",
Remark: "123456",
}); err != nil {
t.Error(err)
}
}
func TestModifySubAccountSpotAPIs(t *testing.T) {
t.Parallel()
var resp SpotAPISubAccount
err := json.Unmarshal([]byte(modifySubAccountSpotAPIs), &resp)
if err != nil {
t.Fatal(err)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
if _, err := ku.ModifySubAccountSpotAPIs(context.Background(), &SpotAPISubAccountParams{
SubAccountName: "gocryptoTrader1",
Passphrase: "mysecretPassphrase123",
Remark: "123456",
}); err != nil {
t.Error(err)
}
}
func TestDeleteSubAccountSpotAPI(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
if _, err := ku.DeleteSubAccountSpotAPI(context.Background(), apiKey, "mysecretPassphrase123", "gocryptoTrader1"); err != nil {
t.Error(err)
}
}
func TestGetUserInfoOfAllSubAccounts(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
if _, err := ku.GetUserInfoOfAllSubAccounts(context.Background()); err != nil {
t.Error(err)
}
}
func TestGetPaginatedListOfSubAccounts(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
if _, err := ku.GetPaginatedListOfSubAccounts(context.Background(), 1, 100); err != nil {
t.Error(err)
}
}
func setupWS() {
if !ku.Websocket.IsEnabled() {
return
}
if !sharedtestvalues.AreAPICredentialsSet(ku) {
ku.Websocket.SetCanUseAuthenticatedEndpoints(false)
}
err := ku.WsConnect()
if err != nil {
log.Fatal(err)
}
}
func TestGetFundingHistory(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.GetAccountFundingHistory(context.Background())
if err != nil {
t.Error(err)
}
}
func getFirstTradablePairOfAssets() {
if err := ku.UpdateTradablePairs(context.Background(), true); err != nil {
log.Fatalf("Kucoin error while updating tradable pairs. %v", err)
}
enabledPairs, err := ku.GetEnabledPairs(asset.Spot)
if err != nil {
log.Fatalf("Kucoin %v, trying to get %v enabled pairs error", err, asset.Spot)
}
spotTradablePair = enabledPairs[0]
enabledPairs, err = ku.GetEnabledPairs(asset.Margin)
if err != nil {
log.Fatalf("Kucoin %v, trying to get %v enabled pairs error", err, asset.Margin)
}
marginTradablePair = enabledPairs[0]
enabledPairs, err = ku.GetEnabledPairs(asset.Futures)
if err != nil {
log.Fatalf("Kucoin %v, trying to get %v enabled pairs error", err, asset.Futures)
}
futuresTradablePair = enabledPairs[0]
futuresTradablePair.Delimiter = ""
}
func TestFetchAccountInfo(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
var err error
_, err = ku.FetchAccountInfo(context.Background(), asset.Spot)
if err != nil {
t.Fatal(err)
}
_, err = ku.FetchAccountInfo(context.Background(), asset.Margin)
if err != nil {
t.Fatal(err)
}
_, err = ku.FetchAccountInfo(context.Background(), asset.Futures)
if err != nil {
t.Fatal(err)
}
}
func TestUpdateAccountInfo(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
_, err := ku.UpdateAccountInfo(context.Background(), asset.Spot)
if err != nil {
t.Error("Kucoin UpdateAccountInfo() error", err)
}
_, err = ku.UpdateAccountInfo(context.Background(), asset.Futures)
if err != nil {
t.Error("Kucoin UpdateAccountInfo() error", err)
}
_, err = ku.UpdateAccountInfo(context.Background(), asset.Margin)
if err != nil {
t.Error("Kucoin UpdateAccountInfo() error", err)
}
}
const (
orderbookLevel5PushData = `{"type": "message","topic": "/spotMarket/level2Depth50:BTC-USDT","subject": "level2","data": {"asks": [["21621.7","3.03206193"],["21621.8","1.00048239"],["21621.9","0.29558803"],["21622","0.0049653"],["21622.4","0.06177582"],["21622.9","0.39664116"],["21623.7","0.00803466"],["21624.2","0.65405"],["21624.3","0.34661426"],["21624.6","0.00035589"],["21624.9","0.61282048"],["21625.2","0.16421424"],["21625.4","0.90107014"],["21625.5","0.73484442"],["21625.9","0.04"],["21626.2","0.28569324"],["21626.4","0.18403701"],["21627.1","0.06503999"],["21627.2","0.56105832"],["21627.7","0.10649999"],["21628.1","2.66459953"],["21628.2","0.32"],["21628.5","0.27605551"],["21628.6","1.59482596"],["21628.9","0.16"],["21629.8","0.08"],["21630","0.04"],["21631.6","0.1"],["21631.8","0.0920185"],["21633.6","0.00447983"],["21633.7","0.00015044"],["21634.3","0.32193346"],["21634.4","0.00004"],["21634.5","0.1"],["21634.6","0.0002865"],["21635.6","0.12069941"],["21635.8","0.00117158"],["21636","0.00072816"],["21636.5","0.98611492"],["21636.6","0.00007521"],["21637.2","0.00699999"],["21637.6","0.00017129"],["21638","0.00013035"],["21638.1","0.05"],["21638.5","0.92427"],["21639.2","1.84998696"],["21639.3","0.04827233"],["21640","0.56255996"],["21640.9","0.8"],["21641","0.12"]],"bids": [["21621.6","0.40949924"],["21621.5","0.27703279"],["21621.3","0.04"],["21621.1","0.0086"],["21621","0.6653104"],["21620.9","0.35435999"],["21620.8","0.37224309"],["21620.5","0.416184"],["21620.3","0.24"],["21619.6","0.13883999"],["21619.5","0.21053355"],["21618.7","0.2"],["21618.6","0.001"],["21618.5","0.2258151"],["21618.4","0.06503999"],["21618.3","0.00370056"],["21618","0.12067842"],["21617.7","0.34844131"],["21617.6","0.92845495"],["21617.5","0.66460535"],["21617","0.01"],["21616.7","0.0004624"],["21616.4","0.02"],["21615.6","0.04828251"],["21615","0.59065665"],["21614.4","0.00227"],["21614.3","0.1"],["21613","0.32193346"],["21612.9","0.0028638"],["21612.6","0.1"],["21612.5","0.92539"],["21610.7","0.08208616"],["21610.6","0.00967666"],["21610.3","0.12"],["21610.2","0.00611126"],["21609.9","0.00226344"],["21609.8","0.00315812"],["21609.1","0.00547218"],["21608.6","0.09793157"],["21608.5","0.00437793"],["21608.4","1.85013454"],["21608.1","0.00366647"],["21607.9","0.00611595"],["21607.7","0.83263561"],["21607.6","0.00368919"],["21607.5","0.00280702"],["21607.1","0.66610849"],["21606.8","0.00364164"],["21606.2","0.80351642"],["21605.7","0.075"]],"timestamp": 1676319280783}}`
wsOrderbookData = `{"changes":{"asks":[["21621.7","3.03206193",""],["21621.8","1.00048239",""],["21621.9","0.29558803",""],["21622","0.0049653",""],["21622.4","0.06177582",""],["21622.9","0.39664116",""],["21623.7","0.00803466",""],["21624.2","0.65405",""],["21624.3","0.34661426",""],["21624.6","0.00035589",""],["21624.9","0.61282048",""],["21625.2","0.16421424",""],["21625.4","0.90107014",""],["21625.5","0.73484442",""],["21625.9","0.04",""],["21626.2","0.28569324",""],["21626.4","0.18403701",""],["21627.1","0.06503999",""],["21627.2","0.56105832",""],["21627.7","0.10649999",""],["21628.1","2.66459953",""],["21628.2","0.32",""],["21628.5","0.27605551",""],["21628.6","1.59482596",""],["21628.9","0.16",""],["21629.8","0.08",""],["21630","0.04",""],["21631.6","0.1",""],["21631.8","0.0920185",""],["21633.6","0.00447983",""],["21633.7","0.00015044",""],["21634.3","0.32193346",""],["21634.4","0.00004",""],["21634.5","0.1",""],["21634.6","0.0002865",""],["21635.6","0.12069941",""],["21635.8","0.00117158",""],["21636","0.00072816",""],["21636.5","0.98611492",""],["21636.6","0.00007521",""],["21637.2","0.00699999",""],["21637.6","0.00017129",""],["21638","0.00013035",""],["21638.1","0.05",""],["21638.5","0.92427",""],["21639.2","1.84998696",""],["21639.3","0.04827233",""],["21640","0.56255996",""],["21640.9","0.8",""],["21641","0.12",""]],"bids":[["21621.6","0.40949924",""],["21621.5","0.27703279",""],["21621.3","0.04",""],["21621.1","0.0086",""],["21621","0.6653104",""],["21620.9","0.35435999",""],["21620.8","0.37224309",""],["21620.5","0.416184",""],["21620.3","0.24",""],["21619.6","0.13883999",""],["21619.5","0.21053355",""],["21618.7","0.2",""],["21618.6","0.001",""],["21618.5","0.2258151",""],["21618.4","0.06503999",""],["21618.3","0.00370056",""],["21618","0.12067842",""],["21617.7","0.34844131",""],["21617.6","0.92845495",""],["21617.5","0.66460535",""],["21617","0.01",""],["21616.7","0.0004624",""],["21616.4","0.02",""],["21615.6","0.04828251",""],["21615","0.59065665",""],["21614.4","0.00227",""],["21614.3","0.1",""],["21613","0.32193346",""],["21612.9","0.0028638",""],["21612.6","0.1",""],["21612.5","0.92539",""],["21610.7","0.08208616",""],["21610.6","0.00967666",""],["21610.3","0.12",""],["21610.2","0.00611126",""],["21609.9","0.00226344",""],["21609.8","0.00315812",""],["21609.1","0.00547218",""],["21608.6","0.09793157",""],["21608.5","0.00437793",""],["21608.4","1.85013454",""],["21608.1","0.00366647",""],["21607.9","0.00611595",""],["21607.7","0.83263561",""],["21607.6","0.00368919",""],["21607.5","0.00280702",""],["21607.1","0.66610849",""],["21606.8","0.00364164",""],["21606.2","0.80351642",""],["21605.7","0.075",""]]},"sequenceEnd":1676319280783,"sequenceStart":0,"symbol":"BTC-USDT","time":1676319280783}`
)
func TestProcessOrderbook(t *testing.T) {
t.Parallel()
response := &WsOrderbook{}
err := json.Unmarshal([]byte(wsOrderbookData), &response)
if err != nil {
t.Error(err)
}
_, err = ku.UpdateLocalBuffer(response, asset.Spot)
if err != nil {
t.Error(err)
}
err = ku.processOrderbook([]byte(orderbookLevel5PushData), "BTC-USDT", "")
if err != nil {
t.Error(err)
}
err = ku.wsHandleData([]byte(orderbookLevel5PushData))
if err != nil {
t.Error(err)
}
}
func TestProcessMarketSnapshot(t *testing.T) {
t.Parallel()
n := new(Kucoin)
sharedtestvalues.TestFixtureToDataHandler(t, ku, n, "testdata/wsMarketSnapshot.json", n.wsHandleData)
seen := 0
seenAssetTypes := map[asset.Item]int{}
for reading := true; reading; {
select {
default:
reading = false
case resp := <-n.GetBase().Websocket.DataHandler:
seen++
switch v := resp.(type) {
case *ticker.Price:
switch seen {
case 1:
assert.Equal(t, asset.Margin, v.AssetType, "AssetType")
assert.Equal(t, time.UnixMilli(1700555342007), v.LastUpdated, "datetime")
assert.Equal(t, 0.004445, v.High, "high")
assert.Equal(t, 0.004415, v.Last, "lastTradedPrice")
assert.Equal(t, 0.004191, v.Low, "low")
assert.Equal(t, currency.NewPairWithDelimiter("TRX", "BTC", "-"), v.Pair, "symbol")
assert.Equal(t, 13097.3357, v.Volume, "volume")
assert.Equal(t, 57.44552981, v.QuoteVolume, "volValue")
case 2, 3:
assert.Equal(t, time.UnixMilli(1700555340197), v.LastUpdated, "datetime")
assert.Contains(t, []asset.Item{asset.Spot, asset.Margin}, v.AssetType, "AssetType is Spot or Margin")
seenAssetTypes[v.AssetType]++
assert.Equal(t, 1, seenAssetTypes[v.AssetType], "Each Asset Type is sent only once per unique snapshot")
assert.Equal(t, 0.054846, v.High, "high")
assert.Equal(t, 0.053778, v.Last, "lastTradedPrice")
assert.Equal(t, 0.05364, v.Low, "low")
assert.Equal(t, currency.NewPairWithDelimiter("ETH", "BTC", "-"), v.Pair, "symbol")
assert.Equal(t, 2958.3139116, v.Volume, "volume")
assert.Equal(t, 160.7847672784213, v.QuoteVolume, "volValue")
case 4:
assert.Equal(t, asset.Spot, v.AssetType, "AssetType")
assert.Equal(t, time.UnixMilli(1700555342151), v.LastUpdated, "datetime")
assert.Equal(t, 37750.0, v.High, "high")
assert.Equal(t, 37366.8, v.Last, "lastTradedPrice")
assert.Equal(t, 36700.0, v.Low, "low")
assert.Equal(t, currency.NewPairWithDelimiter("BTC", "USDT", "-"), v.Pair, "symbol")
assert.Equal(t, 2900.37846402, v.Volume, "volume")
assert.Equal(t, 108210331.34015164, v.QuoteVolume, "volValue")
default:
t.Errorf("Got an unexpected *ticker.Price: %v", v)
}
case error:
t.Error(v)
default:
t.Errorf("Got unexpected data: %T %v", v, v)
}
}
}
assert.Equal(t, 4, seen, "Number of messages")
}
func TestSubscribeMarketSnapshot(t *testing.T) {
t.Parallel()
setupWS()
err := ku.Subscribe([]subscription.Subscription{{Channel: marketSymbolSnapshotChannel, Pair: currency.Pair{Base: currency.BTC}}})
assert.NoError(t, err, "Subscribe to MarketSnapshot should not error")
}
func TestSeedLocalCache(t *testing.T) {
t.Parallel()
pair, err := currency.NewPairFromString("ETH-USDT")
if err != nil {
t.Error(err)
}
err = ku.SeedLocalCache(context.Background(), pair, asset.Margin)
if err != nil {
t.Error(err)
}
}
func TestGetFuturesContractDetails(t *testing.T) {
t.Parallel()
_, err := ku.GetFuturesContractDetails(context.Background(), asset.Spot)
assert.ErrorIs(t, err, futures.ErrNotFuturesAsset)
_, err = ku.GetFuturesContractDetails(context.Background(), asset.USDTMarginedFutures)
assert.ErrorIs(t, err, asset.ErrNotSupported)
_, err = ku.GetFuturesContractDetails(context.Background(), asset.Futures)
assert.NoError(t, err)
}
func TestGetLatestFundingRates(t *testing.T) {
t.Parallel()
_, err := ku.GetLatestFundingRates(context.Background(), nil)
assert.ErrorIs(t, err, common.ErrNilPointer)
req := &fundingrate.LatestRateRequest{
Asset: asset.Futures,
Pair: currency.NewPair(currency.BTC, currency.USD),
}
_, err = ku.GetLatestFundingRates(context.Background(), req)
assert.ErrorIs(t, err, futures.ErrNotPerpetualFuture)
req = &fundingrate.LatestRateRequest{
Asset: asset.Futures,
Pair: currency.NewPair(currency.XBT, currency.USDTM),
}
resp, err := ku.GetLatestFundingRates(context.Background(), req)
assert.NoError(t, err)
assert.Len(t, resp, 1)
req = &fundingrate.LatestRateRequest{
Asset: asset.Futures,
Pair: currency.EMPTYPAIR,
}
resp, err = ku.GetLatestFundingRates(context.Background(), req)
assert.NoError(t, err)
assert.NotEmpty(t, resp)
}
func TestIsPerpetualFutureCurrency(t *testing.T) {
t.Parallel()
is, err := ku.IsPerpetualFutureCurrency(asset.Spot, currency.EMPTYPAIR)
assert.NoError(t, err)
assert.False(t, is)
is, err = ku.IsPerpetualFutureCurrency(asset.Futures, currency.EMPTYPAIR)
assert.NoError(t, err)
assert.False(t, is)
is, err = ku.IsPerpetualFutureCurrency(asset.Futures, currency.NewPair(currency.XBT, currency.EOS))
assert.NoError(t, err)
assert.False(t, is)
is, err = ku.IsPerpetualFutureCurrency(asset.Futures, currency.NewPair(currency.XBT, currency.USDTM))
assert.NoError(t, err)
assert.True(t, is)
is, err = ku.IsPerpetualFutureCurrency(asset.Futures, currency.NewPair(currency.XBT, currency.USDM))
assert.NoError(t, err)
assert.True(t, is)
}
func TestChangePositionMargin(t *testing.T) {
t.Parallel()
_, err := ku.ChangePositionMargin(context.Background(), nil)
assert.ErrorIs(t, err, common.ErrNilPointer)
req := &margin.PositionChangeRequest{}
_, err = ku.ChangePositionMargin(context.Background(), req)
assert.ErrorIs(t, err, futures.ErrNotFuturesAsset)
req.Asset = asset.Futures
_, err = ku.ChangePositionMargin(context.Background(), req)
assert.ErrorIs(t, err, currency.ErrCurrencyPairEmpty)
req.Pair = currency.NewPair(currency.XBT, currency.USDTM)
_, err = ku.ChangePositionMargin(context.Background(), req)
assert.ErrorIs(t, err, margin.ErrMarginTypeUnsupported)
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
req.MarginType = margin.Isolated
_, err = ku.ChangePositionMargin(context.Background(), req)
assert.Error(t, err)
req.NewAllocatedMargin = 1337
_, err = ku.ChangePositionMargin(context.Background(), req)
assert.NoError(t, err)
}
func TestGetFuturesPositionSummary(t *testing.T) {
t.Parallel()
_, err := ku.GetFuturesPositionSummary(context.Background(), nil)
assert.ErrorIs(t, err, common.ErrNilPointer)
req := &futures.PositionSummaryRequest{}
_, err = ku.GetFuturesPositionSummary(context.Background(), req)
assert.ErrorIs(t, err, futures.ErrNotPerpetualFuture)
req.Asset = asset.Futures
_, err = ku.GetFuturesPositionSummary(context.Background(), req)
assert.ErrorIs(t, err, currency.ErrCurrencyPairEmpty)
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
req.Pair = currency.NewPair(currency.XBT, currency.USDTM)
_, err = ku.GetFuturesPositionSummary(context.Background(), req)
assert.NoError(t, err)
}
func TestGetFuturesPositionOrders(t *testing.T) {
t.Parallel()
_, err := ku.GetFuturesPositionOrders(context.Background(), nil)
assert.ErrorIs(t, err, common.ErrNilPointer)
req := &futures.PositionsRequest{}
_, err = ku.GetFuturesPositionOrders(context.Background(), req)
assert.ErrorIs(t, err, futures.ErrNotPerpetualFuture)
req.Asset = asset.Futures
_, err = ku.GetFuturesPositionOrders(context.Background(), req)
assert.ErrorIs(t, err, currency.ErrCurrencyPairEmpty)
req.Pairs = currency.Pairs{
currency.NewPair(currency.XBT, currency.USDTM),
}
_, err = ku.GetFuturesPositionOrders(context.Background(), req)
assert.ErrorIs(t, err, common.ErrDateUnset)
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
req.EndDate = time.Now()
req.StartDate = req.EndDate.Add(-time.Hour * 24 * 7)
_, err = ku.GetFuturesPositionOrders(context.Background(), req)
assert.NoError(t, err)
req.StartDate = req.EndDate.Add(-time.Hour * 24 * 30)
_, err = ku.GetFuturesPositionOrders(context.Background(), req)
assert.ErrorIs(t, err, futures.ErrOrderHistoryTooLarge)
req.RespectOrderHistoryLimits = true
_, err = ku.GetFuturesPositionOrders(context.Background(), req)
assert.NoError(t, err)
}
func TestUpdateOrderExecutionLimits(t *testing.T) {
t.Parallel()
err := ku.UpdateOrderExecutionLimits(context.Background(), asset.Binary)
if !errors.Is(err, asset.ErrNotSupported) {
t.Fatalf("Received %v, expected %v", err, asset.ErrNotSupported)
}
assets := []asset.Item{asset.Spot, asset.Futures, asset.Margin}
for x := range assets {
err = ku.UpdateOrderExecutionLimits(context.Background(), assets[x])
if !errors.Is(err, nil) {
t.Fatalf("received %v, expected %v", err, nil)
}
enabled, err := ku.GetEnabledPairs(assets[x])
if err != nil {
t.Fatal(err)
}
for y := range enabled {
lim, err := ku.GetOrderExecutionLimits(assets[x], enabled[y])
if err != nil {
t.Fatalf("%v %s %v", err, enabled[y], assets[x])
}
assert.NotEmpty(t, lim, "limit cannot be empty")
}
}
}
func TestGetOpenInterest(t *testing.T) {
t.Parallel()
nu := new(Kucoin)
require.NoError(t, testexch.TestInstance(nu), "TestInstance setup should not error")
_, err := nu.GetOpenInterest(context.Background(), key.PairAsset{
Base: currency.ETH.Item,
Quote: currency.USDT.Item,
Asset: asset.USDTMarginedFutures,
})
assert.ErrorIs(t, err, asset.ErrNotSupported)
resp, err := nu.GetOpenInterest(context.Background(), key.PairAsset{
Base: futuresTradablePair.Base.Item,
Quote: futuresTradablePair.Quote.Item,
Asset: asset.Futures,
})
assert.NoError(t, err)
assert.NotEmpty(t, resp)
cp1 := currency.NewPair(currency.ETH, currency.USDTM)
sharedtestvalues.SetupCurrencyPairsForExchangeAsset(t, nu, asset.Futures, cp1)
resp, err = nu.GetOpenInterest(context.Background(),
key.PairAsset{
Base: futuresTradablePair.Base.Item,
Quote: futuresTradablePair.Quote.Item,
Asset: asset.Futures,
},
key.PairAsset{
Base: cp1.Base.Item,
Quote: cp1.Quote.Item,
Asset: asset.Futures,
},
)
assert.NoError(t, err)
assert.NotEmpty(t, resp)
resp, err = nu.GetOpenInterest(context.Background())
assert.NoError(t, err)
assert.NotEmpty(t, resp)
}