Files
gocryptotrader/exchanges/okx/okx_test.go
Gareth Kirwan 8ce30a8375 Okx: Fix GetBlockTrades and enhance test coverage (#1416)
* Okx: Remove UpdateTradablePairs from TestMain

When running individual tests we do not want to be forced to update
trading pairs.
It also does not seem to be required, since disabling UpdateTradingPairs
entirely doesn't stop any tests from passing.

If it is required we can enact this pattern:
```
func TestUpdateTradablePairs(t *testing.T) {
    t.Parallel()
    updatePairsOnce(t)
}
var updatePairsGuard sync.Once
func updatePairsOnce(tb testing.TB) {
	tb.Helper()
	updatePairsGuard.Do(func() {
		err := ok.UpdateTradablePairs(context.Background(), true)
		assert.NoError(tb, err, "UpdateTradablePairs should not error")
	})
```

* Okx: Fix GetBlockTrades url

Endpoint was wrong

Not convinced we should prefix with market vs public, but not
committing a driveby

* Okx: Expand test coverage for GetBlockTrades

* Okx: Fix GetPublicBlockTrades

Was marked as an authenticated API call, and it's not.
Also renames it because without the context of "Block" (or RFQ) it's
misleading.
Adds tests.

* Okx: Fix GetPublicBlockTrades to be public

Expand coverage of GetBlockTrade and GetPublicBlockTrades
2023-12-14 15:53:39 +11:00

3754 lines
146 KiB
Go

package okx
import (
"context"
"encoding/json"
"errors"
"fmt"
"log"
"os"
"strings"
"sync"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/thrasher-corp/gocryptotrader/common"
"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/collateral"
"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/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
// Please supply your own keys here to do authenticated endpoint testing
const (
apiKey = ""
apiSecret = ""
passphrase = ""
canManipulateRealOrders = false
useTestNet = false
)
var ok = &Okx{}
func TestMain(m *testing.M) {
cfg := config.GetConfig()
err := cfg.LoadConfig("../../testdata/configtest.json", true)
if err != nil {
log.Fatal(err)
}
exchCfg, err := cfg.GetExchangeConfig("Okx")
if err != nil {
log.Fatal(err)
}
exchCfg.API.Credentials.Key = apiKey
exchCfg.API.Credentials.Secret = apiSecret
exchCfg.API.Credentials.ClientID = passphrase
ok.SetDefaults()
if apiKey != "" && apiSecret != "" && passphrase != "" {
exchCfg.API.AuthenticatedSupport = true
exchCfg.API.AuthenticatedWebsocketSupport = true
}
if !useTestNet {
ok.Websocket = sharedtestvalues.NewTestWebsocket()
}
err = ok.Setup(exchCfg)
if err != nil {
log.Fatal(err)
}
request.MaxRequestJobs = 200
if !useTestNet {
ok.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
ok.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
setupWS()
}
os.Exit(m.Run())
}
// contextGenerate sends an optional value to allow test requests
// named this way, so it shows up in auto-complete and reminds you to use it
func contextGenerate() context.Context {
ctx := context.Background()
if useTestNet {
ctx = context.WithValue(ctx, testNetKey("testnet"), useTestNet)
}
return ctx
}
func TestStart(t *testing.T) {
t.Parallel()
err := ok.Start(contextGenerate(), nil)
if !errors.Is(err, common.ErrNilPointer) {
t.Fatalf("received: '%v' but expected: '%v'", err, common.ErrNilPointer)
}
var testWg sync.WaitGroup
err = ok.Start(contextGenerate(), &testWg)
if err != nil {
t.Fatal(err)
}
testWg.Wait()
}
func TestGetTickers(t *testing.T) {
t.Parallel()
_, err := ok.GetTickers(contextGenerate(), "OPTION", "", "SOL-USD")
if err != nil {
t.Error("Okx GetTickers() error", err)
}
}
func TestGetIndexTicker(t *testing.T) {
t.Parallel()
_, err := ok.GetIndexTickers(contextGenerate(), "USDT", "NEAR-USDT-SWAP")
if err != nil {
t.Error("OKX GetIndexTicker() error", err)
}
}
func TestGetTicker(t *testing.T) {
t.Parallel()
if _, err := ok.GetTicker(contextGenerate(), "NEAR-USDT-SWAP"); err != nil {
t.Error("Okx GetTicker() error", err)
}
}
func TestGetOrderBookDepth(t *testing.T) {
t.Parallel()
_, err := ok.GetOrderBookDepth(contextGenerate(), "BTC-USDT", 400)
if err != nil {
t.Error("OKX GetOrderBookDepth() error", err)
}
}
func TestGetCandlesticks(t *testing.T) {
t.Parallel()
_, err := ok.GetCandlesticks(contextGenerate(), "BTC-USDT", kline.OneHour, time.Now().Add(-time.Minute*2), time.Now(), 2)
if err != nil {
t.Error("Okx GetCandlesticks() error", err)
}
}
func TestGetCandlesticksHistory(t *testing.T) {
t.Parallel()
_, err := ok.GetCandlesticksHistory(contextGenerate(), "BTC-USDT", kline.OneHour, time.Unix(time.Now().Unix()-int64(time.Minute), 3), time.Now(), 3)
if err != nil {
t.Error("Okx GetCandlesticksHistory() error", err)
}
}
func TestGetTrades(t *testing.T) {
t.Parallel()
_, err := ok.GetTrades(contextGenerate(), "BTC-USDT", 3)
if err != nil {
t.Error("Okx GetTrades() error", err)
}
}
func TestGetTradeHistory(t *testing.T) {
t.Parallel()
if _, err := ok.GetTradesHistory(contextGenerate(), "BTC-USDT", "", "", 2); err != nil {
t.Error("Okx GetTradeHistory() error", err)
}
}
func TestGet24HTotalVolume(t *testing.T) {
t.Parallel()
_, err := ok.Get24HTotalVolume(contextGenerate())
if err != nil {
t.Error("Okx Get24HTotalVolume() error", err)
}
}
func TestGetOracle(t *testing.T) {
t.Parallel()
_, err := ok.GetOracle(contextGenerate())
if err != nil {
t.Error("Okx GetOracle() error", err)
}
}
func TestGetExchangeRate(t *testing.T) {
t.Parallel()
_, err := ok.GetExchangeRate(contextGenerate())
if err != nil {
t.Error("Okx GetExchangeRate() error", err)
}
}
func TestGetIndexComponents(t *testing.T) {
t.Parallel()
_, err := ok.GetIndexComponents(contextGenerate(), "ETH-USDT")
if err != nil {
t.Error("Okx GetIndexComponents() error", err)
}
}
func TestGetBlockTickers(t *testing.T) {
t.Parallel()
if _, err := ok.GetBlockTickers(contextGenerate(), "SWAP", ""); err != nil {
t.Error("Okx GetBlockTickers() error", err)
}
}
func TestGetBlockTicker(t *testing.T) {
t.Parallel()
if _, err := ok.GetBlockTicker(contextGenerate(), "BTC-USDT"); err != nil {
t.Error("Okx GetBlockTicker() error", err)
}
}
func TestGetBlockTrade(t *testing.T) {
t.Parallel()
trades, err := ok.GetBlockTrades(contextGenerate(), "BTC-USDT")
assert.NoError(t, err, "GetBlockTrades should not error")
if assert.NotEmpty(t, trades, "Should get some block trades") {
trade := trades[0]
assert.Equal(t, "BTC-USDT", trade.InstrumentID, "InstrumentID should have correct value")
assert.NotEmpty(t, trade.TradeID, "TradeID should not be empty")
assert.Positive(t, trade.Price, "Price should have a positive value")
assert.Positive(t, trade.Size, "Size should have a positive value")
assert.Contains(t, []order.Side{order.Buy, order.Sell}, trade.Side, "Side should be a side")
assert.WithinRange(t, trade.Timestamp.Time(), time.Now().Add(time.Hour*-24*7), time.Now(), "Timestamp should be within last 7 days")
}
updatePairsOnce(t)
pairs, err := ok.GetAvailablePairs(asset.Options)
assert.NoError(t, err, "GetAvailablePairs should not error")
assert.NotEmpty(t, pairs, "Should get some Option pairs")
publicTrades, err := ok.GetPublicBlockTrades(contextGenerate(), "", "", 100)
assert.NoError(t, err, "GetPublicBlockTrades should not error")
tested := false
LOOP:
for _, trade := range publicTrades {
for _, leg := range trade.Legs {
p, err := ok.MatchSymbolWithAvailablePairs(leg.InstrumentID, asset.Options, true)
if err != nil {
continue
}
trades, err = ok.GetBlockTrades(contextGenerate(), p.String())
assert.NoError(t, err, "GetBlockTrades should not error on Options")
for _, trade := range trades {
assert.Equal(t, p.String(), trade.InstrumentID, "InstrumentID should have correct value")
assert.NotEmpty(t, trade.TradeID, "TradeID should not be empty")
assert.Positive(t, trade.Price, "Price should have a positive value")
assert.Positive(t, trade.Size, "Size should have a positive value")
assert.Contains(t, []order.Side{order.Buy, order.Sell}, trade.Side, "Side should be a side")
assert.Positive(t, trade.FillVolatility, "FillVolatility should have a positive value")
assert.Positive(t, trade.ForwardPrice, "ForwardPrice should have a positive value")
assert.Positive(t, trade.IndexPrice, "IndexPrice should have a positive value")
assert.Positive(t, trade.MarkPrice, "MarkPrice should have a positive value")
assert.NotEmpty(t, trade.Timestamp, "Timestamp should not be empty")
tested = true
break LOOP
}
}
}
assert.True(t, tested, "Should find at least one BlockTrade somewhere")
}
func TestGetInstrument(t *testing.T) {
t.Parallel()
_, err := ok.GetInstruments(contextGenerate(), &InstrumentsFetchParams{
InstrumentType: "OPTION",
Underlying: "SOL-USD",
})
if err != nil {
t.Error("Okx GetInstruments() error", err)
}
_, err = ok.GetInstruments(contextGenerate(), &InstrumentsFetchParams{
InstrumentType: "OPTION",
Underlying: "SOL-USD",
})
if err != nil {
t.Error("Okx GetInstruments() error", err)
}
}
func TestGetDeliveryHistory(t *testing.T) {
t.Parallel()
_, err := ok.GetDeliveryHistory(contextGenerate(), "FUTURES", "BTC-USDT", time.Time{}, time.Time{}, 3)
if err != nil {
t.Error("okx GetDeliveryHistory() error", err)
}
}
func TestGetOpenInterest(t *testing.T) {
t.Parallel()
if _, err := ok.GetOpenInterest(contextGenerate(), "FUTURES", "BTC-USDT", ""); err != nil {
t.Error("Okx GetOpenInterest() error", err)
}
}
func TestGetSingleFundingRate(t *testing.T) {
t.Parallel()
if _, err := ok.GetSingleFundingRate(context.Background(), "BTC-USD-SWAP"); err != nil {
t.Error("okx GetSingleFundingRate() error", err)
}
}
func TestGetFundingRateHistory(t *testing.T) {
t.Parallel()
if _, err := ok.GetFundingRateHistory(contextGenerate(), "BTC-USD-SWAP", time.Time{}, time.Time{}, 2); err != nil {
t.Error("Okx GetFundingRateHistory() error", err)
}
}
func TestGetLimitPrice(t *testing.T) {
t.Parallel()
if _, err := ok.GetLimitPrice(contextGenerate(), "BTC-USD-SWAP"); err != nil {
t.Error("okx GetLimitPrice() error", err)
}
}
func TestGetOptionMarketData(t *testing.T) {
t.Parallel()
if _, err := ok.GetOptionMarketData(contextGenerate(), "BTC-USD", time.Time{}); err != nil {
t.Error("Okx GetOptionMarketData() error", err)
}
}
func TestGetEstimatedDeliveryPrice(t *testing.T) {
t.Parallel()
r, err := ok.FetchTradablePairs(contextGenerate(), asset.Futures)
if err != nil {
t.Fatal(err)
}
if _, err := ok.GetEstimatedDeliveryPrice(contextGenerate(), r[0].String()); err != nil {
t.Error("Okx GetEstimatedDeliveryPrice() error", err)
}
}
func TestGetDiscountRateAndInterestFreeQuota(t *testing.T) {
t.Parallel()
_, err := ok.GetDiscountRateAndInterestFreeQuota(contextGenerate(), "", 0)
if err != nil {
t.Error("Okx GetDiscountRateAndInterestFreeQuota() error", err)
}
}
func TestGetSystemTime(t *testing.T) {
t.Parallel()
if _, err := ok.GetSystemTime(contextGenerate()); err != nil {
t.Error("Okx GetSystemTime() error", err)
}
}
func TestGetLiquidationOrders(t *testing.T) {
t.Parallel()
insts, err := ok.FetchTradablePairs(contextGenerate(), asset.Margin)
if err != nil {
t.Skip(err)
}
if _, err := ok.GetLiquidationOrders(contextGenerate(), &LiquidationOrderRequestParams{
InstrumentType: okxInstTypeMargin,
Underlying: insts[0].String(),
Currency: currency.BTC,
Limit: 2,
}); err != nil {
t.Error("Okx GetLiquidationOrders() error", err)
}
}
func TestGetMarkPrice(t *testing.T) {
t.Parallel()
if _, err := ok.GetMarkPrice(contextGenerate(), "MARGIN", "", ""); err != nil {
t.Error("Okx GetMarkPrice() error", err)
}
}
func TestGetPositionTiers(t *testing.T) {
t.Parallel()
if _, err := ok.GetPositionTiers(contextGenerate(), "FUTURES", "cross", "BTC-USDT", "", ""); err != nil {
t.Error("Okx GetPositionTiers() error", err)
}
}
func TestGetInterestRateAndLoanQuota(t *testing.T) {
t.Parallel()
if _, err := ok.GetInterestRateAndLoanQuota(contextGenerate()); err != nil {
t.Error("Okx GetInterestRateAndLoanQuota() error", err)
}
}
func TestGetInterestRateAndLoanQuotaForVIPLoans(t *testing.T) {
t.Parallel()
if _, err := ok.GetInterestRateAndLoanQuotaForVIPLoans(contextGenerate()); err != nil {
t.Error("Okx GetInterestRateAndLoanQuotaForVIPLoans() error", err)
}
}
func TestGetPublicUnderlyings(t *testing.T) {
t.Parallel()
if _, err := ok.GetPublicUnderlyings(contextGenerate(), "swap"); err != nil {
t.Error("Okx GetPublicUnderlyings() error", err)
}
}
func TestGetInsuranceFundInformation(t *testing.T) {
t.Parallel()
r, err := ok.GetInsuranceFundInformation(contextGenerate(), &InsuranceFundInformationRequestParams{
InstrumentType: "FUTURES",
Underlying: "BTC-USDT",
Limit: 2,
})
assert.NoError(t, err, "GetInsuranceFundInformation should not error")
assert.Positive(t, r.Total, "Total should be positive")
assert.NotEmpty(t, r.Details, "Should have some details")
for _, d := range r.Details {
assert.Positive(t, d.Balance, "Balance should be positive")
assert.NotEmpty(t, d.Type, "Type should not be empty")
assert.Positive(t, d.Timestamp, "Timestamp should be positive")
}
}
func TestCurrencyUnitConvert(t *testing.T) {
t.Parallel()
if _, err := ok.CurrencyUnitConvert(contextGenerate(), "BTC-USD-SWAP", 1, 3500, 1, ""); err != nil {
t.Error("Okx CurrencyUnitConvert() error", err)
}
}
// Trading related endpoints test functions.
func TestGetSupportCoins(t *testing.T) {
t.Parallel()
if _, err := ok.GetSupportCoins(contextGenerate()); err != nil {
t.Error("Okx GetSupportCoins() error", err)
}
}
func TestGetTakerVolume(t *testing.T) {
t.Parallel()
if _, err := ok.GetTakerVolume(contextGenerate(), "BTC", "SPOT", time.Time{}, time.Time{}, kline.OneDay); err != nil {
t.Error("Okx GetTakerVolume() error", err)
}
}
func TestGetMarginLendingRatio(t *testing.T) {
t.Parallel()
if _, err := ok.GetMarginLendingRatio(contextGenerate(), "BTC", time.Time{}, time.Time{}, kline.FiveMin); err != nil {
t.Error("Okx GetMarginLendingRatio() error", err)
}
}
func TestGetLongShortRatio(t *testing.T) {
t.Parallel()
if _, err := ok.GetLongShortRatio(contextGenerate(), "BTC", time.Time{}, time.Time{}, kline.OneDay); err != nil {
t.Error("Okx GetLongShortRatio() error", err)
}
}
func TestGetContractsOpenInterestAndVolume(t *testing.T) {
t.Parallel()
if _, err := ok.GetContractsOpenInterestAndVolume(contextGenerate(), "BTC", time.Time{}, time.Time{}, kline.OneDay); err != nil {
t.Error("Okx GetContractsOpenInterestAndVolume() error", err)
}
}
func TestGetOptionsOpenInterestAndVolume(t *testing.T) {
t.Parallel()
if _, err := ok.GetOptionsOpenInterestAndVolume(contextGenerate(), "BTC", kline.OneDay); err != nil {
t.Error("Okx GetOptionsOpenInterestAndVolume() error", err)
}
}
func TestGetPutCallRatio(t *testing.T) {
t.Parallel()
if _, err := ok.GetPutCallRatio(contextGenerate(), "BTC", kline.OneDay); err != nil {
t.Error("Okx GetPutCallRatio() error", err)
}
}
func TestGetOpenInterestAndVolumeExpiry(t *testing.T) {
t.Parallel()
if _, err := ok.GetOpenInterestAndVolumeExpiry(contextGenerate(), "BTC", kline.OneDay); err != nil {
t.Error("Okx GetOpenInterestAndVolume() error", err)
}
}
func TestGetOpenInterestAndVolumeStrike(t *testing.T) {
t.Parallel()
if _, err := ok.GetOpenInterestAndVolumeStrike(contextGenerate(), "BTC", time.Now(), kline.OneDay); err != nil {
t.Error("Okx GetOpenInterestAndVolumeStrike() error", err)
}
}
func TestGetTakerFlow(t *testing.T) {
t.Parallel()
if _, err := ok.GetTakerFlow(contextGenerate(), "BTC", kline.OneDay); err != nil {
t.Error("Okx GetTakerFlow() error", err)
}
}
func TestPlaceOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.PlaceOrder(contextGenerate(), &PlaceOrderRequestParam{
InstrumentID: "BTC-USDC",
TradeMode: "cross",
Side: "Buy",
OrderType: "limit",
Amount: 2.6,
Price: 2.1,
Currency: "BTC",
}, asset.Margin); err != nil {
t.Error("Okx PlaceOrder() error", err)
}
}
const placeMultipleOrderParamsJSON = `[{"instId":"BTC-USDT","tdMode":"cash","clOrdId":"b159","side":"buy","ordType":"limit","px":"2.15","sz":"2"},{"instId":"BTC-USDT","tdMode":"cash","clOrdId":"b15","side":"buy","ordType":"limit","px":"2.15","sz":"2"}]`
func TestPlaceMultipleOrders(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
var params []PlaceOrderRequestParam
err := json.Unmarshal([]byte(placeMultipleOrderParamsJSON), &params)
if err != nil {
t.Fatal(err)
}
if _, err = ok.PlaceMultipleOrders(contextGenerate(),
params); err != nil {
t.Error("Okx PlaceMultipleOrders() error", err)
}
}
func TestCancelSingleOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.CancelSingleOrder(contextGenerate(),
CancelOrderRequestParam{
InstrumentID: "BTC-USDT",
OrderID: "2510789768709120",
}); err != nil {
t.Error("Okx CancelOrder() error", err)
}
}
func TestCancelMultipleOrders(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.CancelMultipleOrders(contextGenerate(), []CancelOrderRequestParam{{
InstrumentID: "DCR-BTC",
OrderID: "2510789768709120",
}}); err != nil {
t.Error("Okx CancelMultipleOrders() error", err)
}
}
func TestAmendOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.AmendOrder(contextGenerate(), &AmendOrderRequestParams{
InstrumentID: "DCR-BTC",
OrderID: "2510789768709120",
NewPrice: 1233324.332,
}); err != nil {
t.Error("Okx AmendOrder() error", err)
}
}
func TestAmendMultipleOrders(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.AmendMultipleOrders(contextGenerate(), []AmendOrderRequestParams{{
InstrumentID: "BTC-USDT",
OrderID: "2510789768709120",
NewPrice: 1233324.332,
}}); err != nil {
t.Error("Okx AmendMultipleOrders() error", err)
}
}
func TestClosePositions(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.ClosePositions(contextGenerate(), &ClosePositionsRequestParams{
InstrumentID: "BTC-USDT",
MarginMode: "cross",
Currency: "BTC",
}); err != nil {
t.Error("Okc ClosePositions() error", err)
}
}
func TestGetOrderDetail(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetOrderDetail(contextGenerate(), &OrderDetailRequestParam{
InstrumentID: "BTC-USDT",
OrderID: "2510789768709120",
}); !strings.Contains(err.Error(), "Order does not exist") {
t.Error("Okx GetOrderDetail() error", err)
}
}
func TestGetOrderList(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetOrderList(contextGenerate(), &OrderListRequestParams{
Limit: 1,
}); err != nil {
t.Error("Okx GetOrderList() error", err)
}
}
func TestGet7And3MonthDayOrderHistory(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.Get7DayOrderHistory(contextGenerate(), &OrderHistoryRequestParams{
OrderListRequestParams: OrderListRequestParams{InstrumentType: "MARGIN"},
}); err != nil {
t.Error("Okx Get7DayOrderHistory() error", err)
}
if _, err := ok.Get3MonthOrderHistory(contextGenerate(), &OrderHistoryRequestParams{
OrderListRequestParams: OrderListRequestParams{InstrumentType: "MARGIN"},
}); err != nil {
t.Error("Okx Get3MonthOrderHistory() error", err)
}
}
func TestTransactionHistory(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetTransactionDetailsLast3Days(contextGenerate(), &TransactionDetailRequestParams{
InstrumentType: "MARGIN",
Limit: 1,
}); err != nil {
t.Error("Okx GetTransactionDetailsLast3Days() error", err)
}
if _, err := ok.GetTransactionDetailsLast3Months(contextGenerate(), &TransactionDetailRequestParams{
InstrumentType: "MARGIN",
}); err != nil {
t.Error("Okx GetTransactionDetailsLast3Days() error", err)
}
}
func TestStopOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.PlaceStopOrder(contextGenerate(), &AlgoOrderParams{
TakeProfitTriggerPriceType: "index",
InstrumentID: "BTC-USDT",
OrderType: "conditional",
Side: order.Sell,
TradeMode: "isolated",
Size: 12,
TakeProfitTriggerPrice: 12335,
TakeProfitOrderPrice: 1234,
}); err != nil {
t.Errorf("Okx StopOrderParams() error %v", err)
}
if _, err := ok.PlaceTrailingStopOrder(contextGenerate(), &AlgoOrderParams{
CallbackRatio: 0.01,
InstrumentID: "BTC-USDT",
OrderType: "move_order_stop",
Side: order.Buy,
TradeMode: "isolated",
Size: 2,
ActivePrice: 1234,
}); err != nil {
t.Error("Okx PlaceTrailingStopOrder error", err)
}
if _, err := ok.PlaceIcebergOrder(contextGenerate(), &AlgoOrderParams{
PriceLimit: 100.22,
SizeLimit: 9999.9,
PriceSpread: "0.04",
InstrumentID: "BTC-USDT",
OrderType: "iceberg",
Side: order.Buy,
TradeMode: "isolated",
Size: 6,
}); err != nil {
t.Error("Okx PlaceIceburgOrder() error", err)
}
if _, err := ok.PlaceTWAPOrder(contextGenerate(), &AlgoOrderParams{
InstrumentID: "BTC-USDT",
PriceLimit: 100.22,
SizeLimit: 9999.9,
OrderType: "twap",
PriceSpread: "0.4",
TradeMode: "cross",
Side: order.Sell,
Size: 6,
TimeInterval: kline.ThreeDay,
}); err != nil {
t.Error("Okx PlaceTWAPOrder() error", err)
}
if _, err := ok.TriggerAlgoOrder(contextGenerate(), &AlgoOrderParams{
TriggerPriceType: "mark",
TriggerPrice: 1234,
InstrumentID: "BTC-USDT",
OrderType: "trigger",
Side: order.Buy,
TradeMode: "cross",
Size: 5,
}); err != nil {
t.Error("Okx TriggerAlogOrder() error", err)
}
}
func TestCancelAlgoOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.CancelAlgoOrder(contextGenerate(), []AlgoOrderCancelParams{
{
InstrumentID: "BTC-USDT",
AlgoOrderID: "90994943",
},
}); err != nil {
t.Error("Okx CancelAlgoOrder() error", err)
}
}
func TestCancelAdvanceAlgoOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.CancelAdvanceAlgoOrder(contextGenerate(), []AlgoOrderCancelParams{{
InstrumentID: "BTC-USDT",
AlgoOrderID: "90994943",
}}); err != nil {
t.Error("Okx CancelAdvanceAlgoOrder() error", err)
}
}
func TestGetAlgoOrderList(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetAlgoOrderList(contextGenerate(), "conditional", "", "", "", "", time.Time{}, time.Time{}, 1); err != nil {
t.Error("Okx GetAlgoOrderList() error", err)
}
}
func TestGetAlgoOrderHistory(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetAlgoOrderHistory(contextGenerate(), "conditional", "effective", "", "", "", time.Time{}, time.Time{}, 1); err != nil {
t.Error("Okx GetAlgoOrderList() error", err)
}
}
func TestGetEasyConvertCurrencyList(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetEasyConvertCurrencyList(contextGenerate()); err != nil {
t.Errorf("%s GetEasyConvertCurrencyList() error %v", ok.Name, err)
}
}
func TestGetOneClickRepayCurrencyList(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetOneClickRepayCurrencyList(contextGenerate(), "cross"); err != nil && !strings.Contains(err.Error(), "Parameter acctLv error") {
t.Error(err)
}
}
func TestPlaceEasyConvert(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.PlaceEasyConvert(contextGenerate(),
PlaceEasyConvertParam{
FromCurrency: []string{"BTC"},
ToCurrency: "USDT"}); err != nil {
t.Errorf("%s PlaceEasyConvert() error %v", ok.Name, err)
}
}
func TestGetEasyConvertHistory(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetEasyConvertHistory(contextGenerate(), time.Time{}, time.Time{}, 1); err != nil {
t.Errorf("%s GetEasyConvertHistory() error %v", ok.Name, err)
}
}
func TestGetOneClickRepayHistory(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetOneClickRepayHistory(contextGenerate(), time.Time{}, time.Time{}, 1); err != nil && !strings.Contains(err.Error(), "Parameter acctLv error") {
t.Errorf("%s GetOneClickRepayHistory() error %v", ok.Name, err)
}
}
func TestTradeOneClickRepay(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.TradeOneClickRepay(contextGenerate(), TradeOneClickRepayParam{
DebtCurrency: []string{"BTC"},
RepayCurrency: "USDT",
}); err != nil {
t.Errorf("%s TradeOneClickRepay() error %v", ok.Name, err)
}
}
func TestGetCounterparties(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetCounterparties(contextGenerate()); err != nil && !strings.Contains(err.Error(), "code: 70006 message: Does not meet the minimum asset requirement.") {
t.Error("Okx GetCounterparties() error", err)
}
}
const createRfqInputJSON = `{"anonymous": true,"counterparties":["Trader1","Trader2"],"clRfqId":"rfq01","legs":[{"sz":"25","side":"buy","instId":"BTCUSD-221208-100000-C"},{"sz":"150","side":"buy","instId":"ETH-USDT","tgtCcy":"base_ccy"}]}`
func TestCreateRfq(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
var input CreateRfqInput
if err := json.Unmarshal([]byte(createRfqInputJSON), &input); err != nil {
t.Error("Okx Decerializing to CreateRfqInput", err)
}
if _, err := ok.CreateRfq(contextGenerate(), input); err != nil {
t.Error("Okx CreateRfq() error", err)
}
}
func TestCancelRfq(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
_, err := ok.CancelRfq(contextGenerate(), CancelRfqRequestParam{})
if err != nil && !errors.Is(err, errMissingRfqIDAndClientRfqID) {
t.Errorf("Okx CancelRfq() expecting %v, but found %v", errMissingRfqIDAndClientRfqID, err)
}
_, err = ok.CancelRfq(context.Background(), CancelRfqRequestParam{
ClientRfqID: "somersdjskfjsdkfjxvxv",
})
if err != nil {
t.Error("Okx CancelRfq() error", err)
}
}
func TestMultipleCancelRfq(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
_, err := ok.CancelMultipleRfqs(contextGenerate(), CancelRfqRequestsParam{})
if err != nil && !errors.Is(err, errMissingRfqIDAndClientRfqID) {
t.Errorf("Okx CancelMultipleRfqs() expecting %v, but found %v", errMissingRfqIDAndClientRfqID, err)
}
_, err = ok.CancelMultipleRfqs(contextGenerate(), CancelRfqRequestsParam{
ClientRfqIDs: []string{"somersdjskfjsdkfjxvxv"},
})
if err != nil {
t.Error("Okx CancelMultipleRfqs() error", err)
}
}
func TestCancelAllRfqs(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.CancelAllRfqs(contextGenerate()); err != nil {
t.Errorf("%s CancelAllRfqs() error %v", ok.Name, err)
}
}
func TestExecuteQuote(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
_, err := ok.ExecuteQuote(contextGenerate(), ExecuteQuoteParams{})
if err != nil && !errors.Is(err, errMissingRfqIDOrQuoteID) {
t.Errorf("Okx ExecuteQuote() expected %v, but found %v", errMissingRfqIDOrQuoteID, err)
}
if _, err = ok.ExecuteQuote(contextGenerate(), ExecuteQuoteParams{
RfqID: "22540",
QuoteID: "84073",
}); err != nil {
t.Error("Okx ExecuteQuote() error", err)
}
}
func TestSetQuoteProducts(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.SetQuoteProducts(contextGenerate(), []SetQuoteProductParam{
{
InstrumentType: "SWAP",
Data: []MakerInstrumentSetting{
{
Underlying: "BTC-USD",
MaxBlockSize: 10000,
MakerPriceBand: 5,
},
{
Underlying: "ETH-USDT",
},
},
}}); err != nil {
t.Errorf("%s SetQuoteProducts() error %v", ok.Name, err)
}
}
func TestResetMMPStatus(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.ResetMMPStatus(contextGenerate()); err != nil && !strings.Contains(err.Error(), "No permission to use this API") {
t.Errorf("%s ResetMMPStatus() error %v", ok.Name, err)
}
}
func TestCreateQuote(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.CreateQuote(contextGenerate(), CreateQuoteParams{}); err != nil && !errors.Is(err, errMissingRfqID) {
t.Errorf("Okx CreateQuote() expecting %v, but found %v", errMissingRfqID, err)
}
if _, err := ok.CreateQuote(contextGenerate(), CreateQuoteParams{
RfqID: "12345",
QuoteSide: order.Buy,
Legs: []QuoteLeg{
{
Price: 1234,
SizeOfQuoteLeg: 2,
InstrumentID: "SOL-USD-220909",
Side: order.Sell,
},
{
Price: 1234,
SizeOfQuoteLeg: 1,
InstrumentID: "SOL-USD-220909",
Side: order.Buy,
},
},
}); err != nil {
t.Errorf("%s CreateQuote() error %v", ok.Name, err)
}
}
func TestCancelQuote(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.CancelQuote(contextGenerate(), CancelQuoteRequestParams{}); err != nil && !errors.Is(err, errMissingQuoteIDOrClientQuoteID) {
t.Error("Okx CancelQuote() error", err)
}
if _, err := ok.CancelQuote(contextGenerate(), CancelQuoteRequestParams{
QuoteID: "1234",
}); err != nil {
t.Error("Okx CancelQuote() error", err)
}
if _, err := ok.CancelQuote(contextGenerate(), CancelQuoteRequestParams{
ClientQuoteID: "1234",
}); err != nil {
t.Error("Okx CancelQuote() error", err)
}
}
func TestCancelMultipleQuote(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.CancelMultipleQuote(contextGenerate(), CancelQuotesRequestParams{}); err != nil && !errors.Is(errMissingEitherQuoteIDAOrClientQuoteIDs, err) {
t.Error("Okx CancelQuote() error", err)
}
if _, err := ok.CancelMultipleQuote(contextGenerate(), CancelQuotesRequestParams{
QuoteIDs: []string{"1150", "1151", "1152"},
// Block trades require a minimum of $100,000 in assets in your trading account
}); err != nil {
t.Error("Okx CancelQuote() error", err)
}
}
func TestCancelAllQuotes(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
time, err := ok.CancelAllQuotes(contextGenerate())
switch {
case err != nil:
t.Error("Okx CancelAllQuotes() error", err)
case err == nil && time.IsZero():
t.Error("Okx CancelAllQuotes() zero timestamp message ")
}
}
func TestGetRfqs(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetRfqs(contextGenerate(), &RfqRequestParams{
Limit: 1,
}); err != nil {
t.Error("Okx GetRfqs() error", err)
}
}
func TestGetQuotes(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetQuotes(contextGenerate(), &QuoteRequestParams{
Limit: 3,
}); err != nil {
t.Error("Okx GetQuotes() error", err)
}
}
func TestGetRfqTrades(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetRfqTrades(contextGenerate(), &RfqTradesRequestParams{
Limit: 1,
}); err != nil {
t.Error("Okx GetRfqTrades() error", err)
}
}
func TestGetPublicBlockTrades(t *testing.T) {
t.Parallel()
trades, err := ok.GetPublicBlockTrades(contextGenerate(), "", "", 3)
assert.NoError(t, err, "GetPublicBlockTrades should not error")
assert.NotEmpty(t, trades, "Should get some block trades back")
for _, trade := range trades {
assert.NotEmpty(t, trade.CreationTime, "CreationTime shound not be empty")
assert.NotEmpty(t, trade.BlockTradeID, "BlockTradeID shound not be empty")
if assert.NotEmpty(t, trade.Legs, "Should get some trades") {
leg := trade.Legs[0]
assert.NotEmpty(t, leg.InstrumentID, "InstrumentID should have correct value")
assert.NotEmpty(t, leg.TradeID, "TradeID should not be empty")
assert.Positive(t, leg.Price, "Price should have a positive value")
assert.Positive(t, leg.Size, "Size should have a positive value")
assert.Contains(t, []order.Side{order.Buy, order.Sell}, leg.Side, "Side should be a side")
}
}
}
func TestGetFundingCurrencies(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetFundingCurrencies(contextGenerate()); err != nil {
t.Error("Okx GetFundingCurrencies() error", err)
}
}
func TestGetBalance(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetBalance(contextGenerate(), ""); err != nil {
t.Error("Okx GetBalance() error", err)
}
}
func TestGetAccountAssetValuation(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetAccountAssetValuation(contextGenerate(), ""); err != nil {
t.Error("Okx GetAccountAssetValuation() error", err)
}
}
func TestFundingTransfer(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.FundingTransfer(contextGenerate(), &FundingTransferRequestInput{
Amount: 12.000,
To: "6",
From: "18",
Currency: "BTC",
}); err != nil {
t.Error("Okx FundingTransfer() error", err)
}
}
func TestGetFundsTransferState(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetFundsTransferState(contextGenerate(), "754147", "1232", 1); err != nil && !strings.Contains(err.Error(), "Parameter transId error") {
t.Error("Okx GetFundsTransferState() error", err)
}
}
func TestGetAssetBillsDetails(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
_, err := ok.GetAssetBillsDetails(contextGenerate(), "", "", time.Time{}, time.Time{}, 0, 1)
if err != nil {
t.Error("Okx GetAssetBillsDetail() error", err)
}
}
func TestGetLightningDeposits(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetLightningDeposits(contextGenerate(), "BTC", 1.00, 0); err != nil && !strings.Contains(err.Error(), "58355") {
t.Error("Okx GetLightningDeposits() error", err)
}
}
func TestGetCurrencyDepositAddress(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetCurrencyDepositAddress(contextGenerate(), "BTC"); err != nil {
t.Error("Okx GetCurrencyDepositAddress() error", err)
}
}
func TestGetCurrencyDepositHistory(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetCurrencyDepositHistory(contextGenerate(), "BTC", "", "", time.Time{}, time.Time{}, 0, 1); err != nil {
t.Error("Okx GetCurrencyDepositHistory() error", err)
}
}
func TestWithdrawal(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
_, err := ok.Withdrawal(contextGenerate(), &WithdrawalInput{Amount: 0.1, TransactionFee: 0.00005, Currency: "BTC", WithdrawalDestination: "4", ToAddress: core.BitcoinDonationAddress})
if err != nil {
t.Error("Okx Withdrawal error", err)
}
}
func TestLightningWithdrawal(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.LightningWithdrawal(contextGenerate(), LightningWithdrawalRequestInput{
Currency: currency.BTC.String(),
Invoice: "lnbc100u1psnnvhtpp5yq2x3q5hhrzsuxpwx7ptphwzc4k4wk0j3stp0099968m44cyjg9sdqqcqzpgxqzjcsp5hz",
}); err != nil {
t.Error("Okx LightningWithdrawal() error", err)
}
}
func TestCancelWithdrawal(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.CancelWithdrawal(contextGenerate(), "fjasdfkjasdk"); err != nil {
t.Error("Okx CancelWithdrawal() error", err.Error())
}
}
func TestGetWithdrawalHistory(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetWithdrawalHistory(contextGenerate(), "BTC", "", "", "", "", time.Time{}, time.Time{}, 1); err != nil {
t.Error("Okx GetWithdrawalHistory() error", err)
}
}
func TestSmallAssetsConvert(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.SmallAssetsConvert(contextGenerate(), []string{"BTC", "USDT"}); err != nil {
t.Error("Okx SmallAssetsConvert() error", err)
}
}
func TestGetSavingBalance(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetSavingBalance(contextGenerate(), "BTC"); err != nil {
t.Error("Okx GetSavingBalance() error", err)
}
}
func TestSavingsPurchase(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.SavingsPurchaseOrRedemption(contextGenerate(), &SavingsPurchaseRedemptionInput{
Amount: 123.4,
Currency: "BTC",
Rate: 1,
ActionType: "purchase",
}); err != nil {
t.Error("Okx SavingsPurchaseOrRedemption() error", err)
}
if _, err := ok.SavingsPurchaseOrRedemption(contextGenerate(), &SavingsPurchaseRedemptionInput{
Amount: 123.4,
Currency: "BTC",
Rate: 1,
ActionType: "redempt",
}); err != nil {
t.Error("Okx SavingsPurchaseOrRedemption() error", err)
}
}
func TestSetLendingRate(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.SetLendingRate(contextGenerate(), LendingRate{Currency: "BTC", Rate: 2}); err != nil {
t.Error("Okx SetLendingRate() error", err)
}
}
func TestGetLendingHistory(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetLendingHistory(contextGenerate(), "USDT", time.Time{}, time.Time{}, 1); err != nil {
t.Error("Okx GetLendingHostory() error", err)
}
}
func TestGetPublicBorrowInfo(t *testing.T) {
t.Parallel()
if _, err := ok.GetPublicBorrowInfo(contextGenerate(), ""); err != nil {
t.Error("Okx GetPublicBorrowInfo() error", err)
}
if _, err := ok.GetPublicBorrowInfo(context.Background(), "USDT"); err != nil {
t.Error("Okx GetPublicBorrowInfo() error", err)
}
}
func TestGetPublicBorrowHistory(t *testing.T) {
t.Parallel()
if _, err := ok.GetPublicBorrowHistory(context.Background(), "USDT", time.Time{}, time.Time{}, 1); err != nil {
t.Error("Okx GetPublicBorrowHistory() error", err)
}
}
func TestGetConvertCurrencies(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetConvertCurrencies(contextGenerate()); err != nil {
t.Error("Okx GetConvertCurrencies() error", err)
}
}
func TestGetConvertCurrencyPair(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetConvertCurrencyPair(contextGenerate(), "USDT", "BTC"); err != nil {
t.Error("Okx GetConvertCurrencyPair() error", err)
}
}
func TestEstimateQuote(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.EstimateQuote(contextGenerate(), &EstimateQuoteRequestInput{
BaseCurrency: "BTC",
QuoteCurrency: "USDT",
Side: "sell",
RfqAmount: 30,
RfqSzCurrency: "USDT",
}); err != nil {
t.Error("Okx EstimateQuote() error", err)
}
}
func TestConvertTrade(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.ConvertTrade(contextGenerate(), &ConvertTradeInput{
BaseCurrency: "BTC",
QuoteCurrency: "USDT",
Side: "Buy",
Size: 2,
SizeCurrency: "USDT",
QuoteID: "quoterETH-USDT16461885104612381",
}); err != nil {
t.Error("Okx ConvertTrade() error", err)
}
}
func TestGetConvertHistory(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetConvertHistory(contextGenerate(), time.Time{}, time.Time{}, 1, ""); err != nil {
t.Error("Okx GetConvertHistory() error", err)
}
}
func TestGetNonZeroAccountBalance(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.AccountBalance(contextGenerate(), ""); err != nil {
t.Error("Okx GetBalance() error", err)
}
}
func TestGetPositions(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetPositions(contextGenerate(), "", "", ""); err != nil {
t.Error("Okx GetPositions() error", err)
}
}
func TestGetPositionsHistory(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetPositionsHistory(contextGenerate(), "", "", "", 0, 1, time.Time{}, time.Time{}); err != nil {
t.Error("Okx GetPositionsHistory() error", err)
}
}
func TestGetAccountAndPositionRisk(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetAccountAndPositionRisk(contextGenerate(), ""); err != nil {
t.Error("Okx GetAccountAndPositionRisk() error", err)
}
}
func TestGetBillsDetail(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetBillsDetailLast7Days(contextGenerate(), &BillsDetailQueryParameter{
Limit: 3,
}); err != nil {
t.Error("Okx GetBillsDetailLast7Days() error", err)
}
}
func TestGetAccountConfiguration(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetAccountConfiguration(contextGenerate()); err != nil {
t.Error("Okx GetAccountConfiguration() error", err)
}
}
func TestSetPositionMode(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.SetPositionMode(contextGenerate(), "net_mode"); err != nil {
t.Error("Okx SetPositionMode() error", err)
}
}
func TestSetLeverageRate(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.SetLeverageRate(contextGenerate(), SetLeverageInput{
Currency: "USDT",
Leverage: 5,
MarginMode: "cross",
InstrumentID: "BTC-USDT",
}); err != nil && !errors.Is(err, errNoValidResponseFromServer) {
t.Error("Okx SetLeverageRate() error", err)
}
}
func TestGetMaximumBuySellAmountOROpenAmount(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetMaximumBuySellAmountOROpenAmount(contextGenerate(), "BTC-USDT", "cross", "BTC", "", 5); err != nil {
t.Error("Okx GetMaximumBuySellAmountOROpenAmount() error", err)
}
}
func TestGetMaximumAvailableTradableAmount(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetMaximumAvailableTradableAmount(contextGenerate(), "BTC-USDT", "BTC", "cross", true, 123); err != nil && !strings.Contains(err.Error(), "51010") {
t.Error("Okx GetMaximumAvailableTradableAmount() error", err)
}
}
func TestIncreaseDecreaseMargin(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.IncreaseDecreaseMargin(contextGenerate(), IncreaseDecreaseMarginInput{
InstrumentID: "BTC-USDT",
PositionSide: "long",
Type: "add",
Amount: 1000,
Currency: "USD",
}); err != nil {
t.Error("Okx IncreaseDecreaseMargin() error", err)
}
}
func TestGetLeverageRate(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetLeverageRate(contextGenerate(), "BTC-USDT", "cross"); err != nil {
t.Error("Okx GetLeverageRate() error", err)
}
}
func TestGetMaximumLoanOfInstrument(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetMaximumLoanOfInstrument(contextGenerate(), "ZRX-BTC", "isolated", "ZRX"); err != nil && !strings.Contains(err.Error(), "51010") {
t.Error("Okx GetMaximumLoanOfInstrument() error", err)
}
}
func TestGetTradeFee(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetTradeFee(contextGenerate(), "SPOT", "", ""); err != nil {
t.Error("Okx GetTradeFeeRate() error", err)
}
}
func TestGetInterestAccruedData(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetInterestAccruedData(contextGenerate(), 0, 1, "", "", "", time.Time{}, time.Time{}); err != nil {
t.Error("Okx GetInterestAccruedData() error", err)
}
}
func TestGetInterestRate(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetInterestRate(contextGenerate(), ""); err != nil {
t.Error("Okx GetInterestRate() error", err)
}
}
func TestSetGreeks(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.SetGreeks(contextGenerate(), "PA"); err != nil {
t.Error("Okx SetGreeks() error", err)
}
}
func TestIsolatedMarginTradingSettings(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.IsolatedMarginTradingSettings(contextGenerate(), IsolatedMode{
IsoMode: "autonomy",
InstrumentType: "MARGIN",
}); err != nil {
t.Error("Okx IsolatedMarginTradingSettings() error", err)
}
}
func TestGetMaximumWithdrawals(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetMaximumWithdrawals(contextGenerate(), "BTC"); err != nil {
t.Error("Okx GetMaximumWithdrawals() error", err)
}
}
func TestGetAccountRiskState(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetAccountRiskState(contextGenerate()); err != nil && !strings.Contains(err.Error(), "51010") {
t.Error("Okx GetAccountRiskState() error", err)
}
}
func TestVIPLoansBorrowAndRepay(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.VIPLoansBorrowAndRepay(contextGenerate(), LoanBorrowAndReplayInput{Currency: "BTC", Side: "borrow", Amount: 12}); err != nil &&
!strings.Contains(err.Error(), "Your account does not support VIP loan") {
t.Error("Okx VIPLoansBorrowAndRepay() error", err)
}
}
func TestGetBorrowAndRepayHistoryForVIPLoans(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetBorrowAndRepayHistoryForVIPLoans(contextGenerate(), "", time.Time{}, time.Time{}, 3); err != nil {
t.Error("Okx GetBorrowAndRepayHistoryForVIPLoans() error", err)
}
}
func TestGetBorrowInterestAndLimit(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetBorrowInterestAndLimit(contextGenerate(), 1, "BTC"); err != nil && !strings.Contains(err.Error(), "59307") { // You are not eligible for VIP loans
t.Error("Okx GetBorrowInterestAndLimit() error", err)
}
}
func TestPositionBuilder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.PositionBuilder(contextGenerate(), PositionBuilderInput{
ImportExistingPosition: true,
}); err != nil {
t.Error("Okx PositionBuilder() error", err)
}
}
func TestGetGreeks(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetGreeks(contextGenerate(), ""); err != nil && !strings.Contains(err.Error(), "Unsupported operation") {
t.Error("Okx GetGreeks() error", err)
}
}
func TestGetPMLimitation(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetPMLimitation(contextGenerate(), "SWAP", "BTC-USDT"); err != nil {
t.Errorf("%s GetPMLimitation() error %v", ok.Name, err)
}
}
func TestViewSubaccountList(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.ViewSubAccountList(contextGenerate(), false, "", time.Time{}, time.Time{}, 2); err != nil {
t.Error("Okx ViewSubaccountList() error", err)
}
}
func TestResetSubAccountAPIKey(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.ResetSubAccountAPIKey(contextGenerate(), &SubAccountAPIKeyParam{
SubAccountName: "sam",
APIKey: apiKey,
APIKeyPermission: "trade",
}); err != nil && !strings.Contains(err.Error(), "Parameter subAcct can not be empty.") {
t.Errorf("%s ResetSubAccountAPIKey() error %v", ok.Name, err)
}
if _, err := ok.ResetSubAccountAPIKey(contextGenerate(), &SubAccountAPIKeyParam{
SubAccountName: "sam",
APIKey: apiKey,
Permissions: []string{"trade", "read"},
}); err != nil && !strings.Contains(err.Error(), "Parameter subAcct can not be empty.") {
t.Errorf("%s ResetSubAccountAPIKey() error %v", ok.Name, err)
}
}
func TestGetSubaccountTradingBalance(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetSubaccountTradingBalance(contextGenerate(), ""); err != nil && !errors.Is(err, errMissingRequiredParameterSubaccountName) {
t.Errorf("Okx GetSubaccountTradingBalance() expecting \"%v\", but found \"%v\"", errMissingRequiredParameterSubaccountName, err)
}
if _, err := ok.GetSubaccountTradingBalance(contextGenerate(), "test1"); err != nil && !strings.Contains(err.Error(), "sub-account does not exist") {
t.Error("Okx GetSubaccountTradingBalance() error", err)
}
}
func TestGetSubaccountFundingBalance(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetSubaccountFundingBalance(contextGenerate(), "test1", ""); err != nil && !strings.Contains(err.Error(), "Sub-account test1 does not exists") && !strings.Contains(err.Error(), "59510") {
t.Error("Okx GetSubaccountFundingBalance() error", err)
}
}
func TestHistoryOfSubaccountTransfer(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.HistoryOfSubaccountTransfer(contextGenerate(), "", "0", "", time.Time{}, time.Time{}, 1); err != nil {
t.Error("Okx HistoryOfSubaccountTransfer() error", err)
}
}
func TestMasterAccountsManageTransfersBetweenSubaccounts(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.MasterAccountsManageTransfersBetweenSubaccounts(contextGenerate(), SubAccountAssetTransferParams{Currency: "BTC", Amount: 1200, From: 9, To: 9, FromSubAccount: "", ToSubAccount: "", LoanTransfer: true}); err != nil && !errors.Is(err, errInvalidSubaccount) {
t.Error("Okx MasterAccountsManageTransfersBetweenSubaccounts() error", err)
}
if _, err := ok.MasterAccountsManageTransfersBetweenSubaccounts(contextGenerate(), SubAccountAssetTransferParams{Currency: "BTC", Amount: 1200, From: 8, To: 8, FromSubAccount: "", ToSubAccount: "", LoanTransfer: true}); err != nil && !errors.Is(err, errInvalidSubaccount) {
t.Error("Okx MasterAccountsManageTransfersBetweenSubaccounts() error", err)
}
if _, err := ok.MasterAccountsManageTransfersBetweenSubaccounts(contextGenerate(), SubAccountAssetTransferParams{Currency: "BTC", Amount: 1200, From: 6, To: 6, FromSubAccount: "test1", ToSubAccount: "test2", LoanTransfer: true}); err != nil && !strings.Contains(err.Error(), "Sub-account test1 does not exists") {
t.Error("Okx MasterAccountsManageTransfersBetweenSubaccounts() error", err)
}
}
func TestSetPermissionOfTransferOut(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.SetPermissionOfTransferOut(contextGenerate(), PermissionOfTransfer{SubAcct: "Test1"}); err != nil && !strings.Contains(err.Error(), "Sub-account does not exist") {
t.Error("Okx SetPermissionOfTransferOut() error", err)
}
}
func TestGetCustodyTradingSubaccountList(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetCustodyTradingSubaccountList(contextGenerate(), ""); err != nil {
t.Error("Okx GetCustodyTradingSubaccountList() error", err)
}
}
const gridTradingPlaceOrder = `{"instId": "BTC-USD-SWAP","algoOrdType": "contract_grid","maxPx": "5000","minPx": "400","gridNum": "10","runType": "1","sz": "200", "direction": "long","lever": "2"}`
func TestPlaceGridAlgoOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
var input GridAlgoOrder
if err := json.Unmarshal([]byte(gridTradingPlaceOrder), &input); err != nil {
t.Error("Okx Decerializing to GridALgoOrder error", err)
}
if _, err := ok.PlaceGridAlgoOrder(contextGenerate(), &input); err != nil {
t.Error("Okx PlaceGridAlgoOrder() error", err)
}
}
const gridOrderAmendAlgo = `{
"algoId":"448965992920907776",
"instId":"BTC-USDT",
"slTriggerPx":"1200",
"tpTriggerPx":""
}`
func TestAmendGridAlgoOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
var input GridAlgoOrderAmend
if err := json.Unmarshal([]byte(gridOrderAmendAlgo), &input); err != nil {
t.Error("Okx Decerializing to GridAlgoOrderAmend error", err)
}
if _, err := ok.AmendGridAlgoOrder(contextGenerate(), input); err != nil {
t.Error("Okx AmendGridAlgoOrder() error", err)
}
}
const stopGridAlgoOrderJSON = `{"algoId":"198273485", "instId":"BTC-USDT", "stopType":"1", "algoOrdType":"grid"}`
func TestStopGridAlgoOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
var resp StopGridAlgoOrderRequest
if err := json.Unmarshal([]byte(stopGridAlgoOrderJSON), &resp); err != nil {
t.Error("error deserializing to StopGridAlgoOrder error", err)
}
if _, err := ok.StopGridAlgoOrder(contextGenerate(), []StopGridAlgoOrderRequest{
resp,
}); err != nil && !strings.Contains(err.Error(), "The strategy does not exist or has stopped") {
t.Error("Okx StopGridAlgoOrder() error", err)
}
}
func TestGetGridAlgoOrdersList(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetGridAlgoOrdersList(contextGenerate(), "grid", "", "", "", "", "", 1); err != nil {
t.Error("Okx GetGridAlgoOrdersList() error", err)
}
}
func TestGetGridAlgoOrderHistory(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetGridAlgoOrderHistory(contextGenerate(), "contract_grid", "", "", "", "", "", 1); err != nil {
t.Error("Okx GetGridAlgoOrderHistory() error", err)
}
}
func TestGetGridAlgoOrderDetails(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetGridAlgoOrderDetails(contextGenerate(), "grid", ""); err != nil && !errors.Is(err, errMissingAlgoOrderID) {
t.Errorf("Okx GetGridAlgoOrderDetails() expecting %v, but found %v error", errMissingAlgoOrderID, err)
}
if _, err := ok.GetGridAlgoOrderDetails(contextGenerate(), "grid", "7878"); err != nil && !strings.Contains(err.Error(), "Order does not exist") {
t.Error("Okx GetGridAlgoOrderDetails() error", err)
}
}
func TestGetGridAlgoSubOrders(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetGridAlgoSubOrders(contextGenerate(), "", "", "", "", "", "", 2); err != nil && !errors.Is(err, errMissingAlgoOrderType) {
t.Errorf("Okx GetGridAlgoSubOrders() expecting %v, but found %v", err, errMissingAlgoOrderType)
}
if _, err := ok.GetGridAlgoSubOrders(contextGenerate(), "grid", "", "", "", "", "", 2); err != nil && !errors.Is(err, errMissingAlgoOrderID) {
t.Errorf("Okx GetGridAlgoSubOrders() expecting %v, but found %v", err, errMissingAlgoOrderID)
}
if _, err := ok.GetGridAlgoSubOrders(contextGenerate(), "grid", "1234", "", "", "", "", 2); err != nil && !errors.Is(err, errMissingSubOrderType) {
t.Errorf("Okx GetGridAlgoSubOrders() expecting %v, but found %v", err, errMissingSubOrderType)
}
if _, err := ok.GetGridAlgoSubOrders(contextGenerate(), "grid", "1234", "live", "", "", "", 2); err != nil && !errors.Is(err, errMissingSubOrderType) {
t.Errorf("Okx GetGridAlgoSubOrders() expecting %v, but found %v", err, errMissingSubOrderType)
}
}
const spotGridAlgoOrderPosition = `{"adl": "1","algoId": "449327675342323712","avgPx": "29215.0142857142857149","cTime": "1653400065917","ccy": "USDT","imr": "2045.386","instId": "BTC-USDT-SWAP","instType": "SWAP","last": "29206.7","lever": "5","liqPx": "661.1684795867162","markPx": "29213.9","mgnMode": "cross","mgnRatio": "217.19370606167573","mmr": "40.907720000000005","notionalUsd": "10216.70307","pos": "35","posSide": "net","uTime": "1653400066938","upl": "1.674999999999818","uplRatio": "0.0008190504784478"}`
func TestGetGridAlgoOrderPositions(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
var resp AlgoOrderPosition
if err := json.Unmarshal([]byte(spotGridAlgoOrderPosition), &resp); err != nil {
t.Error("Okx Decerializing to AlgoOrderPosition error", err)
}
if _, err := ok.GetGridAlgoOrderPositions(contextGenerate(), "", ""); err != nil && !errors.Is(err, errInvalidAlgoOrderType) {
t.Errorf("Okx GetGridAlgoOrderPositions() expecting %v, but found %v", errInvalidAlgoOrderType, err)
}
if _, err := ok.GetGridAlgoOrderPositions(contextGenerate(), "contract_grid", ""); err != nil && !errors.Is(err, errMissingAlgoOrderID) {
t.Errorf("Okx GetGridAlgoOrderPositions() expecting %v, but found %v", errMissingAlgoOrderID, err)
}
if _, err := ok.GetGridAlgoOrderPositions(contextGenerate(), "contract_grid", ""); err != nil && !errors.Is(err, errMissingAlgoOrderID) {
t.Errorf("Okx GetGridAlgoOrderPositions() expecting %v, but found %v", errMissingAlgoOrderID, err)
}
if _, err := ok.GetGridAlgoOrderPositions(contextGenerate(), "contract_grid", "448965992920907776"); err != nil && !strings.Contains(err.Error(), "The strategy does not exist or has stopped") {
t.Errorf("Okx GetGridAlgoOrderPositions() expecting %v, but found %v", errMissingAlgoOrderID, err)
}
}
func TestSpotGridWithdrawProfit(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.SpotGridWithdrawProfit(contextGenerate(), ""); err != nil && !errors.Is(err, errMissingAlgoOrderID) {
t.Errorf("Okx SpotGridWithdrawProfit() expecting %v, but found %v", errMissingAlgoOrderID, err)
}
if _, err := ok.SpotGridWithdrawProfit(contextGenerate(), "1234"); err != nil {
t.Error("Okx SpotGridWithdrawProfit() error", err)
}
}
func TestComputeMarginBalance(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.ComputeMarginBalance(contextGenerate(), MarginBalanceParam{
AlgoID: "123456",
Type: "other",
}); err != nil && !errors.Is(err, errInvalidMarginTypeAdjust) {
t.Errorf("%s ComputeMarginBalance() expected %v, but found %v", ok.Name, errInvalidMarginTypeAdjust, err)
}
if _, err := ok.ComputeMarginBalance(contextGenerate(), MarginBalanceParam{
AlgoID: "123456",
Type: "add",
}); err != nil && !strings.Contains(err.Error(), "The strategy does not exist or has stopped") {
t.Errorf("%s ComputeMarginBalance() error %v", ok.Name, err)
}
}
func TestAdjustMarginBalance(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.AdjustMarginBalance(contextGenerate(), MarginBalanceParam{
AlgoID: "1234",
Type: "add",
Amount: 12345,
}); err != nil {
t.Errorf("%s AdjustMarginBalance() error %v", ok.Name, err)
}
}
const gridAIParamJSON = `{"algoOrdType": "grid","annualizedRate": "1.5849","ccy": "USDT","direction": "", "duration": "7D","gridNum": "5","instId": "BTC-USDT","lever": "0","maxPx": "21373.3","minInvestment": "0.89557758", "minPx": "15544.2", "perMaxProfitRate": "0.0733865364573281","perMinProfitRate": "0.0561101403446263","runType": "1"}`
func TestGetGridAIParameter(t *testing.T) {
t.Parallel()
var response GridAIParameterResponse
if err := json.Unmarshal([]byte(gridAIParamJSON), &response); err != nil {
t.Errorf("%s error while deserializing to GridAIParameterResponse error %v", ok.Name, err)
}
if _, err := ok.GetGridAIParameter(contextGenerate(), "grid", "BTC-USDT", "", ""); err != nil {
t.Errorf("%s GetGridAIParameter() error %v", ok.Name, err)
}
}
func TestGetOffers(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetOffers(contextGenerate(), "", "", ""); err != nil {
t.Errorf("%s GetOffers() error %v", ok.Name, err)
}
}
func TestPurchase(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.Purchase(contextGenerate(), PurchaseRequestParam{
ProductID: "1234",
InvestData: []PurchaseInvestDataItem{
{
Currency: "BTC",
Amount: 100,
},
{
Currency: "ETH",
Amount: 100,
},
},
Term: 30,
}); err != nil {
t.Errorf("%s Purchase() %v", ok.Name, err)
}
}
func TestRedeem(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.Redeem(contextGenerate(), RedeemRequestParam{
OrderID: "754147",
ProtocolType: "defi",
AllowEarlyRedeem: true,
}); err != nil && !strings.Contains(err.Error(), "Order not found") {
t.Errorf("%s Redeem() error %v", ok.Name, err)
}
}
func TestCancelPurchaseOrRedemption(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.CancelPurchaseOrRedemption(contextGenerate(), CancelFundingParam{
OrderID: "754147",
ProtocolType: "defi",
}); err != nil && !strings.Contains(err.Error(), "Order not found") {
t.Errorf("%s CancelPurchaseOrRedemption() error %v", ok.Name, err)
}
}
func TestGetEarnActiveOrders(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetEarnActiveOrders(contextGenerate(), "", "", "", ""); err != nil {
t.Errorf("%s GetEarnActiveOrders() error %v", ok.Name, err)
}
}
func TestGetFundingOrderHistory(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetFundingOrderHistory(contextGenerate(), "", "", "", time.Time{}, time.Time{}, 1); err != nil {
t.Errorf("%s GetFundingOrderHistory() error %v", ok.Name, err)
}
}
func TestSystemStatusResponse(t *testing.T) {
t.Parallel()
if _, err := ok.SystemStatusResponse(contextGenerate(), "completed"); err != nil {
t.Error("Okx SystemStatusResponse() error", err)
}
}
/********************************** Wrapper Functions **************************************/
func TestFetchTradablePairs(t *testing.T) {
t.Parallel()
if _, err := ok.FetchTradablePairs(contextGenerate(), asset.Options); err != nil {
t.Error("Okx FetchTradablePairs() error", err)
}
}
func TestUpdateTradablePairs(t *testing.T) {
t.Parallel()
updatePairsOnce(t)
}
var updatePairsGuard sync.Once
func updatePairsOnce(tb testing.TB) {
tb.Helper()
updatePairsGuard.Do(func() {
err := ok.UpdateTradablePairs(context.Background(), true)
assert.NoError(tb, err, "UpdateTradablePairs should not error")
})
}
func TestUpdateOrderExecutionLimits(t *testing.T) {
t.Parallel()
tests := map[asset.Item][]currency.Pair{
asset.Spot: {
currency.NewPair(currency.ETH, currency.USDT),
currency.NewPair(currency.BTC, currency.USDT),
},
asset.Margin: {
currency.NewPair(currency.ETH, currency.USDT),
currency.NewPair(currency.ETH, currency.BTC),
},
}
for _, a := range []asset.Item{asset.PerpetualSwap, asset.Futures, asset.Options} {
pairs, err := ok.FetchTradablePairs(context.Background(), a)
if assert.NoErrorf(t, err, "FetchTradablePairs should not error for %s", a) {
tests[a] = []currency.Pair{pairs[0]}
}
}
for _, a := range ok.GetAssetTypes(false) {
if err := ok.UpdateOrderExecutionLimits(context.Background(), a); err != nil {
t.Error("Okx UpdateOrderExecutionLimits() error", err)
continue
}
for _, p := range tests[a] {
limits, err := ok.GetOrderExecutionLimits(a, p)
if assert.NoError(t, err, "GetOrderExecutionLimits should not error") {
assert.Positivef(t, limits.PriceStepIncrementSize, "PriceStepIncrementSize should be positive for %s", p)
assert.Positivef(t, limits.MinimumBaseAmount, "PriceStepIncrementSize should be positive for %s", p)
}
}
}
}
func TestUpdateTicker(t *testing.T) {
t.Parallel()
if _, err := ok.UpdateTicker(contextGenerate(), currency.NewPair(currency.BTC, currency.USDT), asset.Spot); err != nil {
t.Error("Okx UpdateTicker() error", err)
}
}
func TestUpdateTickers(t *testing.T) {
t.Parallel()
if err := ok.UpdateTickers(contextGenerate(), asset.Spot); err != nil {
t.Error("Okx UpdateTicker() error", err)
}
}
func TestFetchTicker(t *testing.T) {
t.Parallel()
_, err := ok.FetchTicker(contextGenerate(), currency.NewPair(currency.BTC, currency.NewCode("USDT-SWAP")), asset.PerpetualSwap)
if err != nil {
t.Error("Okx FetchTicker() error", err)
}
if _, err = ok.FetchTicker(contextGenerate(), currency.NewPair(currency.BTC, currency.USDT), asset.Spot); err != nil {
t.Error("Okx FetchTicker() error", err)
}
}
func TestFetchOrderbook(t *testing.T) {
t.Parallel()
if _, err := ok.FetchOrderbook(contextGenerate(), currency.NewPair(currency.BTC, currency.USDT), asset.Spot); err != nil {
t.Error("Okx FetchOrderbook() error", err)
}
}
func TestUpdateOrderbook(t *testing.T) {
t.Parallel()
if _, err := ok.UpdateOrderbook(contextGenerate(), currency.NewPair(currency.BTC, currency.NewCode("USDT-SWAP")), asset.Spot); err != nil {
t.Error("Okx UpdateOrderbook() error", err)
}
}
func TestUpdateAccountInfo(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.UpdateAccountInfo(contextGenerate(), asset.Spot); err != nil {
t.Error("Okx UpdateAccountInfo() error", err)
}
}
func TestFetchAccountInfo(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.FetchAccountInfo(contextGenerate(), asset.Spot); err != nil {
t.Error("Okx FetchAccountInfo() error", err)
}
}
func TestGetAccountFundingHistory(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetAccountFundingHistory(contextGenerate()); err != nil {
t.Error("Okx GetFundingHistory() error", err)
}
}
func TestGetWithdrawalsHistory(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetWithdrawalsHistory(contextGenerate(), currency.BTC, asset.Spot); err != nil {
t.Error("Okx GetWithdrawalsHistory() error", err)
}
}
func TestGetRecentTrades(t *testing.T) {
t.Parallel()
if _, err := ok.GetRecentTrades(contextGenerate(), currency.NewPair(currency.BTC, currency.USDT), asset.PerpetualSwap); err != nil {
t.Error("Okx GetRecentTrades() error", err)
}
}
func TestSubmitOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
var resp WsPlaceOrderInput
err := json.Unmarshal([]byte(placeOrderArgs), &resp)
if err != nil {
t.Fatal(err)
}
if len(resp.Arguments) == 0 {
t.Error("order not found")
}
var orderSubmission = &order.Submit{
Pair: currency.Pair{
Base: currency.LTC,
Quote: currency.BTC,
},
Exchange: ok.Name,
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1000000000,
ClientID: "yeneOrder",
AssetType: asset.Spot,
}
_, err = ok.SubmitOrder(contextGenerate(), orderSubmission)
if err != nil {
t.Error("Okx SubmitOrder() error", err)
}
cp, err := currency.NewPairFromString("BTC-USDT-230630")
if err != nil {
t.Fatal(err)
}
orderSubmission = &order.Submit{
Pair: cp,
Exchange: ok.Name,
Side: order.Buy,
Type: order.Market,
Amount: 1,
ClientID: "hellomoto",
AssetType: asset.Futures,
MarginType: margin.Multi,
}
_, err = ok.SubmitOrder(contextGenerate(), orderSubmission)
if err != nil {
t.Error("Okx SubmitOrder() error", err)
}
}
func TestCancelOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
var orderCancellation = &order.Cancel{
OrderID: "1",
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currency.NewPair(currency.LTC, currency.BTC),
AssetType: asset.Spot,
}
if err := ok.CancelOrder(contextGenerate(), orderCancellation); err != nil {
t.Error(err)
}
}
func TestCancelBatchOrders(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
var orderCancellationParams = []order.Cancel{
{
OrderID: "1",
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currency.NewPair(currency.LTC, currency.BTC),
AssetType: asset.Spot,
},
{
OrderID: "1",
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currency.NewPair(currency.LTC, currency.BTC),
AssetType: asset.PerpetualSwap,
},
}
_, err := ok.CancelBatchOrders(contextGenerate(), orderCancellationParams)
if err != nil && !strings.Contains(err.Error(), "order does not exist.") {
t.Error("Okx CancelBatchOrders() error", err)
}
}
func TestCancelAllOrders(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.CancelAllOrders(contextGenerate(), &order.Cancel{}); err != nil {
t.Errorf("%s CancelAllOrders() error: %v", ok.Name, err)
}
}
func TestModifyOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
_, err := ok.ModifyOrder(contextGenerate(),
&order.Modify{
AssetType: asset.Spot,
Pair: currency.NewPair(currency.LTC, currency.BTC),
OrderID: "1234",
Price: 123456.44,
Amount: 123,
})
if err != nil {
t.Errorf("Okx ModifyOrder() error %v", err)
}
}
func TestGetOrderInfo(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
enabled, err := ok.GetEnabledPairs(asset.Spot)
if err != nil {
t.Error("couldn't find enabled tradable pairs")
}
if len(enabled) == 0 {
t.SkipNow()
}
_, err = ok.GetOrderInfo(contextGenerate(),
"123", enabled[0], asset.Futures)
if err != nil && !strings.Contains(err.Error(), "Order does not exist") {
t.Errorf("Okx GetOrderInfo() expecting %s, but found %v", "Order does not exist", err)
}
}
func TestGetDepositAddress(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetDepositAddress(contextGenerate(), currency.BTC, "", ""); err != nil && !errors.Is(err, errDepositAddressNotFound) {
t.Error("Okx GetDepositAddress() error", err)
}
}
func TestWithdraw(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
withdrawCryptoRequest := withdraw.Request{
Exchange: ok.Name,
Amount: 0.00000000001,
Currency: currency.BTC,
Crypto: withdraw.CryptoRequest{
Address: core.BitcoinDonationAddress,
},
}
if _, err := ok.WithdrawCryptocurrencyFunds(contextGenerate(), &withdrawCryptoRequest); err != nil {
t.Error("Okx WithdrawCryptoCurrencyFunds() error", err)
}
}
func TestGetPairFromInstrumentID(t *testing.T) {
t.Parallel()
instruments := []string{
"BTC-USDT",
"BTC-USDT-SWAP",
"BTC-USDT-ER33234",
}
if _, err := ok.GetPairFromInstrumentID(instruments[0]); err != nil {
t.Error("Okx GetPairFromInstrumentID() error", err)
}
if _, ere := ok.GetPairFromInstrumentID(instruments[1]); ere != nil {
t.Error("Okx GetPairFromInstrumentID() error", ere)
}
if _, erf := ok.GetPairFromInstrumentID(instruments[2]); erf != nil {
t.Error("Okx GetPairFromInstrumentID() error", erf)
}
}
func TestGetActiveOrders(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
pair, err := currency.NewPairFromString("BTC-USD")
if err != nil {
t.Error(err)
}
var getOrdersRequest = order.MultiOrderRequest{
Type: order.Limit,
Pairs: currency.Pairs{pair, currency.NewPair(currency.USDT, currency.USD), currency.NewPair(currency.USD, currency.LTC)},
AssetType: asset.Spot,
Side: order.Buy,
}
if _, err := ok.GetActiveOrders(contextGenerate(), &getOrdersRequest); err != nil {
t.Error("Okx GetActiveOrders() error", err)
}
}
func TestGetOrderHistory(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
var getOrdersRequest = order.MultiOrderRequest{
Type: order.AnyType,
AssetType: asset.Spot,
Side: order.Buy,
}
_, err := ok.GetOrderHistory(contextGenerate(), &getOrdersRequest)
if err == nil {
t.Errorf("Okx GetOrderHistory() Expected: %v. received nil", err)
} else if err != nil && !errors.Is(err, errMissingAtLeast1CurrencyPair) {
t.Errorf("Okx GetOrderHistory() Expected: %v, but found %v", errMissingAtLeast1CurrencyPair, err)
}
getOrdersRequest.Pairs = []currency.Pair{
currency.NewPair(currency.LTC,
currency.BTC)}
if _, err := ok.GetOrderHistory(contextGenerate(), &getOrdersRequest); err != nil {
t.Error("Okx GetOrderHistory() error", err)
}
}
func TestGetFeeByType(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetFeeByType(contextGenerate(), &exchange.FeeBuilder{
Amount: 1,
FeeType: exchange.CryptocurrencyTradeFee,
Pair: currency.NewPairWithDelimiter(currency.BTC.String(),
currency.USDT.String(),
"-"),
PurchasePrice: 1,
FiatCurrency: currency.USD,
BankTransactionType: exchange.WireTransfer,
}); err != nil {
t.Errorf("%s GetFeeByType() error %v", ok.Name, err)
}
}
func TestValidateAPICredentials(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if err := ok.ValidateAPICredentials(contextGenerate(), asset.Spot); err != nil {
t.Errorf("%s ValidateAPICredentials() error %v", ok.Name, err)
}
}
func TestGetHistoricCandles(t *testing.T) {
t.Parallel()
pair := currency.NewPair(currency.BTC, currency.USDT)
startTime := time.Date(2021, 2, 1, 0, 0, 0, 0, time.UTC)
endTime := startTime.AddDate(0, 0, 100)
_, err := ok.GetHistoricCandles(contextGenerate(), pair, asset.Spot, kline.OneDay, startTime, endTime)
if err != nil {
t.Fatal(err)
}
_, err = ok.GetHistoricCandles(contextGenerate(), pair, asset.Spot, kline.Interval(time.Hour*4), startTime, endTime)
if !errors.Is(err, kline.ErrRequestExceedsExchangeLimits) {
t.Errorf("received: '%v' but expected: '%v'", err, kline.ErrRequestExceedsExchangeLimits)
}
}
func TestGetHistoricCandlesExtended(t *testing.T) {
t.Parallel()
currencyPair := currency.NewPair(currency.BTC, currency.USDT)
_, err := ok.GetHistoricCandlesExtended(contextGenerate(), currencyPair, asset.Spot, kline.OneMin, time.Now().Add(-time.Hour), time.Now())
if err != nil {
t.Errorf("%s GetHistoricCandlesExtended() error: %v", ok.Name, err)
}
}
const wsInstrumentPushData = `{"arg": {"channel": "instruments","instType": "FUTURES"},"data": [{"instType": "FUTURES","instId": "BTC-USD-191115","uly": "BTC-USD","category": "1","baseCcy": "","quoteCcy": "","settleCcy": "BTC","ctVal": "10","ctMult": "1","ctValCcy": "USD","optType": "","stk": "","listTime": "","expTime": "","tickSz": "0.01","lotSz": "1","minSz": "1","ctType": "linear","alias": "this_week","state": "live","maxLmtSz":"10000","maxMktSz":"99999","maxTwapSz":"99999","maxIcebergSz":"99999","maxTriggerSz":"9999","maxStopSz":"9999"}]}`
func TestWSInstruments(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(wsInstrumentPushData)); err != nil {
t.Errorf("%s Websocket Instruments Push Data error %v", ok.Name, err)
}
}
var tickerChannelPushData = `{"arg": {"channel": "tickers","instId": "%v"},"data": [{"instType": "SWAP","instId": "%v","last": "9999.99","lastSz": "0.1","askPx": "9999.99","askSz": "11","bidPx": "8888.88","bidSz": "5","open24h": "9000","high24h": "10000","low24h": "8888.88","volCcy24h": "2222","vol24h": "2222","sodUtc0": "2222","sodUtc8": "2222","ts": "1597026383085"}]}`
func TestTickerChannel(t *testing.T) {
t.Parallel()
curr := ok.CurrencyPairs.Pairs[asset.PerpetualSwap].Enabled[0]
if err := ok.WsHandleData([]byte(fmt.Sprintf(tickerChannelPushData, curr, curr))); err != nil {
t.Error("Okx TickerChannel push data error", err)
}
}
const openInterestChannelPushData = `{"arg": {"channel": "open-interest","instId": "LTC-USD-SWAP"},"data": [{"instType": "SWAP","instId": "LTC-USD-SWAP","oi": "5000","oiCcy": "555.55","ts": "1597026383085"}]}`
func TestOpenInterestPushData(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(openInterestChannelPushData)); err != nil {
t.Error("Okx Open Interest Push Data error", err)
}
}
var candlesticksPushData = `{"arg": {"channel": "candle1D","instId": "%v"},"data": [["1597026383085","8533.02","8553.74","8527.17","8548.26","45247","529.5858061"]]}`
func TestCandlestickPushData(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(fmt.Sprintf(candlesticksPushData, ok.CurrencyPairs.Pairs[asset.Futures].Enabled[0]))); err != nil {
t.Error("Okx Candlestick Push Data error", err)
}
}
const tradePushDataJSON = `{"arg": {"channel": "trades","instId": "BTC-USDT"},"data": [{"instId": "BTC-USDT","tradeId": "130639474","px": "42219.9","sz": "0.12060306","side": "buy","ts": "1630048897897"}]}`
func TestTradePushData(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(tradePushDataJSON)); err != nil {
t.Error("Okx Trade Push Data error", err)
}
}
const estimatedDeliveryAndExercisePricePushDataJSON = `{"arg": {"args": "estimated-price","instType": "FUTURES","uly": "BTC-USD"},"data": [{"instType": "FUTURES","instId": "BTC-USD-170310","settlePx": "200","ts": "1597026383085"}]}`
func TestEstimatedDeliveryAndExercisePricePushData(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(estimatedDeliveryAndExercisePricePushDataJSON)); err != nil {
t.Error("Okx Estimated Delivery and Exercise Price Push Data error", err)
}
}
const markPricePushData = `{"arg": {"channel": "mark-price","instId": "LTC-USD-190628"},"data": [{"instType": "FUTURES","instId": "LTC-USD-190628","markPx": "0.1","ts": "1597026383085"}]}`
func TestMarkPricePushData(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(markPricePushData)); err != nil {
t.Error("Okx Mark Price Push Data error", err)
}
}
const markPriceCandlestickPushData = `{"arg": {"channel": "mark-price-candle1D","instId": "BTC-USD-190628"},"data": [["1597026383085", "3.721", "3.743", "3.677", "3.708"],["1597026383085", "3.731", "3.799", "3.494", "3.72"]]}`
func TestMarkPriceCandlestickPushData(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(markPriceCandlestickPushData)); err != nil {
t.Error("Okx Mark Price Candlestick Push Data error", err)
}
}
const priceLimitPushDataJSON = `{ "arg": { "channel": "price-limit", "instId": "LTC-USD-190628" }, "data": [{ "instId": "LTC-USD-190628", "buyLmt": "200", "sellLmt": "300", "ts": "1597026383085" }]}`
func TestPriceLimitPushData(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(priceLimitPushDataJSON)); err != nil {
t.Error("Okx Price Limit Push Data error", err)
}
}
const testSnapshotOrderbookPushData = `{"arg":{"channel":"books","instId":"BTC-USDT"},"action":"snapshot","data":[{"asks":[["0.07026","5","0","1"],["0.07027","765","0","3"],["0.07028","110","0","1"],["0.0703","1264","0","1"],["0.07034","280","0","1"],["0.07035","2255","0","1"],["0.07036","28","0","1"],["0.07037","63","0","1"],["0.07039","137","0","2"],["0.0704","48","0","1"],["0.07041","32","0","1"],["0.07043","3985","0","1"],["0.07057","257","0","1"],["0.07058","7870","0","1"],["0.07059","161","0","1"],["0.07061","4539","0","1"],["0.07068","1438","0","3"],["0.07088","3162","0","1"],["0.07104","99","0","1"],["0.07108","5018","0","1"],["0.07115","1540","0","1"],["0.07129","5080","0","1"],["0.07145","1512","0","1"],["0.0715","5016","0","1"],["0.07171","5026","0","1"],["0.07192","5062","0","1"],["0.07197","1517","0","1"],["0.0726","1511","0","1"],["0.07314","10376","0","1"],["0.07354","1","0","1"],["0.07466","10277","0","1"],["0.07626","269","0","1"],["0.07636","269","0","1"],["0.0809","1","0","1"],["0.08899","1","0","1"],["0.09789","1","0","1"],["0.10768","1","0","1"]],"bids":[["0.07014","56","0","2"],["0.07011","608","0","1"],["0.07009","110","0","1"],["0.07006","1264","0","1"],["0.07004","2347","0","3"],["0.07003","279","0","1"],["0.07001","52","0","1"],["0.06997","91","0","1"],["0.06996","4242","0","2"],["0.06995","486","0","1"],["0.06992","161","0","1"],["0.06991","63","0","1"],["0.06988","7518","0","1"],["0.06976","186","0","1"],["0.06975","71","0","1"],["0.06973","1086","0","1"],["0.06961","513","0","2"],["0.06959","4603","0","1"],["0.0695","186","0","1"],["0.06946","3043","0","1"],["0.06939","103","0","1"],["0.0693","5053","0","1"],["0.06909","5039","0","1"],["0.06888","5037","0","1"],["0.06886","1526","0","1"],["0.06867","5008","0","1"],["0.06846","5065","0","1"],["0.06826","1572","0","1"],["0.06801","1565","0","1"],["0.06748","67","0","1"],["0.0674","111","0","1"],["0.0672","10038","0","1"],["0.06652","1","0","1"],["0.06625","1526","0","1"],["0.06619","10924","0","1"],["0.05986","1","0","1"],["0.05387","1","0","1"],["0.04848","1","0","1"],["0.04363","1","0","1"]],"ts":"1659792392540","checksum":-1462286744}]}`
const updateOrderBookPushDataJSON = `{"arg":{"channel":"books","instId":"BTC-USDT"},"action":"update","data":[{"asks":[["0.07026","5","0","1"],["0.07027","765","0","3"],["0.07028","110","0","1"],["0.0703","1264","0","1"],["0.07034","280","0","1"],["0.07035","2255","0","1"],["0.07036","28","0","1"],["0.07037","63","0","1"],["0.07039","137","0","2"],["0.0704","48","0","1"],["0.07041","32","0","1"],["0.07043","3985","0","1"],["0.07057","257","0","1"],["0.07058","7870","0","1"],["0.07059","161","0","1"],["0.07061","4539","0","1"],["0.07068","1438","0","3"],["0.07088","3162","0","1"],["0.07104","99","0","1"],["0.07108","5018","0","1"],["0.07115","1540","0","1"],["0.07129","5080","0","1"],["0.07145","1512","0","1"],["0.0715","5016","0","1"],["0.07171","5026","0","1"],["0.07192","5062","0","1"],["0.07197","1517","0","1"],["0.0726","1511","0","1"],["0.07314","10376","0","1"],["0.07354","1","0","1"],["0.07466","10277","0","1"],["0.07626","269","0","1"],["0.07636","269","0","1"],["0.0809","1","0","1"],["0.08899","1","0","1"],["0.09789","1","0","1"],["0.10768","1","0","1"]],"bids":[["0.07014","56","0","2"],["0.07011","608","0","1"],["0.07009","110","0","1"],["0.07006","1264","0","1"],["0.07004","2347","0","3"],["0.07003","279","0","1"],["0.07001","52","0","1"],["0.06997","91","0","1"],["0.06996","4242","0","2"],["0.06995","486","0","1"],["0.06992","161","0","1"],["0.06991","63","0","1"],["0.06988","7518","0","1"],["0.06976","186","0","1"],["0.06975","71","0","1"],["0.06973","1086","0","1"],["0.06961","513","0","2"],["0.06959","4603","0","1"],["0.0695","186","0","1"],["0.06946","3043","0","1"],["0.06939","103","0","1"],["0.0693","5053","0","1"],["0.06909","5039","0","1"],["0.06888","5037","0","1"],["0.06886","1526","0","1"],["0.06867","5008","0","1"],["0.06846","5065","0","1"],["0.06826","1572","0","1"],["0.06801","1565","0","1"],["0.06748","67","0","1"],["0.0674","111","0","1"],["0.0672","10038","0","1"],["0.06652","1","0","1"],["0.06625","1526","0","1"],["0.06619","10924","0","1"],["0.05986","1","0","1"],["0.05387","1","0","1"],["0.04848","1","0","1"],["0.04363","1","0","1"]],"ts":"1659792392540","checksum":-1462286744}]}`
func TestSnapshotAndUpdateOrderBookPushData(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(testSnapshotOrderbookPushData)); err != nil {
t.Error("Okx Snapshot order book push data error", err)
}
if err := ok.WsHandleData([]byte(updateOrderBookPushDataJSON)); err != nil {
t.Error("Okx Update Order Book Push Data error", err)
}
}
var snapshotOrderBookPushData = `{"arg":{"channel":"books","instId":"%v"},"action":"snapshot","data":[{"asks":[["0.07026","5","0","1"],["0.07027","765","0","3"],["0.07028","110","0","1"],["0.0703","1264","0","1"],["0.07034","280","0","1"],["0.07035","2255","0","1"],["0.07036","28","0","1"],["0.07037","63","0","1"],["0.07039","137","0","2"],["0.0704","48","0","1"],["0.07041","32","0","1"],["0.07043","3985","0","1"],["0.07057","257","0","1"],["0.07058","7870","0","1"],["0.07059","161","0","1"],["0.07061","4539","0","1"],["0.07068","1438","0","3"],["0.07088","3162","0","1"],["0.07104","99","0","1"],["0.07108","5018","0","1"],["0.07115","1540","0","1"],["0.07129","5080","0","1"],["0.07145","1512","0","1"],["0.0715","5016","0","1"],["0.07171","5026","0","1"],["0.07192","5062","0","1"],["0.07197","1517","0","1"],["0.0726","1511","0","1"],["0.07314","10376","0","1"],["0.07354","1","0","1"],["0.07466","10277","0","1"],["0.07626","269","0","1"],["0.07636","269","0","1"],["0.0809","1","0","1"],["0.08899","1","0","1"],["0.09789","1","0","1"],["0.10768","1","0","1"]],"bids":[["0.07014","56","0","2"],["0.07011","608","0","1"],["0.07009","110","0","1"],["0.07006","1264","0","1"],["0.07004","2347","0","3"],["0.07003","279","0","1"],["0.07001","52","0","1"],["0.06997","91","0","1"],["0.06996","4242","0","2"],["0.06995","486","0","1"],["0.06992","161","0","1"],["0.06991","63","0","1"],["0.06988","7518","0","1"],["0.06976","186","0","1"],["0.06975","71","0","1"],["0.06973","1086","0","1"],["0.06961","513","0","2"],["0.06959","4603","0","1"],["0.0695","186","0","1"],["0.06946","3043","0","1"],["0.06939","103","0","1"],["0.0693","5053","0","1"],["0.06909","5039","0","1"],["0.06888","5037","0","1"],["0.06886","1526","0","1"],["0.06867","5008","0","1"],["0.06846","5065","0","1"],["0.06826","1572","0","1"],["0.06801","1565","0","1"],["0.06748","67","0","1"],["0.0674","111","0","1"],["0.0672","10038","0","1"],["0.06652","1","0","1"],["0.06625","1526","0","1"],["0.06619","10924","0","1"],["0.05986","1","0","1"],["0.05387","1","0","1"],["0.04848","1","0","1"],["0.04363","1","0","1"]],"ts":"1659792392540","checksum":-1462286744}]}`
func TestSnapshotPushData(t *testing.T) {
t.Parallel()
err := ok.WsHandleData([]byte(fmt.Sprintf(snapshotOrderBookPushData, ok.CurrencyPairs.Pairs[asset.Futures].Enabled[0])))
if err != nil {
t.Error("Okx Snapshot order book push data error", err)
}
}
const calculateOrderbookChecksumUpdateorderbookJSON = `{"Bids":[{"Amount":56,"Price":0.07014,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":608,"Price":0.07011,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":110,"Price":0.07009,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":1264,"Price":0.07006,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":2347,"Price":0.07004,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":279,"Price":0.07003,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":52,"Price":0.07001,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":91,"Price":0.06997,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":4242,"Price":0.06996,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":486,"Price":0.06995,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":161,"Price":0.06992,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":63,"Price":0.06991,"ID":0,"Period":0,"LiquidationOrders":0,
"OrderCount":0},{"Amount":7518,"Price":0.06988,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":186,"Price":0.06976,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":71,"Price":0.06975,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":1086,"Price":0.06973,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":513,"Price":0.06961,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":4603,"Price":0.06959,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":186,"Price":0.0695,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":3043,"Price":0.06946,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":103,"Price":0.06939,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":5053,"Price":0.0693,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":5039,"Price":0.06909,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":5037,"Price":0.06888,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":1526,"Price":0.06886,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":5008,"Price":0.06867,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":5065,"Price":0.06846,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":1572,"Price":0.06826,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":1565,"Price":0.06801,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":67,"Price":0.06748,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":111,"Price":0.0674,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":10038,"Price":0.0672,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":1,"Price":0.06652,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":1526,"Price":0.06625,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":10924,"Price":0.06619,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":1,"Price":0.05986,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":1,"Price":0.05387,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":1,"Price":0.04848,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":1,"Price":0.04363,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0}],"Asks":[{"Amount":5,"Price":0.07026,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":765,"Price":0.07027,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":110,"Price":0.07028,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":1264,"Price":0.0703,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":280,"Price":0.07034,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":2255,"Price":0.07035,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":28,"Price":0.07036,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":63,"Price":0.07037,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":137,"Price":0.07039,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":48,"Price":0.0704,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":32,"Price":0.07041,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":3985,"Price":0.07043,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":257,"Price":0.07057,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":7870,"Price":0.07058,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":161,"Price":0.07059,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":4539,"Price":0.07061,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":1438,"Price":0.07068,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":3162,"Price":0.07088,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":99,"Price":0.07104,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":5018,"Price":0.07108,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":1540,"Price":0.07115,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":5080,"Price":0.07129,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":1512,"Price":0.07145,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":5016,"Price":0.0715,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":5026,"Price":0.07171,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":5062,"Price":0.07192,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":1517,"Price":0.07197,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":1511,"Price":0.0726,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":10376,"Price":0.07314,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":1,"Price":0.07354,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":10277,"Price":0.07466,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":269,"Price":0.07626,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":269,"Price":0.07636,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":1,"Price":0.0809,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":1,"Price":0.08899,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":1,"Price":0.09789,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0},{"Amount":1,"Price":0.10768,"ID":0,"Period":0,"LiquidationOrders":0,"OrderCount":0}],"Exchange":"Okx","Pair":"BTC-USDT","Asset":"spot","LastUpdated":"0001-01-01T00:00:00Z","LastUpdateID":0,"PriceDuplication":false,"IsFundingRate":false,"RestSnapshot":false,"IDAlignment":false}`
func TestCalculateUpdateOrderbookChecksum(t *testing.T) {
t.Parallel()
var orderbookBase orderbook.Base
err := json.Unmarshal([]byte(calculateOrderbookChecksumUpdateorderbookJSON), &orderbookBase)
if err != nil {
t.Errorf("%s error while deserializing to orderbook.Base %v", ok.Name, err)
}
if err := ok.CalculateUpdateOrderbookChecksum(&orderbookBase, 2832680552); err != nil {
t.Errorf("%s CalculateUpdateOrderbookChecksum() error: %v", ok.Name, err)
}
}
const optionSummaryPushDataJSON = `{"arg": {"channel": "opt-summary","uly": "BTC-USD"},"data": [{"instType": "OPTION","instId": "BTC-USD-200103-5500-C","uly": "BTC-USD","delta": "0.7494223636","gamma": "-0.6765419039","theta": "-0.0000809873","vega": "0.0000077307","deltaBS": "0.7494223636","gammaBS": "-0.6765419039","thetaBS": "-0.0000809873","vegaBS": "0.0000077307","realVol": "0","bidVol": "","askVol": "1.5625","markVol": "0.9987","lever": "4.0342","fwdPx": "39016.8143629068452065","ts": "1597026383085"}]}`
func TestOptionSummaryPushData(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(optionSummaryPushDataJSON)); err != nil {
t.Error("Okx Option Summary Push Data error", err)
}
}
const fundingRatePushDataJSON = `{"arg": {"channel": "funding-rate","instId": "BTC-USD-SWAP"},"data": [{"instType": "SWAP","instId": "BTC-USD-SWAP","fundingRate": "0.018","nextFundingRate": "","fundingTime": "1597026383085"}]}`
func TestFundingRatePushData(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(fundingRatePushDataJSON)); err != nil {
t.Error("Okx Funding Rate Push Data error", err)
}
}
var indexCandlestickPushDataJSON = `{"arg": {"channel": "index-candle30m","instId": "BTC-USDT"},"data": [["1597026383085", "3811.31", "3811.31", "3811.31", "3811.31"]]}`
func TestIndexCandlestickPushData(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(indexCandlestickPushDataJSON)); err != nil {
t.Error("Okx Index Candlestick Push Data error", err)
}
}
const indexTickerPushDataJSON = `{"arg": {"channel": "index-tickers","instId": "BTC-USDT"},"data": [{"instId": "BTC-USDT","idxPx": "0.1","high24h": "0.5","low24h": "0.1","open24h": "0.1","sodUtc0": "0.1","sodUtc8": "0.1","ts": "1597026383085"}]}`
func TestIndexTickersPushData(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(indexTickerPushDataJSON)); err != nil {
t.Error("Okx Index Ticker Push Data error", err)
}
}
const statusPushDataJSON = `{"arg": {"channel": "status"},"data": [{"title": "Spot System Upgrade","state": "scheduled","begin": "1610019546","href": "","end": "1610019546","serviceType": "1","system": "classic","scheDesc": "","ts": "1597026383085"}]}`
func TestStatusPushData(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(statusPushDataJSON)); err != nil {
t.Error("Okx Status Push Data error", err)
}
}
const publicStructBlockTradesPushDataJSON = `{"arg":{"channel":"public-struc-block-trades"},"data":[{"cTime":"1608267227834","blockTdId":"1802896","legs":[{"px":"0.323","sz":"25.0","instId":"BTC-USD-20220114-13250-C","side":"sell","tradeId":"15102"},{"px":"0.666","sz":"25","instId":"BTC-USD-20220114-21125-C","side":"buy","tradeId":"15103"}]}]}`
func TestPublicStructBlockTrades(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(publicStructBlockTradesPushDataJSON)); err != nil {
t.Error("Okx Public Struct Block Trades error", err)
}
}
const blockTickerPushDataJSON = `{"arg": {"channel": "block-tickers"},"data": [{"instType": "SWAP","instId": "LTC-USD-SWAP","volCcy24h": "0","vol24h": "0","ts": "1597026383085"}]}`
func TestBlockTickerPushData(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(blockTickerPushDataJSON)); err != nil {
t.Error("Okx Block Tickers push data error", err)
}
}
const accountPushDataJSON = `{"arg": {"channel": "block-tickers"},"data": [{"instType": "SWAP","instId": "LTC-USD-SWAP","volCcy24h": "0","vol24h": "0","ts": "1597026383085"}]}`
func TestAccountPushData(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(accountPushDataJSON)); err != nil {
t.Error("Okx Account Push Data error", err)
}
}
const positionPushDataJSON = `{"arg":{"channel":"positions","instType":"FUTURES"},"data":[{"adl":"1","availPos":"1","avgPx":"2566.31","cTime":"1619507758793","ccy":"ETH","deltaBS":"","deltaPA":"","gammaBS":"","gammaPA":"","imr":"","instId":"ETH-USD-210430","instType":"FUTURES","interest":"0","last":"2566.22","lever":"10","liab":"","liabCcy":"","liqPx":"2352.8496681818233","markPx":"2353.849","margin":"0.0003896645377994","mgnMode":"isolated","mgnRatio":"11.731726509588816","mmr":"0.0000311811092368","notionalUsd":"2276.2546609009605","optVal":"","pTime":"1619507761462","pos":"1","posCcy":"","posId":"307173036051017730","posSide":"long","thetaBS":"","thetaPA":"","tradeId":"109844","uTime":"1619507761462","upl":"-0.0000009932766034","uplRatio":"-0.0025490556801078","vegaBS":"","vegaPA":""}]}`
const positionPushDataWithUnderlyingJSON = `{"arg": {"channel": "positions","uid": "77982378738415879","instType": "FUTURES"},"data": [{"adl":"1","availPos":"1","avgPx":"2566.31","cTime":"1619507758793","ccy":"ETH","deltaBS":"","deltaPA":"","gammaBS":"","gammaPA":"","imr":"","instId":"ETH-USD-210430","instType":"FUTURES","interest":"0","last":"2566.22","usdPx":"","lever":"10","liab":"","liabCcy":"","liqPx":"2352.8496681818233","markPx":"2353.849","margin":"0.0003896645377994","mgnMode":"isolated","mgnRatio":"11.731726509588816","mmr":"0.0000311811092368","notionalUsd":"2276.2546609009605","optVal":"","pTime":"1619507761462","pos":"1","posCcy":"","posId":"307173036051017730","posSide":"long","thetaBS":"","thetaPA":"","tradeId":"109844","uTime":"1619507761462","upl":"-0.0000009932766034","uplRatio":"-0.0025490556801078","vegaBS":"","vegaPA":""}, {"adl":"1","availPos":"1","avgPx":"2566.31","cTime":"1619507758793","ccy":"ETH","deltaBS":"","deltaPA":"","gammaBS":"","gammaPA":"","imr":"","instId":"ETH-USD-SWAP","instType":"SWAP","interest":"0","last":"2566.22","usdPx":"","lever":"10","liab":"","liabCcy":"","liqPx":"2352.8496681818233","markPx":"2353.849","margin":"0.0003896645377994","mgnMode":"isolated","mgnRatio":"11.731726509588816","mmr":"0.0000311811092368","notionalUsd":"2276.2546609009605","optVal":"","pTime":"1619507761462","pos":"1","posCcy":"","posId":"307173036051017730","posSide":"long","thetaBS":"","thetaPA":"","tradeId":"109844","uTime":"1619507761462","upl":"-0.0000009932766034","uplRatio":"-0.0025490556801078","vegaBS":"","vegaPA":""}]}`
func TestPositionPushData(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(positionPushDataJSON)); err != nil {
t.Error("Okx Account Push Data error", err)
}
if err := ok.WsHandleData([]byte(positionPushDataWithUnderlyingJSON)); err != nil {
t.Error("Okx Account Push Data error", err)
}
}
const balanceAndPositionJSON = `{"arg": {"channel": "balance_and_position","uid": "77982378738415879"},"data": [{"pTime": "1597026383085","eventType": "snapshot","balData": [{"ccy": "BTC","cashBal": "1","uTime": "1597026383085"}],"posData": [{"posId": "1111111111","tradeId": "2","instId": "BTC-USD-191018","instType": "FUTURES","mgnMode": "cross","posSide": "long","pos": "10","ccy": "BTC","posCcy": "","avgPx": "3320","uTIme": "1597026383085"}]}]}`
func TestBalanceAndPosition(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(balanceAndPositionJSON)); err != nil {
t.Error("Okx Balance And Position error", err)
}
}
func TestOrderPushData(t *testing.T) {
t.Parallel()
n := new(Okx)
sharedtestvalues.TestFixtureToDataHandler(t, ok, n, "testdata/wsOrders.json", n.WsHandleData)
seen := 0
for reading := true; reading; {
select {
default:
reading = false
case resp := <-n.GetBase().Websocket.DataHandler:
seen++
switch v := resp.(type) {
case *order.Detail:
switch seen {
case 1:
assert.Equal(t, "452197707845865472", v.OrderID, "OrderID")
assert.Equal(t, "HamsterParty14", v.ClientOrderID, "ClientOrderID")
assert.Equal(t, asset.Spot, v.AssetType, "AssetType")
assert.Equal(t, order.Sell, v.Side, "Side")
assert.Equal(t, order.Filled, v.Status, "Status")
assert.Equal(t, order.Limit, v.Type, "Type")
assert.Equal(t, currency.NewPairWithDelimiter("BTC", "USDT", "-"), v.Pair, "Pair")
assert.Equal(t, 31527.1, v.AverageExecutedPrice, "AverageExecutedPrice")
assert.Equal(t, time.UnixMilli(1654084334977), v.Date, "Date")
assert.Equal(t, time.UnixMilli(1654084353263), v.CloseTime, "CloseTime")
assert.Equal(t, 0.001, v.Amount, "Amount")
assert.Equal(t, 0.001, v.ExecutedAmount, "ExecutedAmount")
assert.Equal(t, 0.000, v.RemainingAmount, "RemainingAmount")
assert.Equal(t, 31527.1, v.Price, "Price")
assert.Equal(t, 0.02522168, v.Fee, "Fee")
assert.Equal(t, currency.USDT, v.FeeAsset, "FeeAsset")
case 2:
assert.Equal(t, "620258920632008725", v.OrderID, "OrderID")
assert.Equal(t, asset.Spot, v.AssetType, "AssetType")
assert.Equal(t, order.Market, v.Type, "Type")
assert.Equal(t, order.Sell, v.Side, "Side")
assert.Equal(t, order.Active, v.Status, "Status")
assert.Equal(t, 0.0, v.Amount, "Amount should be 0 for a market sell")
assert.Equal(t, 10.0, v.QuoteAmount, "QuoteAmount")
case 3:
assert.Equal(t, "620258920632008725", v.OrderID, "OrderID")
assert.Equal(t, 10.0, v.QuoteAmount, "QuoteAmount")
assert.Equal(t, 0.00038127046945832905, v.Amount, "Amount")
assert.Equal(t, 0.010000249968, v.Fee, "Fee")
assert.Equal(t, 0.0, v.RemainingAmount, "RemainingAmount")
assert.Equal(t, 0.00038128, v.ExecutedAmount, "ExecutedAmount")
assert.Equal(t, order.PartiallyFilled, v.Status, "Status")
case 4:
assert.Equal(t, "620258920632008725", v.OrderID, "OrderID")
assert.Equal(t, 10.0, v.QuoteAmount, "QuoteAmount")
assert.Equal(t, 0.010000249968, v.Fee, "Fee")
assert.Equal(t, 0.0, v.RemainingAmount, "RemainingAmount")
assert.Equal(t, 0.00038128, v.ExecutedAmount, "ExecutedAmount")
assert.Equal(t, 0.00038128, v.Amount, "Amount should be derived because order filled")
assert.Equal(t, order.Filled, v.Status, "Status")
}
case error:
t.Error(v)
default:
t.Errorf("Got unexpected data: %T %v", v, v)
}
}
}
assert.Equal(t, 4, seen, "Saw 4 records")
}
const algoOrdersPushDataJSON = `{"arg": {"channel": "orders-algo","uid": "77982378738415879","instType": "FUTURES","instId": "BTC-USD-200329"},"data": [{"instType": "FUTURES","instId": "BTC-USD-200329","ordId": "312269865356374016","ccy": "BTC","algoId": "1234","px": "999","sz": "3","tdMode": "cross","tgtCcy": "","notionalUsd": "","ordType": "trigger","side": "buy","posSide": "long","state": "live","lever": "20","tpTriggerPx": "","tpTriggerPxType": "","tpOrdPx": "","slTriggerPx": "","slTriggerPxType": "","triggerPx": "99","triggerPxType": "last","ordPx": "12","actualSz": "","actualPx": "","tag": "adadadadad","actualSide": "","triggerTime": "1597026383085","cTime": "1597026383000"}]}`
func TestAlgoOrderPushData(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(algoOrdersPushDataJSON)); err != nil {
t.Error("Okx Algo Order Push Data error", err)
}
}
const advancedAlgoOrderPushDataJSON = `{"arg":{"channel":"algo-advance","uid": "77982378738415879","instType":"SPOT","instId":"BTC-USDT"},"data":[{"actualPx":"","actualSide":"","actualSz":"0","algoId":"355056228680335360","cTime":"1630924001545","ccy":"","count":"1","instId":"BTC-USDT","instType":"SPOT","lever":"0","notionalUsd":"","ordPx":"","ordType":"iceberg","pTime":"1630924295204","posSide":"net","pxLimit":"10","pxSpread":"1","pxVar":"","side":"buy","slOrdPx":"","slTriggerPx":"","state":"pause","sz":"0.1","szLimit":"0.1","tdMode":"cash","timeInterval":"","tpOrdPx":"","tpTriggerPx":"","tag": "adadadadad","triggerPx":"","triggerTime":"","callbackRatio":"","callbackSpread":"","activePx":"","moveTriggerPx":""}]}`
func TestAdvancedAlgoOrderPushData(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(advancedAlgoOrderPushDataJSON)); err != nil {
t.Error("Okx Advanced Algo Orders Push Data error", err)
}
}
const positionRiskPushDataJSON = `{"arg": {"channel": "liquidation-warning","uid": "77982378738415879","instType": "FUTURES"},"data": [{"adl":"1","availPos":"1","avgPx":"2566.31","cTime":"1619507758793","ccy":"ETH","deltaBS":"","deltaPA":"","gammaBS":"","gammaPA":"","imr":"","instId":"ETH-USD-210430","instType":"FUTURES","interest":"0","last":"2566.22","lever":"10","liab":"","liabCcy":"","liqPx":"2352.8496681818233","markPx":"2353.849","margin":"0.0003896645377994","mgnMode":"isolated","mgnRatio":"11.731726509588816","mmr":"0.0000311811092368","notionalUsd":"2276.2546609009605","optVal":"","pTime":"1619507761462","pos":"1","posCcy":"","posId":"307173036051017730","posSide":"long","thetaBS":"","thetaPA":"","tradeId":"109844","uTime":"1619507761462","upl":"-0.0000009932766034","uplRatio":"-0.0025490556801078","vegaBS":"","vegaPA":""}, {"adl":"1","availPos":"1","avgPx":"2566.31","cTime":"1619507758793","ccy":"ETH","deltaBS":"","deltaPA":"","gammaBS":"","gammaPA":"","imr":"","instId":"ETH-USD-SWAP","instType":"SWAP","interest":"0","last":"2566.22","lever":"10","liab":"","liabCcy":"","liqPx":"2352.8496681818233","markPx":"2353.849","margin":"0.0003896645377994","mgnMode":"isolated","mgnRatio":"11.731726509588816","mmr":"0.0000311811092368","notionalUsd":"2276.2546609009605","optVal":"","pTime":"1619507761462","pos":"1","posCcy":"","posId":"307173036051017730","posSide":"long","thetaBS":"","thetaPA":"","tradeId":"109844","uTime":"1619507761462","upl":"-0.0000009932766034","uplRatio":"-0.0025490556801078","vegaBS":"","vegaPA":""}]}`
func TestPositionRiskPushDataJSON(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(positionRiskPushDataJSON)); err != nil {
t.Error("Okx Position Risk Push Data error", err)
}
}
const accountGreeksPushData = `{"arg": {"channel": "account-greeks","ccy": "BTC"},"data": [{"thetaBS": "","thetaPA":"","deltaBS":"","deltaPA":"","gammaBS":"","gammaPA":"","vegaBS":"", "vegaPA":"","ccy":"BTC","ts":"1620282889345"}]}`
func TestAccountGreeksPushData(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(accountGreeksPushData)); err != nil {
t.Error("Okx Account Greeks Push Data error", err)
}
}
const rfqsPushDataJSON = `{"arg": {"channel": "account-greeks","ccy": "BTC"},"data": [{"thetaBS": "","thetaPA":"","deltaBS":"","deltaPA":"","gammaBS":"","gammaPA":"","vegaBS":"", "vegaPA":"","ccy":"BTC","ts":"1620282889345"}]}`
func TestRfqs(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(rfqsPushDataJSON)); err != nil {
t.Error("Okx Rfqs Push Data error", err)
}
}
const accountsPushDataJSON = `{ "arg": { "channel": "account", "ccy": "BTC", "uid": "77982378738415879" }, "data": [ { "uTime": "1597026383085", "totalEq": "41624.32", "isoEq": "3624.32", "adjEq": "41624.32", "ordFroz": "0", "imr": "4162.33", "mmr": "4", "notionalUsd": "", "mgnRatio": "41624.32", "details": [ { "availBal": "", "availEq": "1", "ccy": "BTC", "cashBal": "1", "uTime": "1617279471503", "disEq": "50559.01", "eq": "1", "eqUsd": "45078.3790756226851775", "frozenBal": "0", "interest": "0", "isoEq": "0", "liab": "0", "maxLoan": "", "mgnRatio": "", "notionalLever": "0.0022195262185864", "ordFrozen": "0", "upl": "0", "uplLiab": "0", "crossLiab": "0", "isoLiab": "0", "coinUsdPrice": "60000", "stgyEq":"0", "spotInUseAmt":"", "isoUpl":"" } ] } ]}`
func TestAccounts(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(accountsPushDataJSON)); err != nil {
t.Errorf("%s Accounts push data error %v", ok.Name, err)
}
}
const quotesPushDataJSON = `{"arg":{"channel":"quotes"},"data":[{"validUntil":"1608997227854","uTime":"1608267227834","cTime":"1608267227834","legs":[{"px":"0.0023","sz":"25.0","instId":"BTC-USD-220114-25000-C","side":"sell","tgtCcy":""},{"px":"0.0045","sz":"25","instId":"BTC-USD-220114-35000-C","side":"buy","tgtCcy":""}],"quoteId":"25092","rfqId":"18753","traderCode":"SATS","quoteSide":"sell","state":"canceled","clQuoteId":""}]}`
func TestQuotesPushData(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(quotesPushDataJSON)); err != nil {
t.Error("Okx Quotes Push Data error", err)
}
}
const structureBlockTradesPushDataJSON = `{"arg":{"channel":"struc-block-trades"},"data":[{"cTime":"1608267227834","rfqId":"18753","clRfqId":"","quoteId":"25092","clQuoteId":"","blockTdId":"180184","tTraderCode":"ANAND","mTraderCode":"WAGMI","legs":[{"px":"0.0023","sz":"25.0","instId":"BTC-USD-20220630-60000-C","side":"sell","fee":"0.1001","feeCcy":"BTC","tradeId":"10211","tgtCcy":""},{"px":"0.0033","sz":"25","instId":"BTC-USD-20220630-50000-C","side":"buy","fee":"0.1001","feeCcy":"BTC","tradeId":"10212","tgtCcy":""}]}]}`
func TestStructureBlockTradesPushData(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(structureBlockTradesPushDataJSON)); err != nil {
t.Error("Okx Structure Block Trades error", err)
}
}
const spotGridAlgoOrdersPushDataJSON = `{"arg": {"channel": "grid-orders-spot","instType": "ANY"},"data": [{"algoId": "448965992920907776","algoOrdType": "grid","annualizedRate": "0","arbitrageNum": "0","baseSz": "0","cTime": "1653313834104","cancelType": "0","curBaseSz": "0.001776289214","curQuoteSz": "46.801755866","floatProfit": "-0.4953878967772","gridNum": "6","gridProfit": "0","instId": "BTC-USDC","instType": "SPOT","investment": "100","maxPx": "33444.8","minPx": "24323.5","pTime": "1653476023742","perMaxProfitRate": "0.060375293181491054543","perMinProfitRate": "0.0455275366818586","pnlRatio": "0","quoteSz": "100","runPx": "30478.1","runType": "1","singleAmt": "0.00059261","slTriggerPx": "","state": "running","stopResult": "0","stopType": "0","totalAnnualizedRate": "-0.9643551057262827","totalPnl": "-0.4953878967772","tpTriggerPx": "","tradeNum": "3","triggerTime": "1653378736894","uTime": "1653378736894"}]}`
func TestSpotGridAlgoOrdersPushData(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(spotGridAlgoOrdersPushDataJSON)); err != nil {
t.Error("Okx Spot Grid Algo Orders Push Data error", err)
}
}
const contractGridAlgoOrdersPushDataJSON = `{"arg": {"channel": "grid-orders-contract","instType": "ANY"},"data": [{"actualLever": "1.02","algoId": "449327675342323712","algoOrdType": "contract_grid","annualizedRate": "0.7572437878956523","arbitrageNum": "1","basePos": true,"cTime": "1653400065912","cancelType": "0","direction": "long","eq": "10129.419829834853","floatProfit": "109.537858234853","gridNum": "50","gridProfit": "19.8819716","instId": "BTC-USDT-SWAP","instType": "SWAP","investment": "10000","lever": "5","liqPx": "603.2149534767834","maxPx": "100000","minPx": "10","pTime": "1653484573918","perMaxProfitRate": "995.7080916791230692","perMinProfitRate": "0.0946277854875634","pnlRatio": "0.0129419829834853","runPx": "29216.3","runType": "1","singleAmt": "1","slTriggerPx": "","state": "running","stopType": "0","sz": "10000","tag": "","totalAnnualizedRate": "4.929207431970923","totalPnl": "129.419829834853","tpTriggerPx": "","tradeNum": "37","triggerTime": "1653400066940","uTime": "1653484573589","uly": "BTC-USDT"}]}`
func TestContractGridAlgoOrdersPushData(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(contractGridAlgoOrdersPushDataJSON)); err != nil {
t.Error("Okx Contract Grid Algo Order Push Data error", err)
}
}
const gridPositionsPushDataJSON = `{"arg": {"channel": "grid-positions","uid": "44705892343619584","algoId": "449327675342323712"},"data": [{"adl": "1","algoId": "449327675342323712","avgPx": "29181.4638888888888895","cTime": "1653400065917","ccy": "USDT","imr": "2089.2690000000002","instId": "BTC-USDT-SWAP","instType": "SWAP","last": "29852.7","lever": "5","liqPx": "604.7617536513744","markPx": "29849.7","mgnMode": "cross","mgnRatio": "217.71740878394456","mmr": "41.78538","notionalUsd": "10435.794191550001","pTime": "1653536068723","pos": "35","posSide": "net","uTime": "1653445498682","upl": "232.83263888888962","uplRatio": "0.1139826489932205"}]}`
func TestGridPositionsPushData(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(gridPositionsPushDataJSON)); err != nil {
t.Error("Okx Grid Positions Push Data error", err)
}
}
const gridSubOrdersPushDataJSON = `{"arg": {"channel": "grid-sub-orders","uid": "44705892343619584","algoId": "449327675342323712"},"data": [{"accFillSz": "0","algoId": "449327675342323712","algoOrdType": "contract_grid","avgPx": "0","cTime": "1653445498664","ctVal": "0.01","fee": "0","feeCcy": "USDT","groupId": "-1","instId": "BTC-USDT-SWAP","instType": "SWAP","lever": "5","ordId": "449518234142904321","ordType": "limit","pTime": "1653486524502","pnl": "","posSide": "net","px": "28007.2","side": "buy","state": "live","sz": "1","tag":"","tdMode": "cross","uTime": "1653445498674"}]}`
func TestGridSubOrdersPushData(t *testing.T) {
t.Parallel()
if err := ok.WsHandleData([]byte(gridSubOrdersPushDataJSON)); err != nil {
t.Error("Okx Grid Sub orders Push Data error", err)
}
}
func TestGetHistoricTrades(t *testing.T) {
t.Parallel()
if _, err := ok.GetHistoricTrades(contextGenerate(), currency.NewPair(currency.BTC, currency.USDT), asset.Spot, time.Now().Add(-time.Minute*4), time.Now().Add(-time.Minute*2)); err != nil {
t.Errorf("%s GetHistoricTrades() error %v", ok.Name, err)
}
}
func setupWS() {
if !ok.Websocket.IsEnabled() {
return
}
if !sharedtestvalues.AreAPICredentialsSet(ok) {
ok.Websocket.SetCanUseAuthenticatedEndpoints(false)
}
err := ok.WsConnect()
if err != nil {
log.Fatal(err)
}
}
// ************************** Public Channel Subscriptions *****************************
func TestInstrumentsSubscription(t *testing.T) {
t.Parallel()
if err := ok.InstrumentsSubscription("subscribe", asset.Spot, currency.NewPair(currency.BTC, currency.USDT)); err != nil {
t.Errorf("%s InstrumentsSubscription() error: %v", ok.Name, err)
}
}
func TestTickersSubscription(t *testing.T) {
t.Parallel()
if err := ok.TickersSubscription("subscribe", asset.Margin, currency.NewPair(currency.BTC, currency.USDT)); err != nil {
t.Errorf("%s TickersSubscription() error: %v", ok.Name, err)
}
if err := ok.TickersSubscription("unsubscribe", asset.Spot, currency.NewPair(currency.BTC, currency.USDT)); err != nil {
t.Errorf("%s TickersSubscription() error: %v", ok.Name, err)
}
}
func TestOpenInterestSubscription(t *testing.T) {
t.Parallel()
if err := ok.OpenInterestSubscription("subscribe", asset.PerpetualSwap, currency.NewPair(currency.BTC, currency.NewCode("USD-SWAP"))); err != nil {
t.Errorf("%s OpenInterestSubscription() error: %v", ok.Name, err)
}
}
func TestCandlesticksSubscription(t *testing.T) {
t.Parallel()
enabled, err := ok.GetEnabledPairs(asset.PerpetualSwap)
if err != nil {
t.Error("couldn't find enabled tradable pairs")
}
if len(enabled) == 0 {
t.SkipNow()
}
if err := ok.CandlesticksSubscription("subscribe", okxChannelCandle1m, asset.Futures, enabled[0]); err != nil {
t.Errorf("%s CandlesticksSubscription() error: %v", ok.Name, err)
}
}
func TestTradesSubscription(t *testing.T) {
t.Parallel()
if err := ok.TradesSubscription("subscribe", asset.Spot, currency.NewPair(currency.BTC, currency.USDT)); err != nil {
t.Errorf("%s TradesSubscription() error: %v", ok.Name, err)
}
}
func TestEstimatedDeliveryExercisePriceSubscription(t *testing.T) {
t.Parallel()
futuresPairs, err := ok.FetchTradablePairs(contextGenerate(), asset.Futures)
if err != nil {
t.Errorf("%s error while fetching tradable pairs for instrument type %v: %v", ok.Name, asset.Futures, err)
}
if len(futuresPairs) == 0 {
t.SkipNow()
}
if err := ok.EstimatedDeliveryExercisePriceSubscription("subscribe", asset.Futures, futuresPairs[0]); err != nil {
t.Errorf("%s EstimatedDeliveryExercisePriceSubscription() error: %v", ok.Name, err)
}
}
func TestMarkPriceSubscription(t *testing.T) {
t.Parallel()
futuresPairs, err := ok.FetchTradablePairs(contextGenerate(), asset.Futures)
if err != nil {
t.Errorf("%s error while fetching tradable pairs for instrument type %v: %v", ok.Name, asset.Futures, err)
}
if len(futuresPairs) == 0 {
t.SkipNow()
}
if err := ok.MarkPriceSubscription("subscribe", asset.Futures, futuresPairs[0]); err != nil {
t.Errorf("%s MarkPriceSubscription() error: %v", ok.Name, err)
}
}
func TestMarkPriceCandlesticksSubscription(t *testing.T) {
t.Parallel()
enabled, err := ok.GetEnabledPairs(asset.Spot)
if err != nil {
t.Error("couldn't find enabled tradable pairs")
}
if len(enabled) == 0 {
t.SkipNow()
}
if err := ok.MarkPriceCandlesticksSubscription("subscribe", okxChannelMarkPriceCandle1Y, asset.Futures, enabled[0]); err != nil {
t.Errorf("%s MarkPriceCandlesticksSubscription() error: %v", ok.Name, err)
}
}
func TestPriceLimitSubscription(t *testing.T) {
t.Parallel()
if err := ok.PriceLimitSubscription("subscribe", currency.Pair{Base: currency.NewCode("BTC"), Quote: currency.NewCode("USDT-SWAP")}); err != nil {
t.Errorf("%s PriceLimitSubscription() error: %v", ok.Name, err)
}
}
func TestOrderBooksSubscription(t *testing.T) {
t.Parallel()
enabled, err := ok.GetEnabledPairs(asset.Spot)
if err != nil {
t.Error("couldn't find enabled tradable pairs")
}
if len(enabled) == 0 {
t.SkipNow()
}
if err := ok.OrderBooksSubscription("subscribe", okxChannelOrderBooks, asset.Futures, enabled[0]); err != nil {
t.Errorf("%s OrderBooksSubscription() error: %v", ok.Name, err)
}
if err := ok.OrderBooksSubscription("unsubscribe", okxChannelOrderBooks, asset.Futures, enabled[0]); err != nil {
t.Errorf("%s OrderBooksSubscription() error: %v", ok.Name, err)
}
}
func TestOptionSummarySubscription(t *testing.T) {
t.Parallel()
if err := ok.OptionSummarySubscription("subscribe", currency.NewPair(currency.SOL, currency.USD)); err != nil {
t.Errorf("%s OptionSummarySubscription() error: %v", ok.Name, err)
}
if err := ok.OptionSummarySubscription("unsubscribe", currency.NewPair(currency.SOL, currency.USD)); err != nil {
t.Errorf("%s OptionSummarySubscription() error: %v", ok.Name, err)
}
}
func TestFundingRateSubscription(t *testing.T) {
t.Parallel()
if err := ok.FundingRateSubscription("subscribe", asset.Spot, currency.NewPair(currency.BTC, currency.NewCode("USDT-SWAP"))); err != nil {
t.Errorf("%s FundingRateSubscription() error: %v", ok.Name, err)
}
if err := ok.FundingRateSubscription("unsubscribe", asset.Spot, currency.NewPair(currency.BTC, currency.NewCode("USDT-SWAP"))); err != nil {
t.Errorf("%s FundingRateSubscription() error: %v", ok.Name, err)
}
}
func TestIndexCandlesticksSubscription(t *testing.T) {
t.Parallel()
if err := ok.IndexCandlesticksSubscription("subscribe", okxChannelIndexCandle6M, asset.Spot, currency.NewPair(currency.SOL, currency.USD)); err != nil {
t.Errorf("%s IndexCandlesticksSubscription() error: %v", ok.Name, err)
}
if err := ok.IndexCandlesticksSubscription("unsubscribe", okxChannelIndexCandle6M, asset.Spot, currency.NewPair(currency.SOL, currency.USD)); err != nil {
t.Errorf("%s IndexCandlesticksSubscription() error: %v", ok.Name, err)
}
}
func TestIndexTickerChannelIndexTickerChannel(t *testing.T) {
t.Parallel()
if err := ok.IndexTickerChannel("subscribe", asset.Spot, currency.NewPair(currency.SOL, currency.USD)); err != nil {
t.Errorf("%s IndexTickerChannel() error: %v", ok.Name, err)
}
if err := ok.IndexTickerChannel("unsubscribe", asset.Spot, currency.NewPair(currency.SOL, currency.USD)); err != nil {
t.Errorf("%s IndexTickerChannel() error: %v", ok.Name, err)
}
}
func TestStatusSubscription(t *testing.T) {
t.Parallel()
if err := ok.StatusSubscription("subscribe", asset.Spot, currency.NewPair(currency.SOL, currency.USD)); err != nil {
t.Errorf("%s StatusSubscription() error: %v", ok.Name, err)
}
if err := ok.StatusSubscription("unsubscribe", asset.Spot, currency.NewPair(currency.SOL, currency.USD)); err != nil {
t.Errorf("%s StatusSubscription() error: %v", ok.Name, err)
}
}
func TestPublicStructureBlockTradesSubscription(t *testing.T) {
t.Parallel()
if err := ok.PublicStructureBlockTradesSubscription("subscribe", asset.Spot, currency.NewPair(currency.SOL, currency.USD)); err != nil {
t.Errorf("%s PublicStructureBlockTradesSubscription() error: %v", ok.Name, err)
}
if err := ok.PublicStructureBlockTradesSubscription("unsubscribe", asset.Spot, currency.NewPair(currency.SOL, currency.USD)); err != nil {
t.Errorf("%s PublicStructureBlockTradesSubscription() error: %v", ok.Name, err)
}
}
func TestBlockTickerSubscription(t *testing.T) {
t.Parallel()
if err := ok.BlockTickerSubscription("subscribe", asset.Options, currency.NewPair(currency.BTC, currency.USDT)); err != nil {
t.Errorf("%s BlockTickerSubscription() error: %v", ok.Name, err)
}
if err := ok.BlockTickerSubscription("unsubscribe", asset.Options, currency.NewPair(currency.BTC, currency.USDT)); err != nil {
t.Errorf("%s BlockTickerSubscription() error: %v", ok.Name, err)
}
}
// ************ Authenticated Websocket endpoints Test **********************************************
func TestWsAccountSubscription(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if err := ok.WsAccountSubscription("subscribe", asset.Spot, currency.NewPair(currency.BTC, currency.USDT)); err != nil {
t.Errorf("%s WsAccountSubscription() error: %v", ok.Name, err)
}
}
const placeOrderJSON = `{ "id": "1512", "op": "order", "args": [{ "instId":"BTC-USDC", "tdMode":"cash", "clOrdId":"b15", "side":"Buy", "ordType":"limit", "px":"2.15", "sz":"2"} ]}`
func TestWsPlaceOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
var resp WsPlaceOrderInput
err := json.Unmarshal([]byte(placeOrderArgs), &resp)
if err != nil {
t.Error(err)
}
var response OrderData
err = json.Unmarshal([]byte(placeOrderJSON), &response)
if err != nil {
t.Error(err)
}
if _, err := ok.WsPlaceOrder(&PlaceOrderRequestParam{
InstrumentID: "BTC-USDC",
TradeMode: "cross",
Side: "Buy",
OrderType: "limit",
Amount: 2.6,
Price: 2.1,
Currency: "BTC",
}); err != nil {
t.Errorf("%s WsPlaceOrder() error: %v", ok.Name, err)
}
}
const placeOrderArgs = `{ "id": "1513", "op": "batch-orders", "args": [ { "side": "buy", "instId": "BTC-USDT", "tdMode": "cash", "ordType": "market", "sz": "100" }, { "side": "buy", "instId": "LTC-USDT", "tdMode": "cash", "ordType": "market", "sz": "1" } ]}`
func TestWsPlaceMultipleOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
var resp WsPlaceOrderInput
if err := json.Unmarshal([]byte(placeOrderArgs), &resp); err != nil {
t.Error(err)
}
pairs, err := ok.FetchTradablePairs(contextGenerate(), asset.Spot)
if err != nil {
t.Fatal(err)
} else if len(pairs) == 0 {
t.Skip("no pairs found")
}
if _, err := ok.WsPlaceMultipleOrder(resp.Arguments); err != nil {
t.Error("Okx WsPlaceMultipleOrder() error", err)
}
}
func TestWsCancelOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.WsCancelOrder(CancelOrderRequestParam{
InstrumentID: "BTC-USD-190927",
OrderID: "2510789768709120",
}); err != nil {
t.Error("Okx WsCancelOrder() error", err)
}
}
func TestWsCancleMultipleOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.WsCancelMultipleOrder([]CancelOrderRequestParam{{
InstrumentID: "DCR-BTC",
OrderID: "2510789768709120",
}}); err != nil && !strings.Contains(err.Error(), "Cancellation failed as the order does not exist.") {
t.Error("Okx WsCancleMultipleOrder() error", err)
}
}
func TestWsAmendOrder(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.WsAmendOrder(&AmendOrderRequestParams{
InstrumentID: "DCR-BTC",
OrderID: "2510789768709120",
NewPrice: 1233324.332,
NewQuantity: 1234,
}); err != nil && !strings.Contains(err.Error(), "order does not exist.") {
t.Errorf("%s WsAmendOrder() error %v", ok.Name, err)
}
}
func TestWsAmendMultipleOrders(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
if _, err := ok.WsAmendMultipleOrders([]AmendOrderRequestParams{
{
InstrumentID: "DCR-BTC",
OrderID: "2510789768709120",
NewPrice: 1233324.332,
NewQuantity: 1234,
},
}); err != nil && !strings.Contains(err.Error(), "Order modification failed as the order does not exist.") {
t.Errorf("%s WsAmendMultipleOrders() %v", ok.Name, err)
}
}
func TestWsPositionChannel(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if err := ok.WsPositionChannel("subscribe", asset.Options, currency.NewPair(currency.USD, currency.BTC)); err != nil {
t.Errorf("%s WsPositionChannel() error : %v", ok.Name, err)
}
}
func TestBalanceAndPositionSubscription(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if err := ok.BalanceAndPositionSubscription("subscribe", "1234"); err != nil {
t.Errorf("%s BalanceAndPositionSubscription() error %v", ok.Name, err)
}
if err := ok.BalanceAndPositionSubscription("unsubscribe", "1234"); err != nil {
t.Errorf("%s BalanceAndPositionSubscription() error %v", ok.Name, err)
}
}
func TestWsOrderChannel(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if err := ok.WsOrderChannel("subscribe", asset.Margin, currency.NewPair(currency.SOL, currency.USDT), ""); err != nil {
t.Errorf("%s WsOrderChannel() error: %v", ok.Name, err)
}
if err := ok.WsOrderChannel("unsubscribe", asset.Margin, currency.NewPair(currency.SOL, currency.USDT), ""); err != nil {
t.Errorf("%s WsOrderChannel() error: %v", ok.Name, err)
}
}
func TestAlgoOrdersSubscription(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if err := ok.AlgoOrdersSubscription("subscribe", asset.PerpetualSwap, currency.NewPair(currency.SOL, currency.NewCode("USD-SWAP"))); err != nil {
t.Errorf("%s AlgoOrdersSubscription() error: %v", ok.Name, err)
}
if err := ok.AlgoOrdersSubscription("unsubscribe", asset.PerpetualSwap, currency.NewPair(currency.SOL, currency.NewCode("USD-SWAP"))); err != nil {
t.Errorf("%s AlgoOrdersSubscription() error: %v", ok.Name, err)
}
}
func TestAdvanceAlgoOrdersSubscription(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if err := ok.AdvanceAlgoOrdersSubscription("subscribe", asset.PerpetualSwap, currency.NewPair(currency.SOL, currency.NewCode("USD-SWAP")), ""); err != nil {
t.Errorf("%s AdvanceAlgoOrdersSubscription() error: %v", ok.Name, err)
}
if err := ok.AdvanceAlgoOrdersSubscription("unsubscribe", asset.PerpetualSwap, currency.NewPair(currency.SOL, currency.NewCode("USD-SWAP")), ""); err != nil {
t.Errorf("%s AdvanceAlgoOrdersSubscription() error: %v", ok.Name, err)
}
}
func TestPositionRiskWarningSubscription(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if err := ok.PositionRiskWarningSubscription("subscribe", asset.PerpetualSwap, currency.NewPair(currency.SOL, currency.NewCode("USD-SWAP"))); err != nil {
t.Errorf("%s PositionRiskWarningSubscription() error: %v", ok.Name, err)
}
if err := ok.PositionRiskWarningSubscription("unsubscribe", asset.PerpetualSwap, currency.NewPair(currency.SOL, currency.NewCode("USD-SWAP"))); err != nil {
t.Errorf("%s PositionRiskWarningSubscription() error: %v", ok.Name, err)
}
}
func TestAccountGreeksSubscription(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if err := ok.AccountGreeksSubscription("subscribe", currency.NewPair(currency.SOL, currency.USD)); err != nil {
t.Errorf("%s AccountGreeksSubscription() error: %v", ok.Name, err)
}
if err := ok.AccountGreeksSubscription("unsubscribe", currency.NewPair(currency.SOL, currency.USD)); err != nil {
t.Errorf("%s AccountGreeksSubscription() error: %v", ok.Name, err)
}
}
func TestRfqSubscription(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if err := ok.RfqSubscription("subscribe", ""); err != nil {
t.Errorf("%s RfqSubscription() error: %v", ok.Name, err)
}
if err := ok.RfqSubscription("unsubscribe", ""); err != nil {
t.Errorf("%s RfqSubscription() error: %v", ok.Name, err)
}
}
func TestQuotesSubscription(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if err := ok.QuotesSubscription("subscribe"); err != nil {
t.Errorf("%s QuotesSubscription() error: %v", ok.Name, err)
}
if err := ok.QuotesSubscription("unsubscribe"); err != nil {
t.Errorf("%s QuotesSubscription() error: %v", ok.Name, err)
}
}
func TestStructureBlockTradesSubscription(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if err := ok.StructureBlockTradesSubscription("subscribe"); err != nil {
t.Errorf("%s StructureBlockTradesSubscription() error: %v", ok.Name, err)
}
if err := ok.StructureBlockTradesSubscription("unsubscribe"); err != nil {
t.Errorf("%s StructureBlockTradesSubscription() error: %v", ok.Name, err)
}
}
func TestSpotGridAlgoOrdersSubscription(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if err := ok.SpotGridAlgoOrdersSubscription("subscribe", asset.Empty, currency.EMPTYPAIR, ""); err != nil {
t.Errorf("%s SpotGridAlgoOrdersSubscription() error: %v", ok.Name, err)
}
if err := ok.SpotGridAlgoOrdersSubscription("unsubscribe", asset.Empty, currency.EMPTYPAIR, ""); err != nil {
t.Errorf("%s SpotGridAlgoOrdersSubscription() error: %v", ok.Name, err)
}
}
func TestContractGridAlgoOrders(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if err := ok.ContractGridAlgoOrders("subscribe", asset.Empty, currency.EMPTYPAIR, ""); err != nil {
t.Errorf("%s ContractGridAlgoOrders() error: %v", ok.Name, err)
}
if err := ok.ContractGridAlgoOrders("unsubscribe", asset.Empty, currency.EMPTYPAIR, ""); err != nil {
t.Errorf("%s ContractGridAlgoOrders() error: %v", ok.Name, err)
}
}
func TestGridPositionsSubscription(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if err := ok.GridPositionsSubscription("subscribe", "1234"); err != nil && !strings.Contains(err.Error(), "channel:grid-positions doesn't exist") {
t.Errorf("%s GridPositionsSubscription() error: %v", ok.Name, err)
}
if err := ok.GridPositionsSubscription("unsubscribe", "1234"); err != nil && !strings.Contains(err.Error(), "channel:grid-positions doesn't exist") {
t.Errorf("%s GridPositionsSubscription() error: %v", ok.Name, err)
}
}
func TestGridSubOrders(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if err := ok.GridSubOrders("subscribe", ""); err != nil && !strings.Contains(err.Error(), "grid-sub-orders doesn't exist") {
t.Errorf("%s GridSubOrders() error: %v", ok.Name, err)
}
if err := ok.GridSubOrders("unsubscribe", ""); err != nil && !strings.Contains(err.Error(), "grid-sub-orders doesn't exist") {
t.Errorf("%s GridSubOrders() error: %v", ok.Name, err)
}
}
func TestGetServerTime(t *testing.T) {
t.Parallel()
if _, err := ok.GetServerTime(contextGenerate(), asset.Empty); err != nil {
t.Error(err)
}
}
func TestGetAvailableTransferChains(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
if _, err := ok.GetAvailableTransferChains(contextGenerate(), currency.BTC); err != nil {
t.Error(err)
}
}
func TestGetIntervalEnum(t *testing.T) {
t.Parallel()
tests := []struct {
Description string
Interval kline.Interval
Expected string
AppendUTC bool
}{
{Description: "4hr with UTC", Interval: kline.FourHour, Expected: "4H", AppendUTC: true},
{Description: "6H without UTC", Interval: kline.SixHour, Expected: "6H"},
{Description: "6H with UTC", Interval: kline.SixHour, Expected: "6Hutc", AppendUTC: true},
{Description: "Unsupported interval with UTC", Expected: "", AppendUTC: true},
}
for x := range tests {
tt := tests[x]
t.Run(tt.Description, func(t *testing.T) {
t.Parallel()
if r := ok.GetIntervalEnum(tt.Interval, tt.AppendUTC); r != tt.Expected {
t.Errorf("%s: received: %s but expected: %s", tt.Description, r, tt.Expected)
}
})
}
}
const instrumentJSON = `{"alias":"","baseCcy":"","category":"1","ctMult":"1","ctType":"linear","ctVal":"0.0001","ctValCcy":"BTC","expTime":"","instFamily":"BTC-USDC","instId":"BTC-USDC-SWAP","instType":"SWAP","lever":"125","listTime":"1666076190000","lotSz":"1","maxIcebergSz":"100000000.0000000000000000","maxLmtSz":"100000000","maxMktSz":"85000","maxStopSz":"85000","maxTriggerSz":"100000000.0000000000000000","maxTwapSz":"","minSz":"1","optType":"","quoteCcy":"","settleCcy":"USDC","state":"live","stk":"","tickSz":"0.1","uly":"BTC-USDC"}`
func TestInstrument(t *testing.T) {
t.Parallel()
var i Instrument
err := json.Unmarshal([]byte(instrumentJSON), &i)
if err != nil {
t.Error(err)
}
if i.Alias != "" {
t.Error("expected empty alias")
}
if i.BaseCurrency != "" {
t.Error("expected empty base currency")
}
if i.Category != "1" {
t.Error("expected 1 category")
}
if i.ContractMultiplier != 1 {
t.Error("expected 1 contract multiplier")
}
if i.ContractType != "linear" {
t.Error("expected linear contract type")
}
if i.ContractValue.Float64() != 0.0001 {
t.Error("expected 0.0001 contract value")
}
if i.ContractValueCurrency != currency.BTC.String() {
t.Error("expected BTC contract value currency")
}
if !i.ExpTime.IsZero() {
t.Error("expected empty expiry time")
}
if i.InstrumentFamily != "BTC-USDC" {
t.Error("expected BTC-USDC instrument family")
}
if i.InstrumentID != "BTC-USDC-SWAP" {
t.Error("expected BTC-USDC-SWAP instrument ID")
}
swap := ok.GetInstrumentTypeFromAssetItem(asset.PerpetualSwap)
if i.InstrumentType != swap {
t.Error("expected SWAP instrument type")
}
if i.MaxLeverage != 125 {
t.Error("expected 125 leverage")
}
if i.ListTime.UnixMilli() != 1666076190000 {
t.Error("expected 1666076190000 listing time")
}
if i.LotSize != 1 {
t.Error("expected 1 lot size")
}
if i.MaxSpotIcebergSize != 100000000.0000000000000000 {
t.Error("expected 100000000.0000000000000000 max iceberg order size")
}
if i.MaxQuantityOfSpotLimitOrder != 100000000 {
t.Error("expected 100000000 max limit order size")
}
if i.MaxQuantityOfMarketLimitOrder != 85000 {
t.Error("expected 85000 max market order size")
}
if i.MaxStopSize != 85000 {
t.Error("expected 85000 max stop order size")
}
if i.MaxTriggerSize != 100000000.0000000000000000 {
t.Error("expected 100000000.0000000000000000 max trigger order size")
}
if i.MaxQuantityOfSpotTwapLimitOrder != 0 {
t.Error("expected empty max TWAP size")
}
if i.MinimumOrderSize != 1 {
t.Error("expected 1 min size")
}
if i.OptionType != "" {
t.Error("expected empty option type")
}
if i.QuoteCurrency != "" {
t.Error("expected empty quote currency")
}
if i.SettlementCurrency != currency.USDC.String() {
t.Error("expected USDC settlement currency")
}
if i.State != "live" {
t.Error("expected live state")
}
if i.StrikePrice != "" {
t.Error("expected empty strike price")
}
if i.TickSize != 0.1 {
t.Error("expected 0.1 tick size")
}
if i.Underlying != "BTC-USDC" {
t.Error("expected BTC-USDC underlying")
}
}
func TestGetLatestFundingRate(t *testing.T) {
t.Parallel()
cp, err := currency.NewPairFromString("BTC-USD-SWAP")
if err != nil {
t.Error(err)
}
_, err = ok.GetLatestFundingRates(contextGenerate(), &fundingrate.LatestRateRequest{
Asset: asset.PerpetualSwap,
Pair: cp,
IncludePredictedRate: true,
})
if err != nil {
t.Error(err)
}
}
func TestGetHistoricalFundingRates(t *testing.T) {
t.Parallel()
cp, err := currency.NewPairFromString("BTC-USD-SWAP")
if err != nil {
t.Error(err)
}
r := &fundingrate.HistoricalRatesRequest{
Asset: asset.PerpetualSwap,
Pair: cp,
PaymentCurrency: currency.USDT,
StartDate: time.Now().Add(-time.Hour * 24 * 7),
EndDate: time.Now(),
IncludePredictedRate: true,
}
if sharedtestvalues.AreAPICredentialsSet(ok) {
r.IncludePayments = true
}
_, err = ok.GetHistoricalFundingRates(contextGenerate(), r)
if err != nil {
t.Error(err)
}
r.StartDate = time.Now().Add(-time.Hour * 24 * 120)
_, err = ok.GetHistoricalFundingRates(contextGenerate(), r)
if !errors.Is(err, fundingrate.ErrFundingRateOutsideLimits) {
t.Error(err)
}
r.RespectHistoryLimits = true
_, err = ok.GetHistoricalFundingRates(contextGenerate(), r)
if err != nil {
t.Error(err)
}
}
func TestIsPerpetualFutureCurrency(t *testing.T) {
t.Parallel()
is, err := ok.IsPerpetualFutureCurrency(asset.Binary, currency.NewPair(currency.BTC, currency.USDT))
if err != nil {
t.Error(err)
}
if is {
t.Error("expected false")
}
cp, err := currency.NewPairFromString("BTC-USD-SWAP")
if err != nil {
t.Error(err)
}
is, err = ok.IsPerpetualFutureCurrency(asset.PerpetualSwap, cp)
if err != nil {
t.Error(err)
}
if !is {
t.Error("expected true")
}
}
func TestGetAssetsFromInstrumentTypeOrID(t *testing.T) {
t.Parallel()
_, err := ok.GetAssetsFromInstrumentTypeOrID("", "")
if !errors.Is(err, errEmptyArgument) {
t.Error(err)
}
assets, err := ok.GetAssetsFromInstrumentTypeOrID("SPOT", "")
if !errors.Is(err, nil) {
t.Error(err)
}
if len(assets) != 1 {
t.Errorf("received %v expected %v", len(assets), 1)
}
if assets[0] != asset.Spot {
t.Errorf("received %v expected %v", assets[0], asset.Spot)
}
assets, err = ok.GetAssetsFromInstrumentTypeOrID("", ok.CurrencyPairs.Pairs[asset.Futures].Enabled[0].String())
if !errors.Is(err, nil) {
t.Error(err)
}
if len(assets) != 1 {
t.Errorf("received %v expected %v", len(assets), 1)
}
if assets[0] != asset.Futures {
t.Errorf("received %v expected %v", assets[0], asset.Futures)
}
assets, err = ok.GetAssetsFromInstrumentTypeOrID("", ok.CurrencyPairs.Pairs[asset.PerpetualSwap].Enabled[0].String())
if !errors.Is(err, nil) {
t.Error(err)
}
if len(assets) != 1 {
t.Errorf("received %v expected %v", len(assets), 1)
}
if assets[0] != asset.PerpetualSwap {
t.Errorf("received %v expected %v", assets[0], asset.PerpetualSwap)
}
_, err = ok.GetAssetsFromInstrumentTypeOrID("", "test")
if !errors.Is(err, currency.ErrCurrencyNotSupported) {
t.Error(err)
}
_, err = ok.GetAssetsFromInstrumentTypeOrID("", "test-test")
if !errors.Is(err, asset.ErrNotSupported) {
t.Error(err)
}
assets, err = ok.GetAssetsFromInstrumentTypeOrID("", ok.CurrencyPairs.Pairs[asset.Margin].Enabled[0].String())
if !errors.Is(err, nil) {
t.Error(err)
}
var found bool
for i := range assets {
if assets[i] == asset.Margin {
found = true
}
}
if !found {
t.Errorf("received %v expected %v", assets, asset.Margin)
}
assets, err = ok.GetAssetsFromInstrumentTypeOrID("", ok.CurrencyPairs.Pairs[asset.Spot].Enabled[0].String())
if !errors.Is(err, nil) {
t.Error(err)
}
found = false
for i := range assets {
if assets[i] == asset.Spot {
found = true
}
}
if !found {
t.Errorf("received %v expected %v", assets, asset.Spot)
}
}
func TestSetMarginType(t *testing.T) {
t.Parallel()
err := ok.SetMarginType(contextGenerate(), asset.Spot, currency.NewBTCUSDT(), margin.Isolated)
if !errors.Is(err, common.ErrFunctionNotSupported) {
t.Errorf("received '%v', expected '%v'", err, asset.ErrNotSupported)
}
}
func TestChangePositionMargin(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
cp, err := currency.NewPairFromString("eth/btc")
if err != nil {
t.Error(err)
}
_, err = ok.ChangePositionMargin(contextGenerate(), &margin.PositionChangeRequest{
Pair: cp,
Asset: asset.Margin,
MarginType: margin.Isolated,
OriginalAllocatedMargin: 4.0695,
NewAllocatedMargin: 5,
})
if err != nil {
t.Error(err)
}
}
func TestGetCollateralMode(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
_, err := ok.GetCollateralMode(contextGenerate(), asset.Spot)
if !errors.Is(err, nil) {
t.Errorf("received '%v', expected '%v'", err, nil)
}
_, err = ok.GetCollateralMode(contextGenerate(), asset.Futures)
if !errors.Is(err, nil) {
t.Errorf("received '%v', expected '%v'", err, nil)
}
_, err = ok.GetCollateralMode(contextGenerate(), asset.USDTMarginedFutures)
if !errors.Is(err, asset.ErrNotSupported) {
t.Errorf("received '%v', expected '%v'", err, asset.ErrNotSupported)
}
}
func TestSetCollateralMode(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
err := ok.SetCollateralMode(contextGenerate(), asset.Spot, collateral.SingleMode)
if !errors.Is(err, common.ErrFunctionNotSupported) {
t.Errorf("received '%v', expected '%v'", err, asset.ErrNotSupported)
}
}
func TestGetPositionSummary(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
pp, err := ok.CurrencyPairs.GetPairs(asset.PerpetualSwap, true)
if err != nil {
t.Error(err)
}
_, err = ok.GetFuturesPositionSummary(contextGenerate(), &futures.PositionSummaryRequest{
Asset: asset.PerpetualSwap,
Pair: pp[0],
UnderlyingPair: currency.EMPTYPAIR,
})
if err != nil {
t.Error(err)
}
pp, err = ok.CurrencyPairs.GetPairs(asset.Futures, true)
if err != nil {
t.Error(err)
}
_, err = ok.GetFuturesPositionSummary(contextGenerate(), &futures.PositionSummaryRequest{
Asset: asset.Futures,
Pair: pp[0],
UnderlyingPair: currency.EMPTYPAIR,
})
if err != nil {
t.Error(err)
}
_, err = ok.GetFuturesPositionSummary(contextGenerate(), &futures.PositionSummaryRequest{
Asset: asset.Spot,
Pair: pp[0],
UnderlyingPair: currency.NewBTCUSDT(),
})
if !errors.Is(err, futures.ErrNotFuturesAsset) {
t.Errorf("received '%v', expected '%v'", err, futures.ErrNotFuturesAsset)
}
}
func TestGetFuturesPositions(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
pp, err := ok.CurrencyPairs.GetPairs(asset.Futures, true)
if err != nil {
t.Error(err)
}
_, err = ok.GetFuturesPositionOrders(contextGenerate(), &futures.PositionsRequest{
Asset: asset.Futures,
Pairs: []currency.Pair{pp[0]},
StartDate: time.Now().Add(time.Hour * 24 * -7),
})
if err != nil {
t.Error(err)
}
_, err = ok.GetFuturesPositionOrders(contextGenerate(), &futures.PositionsRequest{
Asset: asset.Spot,
Pairs: []currency.Pair{pp[0]},
StartDate: time.Now().Add(time.Hour * 24 * -7),
})
if !errors.Is(err, futures.ErrNotFuturesAsset) {
t.Errorf("received '%v', expected '%v'", err, asset.ErrNotSupported)
}
}
func TestGetLeverage(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok)
pp, err := ok.CurrencyPairs.GetPairs(asset.Futures, true)
if err != nil {
t.Error(err)
}
_, err = ok.GetLeverage(contextGenerate(), asset.Futures, pp[0], margin.Multi, order.UnknownSide)
if err != nil {
t.Error(err)
}
_, err = ok.GetLeverage(contextGenerate(), asset.Futures, pp[0], margin.Isolated, order.UnknownSide)
if !errors.Is(err, errOrderSideRequired) {
t.Errorf("received '%v', expected '%v'", err, errOrderSideRequired)
}
_, err = ok.GetLeverage(contextGenerate(), asset.Futures, pp[0], margin.Isolated, order.Long)
if err != nil {
t.Error(err)
}
_, err = ok.GetLeverage(contextGenerate(), asset.Futures, pp[0], margin.Isolated, order.Short)
if err != nil {
t.Error(err)
}
_, err = ok.GetLeverage(contextGenerate(), asset.Futures, pp[0], margin.Isolated, order.CouldNotBuy)
if !errors.Is(err, errInvalidOrderSide) {
t.Errorf("received '%v', expected '%v'", err, errInvalidOrderSide)
}
}
func TestSetLeverage(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
pp, err := ok.CurrencyPairs.GetPairs(asset.Futures, true)
if err != nil {
t.Error(err)
}
err = ok.SetLeverage(contextGenerate(), asset.Futures, pp[0], margin.Multi, 5, order.UnknownSide)
if err != nil {
t.Error(err)
}
err = ok.SetLeverage(contextGenerate(), asset.Futures, pp[0], margin.Isolated, 5, order.UnknownSide)
if !errors.Is(err, errOrderSideRequired) {
t.Errorf("received '%v', expected '%v'", err, errOrderSideRequired)
}
err = ok.SetLeverage(contextGenerate(), asset.Futures, pp[0], margin.Isolated, 5, order.Long)
if err != nil {
t.Error(err)
}
err = ok.SetLeverage(contextGenerate(), asset.Futures, pp[0], margin.Isolated, 5, order.Short)
if err != nil {
t.Error(err)
}
err = ok.SetLeverage(contextGenerate(), asset.Futures, pp[0], margin.Isolated, 5, order.CouldNotBuy)
if !errors.Is(err, errInvalidOrderSide) {
t.Errorf("received '%v', expected '%v'", err, errInvalidOrderSide)
}
err = ok.SetLeverage(contextGenerate(), asset.Spot, pp[0], margin.Multi, 5, order.UnknownSide)
if !errors.Is(err, asset.ErrNotSupported) {
t.Errorf("received '%v', expected '%v'", err, asset.ErrNotSupported)
}
}
func TestGetFuturesContractDetails(t *testing.T) {
t.Parallel()
_, err := ok.GetFuturesContractDetails(context.Background(), asset.Spot)
if !errors.Is(err, futures.ErrNotFuturesAsset) {
t.Error(err)
}
_, err = ok.GetFuturesContractDetails(context.Background(), asset.USDTMarginedFutures)
if !errors.Is(err, asset.ErrNotSupported) {
t.Error(err)
}
_, err = ok.GetFuturesContractDetails(context.Background(), asset.Futures)
if !errors.Is(err, nil) {
t.Error(err)
}
_, err = ok.GetFuturesContractDetails(context.Background(), asset.PerpetualSwap)
if !errors.Is(err, nil) {
t.Error(err)
}
}
func TestWsProcessOrderbook5(t *testing.T) {
t.Parallel()
var ob5payload = []byte(`{"arg":{"channel":"books5","instId":"OKB-USDT"},"data":[{"asks":[["0.0000007465","2290075956","0","4"],["0.0000007466","1747284705","0","4"],["0.0000007467","1338861655","0","3"],["0.0000007468","1661668387","0","6"],["0.0000007469","2715477116","0","5"]],"bids":[["0.0000007464","15693119","0","1"],["0.0000007463","2330835024","0","4"],["0.0000007462","1182926517","0","2"],["0.0000007461","3818684357","0","4"],["0.000000746","6021641435","0","7"]],"instId":"OKB-USDT","ts":"1695864901807","seqId":4826378794}]}`)
err := ok.wsProcessOrderbook5(ob5payload)
if err != nil {
t.Error(err)
}
required := currency.NewPairWithDelimiter("OKB", "USDT", "-")
got, err := orderbook.Get("okx", required, asset.Spot)
if err != nil {
t.Fatal(err)
}
if len(got.Asks) != 5 {
t.Errorf("expected %v, received %v", 5, len(got.Asks))
}
if len(got.Bids) != 5 {
t.Errorf("expected %v, received %v", 5, len(got.Bids))
}
// Book replicated to margin
got, err = orderbook.Get("okx", required, asset.Margin)
if err != nil {
t.Fatal(err)
}
if len(got.Asks) != 5 {
t.Errorf("expected %v, received %v", 5, len(got.Asks))
}
if len(got.Bids) != 5 {
t.Errorf("expected %v, received %v", 5, len(got.Bids))
}
}