package zb import ( "context" "encoding/json" "errors" "net/http" "strconv" "sync" "testing" "time" "github.com/gorilla/websocket" "github.com/thrasher-corp/gocryptotrader/common" "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/kline" "github.com/thrasher-corp/gocryptotrader/exchanges/order" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) // Please supply you own test keys here for due diligence testing. const ( apiKey = "" apiSecret = "" canManipulateRealOrders = false testCurrency = "btc_usdt" ) var z ZB var wsSetupRan bool func areTestAPIKeysSet() bool { return z.ValidateAPICredentials(z.GetDefaultCredentials()) == nil } func setupWsAuth(t *testing.T) { t.Helper() if wsSetupRan { return } if !z.Websocket.IsEnabled() && !z.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() || !canManipulateRealOrders { t.Skip(stream.WebsocketNotEnabled) } var dialer websocket.Dialer err := z.Websocket.Conn.Dial(&dialer, http.Header{}) if err != nil { t.Fatal(err) } go z.wsReadData() wsSetupRan = true } func TestStart(t *testing.T) { t.Parallel() err := z.Start(context.Background(), nil) if !errors.Is(err, common.ErrNilPointer) { t.Fatalf("received: '%v' but expected: '%v'", err, common.ErrNilPointer) } var testWg sync.WaitGroup err = z.Start(context.Background(), &testWg) if err != nil { t.Fatal(err) } testWg.Wait() } func TestSpotNewOrder(t *testing.T) { t.Parallel() if !areTestAPIKeysSet() || !canManipulateRealOrders { t.Skip() } arg := SpotNewOrderRequestParams{ Symbol: testCurrency, Type: SpotNewOrderRequestParamsTypeSell, Amount: 0.01, Price: 10246.1, } _, err := z.SpotNewOrder(context.Background(), arg) if err != nil { t.Errorf("ZB SpotNewOrder: %s", err) } } func TestCancelExistingOrder(t *testing.T) { t.Parallel() if !areTestAPIKeysSet() || !canManipulateRealOrders { t.Skip() } err := z.CancelExistingOrder(context.Background(), 20180629145864850, testCurrency) if err != nil { t.Errorf("ZB CancelExistingOrder: %s", err) } } func TestGetLatestSpotPrice(t *testing.T) { t.Parallel() _, err := z.GetLatestSpotPrice(context.Background(), testCurrency) if err != nil { t.Errorf("ZB GetLatestSpotPrice: %s", err) } } func TestGetTicker(t *testing.T) { t.Parallel() _, err := z.GetTicker(context.Background(), testCurrency) if err != nil { t.Errorf("ZB GetTicker: %s", err) } } func TestGetTickers(t *testing.T) { t.Parallel() _, err := z.GetTickers(context.Background()) if err != nil { t.Errorf("ZB GetTicker: %s", err) } } func TestGetOrderbook(t *testing.T) { t.Parallel() _, err := z.GetOrderbook(context.Background(), testCurrency) if err != nil { t.Errorf("ZB GetTicker: %s", err) } } func TestGetMarkets(t *testing.T) { t.Parallel() _, err := z.GetMarkets(context.Background()) if err != nil { t.Errorf("ZB GetMarkets: %s", err) } } func setFeeBuilder() *exchange.FeeBuilder { return &exchange.FeeBuilder{ Amount: 1, FeeType: exchange.CryptocurrencyTradeFee, Pair: currency.NewPairWithDelimiter(currency.LTC.String(), currency.BTC.String(), "-"), PurchasePrice: 1, FiatCurrency: currency.USD, BankTransactionType: exchange.WireTransfer, } } // TestGetFeeByTypeOfflineTradeFee logic test func TestGetFeeByTypeOfflineTradeFee(t *testing.T) { t.Parallel() var feeBuilder = setFeeBuilder() _, err := z.GetFeeByType(context.Background(), feeBuilder) if err != nil { t.Fatal(err) } if !areTestAPIKeysSet() { if feeBuilder.FeeType != exchange.OfflineTradeFee { t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType) } } else { if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee { t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType) } } } func TestGetFee(t *testing.T) { var feeBuilder = setFeeBuilder() // CryptocurrencyTradeFee Basic if _, err := z.GetFee(feeBuilder); err != nil { t.Error(err) } // CryptocurrencyTradeFee High quantity feeBuilder = setFeeBuilder() feeBuilder.Amount = 1000 feeBuilder.PurchasePrice = 1000 if _, err := z.GetFee(feeBuilder); err != nil { t.Error(err) } // CryptocurrencyTradeFee IsMaker feeBuilder = setFeeBuilder() feeBuilder.IsMaker = true if _, err := z.GetFee(feeBuilder); err != nil { t.Error(err) } // CryptocurrencyTradeFee Negative purchase price feeBuilder = setFeeBuilder() feeBuilder.PurchasePrice = -1000 if _, err := z.GetFee(feeBuilder); err != nil { t.Error(err) } // CryptocurrencyWithdrawalFee Basic feeBuilder = setFeeBuilder() feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee if _, err := z.GetFee(feeBuilder); err != nil { t.Error(err) } // CryptocurrencyWithdrawalFee Invalid currency feeBuilder = setFeeBuilder() feeBuilder.Pair.Base = currency.NewCode("hello") feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee if _, err := z.GetFee(feeBuilder); err != nil { t.Error(err) } // CryptocurrencyDepositFee Basic feeBuilder = setFeeBuilder() feeBuilder.FeeType = exchange.CryptocurrencyDepositFee if _, err := z.GetFee(feeBuilder); err != nil { t.Error(err) } // InternationalBankDepositFee Basic feeBuilder = setFeeBuilder() feeBuilder.FeeType = exchange.InternationalBankDepositFee if _, err := z.GetFee(feeBuilder); err != nil { t.Error(err) } // InternationalBankWithdrawalFee Basic feeBuilder = setFeeBuilder() feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee feeBuilder.FiatCurrency = currency.USD if _, err := z.GetFee(feeBuilder); err != nil { t.Error(err) } } func TestFormatWithdrawPermissions(t *testing.T) { expectedResult := exchange.AutoWithdrawCryptoText + " & " + exchange.NoFiatWithdrawalsText withdrawPermissions := z.FormatWithdrawPermissions() if withdrawPermissions != expectedResult { t.Errorf("Expected: %s, Received: %s", expectedResult, withdrawPermissions) } } func TestGetActiveOrders(t *testing.T) { if mockTests { t.Skip("skipping authenticated function for mock testing") } var getOrdersRequest = order.GetOrdersRequest{ Type: order.AnyType, Pairs: []currency.Pair{currency.NewPair(currency.XRP, currency.USDT)}, AssetType: asset.Spot, Side: order.AnySide, } _, err := z.GetActiveOrders(context.Background(), &getOrdersRequest) if areTestAPIKeysSet() && err != nil { t.Error(err) } else if !areTestAPIKeysSet() && err == nil { t.Error("expecting an error when no keys are set") } } func TestGetOrderHistory(t *testing.T) { if mockTests { t.Skip("skipping authenticated function for mock testing") } var getOrdersRequest = order.GetOrdersRequest{ Type: order.AnyType, Side: order.Buy, AssetType: asset.Spot, Pairs: []currency.Pair{currency.NewPair(currency.LTC, currency.BTC)}, } _, err := z.GetOrderHistory(context.Background(), &getOrdersRequest) if areTestAPIKeysSet() && err != nil { t.Error(err) } else if !areTestAPIKeysSet() && err == nil { t.Error("expecting an error when no keys are set") } } // Any tests below this line have the ability to impact your orders on the exchange. Enable canManipulateRealOrders to run them // ---------------------------------------------------------------------------------------------------------------------------- func TestSubmitOrder(t *testing.T) { if areTestAPIKeysSet() && !canManipulateRealOrders { t.Skipf("Can place orders: %v", canManipulateRealOrders) } if mockTests { t.Skip("skipping authenticated function for mock testing") } var orderSubmission = &order.Submit{ Exchange: z.Name, Pair: currency.Pair{ Delimiter: "_", Base: currency.XRP, Quote: currency.USDT, }, Side: order.Buy, Type: order.Limit, Price: 1, Amount: 1, ClientID: "meowOrder", AssetType: asset.Spot, } response, err := z.SubmitOrder(context.Background(), orderSubmission) if areTestAPIKeysSet() && err != nil { t.Error(err) } else if !areTestAPIKeysSet() && err == nil { t.Error("expecting an error when no keys are set") } if areTestAPIKeysSet() && response.OrderID == "" { t.Error("expected order id") } } func TestCancelExchangeOrder(t *testing.T) { if areTestAPIKeysSet() && !canManipulateRealOrders { t.Skip("API keys set, canManipulateRealOrders false, skipping test") } if mockTests { t.Skip("skipping authenticated function for mock testing") } currencyPair := currency.NewPair(currency.XRP, currency.USDT) var orderCancellation = &order.Cancel{ OrderID: "1", WalletAddress: core.BitcoinDonationAddress, AccountID: "1", Pair: currencyPair, AssetType: asset.Spot, } err := z.CancelOrder(context.Background(), orderCancellation) if areTestAPIKeysSet() && err != nil { t.Error(err) } else if !areTestAPIKeysSet() && err == nil { t.Error("expecting an error when no keys are set") } } func TestCancelAllExchangeOrders(t *testing.T) { if areTestAPIKeysSet() && !canManipulateRealOrders { t.Skip("API keys set, canManipulateRealOrders false, skipping test") } if mockTests { t.Skip("skipping authenticated function for mock testing") } currencyPair := currency.NewPair(currency.XRP, currency.USDT) var orderCancellation = &order.Cancel{ OrderID: "1", WalletAddress: core.BitcoinDonationAddress, AccountID: "1", Pair: currencyPair, AssetType: asset.Spot, } resp, err := z.CancelAllOrders(context.Background(), orderCancellation) if areTestAPIKeysSet() && err != nil { t.Error(err) } else if !areTestAPIKeysSet() && err == nil { t.Error("expecting an error when no keys are set") } if len(resp.Status) > 0 { t.Errorf("%v orders failed to cancel", len(resp.Status)) } } func TestGetAccountInfo(t *testing.T) { if mockTests { t.Skip("skipping authenticated function for mock testing") } if areTestAPIKeysSet() { _, err := z.UpdateAccountInfo(context.Background(), asset.Spot) if err != nil { t.Error("GetAccountInfo() error", err) } } else { _, err := z.UpdateAccountInfo(context.Background(), asset.Spot) if err == nil { t.Error("GetAccountInfo() Expected error") } } } func TestModifyOrder(t *testing.T) { if mockTests { t.Skip("skipping authenticated function for mock testing") } if areTestAPIKeysSet() && !canManipulateRealOrders { t.Skip("API keys set, canManipulateRealOrders false, skipping test") } _, err := z.ModifyOrder(context.Background(), &order.Modify{AssetType: asset.Spot}) if err == nil { t.Error("ModifyOrder() Expected error") } } func TestWithdraw(t *testing.T) { if mockTests { t.Skip("skipping authenticated function for mock testing") } if areTestAPIKeysSet() && !canManipulateRealOrders { t.Skip("API keys set, canManipulateRealOrders false, skipping test") } withdrawCryptoRequest := withdraw.Request{ Exchange: z.Name, Crypto: withdraw.CryptoRequest{ Address: core.BitcoinDonationAddress, FeeAmount: 1, }, Amount: -1, Currency: currency.BTC, Description: "WITHDRAW IT ALL", } _, err := z.WithdrawCryptocurrencyFunds(context.Background(), &withdrawCryptoRequest) if areTestAPIKeysSet() && err != nil { t.Error(err) } else if !areTestAPIKeysSet() && err == nil { t.Error("expecting an error when no keys are set") } } func TestWithdrawFiat(t *testing.T) { if mockTests { t.Skip("skipping authenticated function for mock testing") } if areTestAPIKeysSet() && !canManipulateRealOrders { t.Skip("API keys set, canManipulateRealOrders false, skipping test") } var withdrawFiatRequest = withdraw.Request{} _, err := z.WithdrawFiatFunds(context.Background(), &withdrawFiatRequest) if err != common.ErrFunctionNotSupported { t.Errorf("Expected '%v', received: '%v'", common.ErrFunctionNotSupported, err) } } func TestWithdrawInternationalBank(t *testing.T) { if mockTests { t.Skip("skipping authenticated function for mock testing") } if areTestAPIKeysSet() && !canManipulateRealOrders { t.Skip("API keys set, canManipulateRealOrders false, skipping test") } var withdrawFiatRequest = withdraw.Request{} _, err := z.WithdrawFiatFundsToInternationalBank(context.Background(), &withdrawFiatRequest) if err != common.ErrFunctionNotSupported { t.Errorf("Expected '%v', received: '%v'", common.ErrFunctionNotSupported, err) } } func TestGetDepositAddress(t *testing.T) { if mockTests { t.Skip("skipping authenticated function for mock testing") } if areTestAPIKeysSet() { _, err := z.GetDepositAddress(context.Background(), currency.XRP, "", "") if err != nil { t.Error("GetDepositAddress() error PLEASE MAKE SURE YOU CREATE DEPOSIT ADDRESSES VIA ZB.COM", err) } } else { _, err := z.GetDepositAddress(context.Background(), currency.BTC, "", "") if err == nil { t.Error("GetDepositAddress() Expected error") } } } func TestGetMultiChainDepositAddress(t *testing.T) { if mockTests { t.Skip("skipping authenticated function for mock testing") } if areTestAPIKeysSet() { _, err := z.GetMultiChainDepositAddress(context.Background(), currency.USDT) if err != nil { t.Error("GetDepositAddress() error PLEASE MAKE SURE YOU CREATE DEPOSIT ADDRESSES VIA ZB.COM", err) } } else { _, err := z.GetMultiChainDepositAddress(context.Background(), currency.USDT) if err == nil { t.Error("GetDepositAddress() Expected error") } } } // TestZBInvalidJSON ZB sends poorly formed JSON. this tests the JSON fixer // Then JSON decode it to test if successful func TestZBInvalidJSON(t *testing.T) { data := `{"success":true,"code":1000,"channel":"getSubUserList","message":"[{"isOpenApi":false,"memo":"Memo","userName":"hello@imgoodthanksandyou.com@good","userId":1337,"isFreez":false}]","no":"0"}` fixedJSON := z.wsFixInvalidJSON([]byte(data)) var response WsGetSubUserListResponse err := json.Unmarshal(fixedJSON, &response) if err != nil { t.Fatal(err) } if response.Message[0].UserID != 1337 { t.Fatal("Expected extracted JSON USERID to equal 1337") } data = `{"success":true,"code":1000,"channel":"createSubUserKey","message":"{"apiKey":"thisisnotareallykeyyousillybilly","apiSecret":"lol"}","no":"123"}` fixedJSON = z.wsFixInvalidJSON([]byte(data)) var response2 WsRequestResponse err = json.Unmarshal(fixedJSON, &response2) if err != nil { t.Error(err) } } // TestWsTransferFunds ws test func TestWsTransferFunds(t *testing.T) { setupWsAuth(t) _, err := z.wsDoTransferFunds(context.Background(), currency.BTC, 0.0001, "username1", "username2", ) if err != nil { t.Fatal(err) } } // TestGetSubUserList ws test func TestGetSubUserList(t *testing.T) { setupWsAuth(t) if _, err := z.wsGetSubUserList(context.Background()); err != nil { t.Fatal(err) } } // TestAddSubUser ws test func TestAddSubUser(t *testing.T) { setupWsAuth(t) _, err := z.wsAddSubUser(context.Background(), "1", "123456789101112aA!") if err != nil { t.Fatal(err) } } // TestWsCreateSuUserKey ws test func TestWsCreateSuUserKey(t *testing.T) { setupWsAuth(t) subUsers, err := z.wsGetSubUserList(context.Background()) if err != nil { t.Fatal(err) } if len(subUsers.Message) == 0 { t.Skip("User ID required for test to continue. Create a subuser first") } userID := subUsers.Message[0].UserID _, err = z.wsCreateSubUserKey(context.Background(), true, true, true, true, "subu", strconv.FormatInt(userID, 10)) if err != nil { t.Fatal(err) } } // TestWsSubmitOrder ws test func TestWsSubmitOrder(t *testing.T) { setupWsAuth(t) _, err := z.wsSubmitOrder(context.Background(), currency.NewPairWithDelimiter(currency.LTC.String(), currency.BTC.String(), "").Lower(), 1, 1, 1) if err != nil { t.Fatal(err) } } // TestWsCancelOrder ws test func TestWsCancelOrder(t *testing.T) { setupWsAuth(t) _, err := z.wsCancelOrder(context.Background(), currency.NewPairWithDelimiter(currency.LTC.String(), currency.BTC.String(), "").Lower(), 1234) if err != nil { t.Fatal(err) } } // TestWsGetAccountInfo ws test func TestWsGetAccountInfo(t *testing.T) { setupWsAuth(t) _, err := z.wsGetAccountInfoRequest(context.Background()) if err != nil { t.Fatal(err) } } // TestWsGetOrder ws test func TestWsGetOrder(t *testing.T) { setupWsAuth(t) _, err := z.wsGetOrder(context.Background(), currency.NewPairWithDelimiter(currency.LTC.String(), currency.BTC.String(), "").Lower(), 1234) if err != nil { t.Fatal(err) } } // TestWsGetOrders ws test func TestWsGetOrders(t *testing.T) { setupWsAuth(t) _, err := z.wsGetOrders(context.Background(), currency.NewPairWithDelimiter(currency.LTC.String(), currency.BTC.String(), "").Lower(), 1, 1) if err != nil { t.Fatal(err) } } // TestWsGetOrdersIgnoreTradeType ws test func TestWsGetOrdersIgnoreTradeType(t *testing.T) { setupWsAuth(t) _, err := z.wsGetOrdersIgnoreTradeType(context.Background(), currency.NewPairWithDelimiter(currency.LTC.String(), currency.BTC.String(), "").Lower(), 1, 1) if err != nil { t.Fatal(err) } } func TestWsMarketConfig(t *testing.T) { pressXToJSON := []byte(`{ "code":1000, "data":{ "btc_usdt":{ "amountScale":4, "priceScale":2 }, "bcc_usdt":{ "amountScale":3, "priceScale":2 } }, "success":true, "channel":"markets", "message":"操作成功。" }`) err := z.wsHandleData(pressXToJSON) if err != nil { t.Error(err) } } func TestWsTicker(t *testing.T) { pressXToJSON := []byte(`{ "channel": "ltcbtc_ticker", "date": "1472800466093", "no": "1337", "ticker": { "buy": "3826.94", "high": "3838.22", "last": "3826.94", "low": "3802.0", "sell": "3828.25", "vol": "90151.83" } }`) err := z.wsHandleData(pressXToJSON) if err != nil { t.Error(err) } } func TestWsOrderbook(t *testing.T) { pressXToJSON := []byte(`{ "asks": [ [ 3846.94, 0.659 ] ], "bids": [ [ 3826.94, 4.843 ] ], "channel": "ltcbtc_depth", "no": "1337" }`) err := z.wsHandleData(pressXToJSON) if err != nil { t.Error(err) } } func TestWsTrades(t *testing.T) { pressXToJSON := []byte(`{"data":[{"date":1581473835,"amount":"13.620","price":"242.89","trade_type":"bid","type":"buy","tid":703896035},{"date":1581473835,"amount":"0.156","price":"242.89","trade_type":"bid","type":"buy","tid":703896036}],"dataType":"trades","channel":"ethusdt_trades"}`) err := z.wsHandleData(pressXToJSON) if err != nil { t.Error(err) } } func TestWsPlaceOrderJSON(t *testing.T) { pressXToJSON := []byte(`{"message":"操作成功。","no":"1337","data":"{"entrustId":201711133673}","code":1000,"channel":"btcusdt_order","success":true}`) err := z.wsHandleData(pressXToJSON) if err != nil { t.Error(err) } } func TestWsCancelOrderJSON(t *testing.T) { pressXToJSON := []byte(`{ "success": true, "code": 1000, "channel": "ltcbtc_cancelorder", "message": "操作成功。", "no": "1337" }`) err := z.wsHandleData(pressXToJSON) if err != nil { t.Error(err) } } func TestWsGetOrderJSON(t *testing.T) { pressXToJSON := []byte(`{ "success": true, "code": 1000, "data": { "currency": "ltc_btc", "id": "20160902387645980", "price": 100, "status": 0, "total_amount": 0.01, "trade_amount": 0, "trade_date": 1472814905567, "trade_money": 0, "type": 1 }, "channel": "ltcbtc_getorder", "message": "操作成功。", "no": "1337" }`) err := z.wsHandleData(pressXToJSON) if err != nil { t.Error(err) } } func TestWsGetOrdersJSON(t *testing.T) { pressXToJSON := []byte(`{ "success": true, "code": 1000, "data": [ { "currency": "ltc_btc", "id": "20160901385862136", "price": 3700, "status": 0, "total_amount": 1.845, "trade_amount": 0, "trade_date": 1472706387742, "trade_money": 0, "type": 1 } ], "channel": "ltcbtc_getorders", "message": "操作成功。", "no": "1337" }`) err := z.wsHandleData(pressXToJSON) if err != nil { t.Error(err) } } func TestWsGetOrderIgnoreTypeJSON(t *testing.T) { pressXToJSON := []byte(`{ "success": true, "code": 1000, "data": [ { "currency": "ltc_btc", "id": "20160901385862136", "price": 3700, "status": 0, "total_amount": 1.845, "trade_amount": 0, "trade_date": 1472706387742, "trade_money": 0, "type": 1 } ], "channel": "ltcbtc_getordersignoretradetype", "message": "操作成功。", "no": "1337" }`) err := z.wsHandleData(pressXToJSON) if err != nil { t.Error(err) } } func TestWsGetUserInfo(t *testing.T) { pressXToJSON := []byte(`{ "message": "操作成功", "no": "15207605119", "data": { "coins": [ { "freez": "1.35828369", "enName": "BTC", "unitDecimal": 8, "cnName": "BTC", "unitTag": "฿", "available": "0.72771906", "key": "btc" }, { "freez": "0.011", "enName": "LTC", "unitDecimal": 8, "cnName": "LTC", "unitTag": "Ł", "available": "3.51859814", "key": "ltc" } ], "base": { "username": "15207605119", "trade_password_enabled": true, "auth_google_enabled": true, "auth_mobile_enabled": true } }, "code": 1000, "channel": "getaccountinfo", "success": true }`) err := z.wsHandleData(pressXToJSON) if err != nil { t.Error(err) } } func TestWsGetSubUsersResponse(t *testing.T) { pressXToJSON := []byte(`{"success": true,"code": 1000,"channel": "getSubUserList","message": "[{"isOpenApi": false,"memo": "1","userName": "15914665280@1","userId": 110980,"isFreez": false}, {"isOpenApi": false,"memo": "2","userName": "15914665280@2","userId": 110984,"isFreez": false}, {"isOpenApi": false,"memo": "test3","userName": "15914665280@3","userId": 111014,"isFreez": false}]","no": "0"}`) err := z.wsHandleData(pressXToJSON) if err != nil { t.Error(err) } } func TestWsCreateSubUserResponse(t *testing.T) { pressXToJSON := []byte(`{ "success": true, "code": 1000, "channel": "createSubUserKey", "message": "{"apiKey ":"41 bf75f9 - 525e-4876 - 8257 - b880a938d4d2 ","apiSecret ":"046 b4706fe88b5728991274962d7fc46b4779c0c"}", "no": "1337" }`) err := z.wsHandleData(pressXToJSON) if err != nil { t.Error(err) } } func TestGetSpotKline(t *testing.T) { arg := KlinesRequestParams{ Symbol: testCurrency, Type: kline.OneMin.Short() + "in", Size: int64(z.Features.Enabled.Kline.ResultLimit), } if mockTests { startTime := time.Date(2020, 9, 1, 0, 0, 0, 0, time.UTC) arg.Since = startTime.UnixMilli() arg.Type = "1day" } _, err := z.GetSpotKline(context.Background(), arg) if err != nil { t.Errorf("ZB GetSpotKline: %s", err) } } func TestGetHistoricCandles(t *testing.T) { currencyPair, err := currency.NewPairFromString(testCurrency) if err != nil { t.Fatal(err) } startTime := time.Now().Add(-time.Hour * 24) endTime := time.Now() if mockTests { startTime = time.Date(2020, 9, 1, 0, 0, 0, 0, time.UTC) endTime = time.Date(2020, 9, 2, 0, 0, 0, 0, time.UTC) } // Current endpoint is dead. _, err = z.GetHistoricCandles(context.Background(), currencyPair, asset.Spot, kline.OneDay, startTime, endTime) if err != nil { t.Fatal(err) } } func TestGetHistoricCandlesExtended(t *testing.T) { currencyPair, err := currency.NewPairFromString(testCurrency) if err != nil { t.Fatal(err) } startTime := time.Now().Add(-time.Hour * 24 * 365) endTime := startTime.Add(time.Hour * 1001) _, err = z.GetHistoricCandlesExtended(context.Background(), currencyPair, asset.Spot, kline.OneHour, startTime, endTime) if !errors.Is(err, kline.ErrRequestExceedsMaxLookback) { t.Fatal(err) } startTime = time.Now().Add(-time.Hour * 24 * 365) endTime = time.Now() if mockTests { startTime = time.UnixMilli(1674489600000) endTime = startTime.Add(kline.OneDay.Duration()) } _, err = z.GetHistoricCandlesExtended(context.Background(), currencyPair, asset.Spot, kline.OneDay, startTime, endTime) if err != nil { t.Fatal(err) } } func Test_FormatExchangeKlineInterval(t *testing.T) { testCases := []struct { name string interval kline.Interval output string }{ { "OneMin", kline.OneMin, "1min", }, { "OneHour", kline.OneHour, "1hour", }, { "OneDay", kline.OneDay, "1day", }, { "ThreeDay", kline.ThreeDay, "3day", }, { "OneWeek", kline.OneWeek, "1week", }, { "AllOther", kline.FifteenDay, "", }, } for x := range testCases { test := testCases[x] t.Run(test.name, func(t *testing.T) { ret := z.FormatExchangeKlineInterval(test.interval) if ret != test.output { t.Fatalf("unexpected result return expected: %v received: %v", test.output, ret) } }) } } func TestGetTrades(t *testing.T) { t.Parallel() trades, err := z.GetTrades(context.Background(), "btc_usdt") if err != nil { t.Error(err) } if len(trades) == 0 { t.Error("expected results") } } func TestGetRecentTrades(t *testing.T) { t.Parallel() currencyPair, err := currency.NewPairFromString("btc_usdt") if err != nil { t.Fatal(err) } _, err = z.GetRecentTrades(context.Background(), currencyPair, asset.Spot) if err != nil { t.Error(err) } } func TestGetHistoricTrades(t *testing.T) { t.Parallel() currencyPair, err := currency.NewPairFromString("btc_usdt") if err != nil { t.Fatal(err) } _, err = z.GetHistoricTrades(context.Background(), currencyPair, asset.Spot, time.Now().Add(-time.Minute*15), time.Now()) if err != nil && err != common.ErrFunctionNotSupported { t.Error(err) } } func TestUpdateTicker(t *testing.T) { t.Parallel() cp, err := currency.NewPairFromString("ETH_USDT") if err != nil { t.Fatal(err) } _, err = z.UpdateTicker(context.Background(), cp, asset.Spot) if err != nil { t.Error(err) } } func TestUpdateTickers(t *testing.T) { t.Parallel() if err := z.UpdateTickers(context.Background(), asset.Spot); err != nil { t.Fatal(err) } } func TestGetAvailableTransferChains(t *testing.T) { t.Parallel() if !areTestAPIKeysSet() { t.Skip("api keys not set") } _, err := z.GetAvailableTransferChains(context.Background(), currency.BTC) if err != nil { t.Error(err) } r, err := z.GetAvailableTransferChains(context.Background(), currency.USDT) if err != nil { t.Error(err) } if len(r) != 3 { t.Error("expected 3 results") } }