Files
gocryptotrader/exchanges/bybit/bybit_test.go
Ryan O'Hara-Reid cad7586e98 exchange/websocket, gateio: Rename/export package again, add websocket request functions for futures trading (#1603)
* gateio: Add multi asset websocket support WIP.

* meow

* Add tests and shenanigans

* integrate flushing and for enabling/disabling pairs from rpc shenanigans

* some changes

* linter: fixes strikes again.

* Change name ConnectionAssociation -> ConnectionCandidate for better clarity on purpose. Change connections map to point to candidate to track subscriptions for future dynamic connections holder and drop struct ConnectionDetails.

* Add subscription tests (state functional)

* glorious:nits + proxy handling

* Spelling

* linter: fixerino

* instead of nil, dont do nil.

* clean up nils

* cya nils

* don't need to set URL or check if its running

* stream match update

* update tests

* linter: fix

* glorious: nits + handle context cancellations

* stop ping handler routine leak

* * Fix bug where reader routine on error that is not a disconnection error but websocket frame error or anything really makes the reader routine return and then connection never cycles and the buffer gets filled.
* Handle reconnection via an errors.Is check which is simpler and in that scope allow for quick disconnect reconnect without waiting for connection cycle.
* Dial now uses code from DialContext but just calls context.Background()
* Don't allow reader to return on parse binary response error. Just output error and return a non nil response

* Allow rollback on connect on any error across all connections

* fix shadow jutsu

* glorious/gk: nitters - adds in ws mock server

* linter: fix

* fix deadlock on connection as the previous channel had no reader and would hang connection reader for eternity.

* glorious: whooops

* gk: nits

* Leak issue and edge case

* Websocket: Add SendMessageReturnResponses

* whooooooopsie

* gk: nitssssss

* Update exchanges/stream/stream_match.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* Update exchanges/stream/stream_match_test.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* linter: appease the linter gods

* gk: nits

* gk: drain brain

* started

* more changes before merge match pr

* gateio: still building out

* gateio: finish spot

* fix up tests in gateio

* Add tests for stream package

* rm unused field

* glorious: nits

* rn files, specifically set function names to asset and offload routing to websocket type.

* linter: fix

* Add futures websocket request support

* gateio: integrate with IBOTExchange (cherry pick my nose)

* linter: fix

* glorious: nits

* add counter and update gateio

* fix collision issue

* Update exchanges/stream/websocket.go

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

* glorious: nits

* add tests

* linter: fix

* After merge

* Add error connection info

* upgrade to upstream merge

* Fix edge case where it does not reconnect made by an already closed connection

* stream coverage

* glorious: nits

* glorious: nits removed asset error handling in stream package

* linter: fix

* rm block

* Add basic readme

* fix asset enabled flush cycle for multi connection

* spella: fix

* linter: fix

* Add glorious suggestions, fix some race thing

* reinstate name before any routine gets spawned

* stop on error in mock tests

* glorious: nits

* Set correct price

* glorious: nits found in CI build

* Add test for drain, bumped wait times as there seems to be something happening on macos CI builds, used context.WithTimeout because its instant.

* mutex across shutdown and connect for protection

* lint: fix

* test time withoffset, reinstate stop

* fix whoops

* const trafficCheckInterval; rm testmain

* y

* fix lint

* bump time check window

* stream: fix intermittant test failures while testing routines and remove code that is not needed.

* spells

* cant do what I did

* protect race due to routine.

* update testURL

* use mock websocket connection instead of test URL's

* linter: fix

* remove url because its throwing errors on CI builds

* connections drop all the time, don't need to worry about not being able to echo back ws data as it can be easily reviewed _test file side.

* remove another superfluous url thats not really set up for this

* spawn overwatch routine when there is no errors, inline checker instead of waiting for a time period, add sleep inline with echo handler as this is really quick and wanted to ensure that latency is handing correctly

* linter: fixerino uperino

* fix ID bug, why I do this, I don't know.

* glorious: panix

* linter: things

* whoops

* dont need to make consecutive Unix() calls

* websocket: fix potential panic on error and no responses and adding waitForResponses

* rm json parser and handle in json package instead

* in favour of json package unmarshalling

* linter: fix

* linter: fix again

* * change field name OutboundRequestSignature to WrapperDefinedConnectionSignature for agnostic inbound and outbound connections.
* change method name GetOutboundConnection to GetConnection for agnostic inbound and outbound connections.
* drop outbound field map for improved performance just using a range and field check (less complex as well)
* change field name connections to connectionToWrapper for better clarity

* spells and magic and wands

* glorious: nits

* comparable check for signature

* mv err var

* glorious: nits and stuff

* attempt to fix race

* glorious: nits

* gk: nits; engine log cleanup

* gk: nits; OCD

* gk: nits; move function change file names

* gk: nits; 🚀

* gk: nits; convert variadic function and message inspection to interface and include a specific function for that handling so as to not need nil on every call

* gk: nits; continued

* gk: engine nits; rm loaded exchange

* gk: nits; drop WebsocketLoginResponse

* stream: Add match method EnsureMatchWithData

* gk: nits; rn Inspect to IsFinal

* gk: nits; rn to MessageFilter

* linter: fix

* gateio: update rate limit definitions (cherry-pick)

* Add test and missing

* Shared REST rate limit definitions with Websocket service, set lookup item to nil for systems that do not require rate limiting; add glorious nit

* integrate rate limits for websocket trading spot

* conform to match upstream changes

* standardise names to upstream style

* fix wrapper standards test when sending a auth request through a websocket connection

* whoops

* Update exchanges/gateio/gateio_types.go

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

* glorious: nits

* linter: fix

* linter: overload

* whoops

* spelling fixes on recent merge

* glorious: nits

* linter: fix?

* glorious: nits

* gk: assert errors touched

* gk: unexport derive functions

* gk: nitssssssss

* fix test

* gk: nitters v1

* gk: http status

* gk/nits: Add getAssetFromFuturesPair

* gk: nits single response when submitting

* gk: new pair with delimiter in tests

* gk: param update slice to slice of pointers

* gk: add asset type in params, includes t.Context() for tests

* linter: fix

* linter: fix

* fix merge whoopsie

* glorious: nits

* gk: nit

* shift over to websocket package error

* internal/exchange/websocket -> exchange/websocket

* PEAK OCD!

* appease the OCD gods

* thrasher: nits

---------

Co-authored-by: shazbert <ryan.oharareid@thrasher.io>
Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>
Co-authored-by: Scott <gloriousCode@users.noreply.github.com>
2025-04-11 16:47:33 +10:00

3902 lines
139 KiB
Go

package bybit
import (
"context"
"errors"
"fmt"
"maps"
"slices"
"testing"
"time"
"github.com/gofrs/uuid"
gws "github.com/gorilla/websocket"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/thrasher-corp/gocryptotrader/common"
"github.com/thrasher-corp/gocryptotrader/common/key"
"github.com/thrasher-corp/gocryptotrader/currency"
"github.com/thrasher-corp/gocryptotrader/encoding/json"
"github.com/thrasher-corp/gocryptotrader/exchange/websocket"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/fundingrate"
"github.com/thrasher-corp/gocryptotrader/exchanges/futures"
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
"github.com/thrasher-corp/gocryptotrader/exchanges/margin"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
"github.com/thrasher-corp/gocryptotrader/exchanges/subscription"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
testexch "github.com/thrasher-corp/gocryptotrader/internal/testing/exchange"
testsubs "github.com/thrasher-corp/gocryptotrader/internal/testing/subscriptions"
testws "github.com/thrasher-corp/gocryptotrader/internal/testing/websocket"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
"github.com/thrasher-corp/gocryptotrader/types"
)
// Please supply your own keys here to do authenticated endpoint testing
const (
apiKey = ""
apiSecret = ""
canManipulateRealOrders = false
skipAuthenticatedFunctionsForMockTesting = "skipping authenticated function for mock testing"
skippingWebsocketFunctionsForMockTesting = "skipping websocket function for mock testing"
)
var (
b = &Bybit{}
spotTradablePair, usdcMarginedTradablePair, usdtMarginedTradablePair, inverseTradablePair, optionsTradablePair currency.Pair
)
func TestGetInstrumentInfo(t *testing.T) {
t.Parallel()
_, err := b.GetInstrumentInfo(context.Background(), "spot", "", "", "", "", 0)
require.NoError(t, err)
_, err = b.GetInstrumentInfo(context.Background(), "linear", "", "", "", "", 0)
require.NoError(t, err)
_, err = b.GetInstrumentInfo(context.Background(), "inverse", "", "", "", "", 0)
require.NoError(t, err)
_, err = b.GetInstrumentInfo(context.Background(), "option", "", "", "", "", 0)
require.NoError(t, err)
payload, err := b.GetInstrumentInfo(context.Background(), "linear", "10000000AIDOGEUSDT", "", "", "", 0)
require.NoError(t, err)
require.NotEmpty(t, payload.List)
require.NotZero(t, payload.List[0].LotSizeFilter.MinNotionalValue)
}
func TestGetKlines(t *testing.T) {
t.Parallel()
s := time.Now().Add(-time.Hour)
e := time.Now()
if mockTests {
s = time.Unix(1691897100, 0).Round(kline.FiveMin.Duration())
e = time.Unix(1691907100, 0).Round(kline.FiveMin.Duration())
}
_, err := b.GetKlines(context.Background(), "spot", spotTradablePair.String(), kline.FiveMin, s, e, 100)
if err != nil {
t.Fatal(err)
}
_, err = b.GetKlines(context.Background(), "linear", usdtMarginedTradablePair.String(), kline.FiveMin, s, e, 5)
if err != nil {
t.Fatal(err)
}
_, err = b.GetKlines(context.Background(), "linear", usdcMarginedTradablePair.String(), kline.FiveMin, s, e, 5)
if err != nil {
t.Fatal(err)
}
_, err = b.GetKlines(context.Background(), "inverse", inverseTradablePair.String(), kline.FiveMin, s, e, 5)
if err != nil {
t.Fatal(err)
}
_, err = b.GetKlines(context.Background(), "option", optionsTradablePair.String(), kline.FiveMin, s, e, 5)
if err == nil {
t.Fatalf("expected 'params error: Category is invalid', but found nil")
}
}
func TestGetMarkPriceKline(t *testing.T) {
t.Parallel()
s := time.Now().Add(-time.Hour * 1)
e := time.Now()
if mockTests {
s = time.UnixMilli(1693077167971)
e = time.UnixMilli(1693080767971)
}
_, err := b.GetMarkPriceKline(context.Background(), "linear", usdtMarginedTradablePair.String(), kline.FiveMin, s, e, 5)
if err != nil {
t.Fatal(err)
}
_, err = b.GetMarkPriceKline(context.Background(), "linear", usdcMarginedTradablePair.String(), kline.FiveMin, s, e, 5)
if err != nil {
t.Fatal(err)
}
_, err = b.GetMarkPriceKline(context.Background(), "inverse", inverseTradablePair.String(), kline.FiveMin, s, e, 5)
if err != nil {
t.Fatal(err)
}
_, err = b.GetMarkPriceKline(context.Background(), "option", optionsTradablePair.String(), kline.FiveMin, s, e, 5)
if err == nil {
t.Fatalf("expected 'params error: Category is invalid', but found nil")
}
}
func TestGetIndexPriceKline(t *testing.T) {
t.Parallel()
s := time.Now().Add(-time.Hour * 1)
e := time.Now()
if mockTests {
s = time.UnixMilli(1693077165571)
e = time.UnixMilli(1693080765571)
}
_, err := b.GetIndexPriceKline(context.Background(), "linear", usdtMarginedTradablePair.String(), kline.FiveMin, s, e, 5)
if err != nil {
t.Fatal(err)
}
_, err = b.GetIndexPriceKline(context.Background(), "linear", usdcMarginedTradablePair.String(), kline.FiveMin, s, e, 5)
if err != nil {
t.Fatal(err)
}
_, err = b.GetIndexPriceKline(context.Background(), "inverse", inverseTradablePair.String(), kline.FiveMin, s, e, 5)
if err != nil {
t.Fatal(err)
}
}
func TestGetOrderBook(t *testing.T) {
t.Parallel()
_, err := b.GetOrderBook(context.Background(), "spot", spotTradablePair.String(), 100)
if err != nil {
t.Fatal(err)
}
_, err = b.GetOrderBook(context.Background(), "linear", usdtMarginedTradablePair.String(), 100)
if err != nil {
t.Fatal(err)
}
_, err = b.GetOrderBook(context.Background(), "linear", usdcMarginedTradablePair.String(), 100)
if err != nil {
t.Fatal(err)
}
_, err = b.GetOrderBook(context.Background(), "inverse", inverseTradablePair.String(), 100)
if err != nil {
t.Fatal(err)
}
_, err = b.GetOrderBook(context.Background(), "option", optionsTradablePair.String(), 0)
if err != nil {
t.Fatal(err)
}
}
func TestGetRiskLimit(t *testing.T) {
t.Parallel()
_, err := b.GetRiskLimit(context.Background(), "linear", usdtMarginedTradablePair.String())
if err != nil {
t.Error(err)
}
_, err = b.GetRiskLimit(context.Background(), "linear", usdcMarginedTradablePair.String())
if err != nil {
t.Error(err)
}
_, err = b.GetRiskLimit(context.Background(), "inverse", inverseTradablePair.String())
if err != nil {
t.Error(err)
}
_, err = b.GetRiskLimit(context.Background(), "option", optionsTradablePair.String())
if !errors.Is(err, errInvalidCategory) {
t.Error(err)
}
_, err = b.GetRiskLimit(context.Background(), "spot", spotTradablePair.String())
if !errors.Is(err, errInvalidCategory) {
t.Error(err)
}
}
// test cases for Wrapper
func TestUpdateTicker(t *testing.T) {
t.Parallel()
_, err := b.UpdateTicker(context.Background(), spotTradablePair, asset.Spot)
if err != nil {
t.Error(err)
}
_, err = b.UpdateTicker(context.Background(), usdtMarginedTradablePair, asset.USDTMarginedFutures)
if err != nil {
t.Error(err)
}
_, err = b.UpdateTicker(context.Background(), usdcMarginedTradablePair, asset.USDCMarginedFutures)
if err != nil {
t.Error(err)
}
_, err = b.UpdateTicker(context.Background(), inverseTradablePair, asset.CoinMarginedFutures)
if err != nil {
t.Error(err)
}
_, err = b.UpdateTicker(context.Background(), optionsTradablePair, asset.Options)
if err != nil {
t.Error(err)
}
}
func TestUpdateOrderbook(t *testing.T) {
t.Parallel()
var err error
_, err = b.UpdateOrderbook(context.Background(), spotTradablePair, asset.Spot)
if err != nil {
t.Error(err)
}
_, err = b.UpdateOrderbook(context.Background(), usdcMarginedTradablePair, asset.USDCMarginedFutures)
if err != nil {
t.Error(err)
}
_, err = b.UpdateOrderbook(context.Background(), usdtMarginedTradablePair, asset.USDTMarginedFutures)
if err != nil {
t.Error(err)
}
_, err = b.UpdateOrderbook(context.Background(), inverseTradablePair, asset.CoinMarginedFutures)
if err != nil {
t.Error(err)
}
_, err = b.UpdateOrderbook(context.Background(), optionsTradablePair, asset.Options)
if err != nil {
t.Error(err)
}
}
func TestSubmitOrder(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
orderSubmission := &order.Submit{
Exchange: b.GetName(),
Pair: spotTradablePair,
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientOrderID: "1234",
AssetType: asset.Spot,
}
_, err := b.SubmitOrder(context.Background(), orderSubmission)
if err != nil {
t.Error(err)
}
_, err = b.SubmitOrder(context.Background(), &order.Submit{
Exchange: b.GetName(),
AssetType: asset.Options,
Pair: optionsTradablePair,
Side: order.Sell,
Type: order.Market,
Price: 1,
Amount: 1,
Leverage: 1234,
ClientOrderID: "1234",
})
if err != nil {
t.Error(err)
}
}
func TestModifyOrder(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err := b.ModifyOrder(context.Background(), &order.Modify{
OrderID: "1234",
Type: order.Limit,
Side: order.Buy,
AssetType: asset.Options,
Pair: spotTradablePair,
PostOnly: true,
Price: 1234,
Amount: 0.15,
TriggerPrice: 1145,
RiskManagementModes: order.RiskManagementModes{
StopLoss: order.RiskManagement{
Price: 0,
},
},
})
if err != nil {
t.Error(err)
}
}
func TestGetHistoricCandles(t *testing.T) {
t.Parallel()
end := time.Now()
start := end.AddDate(0, 0, -3)
if mockTests {
start = time.UnixMilli(1692748800000)
end = time.UnixMilli(1693094400000)
}
_, err := b.GetHistoricCandles(context.Background(), spotTradablePair, asset.Spot, kline.OneDay, start, end)
if err != nil {
t.Error(err)
}
_, err = b.GetHistoricCandles(context.Background(), usdtMarginedTradablePair, asset.USDTMarginedFutures, kline.OneDay, start, end)
if err != nil {
t.Error(err)
}
_, err = b.GetHistoricCandles(context.Background(), usdcMarginedTradablePair, asset.USDCMarginedFutures, kline.OneDay, start, end)
if err != nil {
t.Error(err)
}
_, err = b.GetHistoricCandles(context.Background(), inverseTradablePair, asset.CoinMarginedFutures, kline.OneHour, start, end)
if err != nil {
t.Error(err)
}
_, err = b.GetHistoricCandles(context.Background(), optionsTradablePair, asset.Options, kline.OneHour, start, end)
if !errors.Is(err, asset.ErrNotSupported) {
t.Errorf("expected %v, got %v", asset.ErrNotSupported, err)
}
}
func TestGetHistoricCandlesExtended(t *testing.T) {
t.Parallel()
startTime := time.Now().Add(-time.Hour * 24 * 3)
end := time.Now().Add(-time.Hour * 1)
if mockTests {
startTime = time.UnixMilli(1692889428738)
end = time.UnixMilli(1693145028738)
}
_, err := b.GetHistoricCandlesExtended(context.Background(), spotTradablePair, asset.Spot, kline.OneMin, startTime, end)
if err != nil {
t.Error(err)
}
_, err = b.GetHistoricCandlesExtended(context.Background(), inverseTradablePair, asset.CoinMarginedFutures, kline.OneHour, startTime, end)
if err != nil {
t.Error(err)
}
_, err = b.GetHistoricCandlesExtended(context.Background(), usdtMarginedTradablePair, asset.USDTMarginedFutures, kline.OneDay, time.UnixMilli(1692889428738), time.UnixMilli(1693145028738))
if err != nil {
t.Error(err)
}
_, err = b.GetHistoricCandlesExtended(context.Background(), optionsTradablePair, asset.Options, kline.FiveMin, startTime, end)
if !errors.Is(err, asset.ErrNotSupported) {
t.Errorf("found '%v', expected '%v'", err, asset.ErrNotSupported)
}
}
func TestCancelOrder(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
err := b.CancelOrder(context.Background(), &order.Cancel{
Exchange: b.Name,
AssetType: asset.Spot,
Pair: spotTradablePair,
OrderID: "1234",
})
if err != nil {
t.Error(err)
}
err = b.CancelOrder(context.Background(), &order.Cancel{
Exchange: b.Name,
AssetType: asset.USDTMarginedFutures,
Pair: usdtMarginedTradablePair,
OrderID: "1234",
})
if err != nil {
t.Error(err)
}
err = b.CancelOrder(context.Background(), &order.Cancel{
Exchange: b.Name,
AssetType: asset.CoinMarginedFutures,
Pair: inverseTradablePair,
OrderID: "1234",
})
if err != nil {
t.Error(err)
}
err = b.CancelOrder(context.Background(), &order.Cancel{
Exchange: b.Name,
AssetType: asset.Options,
Pair: optionsTradablePair,
OrderID: "1234",
})
if err != nil {
t.Error(err)
}
}
func TestCancelAllOrders(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err := b.CancelAllOrders(context.Background(), &order.Cancel{AssetType: asset.Spot, Pair: spotTradablePair})
if err != nil {
t.Error(err)
}
_, err = b.CancelAllOrders(context.Background(), &order.Cancel{Exchange: b.Name, AssetType: asset.USDTMarginedFutures, Pair: usdtMarginedTradablePair})
if err != nil {
t.Error(err)
}
_, err = b.CancelAllOrders(context.Background(), &order.Cancel{Exchange: b.Name, AssetType: asset.CoinMarginedFutures, Pair: inverseTradablePair})
if err != nil {
t.Error(err)
}
_, err = b.CancelAllOrders(context.Background(), &order.Cancel{Exchange: b.Name, AssetType: asset.Options, Pair: optionsTradablePair})
if err != nil {
t.Error(err)
}
_, err = b.CancelAllOrders(context.Background(), &order.Cancel{Exchange: b.Name, AssetType: asset.Futures, Pair: spotTradablePair})
if !errors.Is(err, asset.ErrNotSupported) {
t.Errorf("expected %v, but found %v", asset.ErrNotSupported, err)
}
}
func TestGetOrderInfo(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetOrderInfo(context.Background(),
"12234", spotTradablePair, asset.Spot)
if err != nil {
t.Error(err)
}
_, err = b.GetOrderInfo(context.Background(),
"12234", usdtMarginedTradablePair, asset.USDTMarginedFutures)
if err != nil {
t.Error(err)
}
_, err = b.GetOrderInfo(context.Background(),
"12234", inverseTradablePair, asset.CoinMarginedFutures)
if err != nil {
t.Error(err)
}
_, err = b.GetOrderInfo(context.Background(),
"12234", optionsTradablePair, asset.Options)
if err != nil {
t.Error(err)
}
}
func TestGetActiveOrders(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
getOrdersRequestSpot := order.MultiOrderRequest{
Pairs: currency.Pairs{spotTradablePair},
AssetType: asset.Spot,
Side: order.AnySide,
Type: order.AnyType,
}
_, err := b.GetActiveOrders(context.Background(), &getOrdersRequestSpot)
if err != nil {
t.Error(err)
}
getOrdersRequestLinear := order.MultiOrderRequest{Pairs: currency.Pairs{usdtMarginedTradablePair}, AssetType: asset.USDTMarginedFutures, Side: order.AnySide, Type: order.AnyType}
_, err = b.GetActiveOrders(context.Background(), &getOrdersRequestLinear)
if err != nil {
t.Error(err)
}
getOrdersRequestInverse := order.MultiOrderRequest{Pairs: currency.Pairs{inverseTradablePair}, AssetType: asset.CoinMarginedFutures, Side: order.AnySide, Type: order.AnyType}
_, err = b.GetActiveOrders(context.Background(), &getOrdersRequestInverse)
if err != nil {
t.Error(err)
}
getOrdersRequestFutures := order.MultiOrderRequest{Pairs: currency.Pairs{optionsTradablePair}, AssetType: asset.Options, Side: order.AnySide, Type: order.AnyType}
_, err = b.GetActiveOrders(context.Background(), &getOrdersRequestFutures)
if err != nil {
t.Error(err)
}
pairs, err := currency.NewPairsFromStrings([]string{"BTC_USDT", "BTC_ETH", "BTC_USDC"})
if err != nil {
t.Fatal(err)
}
getOrdersRequestSpot = order.MultiOrderRequest{Pairs: pairs, AssetType: asset.Spot, Side: order.AnySide, Type: order.AnyType}
_, err = b.GetActiveOrders(context.Background(), &getOrdersRequestSpot)
if err != nil {
t.Error(err)
}
}
func TestGetOrderHistory(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
getOrdersRequestSpot := order.MultiOrderRequest{
Pairs: currency.Pairs{spotTradablePair},
AssetType: asset.Spot,
Type: order.AnyType,
Side: order.AnySide,
}
_, err := b.GetOrderHistory(context.Background(), &getOrdersRequestSpot)
if err != nil {
t.Error(err)
}
getOrdersRequestUMF := order.MultiOrderRequest{
Pairs: currency.Pairs{usdtMarginedTradablePair},
AssetType: asset.USDTMarginedFutures,
Type: order.AnyType,
Side: order.AnySide,
}
_, err = b.GetOrderHistory(context.Background(), &getOrdersRequestUMF)
if err != nil {
t.Error(err)
}
getOrdersRequestUMF.Pairs = currency.Pairs{usdcMarginedTradablePair}
getOrdersRequestUMF.AssetType = asset.USDCMarginedFutures
_, err = b.GetOrderHistory(context.Background(), &getOrdersRequestUMF)
if err != nil {
t.Error(err)
}
getOrdersRequestCMF := order.MultiOrderRequest{
Pairs: currency.Pairs{inverseTradablePair},
AssetType: asset.CoinMarginedFutures,
Type: order.AnyType,
Side: order.AnySide,
}
_, err = b.GetOrderHistory(context.Background(), &getOrdersRequestCMF)
if err != nil {
t.Error(err)
}
getOrdersRequestFutures := order.MultiOrderRequest{
Pairs: currency.Pairs{optionsTradablePair},
AssetType: asset.Options,
Type: order.AnyType,
Side: order.AnySide,
}
_, err = b.GetOrderHistory(context.Background(), &getOrdersRequestFutures)
if err != nil {
t.Error(err)
}
}
func TestGetDepositAddress(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetDepositAddress(context.Background(), currency.USDT, "", currency.ETH.String())
if err != nil {
t.Error(err)
}
}
func TestGetAvailableTransferChains(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetAvailableTransferChains(context.Background(), currency.USDT)
if err != nil {
t.Error(err)
}
}
func TestWithdrawCryptocurrencyFunds(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err := b.WithdrawCryptocurrencyFunds(context.Background(), &withdraw.Request{
Exchange: "Bybit",
Amount: 10,
Currency: currency.LTC,
Crypto: withdraw.CryptoRequest{
Chain: currency.LTC.String(),
Address: "3CDJNfdWX8m2NwuGUV3nhXHXEeLygMXoAj",
AddressTag: "",
},
})
if err != nil && err.Error() != "Withdraw address chain or destination tag are not equal" {
t.Fatal(err)
}
}
func TestUpdateTickers(t *testing.T) {
t.Parallel()
ctx := context.Background()
err := b.UpdateTickers(ctx, asset.Spot)
if err != nil {
t.Fatalf("%v %v\n", asset.Spot, err)
}
err = b.UpdateTickers(ctx, asset.USDTMarginedFutures)
if err != nil {
t.Fatalf("%v %v\n", asset.USDTMarginedFutures, err)
}
err = b.UpdateTickers(ctx, asset.CoinMarginedFutures)
if err != nil {
t.Fatalf("%v %v\n", asset.CoinMarginedFutures, err)
}
err = b.UpdateTickers(ctx, asset.Options)
if err != nil {
t.Fatalf("%v %v\n", asset.Options, err)
}
}
func TestGetTickersV5(t *testing.T) {
t.Parallel()
_, err := b.GetTickers(context.Background(), "bruh", "", "", time.Time{})
require.ErrorIs(t, err, errInvalidCategory)
_, err = b.GetTickers(context.Background(), "option", "BTC-26NOV24-92000-C", "", time.Time{})
require.NoError(t, err)
_, err = b.GetTickers(context.Background(), "spot", "", "", time.Time{})
require.NoError(t, err)
_, err = b.GetTickers(context.Background(), "inverse", "", "", time.Time{})
require.NoError(t, err)
_, err = b.GetTickers(context.Background(), "linear", "", "", time.Time{})
require.NoError(t, err)
_, err = b.GetTickers(context.Background(), "option", "", "BTC", time.Time{})
require.NoError(t, err)
}
func TestGetFundingRateHistory(t *testing.T) {
t.Parallel()
_, err := b.GetFundingRateHistory(context.Background(), "bruh", "", time.Time{}, time.Time{}, 0)
if !errors.Is(err, errInvalidCategory) {
t.Errorf("expected %v, got %v", errInvalidCategory, err)
}
_, err = b.GetFundingRateHistory(context.Background(), "spot", spotTradablePair.String(), time.Time{}, time.Time{}, 100)
if !errors.Is(err, errInvalidCategory) {
t.Errorf("expected %v, got %v", errInvalidCategory, err)
}
_, err = b.GetFundingRateHistory(context.Background(), "linear", usdtMarginedTradablePair.String(), time.Time{}, time.Time{}, 100)
if err != nil {
t.Error(err)
}
_, err = b.GetFundingRateHistory(context.Background(), "linear", usdcMarginedTradablePair.String(), time.Time{}, time.Time{}, 100)
if err != nil {
t.Error(err)
}
_, err = b.GetFundingRateHistory(context.Background(), "inverse", inverseTradablePair.String(), time.Time{}, time.Time{}, 100)
if err != nil {
t.Error(err)
}
_, err = b.GetFundingRateHistory(context.Background(), "option", optionsTradablePair.String(), time.Time{}, time.Time{}, 100)
if !errors.Is(err, errInvalidCategory) {
t.Errorf("expected %v, got %v", errInvalidCategory, err)
}
}
func TestGetPublicTradingHistory(t *testing.T) {
t.Parallel()
_, err := b.GetPublicTradingHistory(context.Background(), "spot", spotTradablePair.String(), "", "", 30)
if err != nil {
t.Error(err)
}
_, err = b.GetPublicTradingHistory(context.Background(), "linear", usdtMarginedTradablePair.String(), "", "", 30)
if err != nil {
t.Error(err)
}
_, err = b.GetPublicTradingHistory(context.Background(), "linear", usdcMarginedTradablePair.String(), "", "", 30)
if err != nil {
t.Error(err)
}
_, err = b.GetPublicTradingHistory(context.Background(), "inverse", inverseTradablePair.String(), "", "", 30)
if err != nil {
t.Error(err)
}
_, err = b.GetPublicTradingHistory(context.Background(), "option", optionsTradablePair.String(), "BTC", "", 30)
if err != nil {
t.Error(err)
}
}
func TestGetOpenInterestData(t *testing.T) {
t.Parallel()
_, err := b.GetOpenInterestData(context.Background(), "spot", spotTradablePair.String(), "5min", time.Time{}, time.Time{}, 0, "")
if !errors.Is(err, errInvalidCategory) {
t.Errorf("expected %v, got %v", errInvalidCategory, err)
}
_, err = b.GetOpenInterestData(context.Background(), "linear", usdtMarginedTradablePair.String(), "5min", time.Time{}, time.Time{}, 0, "")
if err != nil {
t.Error(err)
}
_, err = b.GetOpenInterestData(context.Background(), "linear", usdcMarginedTradablePair.String(), "5min", time.Time{}, time.Time{}, 0, "")
if err != nil {
t.Error(err)
}
_, err = b.GetOpenInterestData(context.Background(), "inverse", inverseTradablePair.String(), "5min", time.Time{}, time.Time{}, 0, "")
if err != nil {
t.Error(err)
}
_, err = b.GetOpenInterestData(context.Background(), "option", optionsTradablePair.String(), "5min", time.Time{}, time.Time{}, 0, "")
if !errors.Is(err, errInvalidCategory) {
t.Errorf("expected %v, got %v", errInvalidCategory, err)
}
}
func TestGetHistoricalVolatility(t *testing.T) {
t.Parallel()
start := time.Now().Add(-time.Hour * 30 * 24)
end := time.Now()
if mockTests {
end = time.UnixMilli(1693080759395)
start = time.UnixMilli(1690488759395)
}
_, err := b.GetHistoricalVolatility(context.Background(), "option", "", 123, start, end)
if err != nil {
t.Error(err)
}
_, err = b.GetHistoricalVolatility(context.Background(), "spot", "", 123, start, end)
if !errors.Is(err, errInvalidCategory) {
t.Errorf("expected %v, but found %v", errInvalidCategory, err)
}
}
func TestGetInsurance(t *testing.T) {
t.Parallel()
_, err := b.GetInsurance(context.Background(), "")
if err != nil {
t.Error(err)
}
}
func TestGetDeliveryPrice(t *testing.T) {
t.Parallel()
_, err := b.GetDeliveryPrice(context.Background(), "spot", spotTradablePair.String(), "", "", 200)
if !errors.Is(err, errInvalidCategory) {
t.Errorf("expected %v, but found %v", errInvalidCategory, err)
}
_, err = b.GetDeliveryPrice(context.Background(), "linear", "", "", "", 200)
if err != nil {
t.Error(err)
}
_, err = b.GetDeliveryPrice(context.Background(), "inverse", "", "", "", 200)
if err != nil {
t.Error(err)
}
_, err = b.GetDeliveryPrice(context.Background(), "option", "", "BTC", "", 200)
if err != nil {
t.Error(err)
}
}
func TestUpdateOrderExecutionLimits(t *testing.T) {
t.Parallel()
err := b.UpdateOrderExecutionLimits(context.Background(), asset.Futures)
assert.ErrorIs(t, err, asset.ErrNotSupported)
err = b.UpdateOrderExecutionLimits(context.Background(), asset.Options)
assert.NoError(t, err)
err = b.UpdateOrderExecutionLimits(context.Background(), asset.USDCMarginedFutures)
assert.NoError(t, err)
err = b.UpdateOrderExecutionLimits(context.Background(), asset.USDTMarginedFutures)
assert.NoError(t, err)
err = b.UpdateOrderExecutionLimits(context.Background(), asset.Spot)
assert.NoError(t, err)
availablePairs, err := b.GetAvailablePairs(asset.Spot)
if err != nil {
t.Fatal("Bybit GetAvailablePairs() error", err)
}
for x := range availablePairs {
var limits order.MinMaxLevel
limits, err = b.GetOrderExecutionLimits(asset.Spot, availablePairs[x])
require.NoError(t, err)
if limits == (order.MinMaxLevel{}) {
t.Fatal("Bybit GetOrderExecutionLimits() error cannot be nil")
}
}
}
func TestPlaceOrder(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
ctx := context.Background()
_, err := b.PlaceOrder(ctx, nil)
if !errors.Is(err, errNilArgument) {
t.Fatalf("expected %v, got %v", errNilArgument, err)
}
_, err = b.PlaceOrder(ctx, &PlaceOrderParams{})
if !errors.Is(err, errCategoryNotSet) {
t.Fatalf("expected %v, got %v", errCategoryNotSet, err)
}
_, err = b.PlaceOrder(ctx, &PlaceOrderParams{
Category: "my-category",
})
if !errors.Is(err, errInvalidCategory) {
t.Fatalf("expected %v, got %v", errInvalidCategory, err)
}
_, err = b.PlaceOrder(ctx, &PlaceOrderParams{
Category: "spot",
})
if !errors.Is(err, currency.ErrCurrencyPairEmpty) {
t.Fatalf("expected %v, got %v", currency.ErrCurrencyPairEmpty, err)
}
_, err = b.PlaceOrder(ctx, &PlaceOrderParams{
Category: "spot",
Symbol: currency.Pair{Delimiter: "", Base: currency.BTC, Quote: currency.USDT},
})
if !errors.Is(err, order.ErrSideIsInvalid) {
t.Fatalf("expected %v, got %v", order.ErrSideIsInvalid, err)
}
_, err = b.PlaceOrder(ctx, &PlaceOrderParams{
Category: "spot",
Symbol: spotTradablePair,
Side: "buy",
})
if !errors.Is(err, order.ErrTypeIsInvalid) {
t.Fatalf("expected %v, got %v", order.ErrTypeIsInvalid, err)
}
_, err = b.PlaceOrder(ctx, &PlaceOrderParams{
Category: "spot",
Symbol: spotTradablePair,
Side: "buy",
OrderType: "limit",
})
if !errors.Is(err, order.ErrAmountBelowMin) {
t.Fatalf("expected %v, got %v", order.ErrAmountBelowMin, err)
}
_, err = b.PlaceOrder(ctx, &PlaceOrderParams{
Category: "spot",
Symbol: spotTradablePair,
Side: "buy",
OrderType: "limit",
OrderQuantity: 1,
TriggerDirection: 3,
})
if !errors.Is(err, errInvalidTriggerDirection) {
t.Fatalf("expected %v, got %v", errInvalidTriggerDirection, err)
}
_, err = b.PlaceOrder(context.Background(), &PlaceOrderParams{
Category: "spot",
Symbol: spotTradablePair,
Side: "buy",
OrderType: "limit",
OrderQuantity: 1,
Price: 31431.48,
TriggerDirection: 2,
})
if err != nil {
t.Error(err)
}
// Spot post only normal order
arg := &PlaceOrderParams{Category: "spot", Symbol: spotTradablePair, Side: "Buy", OrderType: "Limit", OrderQuantity: 0.1, Price: 15600, TimeInForce: "PostOnly", OrderLinkID: "spot-test-01", IsLeverage: 0, OrderFilter: "Order"}
_, err = b.PlaceOrder(context.Background(), arg)
if err != nil {
t.Error(err)
}
// Spot TP/SL order
arg = &PlaceOrderParams{
Category: "spot",
Symbol: spotTradablePair,
Side: "Buy", OrderType: "Limit",
OrderQuantity: 0.1, Price: 15600, TriggerPrice: 15000,
TimeInForce: "GTC", OrderLinkID: "spot-test-02", IsLeverage: 0, OrderFilter: "tpslOrder",
}
_, err = b.PlaceOrder(context.Background(), arg)
if err != nil {
t.Error(err)
}
// Spot margin normal order (UTA)
arg = &PlaceOrderParams{
Category: "spot", Symbol: spotTradablePair, Side: "Buy", OrderType: "Limit",
OrderQuantity: 0.1, Price: 15600, TimeInForce: "IOC", OrderLinkID: "spot-test-limit", IsLeverage: 1, OrderFilter: "Order",
}
_, err = b.PlaceOrder(context.Background(), arg)
if err != nil {
t.Error(err)
}
arg = &PlaceOrderParams{
Category: "spot",
Symbol: spotTradablePair,
Side: "Buy", OrderType: "Market", OrderQuantity: 200,
TimeInForce: "IOC", OrderLinkID: "spot-test-04",
IsLeverage: 0, OrderFilter: "Order",
}
_, err = b.PlaceOrder(context.Background(), arg)
if err != nil {
t.Error(err)
}
// USDT Perp open long position (one-way mode)
arg = &PlaceOrderParams{
Category: "linear",
Symbol: usdcMarginedTradablePair, Side: "Buy", OrderType: "Limit", OrderQuantity: 1, Price: 25000, TimeInForce: "GTC", PositionIdx: 0, OrderLinkID: "usdt-test-01", ReduceOnly: false, TakeProfitPrice: 28000, StopLossPrice: 20000, TpslMode: "Partial", TpOrderType: "Limit", SlOrderType: "Limit", TpLimitPrice: 27500, SlLimitPrice: 20500,
}
_, err = b.PlaceOrder(context.Background(), arg)
if err != nil {
t.Error(err)
}
// USDT Perp close long position (one-way mode)
arg = &PlaceOrderParams{
Category: "linear", Symbol: usdtMarginedTradablePair, Side: "Sell",
OrderType: "Limit", OrderQuantity: 1, Price: 3000, TimeInForce: "GTC", PositionIdx: 0, OrderLinkID: "usdt-test-02", ReduceOnly: true,
}
_, err = b.PlaceOrder(context.Background(), arg)
if err != nil {
t.Error(err)
}
}
func TestAmendOrder(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err := b.AmendOrder(context.Background(), nil)
if !errors.Is(err, errNilArgument) {
t.Fatalf("expected %v, got %v", errNilArgument, err)
}
_, err = b.AmendOrder(context.Background(), &AmendOrderParams{})
if !errors.Is(err, errEitherOrderIDOROrderLinkIDRequired) {
t.Fatalf("expected %v, got %v", errEitherOrderIDOROrderLinkIDRequired, err)
}
_, err = b.AmendOrder(context.Background(), &AmendOrderParams{
OrderID: "c6f055d9-7f21-4079-913d-e6523a9cfffa",
})
if !errors.Is(err, errCategoryNotSet) {
t.Fatalf("expected %v, got %v", errCategoryNotSet, err)
}
_, err = b.AmendOrder(context.Background(), &AmendOrderParams{
OrderID: "c6f055d9-7f21-4079-913d-e6523a9cfffa",
Category: "mycat",
})
if !errors.Is(err, errInvalidCategory) {
t.Fatalf("expected %v, got %v", errInvalidCategory, err)
}
_, err = b.AmendOrder(context.Background(), &AmendOrderParams{
OrderID: "c6f055d9-7f21-4079-913d-e6523a9cfffa",
Category: "option",
})
if !errors.Is(err, currency.ErrCurrencyPairEmpty) {
t.Fatalf("expected %v, got %v", currency.ErrCurrencyPairEmpty, err)
}
_, err = b.AmendOrder(context.Background(), &AmendOrderParams{
OrderID: "c6f055d9-7f21-4079-913d-e6523a9cfffa",
Category: cSpot,
Symbol: spotTradablePair,
TriggerPrice: 1145,
OrderQuantity: 0.15,
Price: 1050,
TakeProfitPrice: 0,
StopLossPrice: 0,
})
if err != nil {
t.Error(err)
}
}
func TestCancelTradeOrder(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err := b.CancelTradeOrder(context.Background(), nil)
if !errors.Is(err, errNilArgument) {
t.Fatalf("expected %v, got %v", errNilArgument, err)
}
_, err = b.CancelTradeOrder(context.Background(), &CancelOrderParams{})
if !errors.Is(err, errEitherOrderIDOROrderLinkIDRequired) {
t.Fatalf("expected %v, got %v", errEitherOrderIDOROrderLinkIDRequired, err)
}
_, err = b.CancelTradeOrder(context.Background(), &CancelOrderParams{
OrderID: "c6f055d9-7f21-4079-913d-e6523a9cfffa",
})
if !errors.Is(err, errCategoryNotSet) {
t.Fatalf("expected %v, got %v", errCategoryNotSet, err)
}
_, err = b.CancelTradeOrder(context.Background(), &CancelOrderParams{
OrderID: "c6f055d9-7f21-4079-913d-e6523a9cfffa",
Category: "mycat",
})
if !errors.Is(err, errInvalidCategory) {
t.Fatalf("expected %v, got %v", errInvalidCategory, err)
}
_, err = b.CancelTradeOrder(context.Background(), &CancelOrderParams{
OrderID: "c6f055d9-7f21-4079-913d-e6523a9cfffa",
Category: "option",
})
if !errors.Is(err, currency.ErrCurrencyPairEmpty) {
t.Fatalf("expected %v, got %v", currency.ErrCurrencyPairEmpty, err)
}
_, err = b.CancelTradeOrder(context.Background(), &CancelOrderParams{
OrderID: "c6f055d9-7f21-4079-913d-e6523a9cfffa",
Category: "option",
Symbol: optionsTradablePair,
})
if err != nil {
t.Fatal(err)
}
}
func TestGetOpenOrders(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
_, err := b.GetOpenOrders(context.Background(), "", "", "", "", "", "", "", "", 0, 100)
if !errors.Is(err, errCategoryNotSet) {
t.Fatalf("expected %v, got %v", errCategoryNotSet, err)
}
_, err = b.GetOpenOrders(context.Background(), "spot", "", "", "", "", "", "", "", 0, 0)
if err != nil {
t.Error(err)
}
}
func TestCancelAllTradeOrders(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err := b.CancelAllTradeOrders(context.Background(), nil)
if !errors.Is(err, errNilArgument) {
t.Fatalf("expected %v, got %v", errNilArgument, err)
}
_, err = b.CancelAllTradeOrders(context.Background(), &CancelAllOrdersParam{})
if !errors.Is(err, errCategoryNotSet) {
t.Fatalf("expected %v, got %v", errCategoryNotSet, err)
}
_, err = b.CancelAllTradeOrders(context.Background(), &CancelAllOrdersParam{Category: "option"})
if err != nil {
t.Error(err)
}
}
func TestGetTradeOrderHistory(t *testing.T) {
t.Parallel()
start := time.Now().Add(-time.Hour * 24 * 6)
end := time.Now()
if mockTests {
end = time.UnixMilli(1700058627109)
start = time.UnixMilli(1699540227109)
} else {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
_, err := b.GetTradeOrderHistory(context.Background(), "", "", "", "", "", "", "", "", "", start, end, 100)
if !errors.Is(err, errCategoryNotSet) {
t.Fatalf("expected %v, got %v", errCategoryNotSet, err)
}
_, err = b.GetTradeOrderHistory(context.Background(), "spot", spotTradablePair.String(), "", "", "BTC", "", "StopOrder", "", "", start, end, 100)
if err != nil {
t.Error(err)
}
}
func TestPlaceBatchOrder(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err := b.PlaceBatchOrder(context.Background(), nil)
if !errors.Is(err, errNilArgument) {
t.Fatalf("expected %v, got %v", errNilArgument, err)
}
_, err = b.PlaceBatchOrder(context.Background(), &PlaceBatchOrderParam{})
if !errors.Is(err, errCategoryNotSet) {
t.Fatalf("expected %v, got %v", errCategoryNotSet, err)
}
_, err = b.PlaceBatchOrder(context.Background(), &PlaceBatchOrderParam{
Category: "linear",
})
if !errors.Is(err, errNoOrderPassed) {
t.Fatalf("expected %v, got %v", errNoOrderPassed, err)
}
_, err = b.PlaceBatchOrder(context.Background(), &PlaceBatchOrderParam{
Category: "option",
Request: []BatchOrderItemParam{
{
Symbol: optionsTradablePair,
OrderType: "Limit",
Side: "Buy",
OrderQuantity: 1,
OrderIv: 6,
TimeInForce: "GTC",
OrderLinkID: "option-test-001",
MarketMakerProtection: false,
ReduceOnly: false,
},
{
Symbol: optionsTradablePair,
OrderType: "Limit",
Side: "Sell",
OrderQuantity: 2,
Price: 700,
TimeInForce: "GTC",
OrderLinkID: "option-test-001",
MarketMakerProtection: false,
ReduceOnly: false,
},
},
})
if err != nil {
t.Fatal(err)
}
_, err = b.PlaceBatchOrder(context.Background(), &PlaceBatchOrderParam{
Category: "linear",
Request: []BatchOrderItemParam{
{
Symbol: optionsTradablePair,
OrderType: "Limit",
Side: "Buy",
OrderQuantity: 1,
OrderIv: 6,
TimeInForce: "GTC",
OrderLinkID: "linear-test-001",
MarketMakerProtection: false,
ReduceOnly: false,
},
{
Symbol: optionsTradablePair,
OrderType: "Limit",
Side: "Sell",
OrderQuantity: 2,
Price: 700,
TimeInForce: "GTC",
OrderLinkID: "linear-test-001",
MarketMakerProtection: false,
ReduceOnly: false,
},
},
})
if err != nil {
t.Fatal(err)
}
}
func TestBatchAmendOrder(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err := b.BatchAmendOrder(context.Background(), "linear", nil)
if !errors.Is(err, errNilArgument) {
t.Fatalf("expected %v, got %v", errNilArgument, err)
}
_, err = b.BatchAmendOrder(context.Background(), "", []BatchAmendOrderParamItem{
{
Symbol: optionsTradablePair,
OrderImpliedVolatility: "6.8",
OrderID: "b551f227-7059-4fb5-a6a6-699c04dbd2f2",
},
})
if !errors.Is(err, errCategoryNotSet) {
t.Fatalf("expected %v, got %v", errCategoryNotSet, err)
}
_, err = b.BatchAmendOrder(context.Background(), "option", []BatchAmendOrderParamItem{
{
Symbol: optionsTradablePair,
OrderImpliedVolatility: "6.8",
OrderID: "b551f227-7059-4fb5-a6a6-699c04dbd2f2",
},
{
Symbol: optionsTradablePair,
Price: 650,
OrderID: "fa6a595f-1a57-483f-b9d3-30e9c8235a52",
},
})
if err != nil {
t.Fatal(err)
}
}
func TestCancelBatchOrder(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err := b.CancelBatchOrder(context.Background(), nil)
if !errors.Is(err, errNilArgument) {
t.Fatalf("expected %v, got %v", errNilArgument, err)
}
_, err = b.CancelBatchOrder(context.Background(), &CancelBatchOrder{})
if !errors.Is(err, errInvalidCategory) {
t.Fatalf("expected %v, got %v", errInvalidCategory, err)
}
_, err = b.CancelBatchOrder(context.Background(), &CancelBatchOrder{Category: cOption})
if !errors.Is(err, errNoOrderPassed) {
t.Fatalf("expected %v, got %v", errNoOrderPassed, err)
}
_, err = b.CancelBatchOrder(context.Background(), &CancelBatchOrder{
Category: "option",
Request: []CancelOrderParams{
{
Symbol: optionsTradablePair,
OrderID: "b551f227-7059-4fb5-a6a6-699c04dbd2f2",
},
{
Symbol: optionsTradablePair,
OrderID: "fa6a595f-1a57-483f-b9d3-30e9c8235a52",
},
},
})
if err != nil {
t.Fatal(err)
}
}
func TestGetBorrowQuota(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
_, err := b.GetBorrowQuota(context.Background(), "", "BTCUSDT", "Buy")
if !errors.Is(err, errCategoryNotSet) {
t.Fatalf("expected %v, got %v", errCategoryNotSet, err)
}
_, err = b.GetBorrowQuota(context.Background(), "spot", "", "Buy")
if !errors.Is(err, errSymbolMissing) {
t.Fatalf("expected %v, got %v", errSymbolMissing, err)
}
_, err = b.GetBorrowQuota(context.Background(), "spot", spotTradablePair.String(), "")
if !errors.Is(err, order.ErrSideIsInvalid) {
t.Error(err)
}
_, err = b.GetBorrowQuota(context.Background(), "spot", spotTradablePair.String(), "Buy")
if err != nil {
t.Error(err)
}
}
func TestSetDisconnectCancelAll(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
err := b.SetDisconnectCancelAll(context.Background(), nil)
if !errors.Is(err, errNilArgument) {
t.Fatalf("expected %v, got %v", errNilArgument, err)
}
err = b.SetDisconnectCancelAll(context.Background(), &SetDCPParams{TimeWindow: 300})
if err != nil {
t.Fatal(err)
}
}
func TestGetPositionInfo(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
_, err := b.GetPositionInfo(context.Background(), "", "", "", "", "", 20)
if !errors.Is(err, errCategoryNotSet) {
t.Fatalf("expected %v, got %v", errCategoryNotSet, err)
}
_, err = b.GetPositionInfo(context.Background(), "spot", "", "", "", "", 20)
if !errors.Is(err, errInvalidCategory) {
t.Fatalf("expected %v, got %v", errInvalidCategory, err)
}
_, err = b.GetPositionInfo(context.Background(), "linear", "BTCUSDT", "", "", "", 20)
if err != nil {
t.Error(err)
}
_, err = b.GetPositionInfo(context.Background(), "option", "BTC-26NOV24-92000-C", "BTC", "", "", 20)
if err != nil {
t.Error(err)
}
}
func TestSetLeverageLevel(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
err := b.SetLeverageLevel(context.Background(), nil)
if !errors.Is(err, errNilArgument) {
t.Errorf("expected %v, got %v", errNilArgument, err)
}
err = b.SetLeverageLevel(context.Background(), &SetLeverageParams{})
if !errors.Is(err, errCategoryNotSet) {
t.Fatalf("expected %v, got %v", errCategoryNotSet, err)
}
err = b.SetLeverageLevel(context.Background(), &SetLeverageParams{Category: "spot"})
if !errors.Is(err, errInvalidCategory) {
t.Fatalf("expected %v, got %v", errInvalidCategory, err)
}
err = b.SetLeverageLevel(context.Background(), &SetLeverageParams{Category: "linear"})
if !errors.Is(err, errSymbolMissing) {
t.Fatalf("expected %v, got %v", errSymbolMissing, err)
}
err = b.SetLeverageLevel(context.Background(), &SetLeverageParams{Category: "linear", Symbol: "BTCUSDT"})
if !errors.Is(err, errInvalidLeverage) {
t.Fatalf("expected %v, got %v", errInvalidLeverage, err)
}
err = b.SetLeverageLevel(context.Background(), &SetLeverageParams{Category: "linear", Symbol: "BTCUSDT", SellLeverage: 3, BuyLeverage: 3})
if err != nil {
t.Error(err)
}
}
func TestSwitchTradeMode(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
err := b.SwitchTradeMode(context.Background(), nil)
if !errors.Is(err, errNilArgument) {
t.Errorf("expected %v, got %v", errNilArgument, err)
}
err = b.SwitchTradeMode(context.Background(), &SwitchTradeModeParams{})
if !errors.Is(err, errCategoryNotSet) {
t.Fatalf("expected %v, got %v", errCategoryNotSet, err)
}
err = b.SwitchTradeMode(context.Background(), &SwitchTradeModeParams{Category: "spot"})
if !errors.Is(err, errInvalidCategory) {
t.Fatalf("expected %v, got %v", errInvalidCategory, err)
}
err = b.SwitchTradeMode(context.Background(), &SwitchTradeModeParams{Category: "linear"})
if !errors.Is(err, errSymbolMissing) {
t.Fatalf("expected %v, got %v", errSymbolMissing, err)
}
err = b.SwitchTradeMode(context.Background(), &SwitchTradeModeParams{Category: "linear", Symbol: usdtMarginedTradablePair.String()})
if !errors.Is(err, errInvalidLeverage) {
t.Fatalf("expected %v, got %v", errInvalidLeverage, err)
}
err = b.SwitchTradeMode(context.Background(), &SwitchTradeModeParams{Category: "linear", Symbol: usdcMarginedTradablePair.String(), SellLeverage: 3, BuyLeverage: 3, TradeMode: 2})
if !errors.Is(err, errInvalidTradeModeValue) {
t.Fatalf("expected %v, got %v", errInvalidTradeModeValue, err)
}
err = b.SwitchTradeMode(context.Background(), &SwitchTradeModeParams{Category: "linear", Symbol: usdtMarginedTradablePair.String(), SellLeverage: 3, BuyLeverage: 3, TradeMode: 1})
if err != nil {
t.Error(err)
}
}
func TestSetTakeProfitStopLossMode(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err := b.SetTakeProfitStopLossMode(context.Background(), nil)
if !errors.Is(err, errNilArgument) {
t.Errorf("expected %v, got %v", errNilArgument, err)
}
_, err = b.SetTakeProfitStopLossMode(context.Background(), &TPSLModeParams{})
if !errors.Is(err, errCategoryNotSet) {
t.Fatalf("expected %v, got %v", errCategoryNotSet, err)
}
_, err = b.SetTakeProfitStopLossMode(context.Background(), &TPSLModeParams{
Category: "spot",
})
if !errors.Is(err, errInvalidCategory) {
t.Fatalf("expected %v, got %v", errInvalidCategory, err)
}
_, err = b.SetTakeProfitStopLossMode(context.Background(), &TPSLModeParams{Category: "spot"})
if !errors.Is(err, errInvalidCategory) {
t.Fatalf("expected %v, got %v", errInvalidCategory, err)
}
_, err = b.SetTakeProfitStopLossMode(context.Background(), &TPSLModeParams{Category: "linear"})
if !errors.Is(err, errSymbolMissing) {
t.Fatalf("expected %v, got %v", errSymbolMissing, err)
}
_, err = b.SetTakeProfitStopLossMode(context.Background(), &TPSLModeParams{Category: "linear", Symbol: "BTCUSDT"})
if !errors.Is(err, errTakeProfitOrStopLossModeMissing) {
t.Fatalf("expected %v, got %v", errTakeProfitOrStopLossModeMissing, err)
}
_, err = b.SetTakeProfitStopLossMode(context.Background(), &TPSLModeParams{Category: "linear", Symbol: "BTCUSDT", TpslMode: "Partial"})
if err != nil {
t.Error(err)
}
}
func TestSwitchPositionMode(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
err := b.SwitchPositionMode(context.Background(), nil)
if !errors.Is(err, errNilArgument) {
t.Fatalf("expected %v, got %v", errNilArgument, err)
}
err = b.SwitchPositionMode(context.Background(), &SwitchPositionModeParams{})
if !errors.Is(err, errCategoryNotSet) {
t.Fatalf("expected %v, got %v", errCategoryNotSet, err)
}
err = b.SwitchPositionMode(context.Background(), &SwitchPositionModeParams{Category: "linear"})
if !errors.Is(err, errEitherSymbolOrCoinRequired) {
t.Fatalf("expected %v, got %v", errInvalidCategory, err)
}
err = b.SwitchPositionMode(context.Background(), &SwitchPositionModeParams{Category: "linear", Symbol: usdtMarginedTradablePair, PositionMode: 3})
if err != nil {
t.Error(err)
}
}
func TestSetRiskLimit(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err := b.SetRiskLimit(context.Background(), nil)
if !errors.Is(err, errNilArgument) {
t.Errorf("expected %v, got %v", errNilArgument, err)
}
_, err = b.SetRiskLimit(context.Background(), &SetRiskLimitParam{})
if !errors.Is(err, errCategoryNotSet) {
t.Errorf("expected %v, got %v", errCategoryNotSet, err)
}
_, err = b.SetRiskLimit(context.Background(), &SetRiskLimitParam{Category: "linear", PositionMode: -2})
if !errors.Is(err, errInvalidPositionMode) {
t.Errorf("expected %v, got %v", errInvalidPositionMode, err)
}
_, err = b.SetRiskLimit(context.Background(), &SetRiskLimitParam{Category: "linear"})
if !errors.Is(err, errSymbolMissing) {
t.Errorf("expected %v, got %v", errSymbolMissing, err)
}
_, err = b.SetRiskLimit(context.Background(), &SetRiskLimitParam{
Category: "linear",
RiskID: 1234,
Symbol: usdtMarginedTradablePair,
PositionMode: 0,
})
if err != nil {
t.Error(err)
}
}
func TestSetTradingStop(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
err := b.SetTradingStop(context.Background(), &TradingStopParams{})
if !errors.Is(err, errCategoryNotSet) {
t.Errorf("expected %v, got %v", errCategoryNotSet, err)
}
err = b.SetTradingStop(context.Background(), &TradingStopParams{Category: "spot"})
if !errors.Is(err, errInvalidCategory) {
t.Errorf("expected %v, got %v", errInvalidCategory, err)
}
err = b.SetTradingStop(context.Background(), &TradingStopParams{
Category: "linear",
Symbol: usdtMarginedTradablePair,
TakeProfit: "0.5",
StopLoss: "0.2",
TakeProfitTriggerType: "MarkPrice",
StopLossTriggerType: "IndexPrice",
TakeProfitOrStopLossMode: "Partial",
TakeProfitOrderType: "Limit",
StopLossOrderType: "Limit",
TakeProfitSize: 50,
StopLossSize: 50,
TakeProfitLimitPrice: 0.49,
StopLossLimitPrice: 0.21,
PositionIndex: 0,
})
if err != nil {
t.Error(err)
}
err = b.SetTradingStop(context.Background(), &TradingStopParams{
Category: "linear",
Symbol: usdcMarginedTradablePair,
TakeProfit: "0.5",
StopLoss: "0.2",
TakeProfitTriggerType: "MarkPrice",
StopLossTriggerType: "IndexPrice",
TakeProfitOrStopLossMode: "Partial",
TakeProfitOrderType: "Limit",
StopLossOrderType: "Limit",
TakeProfitSize: 50,
StopLossSize: 50,
TakeProfitLimitPrice: 0.49,
StopLossLimitPrice: 0.21,
PositionIndex: 0,
})
if err != nil {
t.Error(err)
}
}
func TestSetAutoAddMargin(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
err := b.SetAutoAddMargin(context.Background(), &AutoAddMarginParam{
Category: "inverse",
Symbol: inverseTradablePair,
AutoAddmargin: 0,
PositionIndex: 2,
})
if err != nil {
t.Error(err)
}
}
func TestAddOrReduceMargin(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err := b.AddOrReduceMargin(context.Background(), &AddOrReduceMarginParam{
Category: "inverse",
Symbol: inverseTradablePair,
Margin: -10,
PositionIndex: 2,
})
if err != nil {
t.Error(err)
}
}
func TestGetExecution(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
_, err := b.GetExecution(context.Background(), "spot", "", "", "", "", "Trade", "tpslOrder", "", time.Time{}, time.Time{}, 0)
if err != nil {
t.Fatal(err)
}
}
func TestGetClosedPnL(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
_, err := b.GetClosedPnL(context.Background(), "spot", "", "", time.Time{}, time.Time{}, 0)
if !errors.Is(err, errInvalidCategory) {
t.Fatalf("expected %v, got %v", err, errInvalidCategory)
}
_, err = b.GetClosedPnL(context.Background(), "linear", "", "", time.Time{}, time.Time{}, 0)
if err != nil {
t.Fatal(err)
}
}
func TestConfirmNewRiskLimit(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
err := b.ConfirmNewRiskLimit(context.Background(), "linear", "BTCUSDT")
if err != nil {
t.Error(err)
}
}
func TestGetPreUpgradeOrderHistory(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetPreUpgradeOrderHistory(context.Background(), "", "", "", "", "", "", "", "", time.Time{}, time.Time{}, 100)
if !errors.Is(err, errCategoryNotSet) {
t.Fatalf("expected %v, got %v", errCategoryNotSet, err)
}
_, err = b.GetPreUpgradeOrderHistory(context.Background(), "option", "", "", "", "", "", "", "", time.Time{}, time.Time{}, 0)
if !errors.Is(err, errBaseNotSet) {
t.Fatalf("expected %v, got %v", errBaseNotSet, err)
}
_, err = b.GetPreUpgradeOrderHistory(context.Background(), "linear", "", "", "", "", "", "", "", time.Time{}, time.Time{}, 0)
if err != nil {
t.Error(err)
}
}
func TestGetPreUpgradeTradeHistory(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetPreUpgradeTradeHistory(context.Background(), "", "", "", "", "", "", "", time.Time{}, time.Time{}, 0)
if !errors.Is(err, errCategoryNotSet) {
t.Fatalf("found %v, expected %v", err, errCategoryNotSet)
}
_, err = b.GetPreUpgradeTradeHistory(context.Background(), "option", "", "", "", "", "", "", time.Time{}, time.Time{}, 0)
if !errors.Is(err, errInvalidCategory) {
t.Fatalf("found %v, expected %v", err, errInvalidCategory)
}
_, err = b.GetPreUpgradeTradeHistory(context.Background(), "linear", "", "", "", "", "", "", time.Time{}, time.Time{}, 0)
if err != nil {
t.Error(err)
}
}
func TestGetPreUpgradeClosedPnL(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetPreUpgradeClosedPnL(context.Background(), "option", "BTCUSDT", "", time.Time{}, time.Time{}, 0)
if !errors.Is(err, errInvalidCategory) {
t.Fatalf("expected %v, got %v", errInvalidCategory, err)
}
_, err = b.GetPreUpgradeClosedPnL(context.Background(), "linear", "BTCUSDT", "", time.Time{}, time.Time{}, 0)
if err != nil {
t.Error(err)
}
}
func TestGetPreUpgradeTransactionLog(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetPreUpgradeTransactionLog(context.Background(), "option", "", "", "", time.Time{}, time.Time{}, 0)
if !errors.Is(err, errInvalidCategory) {
t.Fatalf("found %v, expected %v", err, errInvalidCategory)
}
_, err = b.GetPreUpgradeTransactionLog(context.Background(), "linear", "", "", "", time.Time{}, time.Time{}, 0)
if err != nil {
t.Error(err)
}
}
func TestGetPreUpgradeOptionDeliveryRecord(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetPreUpgradeOptionDeliveryRecord(context.Background(), "linear", "", "", time.Time{}, 0)
if !errors.Is(err, errInvalidCategory) {
t.Error(err)
}
_, err = b.GetPreUpgradeOptionDeliveryRecord(context.Background(), "option", "", "", time.Time{}, 0)
if err != nil {
t.Error(err)
}
}
func TestGetPreUpgradeUSDCSessionSettlement(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetPreUpgradeUSDCSessionSettlement(context.Background(), "option", "", "", 10)
if !errors.Is(err, errInvalidCategory) {
t.Fatalf("expected %v, got %v", errInvalidCategory, err)
}
_, err = b.GetPreUpgradeUSDCSessionSettlement(context.Background(), "linear", "", "", 10)
if err != nil {
t.Error(err)
}
}
func TestGetWalletBalance(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
r, err := b.GetWalletBalance(context.Background(), "UNIFIED", "")
require.NoError(t, err, "GetWalletBalance should not error")
require.NotNil(t, r, "GetWalletBalance should return a result")
if mockTests {
require.Len(t, r.List, 1, "GetWalletBalance should return a single list result")
assert.Equal(t, types.Number(0.1997), r.List[0].AccountIMRate, "AccountIMRate should match")
assert.Equal(t, types.Number(0.4996), r.List[0].AccountLTV, "AccountLTV should match")
assert.Equal(t, types.Number(0.0399), r.List[0].AccountMMRate, "AccountMMRate should match")
assert.Equal(t, "UNIFIED", r.List[0].AccountType, "AccountType should match")
assert.Equal(t, types.Number(24616.49915805), r.List[0].TotalAvailableBalance, "TotalAvailableBalance should match")
assert.Equal(t, types.Number(41445.9203332), r.List[0].TotalEquity, "TotalEquity should match")
assert.Equal(t, types.Number(6144.46796478), r.List[0].TotalInitialMargin, "TotalInitialMargin should match")
assert.Equal(t, types.Number(1228.89359295), r.List[0].TotalMaintenanceMargin, "TotalMaintenanceMargin should match")
assert.Equal(t, types.Number(30760.96712284), r.List[0].TotalMarginBalance, "TotalMarginBalance should match")
assert.Equal(t, types.Number(0.0), r.List[0].TotalPerpUPL, "TotalPerpUPL should match")
assert.Equal(t, types.Number(30760.96712284), r.List[0].TotalWalletBalance, "TotalWalletBalance should match")
require.Len(t, r.List[0].Coin, 3, "GetWalletBalance should return 3 coins")
for x := range r.List[0].Coin {
switch x {
case 0:
assert.Equal(t, types.Number(0.21976631), r.List[0].Coin[x].AccruedInterest, "AccruedInterest should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].AvailableToBorrow, "AvailableToBorrow should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].AvailableToWithdraw, "AvailableToWithdraw should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].Bonus, "Bonus should match")
assert.Equal(t, types.Number(30723.630216383711792744), r.List[0].Coin[x].BorrowAmount, "BorrowAmount should match")
assert.Equal(t, currency.USDC, r.List[0].Coin[x].Coin, "Coin should match")
assert.True(t, r.List[0].Coin[x].CollateralSwitch, "CollateralSwitch should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].CumulativeRealisedPNL, "CumulativeRealisedPNL should match")
assert.Equal(t, types.Number(-30723.63021638), r.List[0].Coin[x].Equity, "Equity should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].Locked, "Locked should match")
assert.True(t, r.List[0].Coin[x].MarginCollateral, "MarginCollateral should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].SpotHedgingQuantity, "SpotHedgingQuantity should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].TotalOrderIM, "TotalOrderIM should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].TotalPositionIM, "TotalPositionIM should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].TotalPositionMM, "TotalPositionMM should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].UnrealisedPNL, "UnrealisedPNL should match")
assert.Equal(t, types.Number(-30722.33982391), r.List[0].Coin[x].USDValue, "USDValue should match")
assert.Equal(t, types.Number(-30723.63021638), r.List[0].Coin[x].WalletBalance, "WalletBalance should match")
case 1:
assert.Equal(t, types.Number(0), r.List[0].Coin[x].AccruedInterest, "AccruedInterest should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].AvailableToBorrow, "AvailableToBorrow should match")
assert.Equal(t, types.Number(1005.79191187), r.List[0].Coin[x].AvailableToWithdraw, "AvailableToWithdraw should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].Bonus, "Bonus should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].BorrowAmount, "BorrowAmount should match")
assert.Equal(t, currency.AVAX, r.List[0].Coin[x].Coin, "Coin should match")
assert.True(t, r.List[0].Coin[x].CollateralSwitch, "CollateralSwitch should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].CumulativeRealisedPNL, "CumulativeRealisedPNL should match")
assert.Equal(t, types.Number(2473.9), r.List[0].Coin[x].Equity, "Equity should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].Locked, "Locked should match")
assert.True(t, r.List[0].Coin[x].MarginCollateral, "MarginCollateral should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].SpotHedgingQuantity, "SpotHedgingQuantity should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].TotalOrderIM, "TotalOrderIM should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].TotalPositionIM, "TotalPositionIM should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].TotalPositionMM, "TotalPositionMM should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].UnrealisedPNL, "UnrealisedPNL should match")
assert.Equal(t, types.Number(71233.0214024), r.List[0].Coin[x].USDValue, "USDValue should match")
assert.Equal(t, types.Number(2473.9), r.List[0].Coin[x].WalletBalance, "WalletBalance should match")
case 2:
assert.Equal(t, types.Number(0), r.List[0].Coin[x].AccruedInterest, "AccruedInterest should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].AvailableToBorrow, "AvailableToBorrow should match")
assert.Equal(t, types.Number(935.1415), r.List[0].Coin[x].AvailableToWithdraw, "AvailableToWithdraw should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].Bonus, "Bonus should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].BorrowAmount, "BorrowAmount should match")
assert.Equal(t, currency.USDT, r.List[0].Coin[x].Coin, "Coin should match")
assert.True(t, r.List[0].Coin[x].CollateralSwitch, "CollateralSwitch should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].CumulativeRealisedPNL, "CumulativeRealisedPNL should match")
assert.Equal(t, types.Number(935.1415), r.List[0].Coin[x].Equity, "Equity should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].Locked, "Locked should match")
assert.True(t, r.List[0].Coin[x].MarginCollateral, "MarginCollateral should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].SpotHedgingQuantity, "SpotHedgingQuantity should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].TotalOrderIM, "TotalOrderIM should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].TotalPositionIM, "TotalPositionIM should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].TotalPositionMM, "TotalPositionMM should match")
assert.Equal(t, types.Number(0), r.List[0].Coin[x].UnrealisedPNL, "UnrealisedPNL should match")
assert.Equal(t, types.Number(935.23875471), r.List[0].Coin[x].USDValue, "USDValue should match")
assert.Equal(t, types.Number(935.1415), r.List[0].Coin[x].WalletBalance, "WalletBalance should match")
}
}
}
}
func TestUpgradeToUnifiedAccount(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err := b.UpgradeToUnifiedAccount(context.Background())
if err != nil {
t.Error(err)
}
}
func TestGetBorrowHistory(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
_, err := b.GetBorrowHistory(context.Background(), "BTC", "", time.Time{}, time.Time{}, 0)
if err != nil {
t.Error(err)
}
}
func TestSetCollateralCoin(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
err := b.SetCollateralCoin(context.Background(), currency.BTC, false)
if err != nil {
t.Error(err)
}
}
func TestGetCollateralInfo(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
_, err := b.GetCollateralInfo(context.Background(), "BTC")
if err != nil {
t.Error(err)
}
}
func TestGetCoinGreeks(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
_, err := b.GetCoinGreeks(context.Background(), "BTC")
if err != nil {
t.Error(err)
}
}
func TestGetFeeRate(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
_, err := b.GetFeeRate(context.Background(), "something", "", "BTC")
if !errors.Is(err, errInvalidCategory) {
t.Fatalf("expected %v, got %v", errInvalidCategory, err)
}
_, err = b.GetFeeRate(context.Background(), "linear", "", "BTC")
if err != nil {
t.Error(err)
}
}
func TestGetAccountInfo(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
_, err := b.GetAccountInfo(context.Background())
if err != nil {
t.Error(err)
}
}
func TestGetTransactionLog(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
_, err := b.GetTransactionLog(context.Background(), "option", "", "", "", time.Time{}, time.Time{}, 0)
if err != nil {
t.Error(err)
}
_, err = b.GetTransactionLog(context.Background(), "linear", "", "", "", time.Time{}, time.Time{}, 0)
if err != nil {
t.Error(err)
}
}
func TestSetMarginMode(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err := b.SetMarginMode(context.Background(), "PORTFOLIO_MARGIN")
if err != nil {
t.Error(err)
}
}
func TestSetSpotHedging(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
err := b.SetSpotHedging(context.Background(), true)
if err != nil {
t.Error(err)
}
}
func TestGetSubAccountALLAPIKeys(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetSubAccountAllAPIKeys(context.Background(), "", "", 10)
if !errors.Is(err, errMemberIDRequired) {
t.Errorf("expected %v, got %v", errMemberIDRequired, err)
}
_, err = b.GetSubAccountAllAPIKeys(context.Background(), "1234", "", 10)
if err != nil {
t.Error(err)
}
}
func TestSetMMP(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
err := b.SetMMP(context.Background(), nil)
if !errors.Is(err, errNilArgument) {
t.Fatalf("found %v, expected %v", err, errNilArgument)
}
err = b.SetMMP(context.Background(), &MMPRequestParam{
BaseCoin: "ETH",
TimeWindowMS: 5000,
FrozenPeriod: 100000,
TradeQuantityLimit: 50,
DeltaLimit: 20,
})
if err != nil {
t.Error(err)
}
}
func TestResetMMP(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
err := b.ResetMMP(context.Background(), "USDT")
if !errors.Is(err, errNilArgument) {
t.Fatalf("found %v, expected %v", err, errNilArgument)
}
err = b.ResetMMP(context.Background(), "BTC")
if err != nil {
t.Error(err)
}
}
func TestGetMMPState(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
_, err := b.GetMMPState(context.Background(), "BTC")
if err != nil {
t.Error(err)
}
}
func TestGetCoinExchangeRecords(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
_, err := b.GetCoinExchangeRecords(context.Background(), "", "", "", 20)
if err != nil {
t.Fatal(err)
}
}
func TestGetDeliveryRecord(t *testing.T) {
t.Parallel()
expiryTime := time.Now().Add(time.Hour * 40)
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
} else {
expiryTime = time.UnixMilli(1700216290093)
}
_, err := b.GetDeliveryRecord(context.Background(), "spot", "", "", expiryTime, 20)
if !errors.Is(err, errInvalidCategory) {
t.Fatal(err)
}
_, err = b.GetDeliveryRecord(context.Background(), "linear", "", "", expiryTime, 20)
if err != nil {
t.Error(err)
}
}
func TestGetUSDCSessionSettlement(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
_, err := b.GetUSDCSessionSettlement(context.Background(), "option", "", "", 10)
if !errors.Is(err, errInvalidCategory) {
t.Fatalf("expected %v, got %v", errInvalidCategory, err)
}
_, err = b.GetUSDCSessionSettlement(context.Background(), "linear", "", "", 10)
if err != nil {
t.Error(err)
}
}
func TestGetAssetInfo(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
_, err := b.GetAssetInfo(context.Background(), "", "BTC")
if !errors.Is(err, errMissingAccountType) {
t.Fatal(err)
}
_, err = b.GetAssetInfo(context.Background(), "SPOT", "BTC")
if err != nil {
t.Fatal(err)
}
}
func TestGetAllCoinBalance(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
_, err := b.GetAllCoinBalance(context.Background(), "", "", "", 0)
if !errors.Is(err, errMissingAccountType) {
t.Fatalf("expected %v, got %v", errMissingAccountType, err)
}
_, err = b.GetAllCoinBalance(context.Background(), "FUND", "", "", 0)
if err != nil {
t.Fatal(err)
}
}
func TestGetSingleCoinBalance(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
_, err := b.GetSingleCoinBalance(context.Background(), "", "", "", 0, 0)
if !errors.Is(err, errMissingAccountType) {
t.Fatalf("expected %v, got %v", errMissingAccountType, err)
}
_, err = b.GetSingleCoinBalance(context.Background(), "SPOT", currency.BTC.String(), "", 0, 0)
if err != nil {
t.Fatal(err)
}
}
func TestGetTransferableCoin(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
_, err := b.GetTransferableCoin(context.Background(), "SPOT", "OPTION")
if err != nil {
t.Fatal(err)
}
}
func TestCreateInternalTransfer(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err := b.CreateInternalTransfer(context.Background(), nil)
if !errors.Is(err, errNilArgument) {
t.Fatalf("expected %v, got %v", errNilArgument, err)
}
_, err = b.CreateInternalTransfer(context.Background(), &TransferParams{})
if !errors.Is(err, errMissingTransferID) {
t.Fatalf("expected %v, got %v", errMissingTransferID, err)
}
transferID, err := uuid.NewV7()
if err != nil {
t.Fatal(err)
}
_, err = b.CreateInternalTransfer(context.Background(), &TransferParams{TransferID: transferID})
if !errors.Is(err, currency.ErrCurrencyCodeEmpty) {
t.Fatalf("expected %v, got %v", currency.ErrCurrencyCodeEmpty, err)
}
_, err = b.CreateInternalTransfer(context.Background(), &TransferParams{
TransferID: transferID,
Coin: currency.BTC,
})
if !errors.Is(err, order.ErrAmountIsInvalid) {
t.Fatalf("expected %v, got %v", order.ErrAmountIsInvalid, err)
}
_, err = b.CreateInternalTransfer(context.Background(), &TransferParams{
TransferID: transferID,
Coin: currency.BTC,
Amount: 123.456,
})
if !errors.Is(err, errMissingAccountType) {
t.Fatalf("expected %v, got %v", errMissingAccountType, err)
}
_, err = b.CreateInternalTransfer(context.Background(), &TransferParams{
TransferID: transferID,
Coin: currency.BTC, Amount: 123.456,
})
if !errors.Is(err, errMissingAccountType) {
t.Fatalf("expected %v, got %v", errMissingAccountType, err)
}
_, err = b.CreateInternalTransfer(context.Background(), &TransferParams{
TransferID: transferID,
Coin: currency.BTC, Amount: 123.456, FromAccountType: "UNIFIED",
})
if !errors.Is(err, errMissingAccountType) {
t.Fatalf("expected %v, got %v", errMissingAccountType, err)
}
_, err = b.CreateInternalTransfer(context.Background(), &TransferParams{
TransferID: transferID,
Coin: currency.BTC, Amount: 123.456,
ToAccountType: "CONTRACT",
FromAccountType: "UNIFIED",
})
if err != nil {
t.Error(err)
}
}
func TestGetInternalTransferRecords(t *testing.T) {
t.Parallel()
transferID, err := uuid.NewV7()
if err != nil {
t.Fatal(err)
}
transferIDString := transferID.String()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
} else {
transferIDString = "018bd458-dba0-728b-b5b6-ecd5bd296528"
}
_, err = b.GetInternalTransferRecords(context.Background(), transferIDString, currency.BTC.String(), "", "", time.Time{}, time.Time{}, 0)
if err != nil {
t.Error(err)
}
}
func TestGetSubUID(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
_, err := b.GetSubUID(context.Background())
if err != nil {
t.Error(err)
}
}
func TestEnableUniversalTransferForSubUID(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
err := b.EnableUniversalTransferForSubUID(context.Background())
if !errors.Is(err, errMembersIDsNotSet) {
t.Fatalf("expected %v, got %v", errMembersIDsNotSet, err)
}
transferID1, err := uuid.NewV7()
if err != nil {
t.Fatal(err)
}
transferID2, err := uuid.NewV7()
if err != nil {
t.Fatal(err)
}
err = b.EnableUniversalTransferForSubUID(context.Background(), transferID1.String(), transferID2.String())
if err != nil {
t.Error(err)
}
}
func TestCreateUniversalTransfer(t *testing.T) {
t.Parallel()
_, err := b.CreateUniversalTransfer(context.Background(), nil)
if !errors.Is(err, errNilArgument) {
t.Fatalf("expected %v, got %v", errNilArgument, err)
}
_, err = b.CreateUniversalTransfer(context.Background(), &TransferParams{})
if !errors.Is(err, errMissingTransferID) {
t.Fatalf("expected %v, got %v", errMissingTransferID, err)
}
transferID, err := uuid.NewV7()
if err != nil {
t.Fatal(err)
}
_, err = b.CreateUniversalTransfer(context.Background(), &TransferParams{TransferID: transferID})
if !errors.Is(err, currency.ErrCurrencyCodeEmpty) {
t.Fatalf("expected %v, got %v", currency.ErrCurrencyCodeEmpty, err)
}
_, err = b.CreateUniversalTransfer(context.Background(), &TransferParams{
TransferID: transferID,
Coin: currency.BTC,
})
if !errors.Is(err, order.ErrAmountIsInvalid) {
t.Fatalf("expected %v, got %v", order.ErrAmountIsInvalid, err)
}
_, err = b.CreateUniversalTransfer(context.Background(), &TransferParams{
TransferID: transferID,
Coin: currency.BTC,
Amount: 123.456,
})
if !errors.Is(err, errMissingAccountType) {
t.Fatalf("expected %v, got %v", errMissingAccountType, err)
}
_, err = b.CreateUniversalTransfer(context.Background(), &TransferParams{
TransferID: transferID,
Coin: currency.BTC, Amount: 123.456,
})
if !errors.Is(err, errMissingAccountType) {
t.Fatalf("expected %v, got %v", errMissingAccountType, err)
}
_, err = b.CreateUniversalTransfer(context.Background(), &TransferParams{
TransferID: transferID,
Coin: currency.BTC, Amount: 123.456, FromAccountType: "UNIFIED",
})
if !errors.Is(err, errMissingAccountType) {
t.Fatalf("expected %v, got %v", errMissingAccountType, err)
}
_, err = b.CreateUniversalTransfer(context.Background(), &TransferParams{
TransferID: transferID,
Coin: currency.BTC, Amount: 123.456,
ToAccountType: "CONTRACT",
FromAccountType: "UNIFIED",
})
if !errors.Is(err, errMemberIDRequired) {
t.Fatalf("expected %v, got %v", errMemberIDRequired, err)
}
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err = b.CreateUniversalTransfer(context.Background(), &TransferParams{
TransferID: transferID,
Coin: currency.BTC, Amount: 123.456,
ToAccountType: "CONTRACT",
FromAccountType: "UNIFIED",
FromMemberID: 123,
ToMemberID: 456,
})
if err != nil {
t.Error(err)
}
}
func TestGetUniversalTransferRecords(t *testing.T) {
t.Parallel()
var transferIDString string
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
transferID, err := uuid.NewV7()
if err != nil {
t.Fatal(err)
}
transferIDString = transferID.String()
} else {
transferIDString = "018bd461-cb9c-75ce-94d4-0d3f4d84c339"
}
_, err := b.GetUniversalTransferRecords(context.Background(), transferIDString, currency.BTC.String(), "", "", time.Time{}, time.Time{}, 0)
if err != nil {
t.Error(err)
}
}
func TestGetAllowedDepositCoinInfo(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
_, err := b.GetAllowedDepositCoinInfo(context.Background(), "BTC", "", "", 0)
if err != nil {
t.Error(err)
}
}
func TestSetDepositAccount(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err := b.SetDepositAccount(context.Background(), "FUND")
if err != nil {
t.Error(err)
}
}
func TestGetDepositRecords(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
_, err := b.GetDepositRecords(context.Background(), "", "", time.Time{}, time.Time{}, 0)
if err != nil {
t.Error(err)
}
}
func TestGetSubDepositRecords(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetSubDepositRecords(context.Background(), "12345", "", "", time.Time{}, time.Time{}, 0)
if err != nil {
t.Error(err)
}
}
func TestInternalDepositRecords(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
_, err := b.GetInternalDepositRecordsOffChain(context.Background(), currency.ETH.String(), "", time.Time{}, time.Time{}, 8)
if err != nil {
t.Error(err)
}
}
func TestGetMasterDepositAddress(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
_, err := b.GetMasterDepositAddress(context.Background(), currency.LTC, "")
if err != nil {
t.Error(err)
}
}
func TestGetSubDepositAddress(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetSubDepositAddress(context.Background(), currency.LTC, "LTC", "12345")
if err != nil {
t.Error(err)
}
}
func TestGetCoinInfo(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
_, err := b.GetCoinInfo(context.Background(), currency.BTC)
if err != nil {
t.Error(err)
}
}
func TestGetWithdrawalRecords(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
_, err := b.GetWithdrawalRecords(context.Background(), currency.LTC, "", "", "", time.Time{}, time.Time{}, 10)
if err != nil {
t.Error(err)
}
}
func TestGetWithdrawableAmount(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
_, err := b.GetWithdrawableAmount(context.Background(), currency.LTC)
if err != nil {
t.Error(err)
}
}
func TestWithdrawCurrency(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err := b.WithdrawCurrency(context.Background(), nil)
if !errors.Is(err, errNilArgument) {
t.Fatalf("expected %v, got %v", errNilArgument, err)
}
_, err = b.WithdrawCurrency(context.Background(), &WithdrawalParam{})
if !errors.Is(err, currency.ErrCurrencyCodeEmpty) {
t.Fatalf("expected %v, got %v", currency.ErrCurrencyCodeEmpty, err)
}
_, err = b.WithdrawCurrency(context.Background(), &WithdrawalParam{Coin: currency.BTC})
if !errors.Is(err, errMissingChainInformation) {
t.Fatalf("expected %v, got %v", errMissingChainInformation, err)
}
_, err = b.WithdrawCurrency(context.Background(), &WithdrawalParam{Coin: currency.LTC, Chain: "LTC"})
if !errors.Is(err, errMissingAddressInfo) {
t.Fatalf("expected %v, got %v", errMissingAddressInfo, err)
}
_, err = b.WithdrawCurrency(context.Background(), &WithdrawalParam{Coin: currency.LTC, Chain: "LTC", Address: "234234234"})
if !errors.Is(err, order.ErrAmountBelowMin) {
t.Fatalf("expected %v, got %v", order.ErrAmountBelowMin, err)
}
_, err = b.WithdrawCurrency(context.Background(), &WithdrawalParam{Coin: currency.LTC, Chain: "LTC", Address: "234234234", Amount: 123})
if err != nil {
t.Fatal(err)
}
}
func TestCancelWithdrawal(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err := b.CancelWithdrawal(context.Background(), "")
if !errors.Is(err, errMissingWithdrawalID) {
t.Fatalf("expected %v, got %v", errMissingWithdrawalID, err)
}
_, err = b.CancelWithdrawal(context.Background(), "12314")
if err != nil {
t.Error(err)
}
}
func TestCreateNewSubUserID(t *testing.T) {
t.Parallel()
_, err := b.CreateNewSubUserID(context.Background(), nil)
if !errors.Is(err, errNilArgument) {
t.Fatalf("expected %v, got %v", errNilArgument, err)
}
_, err = b.CreateNewSubUserID(context.Background(), &CreateSubUserParams{MemberType: 1, Switch: 1, Note: "test"})
if !errors.Is(err, errMissingUsername) {
t.Fatalf("expected %v, got %v", errMissingUsername, err)
}
_, err = b.CreateNewSubUserID(context.Background(), &CreateSubUserParams{Username: "Sami", Switch: 1, Note: "test"})
if !errors.Is(err, errInvalidMemberType) {
t.Fatalf("expected %v, got %v", errInvalidMemberType, err)
}
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err = b.CreateNewSubUserID(context.Background(), &CreateSubUserParams{Username: "sami", MemberType: 1, Switch: 1, Note: "test"})
if err != nil {
t.Error(err)
}
}
func TestCreateSubUIDAPIKey(t *testing.T) {
t.Parallel()
_, err := b.CreateSubUIDAPIKey(context.Background(), nil)
if !errors.Is(err, errNilArgument) {
t.Fatalf("expected %v, got %v", errNilArgument, err)
}
_, err = b.CreateSubUIDAPIKey(context.Background(), &SubUIDAPIKeyParam{})
if !errors.Is(err, errMissingUserID) {
t.Fatalf("expected %v, got %v", errMissingUserID, err)
}
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err = b.CreateSubUIDAPIKey(context.Background(), &SubUIDAPIKeyParam{
Subuid: 53888000,
Note: "testxxx",
ReadOnly: 0,
Permissions: map[string][]string{"Wallet": {"AccountTransfer"}},
})
if err != nil {
t.Error(err)
}
}
func TestGetSubUIDList(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetSubUIDList(context.Background())
if err != nil {
t.Error(err)
}
}
func TestFreezeSubUID(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
err := b.FreezeSubUID(context.Background(), "1234", true)
if err != nil {
t.Error(err)
}
}
func TestGetAPIKeyInformation(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetAPIKeyInformation(context.Background())
if err != nil {
t.Error(err)
}
}
func TestGetUIDWalletType(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetUIDWalletType(context.Background(), "234234")
if err != nil {
t.Error(err)
}
}
func TestModifyMasterAPIKey(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err := b.ModifyMasterAPIKey(context.Background(), &SubUIDAPIKeyUpdateParam{})
if !errors.Is(err, errNilArgument) {
t.Fatalf("expected %v, got %v", errNilArgument, err)
}
_, err = b.ModifyMasterAPIKey(context.Background(), &SubUIDAPIKeyUpdateParam{
ReadOnly: 0,
IPs: "*",
Permissions: PermissionsList{
ContractTrade: []string{"Order", "Position"},
Spot: []string{"SpotTrade"},
Wallet: []string{"AccountTransfer", "SubMemberTransfer"},
Options: []string{"OptionsTrade"},
CopyTrading: []string{"CopyTrading"},
Exchange: []string{"ExchangeHistory"},
},
})
if err != nil {
t.Error(err)
}
}
func TestModifySubAPIKey(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err := b.ModifySubAPIKey(context.Background(), &SubUIDAPIKeyUpdateParam{})
if !errors.Is(err, errNilArgument) {
t.Fatalf("expected %v, got %v", errNilArgument, err)
}
_, err = b.ModifySubAPIKey(context.Background(), &SubUIDAPIKeyUpdateParam{
APIKey: "lnqQ8ACaoMLi4168He",
ReadOnly: 0,
IPs: "*",
Permissions: PermissionsList{
ContractTrade: []string{"Order", "Position"},
Spot: []string{"SpotTrade"},
Wallet: []string{"AccountTransfer", "SubMemberTransfer"},
Options: []string{"OptionsTrade"},
CopyTrading: []string{"CopyTrading"},
Exchange: []string{"ExchangeHistory"},
},
})
if err != nil {
t.Error(err)
}
}
func TestDeleteSubUID(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
err := b.DeleteSubUID(context.Background(), "")
if !errors.Is(err, errMemberIDRequired) {
t.Errorf("expected %v, got %v", errMemberIDRequired, err)
}
err = b.DeleteSubUID(context.Background(), "1234")
if err != nil {
t.Error(err)
}
}
func TestDeleteMasterAPIKey(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
err := b.DeleteMasterAPIKey(context.Background())
if err != nil {
t.Error(err)
}
}
func TestDeleteSubAPIKey(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
err := b.DeleteSubAccountAPIKey(context.Background(), "12434")
if err != nil {
t.Error(err)
}
}
func TestGetAffiliateUserInfo(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetAffiliateUserInfo(context.Background(), "1234")
if err != nil {
t.Error(err)
}
}
func TestGetLeverageTokenInfo(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetLeverageTokenInfo(context.Background(), currency.NewCode("BTC3L"))
if err != nil {
t.Error(err)
}
}
func TestGetLeveragedTokenMarket(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetLeveragedTokenMarket(context.Background(), currency.EMPTYCODE)
if !errors.Is(err, currency.ErrCurrencyCodeEmpty) {
t.Fatalf("expected %v, got %v", currency.ErrCurrencyCodeEmpty, err)
}
_, err = b.GetLeveragedTokenMarket(context.Background(), currency.NewCode("BTC3L"))
if err != nil {
t.Error(err)
}
}
func TestPurchaseLeverageToken(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err := b.PurchaseLeverageToken(context.Background(), currency.BTC3L, 100, "")
if err != nil {
t.Error(err)
}
}
func TestRedeemLeverageToken(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err := b.RedeemLeverageToken(context.Background(), currency.BTC3L, 100, "")
if err != nil {
t.Error(err)
}
}
func TestGetPurchaseAndRedemptionRecords(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetPurchaseAndRedemptionRecords(context.Background(), currency.EMPTYCODE, "", "", time.Time{}, time.Time{}, 0, 0)
if err != nil {
t.Error(err)
}
}
func TestToggleMarginTrade(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err := b.ToggleMarginTrade(context.Background(), true)
if err != nil {
t.Error(err)
}
}
func TestSetSpotMarginTradeLeverage(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
err := b.SetSpotMarginTradeLeverage(context.Background(), 3)
if err != nil {
t.Error(err)
}
}
func TestGetMarginCoinInfo(t *testing.T) {
t.Parallel()
_, err := b.GetMarginCoinInfo(context.Background(), currency.BTC)
if err != nil {
t.Error(err)
}
}
func TestGetVIPMarginData(t *testing.T) {
t.Parallel()
_, err := b.GetVIPMarginData(context.Background(), "", "")
if err != nil {
t.Error(err)
}
}
func TestGetBorrowableCoinInfo(t *testing.T) {
t.Parallel()
_, err := b.GetBorrowableCoinInfo(context.Background(), currency.EMPTYCODE)
if err != nil {
t.Error(err)
}
}
func TestGetInterestAndQuota(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetInterestAndQuota(context.Background(), currency.EMPTYCODE)
if !errors.Is(err, currency.ErrCurrencyCodeEmpty) {
t.Errorf("expected %v, got %v", currency.ErrCurrencyCodeEmpty, err)
}
_, err = b.GetInterestAndQuota(context.Background(), currency.BTC)
if err != nil && !errors.Is(err, errEndpointAvailableForNormalAPIKeyHolders) {
t.Error(err)
}
}
func TestGetLoanAccountInfo(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetLoanAccountInfo(context.Background())
if err != nil && !errors.Is(err, errEndpointAvailableForNormalAPIKeyHolders) {
t.Error(err)
}
}
func TestBorrow(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err := b.Borrow(context.Background(), nil)
if !errors.Is(err, errNilArgument) {
t.Errorf("expected %v, got %v", errNilArgument, err)
}
_, err = b.Borrow(context.Background(), &LendArgument{})
if !errors.Is(err, currency.ErrCurrencyCodeEmpty) {
t.Errorf("expected %v, got %v", currency.ErrCurrencyCodeEmpty, err)
}
_, err = b.Borrow(context.Background(), &LendArgument{Coin: currency.BTC})
if !errors.Is(err, order.ErrAmountBelowMin) {
t.Errorf("expected %v, got %v", order.ErrAmountBelowMin, err)
}
_, err = b.Borrow(context.Background(), &LendArgument{Coin: currency.BTC, AmountToBorrow: 0.1})
if err != nil {
t.Error(err)
}
}
func TestRepay(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err := b.Repay(context.Background(), nil)
if !errors.Is(err, errNilArgument) {
t.Errorf("expected %v, got %v", errNilArgument, err)
}
_, err = b.Repay(context.Background(), &LendArgument{})
if !errors.Is(err, currency.ErrCurrencyCodeEmpty) {
t.Errorf("expected %v, got %v", currency.ErrCurrencyCodeEmpty, err)
}
_, err = b.Repay(context.Background(), &LendArgument{Coin: currency.BTC})
if !errors.Is(err, order.ErrAmountBelowMin) {
t.Errorf("expected %v, got %v", order.ErrAmountBelowMin, err)
}
_, err = b.Repay(context.Background(), &LendArgument{Coin: currency.BTC, AmountToBorrow: 0.1})
if err != nil {
t.Error(err)
}
}
func TestGetBorrowOrderDetail(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetBorrowOrderDetail(context.Background(), time.Time{}, time.Time{}, currency.BTC, 0, 0)
if err != nil && !errors.Is(err, errEndpointAvailableForNormalAPIKeyHolders) {
t.Error(err)
}
}
func TestGetRepaymentOrderDetail(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetRepaymentOrderDetail(context.Background(), time.Time{}, time.Time{}, currency.BTC, 0)
if err != nil && !errors.Is(err, errEndpointAvailableForNormalAPIKeyHolders) {
t.Error(err)
}
}
func TestToggleMarginTradeNormal(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.ToggleMarginTradeNormal(context.Background(), true)
if err != nil && !errors.Is(err, errEndpointAvailableForNormalAPIKeyHolders) {
t.Error(err)
}
}
func TestGetProductInfo(t *testing.T) {
t.Parallel()
_, err := b.GetProductInfo(context.Background(), "")
if err != nil {
t.Error(err)
}
}
func TestGetInstitutionalLengingMarginCoinInfo(t *testing.T) {
t.Parallel()
_, err := b.GetInstitutionalLengingMarginCoinInfo(context.Background(), "")
if err != nil {
t.Error(err)
}
}
func TestGetInstitutionalLoanOrders(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetInstitutionalLoanOrders(context.Background(), "", time.Time{}, time.Time{}, 0)
if err != nil && !errors.Is(err, errEndpointAvailableForNormalAPIKeyHolders) {
t.Error(err)
}
}
func TestGetInstitutionalRepayOrders(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetInstitutionalRepayOrders(context.Background(), time.Time{}, time.Time{}, 0)
if err != nil && !errors.Is(err, errEndpointAvailableForNormalAPIKeyHolders) {
t.Error(err)
}
}
func TestGetLTV(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetLTV(context.Background())
if err != nil && !errors.Is(err, errEndpointAvailableForNormalAPIKeyHolders) {
t.Error(err)
}
}
func TestBindOrUnbindUID(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err := b.BindOrUnbindUID(context.Background(), "12234", "0")
if err != nil {
t.Error(err)
}
}
func TestGetC2CLendingCoinInfo(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetC2CLendingCoinInfo(context.Background(), currency.BTC)
if err != nil {
t.Error(err)
}
}
func TestC2CDepositFunds(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err := b.C2CDepositFunds(context.Background(), nil)
if !errors.Is(err, errNilArgument) {
t.Error(err)
}
_, err = b.C2CDepositFunds(context.Background(), &C2CLendingFundsParams{})
if !errors.Is(err, currency.ErrCurrencyCodeEmpty) {
t.Errorf("expected %v, got %v", currency.ErrCurrencyCodeEmpty, err)
}
_, err = b.C2CDepositFunds(context.Background(), &C2CLendingFundsParams{Coin: currency.BTC})
if !errors.Is(err, order.ErrAmountBelowMin) {
t.Errorf("expected %v, got %v", order.ErrAmountBelowMin, err)
}
_, err = b.C2CDepositFunds(context.Background(), &C2CLendingFundsParams{Coin: currency.BTC, Quantity: 1232})
if err != nil {
t.Error(err)
}
}
func TestC2CRedeemFunds(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
_, err := b.C2CRedeemFunds(context.Background(), nil)
if !errors.Is(err, errNilArgument) {
t.Error(err)
}
_, err = b.C2CRedeemFunds(context.Background(), &C2CLendingFundsParams{})
if !errors.Is(err, currency.ErrCurrencyCodeEmpty) {
t.Errorf("expected %v, got %v", currency.ErrCurrencyCodeEmpty, err)
}
_, err = b.C2CRedeemFunds(context.Background(), &C2CLendingFundsParams{Coin: currency.BTC})
if !errors.Is(err, order.ErrAmountBelowMin) {
t.Errorf("expected %v, got %v", order.ErrAmountBelowMin, err)
}
_, err = b.C2CRedeemFunds(context.Background(), &C2CLendingFundsParams{Coin: currency.BTC, Quantity: 1232})
if err != nil {
t.Error(err)
}
}
func TestGetC2CLendingOrderRecords(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetC2CLendingOrderRecords(context.Background(), currency.EMPTYCODE, "", "", time.Time{}, time.Time{}, 0)
if err != nil {
t.Error(err)
}
}
func TestGetC2CLendingAccountInfo(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetC2CLendingAccountInfo(context.Background(), currency.LTC)
if err != nil {
t.Error(err)
}
}
func TestGetBrokerEarning(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetBrokerEarning(context.Background(), "DERIVATIVES", "", time.Time{}, time.Time{}, 0)
if err != nil {
t.Error(err)
}
}
func TestUpdateAccountInfo(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
r, err := b.UpdateAccountInfo(context.Background(), asset.Spot)
require.NoError(t, err, "UpdateAccountInfo should not error")
require.NotEmpty(t, r, "UpdateAccountInfo should return account info")
if mockTests {
require.Len(t, r.Accounts, 1, "Accounts should have 1 item")
require.Len(t, r.Accounts[0].Currencies, 3, "Accounts currencies should have 3 currency items")
for x := range r.Accounts[0].Currencies {
switch x {
case 0:
assert.Equal(t, currency.USDC, r.Accounts[0].Currencies[x].Currency, "Currency should be USDC")
assert.Equal(t, -30723.63021638, r.Accounts[0].Currencies[x].Total, "Total amount should match")
assert.Equal(t, -30723.63021638, r.Accounts[0].Currencies[x].Hold, "Hold amount should match")
assert.Equal(t, 30723.630216383714, r.Accounts[0].Currencies[x].Borrowed, "Borrowed amount should match")
assert.Equal(t, 0.0, r.Accounts[0].Currencies[x].Free, "Free amount should match")
case 1:
assert.Equal(t, currency.AVAX, r.Accounts[0].Currencies[x].Currency, "Currency should be AVAX")
assert.Equal(t, 2473.9, r.Accounts[0].Currencies[x].Total, "Total amount should match")
assert.Equal(t, 1468.10808813, r.Accounts[0].Currencies[x].Hold, "Hold amount should match")
assert.Equal(t, 0.0, r.Accounts[0].Currencies[x].Borrowed, "Borrowed amount should match")
assert.Equal(t, 1005.79191187, r.Accounts[0].Currencies[x].Free, "Free amount should match")
case 2:
assert.Equal(t, currency.USDT, r.Accounts[0].Currencies[x].Currency, "Currency should be USDT")
assert.Equal(t, 935.1415, r.Accounts[0].Currencies[x].Total, "Total amount should match")
assert.Equal(t, 0.0, r.Accounts[0].Currencies[x].Borrowed, "Borrowed amount should match")
assert.Equal(t, 0.0, r.Accounts[0].Currencies[x].Hold, "Hold amount should match")
assert.Equal(t, 935.1415, r.Accounts[0].Currencies[x].Free, "Free amount should match")
}
}
}
}
func TestGetWithdrawalsHistory(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
_, err := b.GetWithdrawalsHistory(context.Background(), currency.BTC, asset.Futures)
if !errors.Is(err, asset.ErrNotSupported) {
t.Errorf("expected %v, got %v", asset.ErrNotSupported, err)
}
_, err = b.GetWithdrawalsHistory(context.Background(), currency.BTC, asset.Spot)
if err != nil {
t.Error("GetWithdrawalsHistory()", err)
}
}
func TestGetRecentTrades(t *testing.T) {
t.Parallel()
for _, tt := range []struct {
a asset.Item
p currency.Pair
}{
{asset.Spot, spotTradablePair},
{asset.Options, optionsTradablePair},
{asset.CoinMarginedFutures, inverseTradablePair},
{asset.USDTMarginedFutures, usdtMarginedTradablePair},
{asset.USDCMarginedFutures, usdcMarginedTradablePair},
} {
_, err := b.GetRecentTrades(context.Background(), tt.p, tt.a)
assert.NoErrorf(t, err, "GetRecentTrades should not error for %s asset", tt.a)
}
_, err := b.GetRecentTrades(context.Background(), spotTradablePair, asset.Futures)
assert.ErrorIs(t, err, asset.ErrNotSupported)
}
func TestGetBybitServerTime(t *testing.T) {
t.Parallel()
_, err := b.GetBybitServerTime(context.Background())
if err != nil {
t.Error(err)
}
}
func TestGetServerTime(t *testing.T) {
t.Parallel()
_, err := b.GetServerTime(context.Background(), asset.Empty)
if err != nil {
t.Error(err)
}
}
func TestGetHistoricTrades(t *testing.T) {
t.Parallel()
_, err := b.GetHistoricTrades(context.Background(), spotTradablePair, asset.Spot, time.Time{}, time.Time{})
if err != nil {
t.Error(err)
}
_, err = b.GetHistoricTrades(context.Background(), usdtMarginedTradablePair, asset.USDTMarginedFutures, time.Time{}, time.Time{})
if err != nil {
t.Error(err)
}
_, err = b.GetHistoricTrades(context.Background(), usdcMarginedTradablePair, asset.USDCMarginedFutures, time.Time{}, time.Time{})
if err != nil {
t.Error(err)
}
_, err = b.GetHistoricTrades(context.Background(), inverseTradablePair, asset.CoinMarginedFutures, time.Time{}, time.Time{})
if err != nil {
t.Error(err)
}
_, err = b.GetHistoricTrades(context.Background(), optionsTradablePair, asset.Options, time.Time{}, time.Time{})
if err != nil {
t.Error(err)
}
}
func TestCancelBatchOrders(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skipAuthenticatedFunctionsForMockTesting)
}
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
orderCancellationParams := []order.Cancel{{
OrderID: "1",
Pair: spotTradablePair,
AssetType: asset.Spot,
}, {
OrderID: "1",
Pair: usdtMarginedTradablePair,
AssetType: asset.USDTMarginedFutures,
}}
_, err := b.CancelBatchOrders(context.Background(), orderCancellationParams)
if !errors.Is(err, asset.ErrNotSupported) {
t.Errorf("expected %v, got %v", asset.ErrNotSupported, err)
}
orderCancellationParams = []order.Cancel{{
OrderID: "1",
AccountID: "1",
Pair: optionsTradablePair,
AssetType: asset.Options,
}, {
OrderID: "2",
Pair: optionsTradablePair,
AssetType: asset.Options,
}}
_, err = b.CancelBatchOrders(context.Background(), orderCancellationParams)
if err != nil {
t.Error(err)
}
}
func TestWsConnect(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skippingWebsocketFunctionsForMockTesting)
}
err := b.WsConnect()
if err != nil {
t.Error(err)
}
}
func TestWsLinearConnect(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skippingWebsocketFunctionsForMockTesting)
}
err := b.WsLinearConnect()
if err != nil && !errors.Is(err, websocket.ErrWebsocketNotEnabled) {
t.Error(err)
}
}
func TestWsInverseConnect(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skippingWebsocketFunctionsForMockTesting)
}
err := b.WsInverseConnect()
if err != nil && !errors.Is(err, websocket.ErrWebsocketNotEnabled) {
t.Error(err)
}
}
func TestWsOptionsConnect(t *testing.T) {
t.Parallel()
if mockTests {
t.Skip(skippingWebsocketFunctionsForMockTesting)
}
err := b.WsOptionsConnect()
if err != nil && !errors.Is(err, websocket.ErrWebsocketNotEnabled) {
t.Error(err)
}
}
var pushDataMap = map[string]string{
"Orderbook Snapshot": `{"topic":"orderbook.50.BTCUSDT","ts":1731035685326,"type":"snapshot","data":{"s":"BTCUSDT","b":[["75848.74","0.067669"],["75848.63","0.004772"],["75848.61","0.00659"],["75848.05","0.000329"],["75847.68","0.00159"],["75846.88","0.00159"],["75845.97","0.026366"],["75845.87","0.013185"],["75845.41","0.077259"],["75845.4","0.132228"],["75844.61","0.00159"],["75844.44","0.026367"],["75844.2","0.013185"],["75844","0.00039"],["75843.13","0.00159"],["75843.07","0.013185"],["75842.33","0.00159"],["75841.99","0.006"],["75841.75","0.019538"],["75841.74","0.04"],["75841.71","0.031817"],["75841.36","0.017336"],["75841.33","0.000072"],["75841.16","0.001872"],["75841.11","0.172641"],["75841.04","0.029772"],["75841","0.000065"],["75840.93","0.015244"],["75840.86","0.00159"],["75840.79","0.000072"],["75840.38","0.043333"],["75840.32","0.092539"],["75840.3","0.132228"],["75840.2","0.054966"],["75840.06","0.00159"],["75840","0.20726"],["75839.64","0.003744"],["75839.29","0.006592"],["75838.58","0.00159"],["75838.52","0.049778"],["75838.14","0.003955"],["75838","0.000065"],["75837.78","0.00159"],["75837.75","0.000587"],["75837.53","0.322245"],["75837.52","0.593323"],["75837.37","0.00384"],["75837.29","0.044335"],["75837.24","0.119228"],["75837.13","0.152844"]],"a":[["75848.75","0.747137"],["75848.89","0.060306"],["75848.9","0.1"],["75851.43","0.00159"],["75851.44","0.080754"],["75852.23","0.00159"],["75852.54","0.131067"],["75852.65","0.003955"],["75853.71","0.00159"],["75853.86","0.003955"],["75854.43","0.015684"],["75854.5","0.130389"],["75854.51","0.00159"],["75855.21","0.031168"],["75855.23","0.271494"],["75855.73","0.042698"],["75855.98","0.00159"],["75856.04","0.01346"],["75856.33","0.001872"],["75856.78","0.00159"],["75857.15","0.000072"],["75857.17","0.015127"],["75857.8","0.043322"],["75857.81","0.045305"],["75857.85","0.003792"],["75858.09","0.026344"],["75858.26","0.00159"],["75859.06","0.031618"],["75859.07","0.025"],["75859.1","0.006592"],["75859.98","0.013183"],["75860.12","0.00384"],["75860.54","0.00159"],["75860.74","0.051204"],["75860.75","0.065861"],["75861.18","0.031222"],["75861.33","0.00159"],["75861.64","0.003888"],["75861.96","0.042213"],["75862.28","0.000777"],["75862.79","0.013184"],["75862.81","0.00159"],["75862.84","0.027959"],["75863.16","0.003888"],["75863.51","0.043628"],["75863.52","0.002525"],["75863.61","0.00159"],["75864.2","0.003955"],["75864.76","0.000072"],["75864.81","0.002018"]],"u":2876700,"seq":47474967795},"cts":1731035685323}`,
"Orderbook Update": `{"topic":"orderbook.50.BTCUSDT","ts":1731035685345,"type":"delta","data":{"s":"BTCUSDT","b":[["75848.62","0.014895"],["75837.13","0"]],"a":[["75848.89","0.088149"],["75851.44","0.078379"],["75852.65","0"],["75855.23","0.260219"],["75857.74","0.049778"]],"u":2876701,"seq":47474967823},"cts":1731035685342}`,
"Public Trade": `{"topic":"publicTrade.BTCUSDT","ts":1690720953113,"type":"snapshot","data":[{"i":"2200000000067341890","T":1690720953111,"p":"3.6279","v":"1.3637","S":"Sell","s":"BTCUSDT","BT":false}]}`,
"Public Kline": `{ "topic": "kline.5.BTCUSDT", "data": [ { "start": 1672324800000, "end": 1672325099999, "interval": "5", "open": "16649.5", "close": "16677", "high": "16677", "low": "16608", "volume": "2.081", "turnover": "34666.4005", "confirm": false, "timestamp": 1672324988882} ], "ts": 1672324988882,"type": "snapshot"}`,
"Public Liquidiation": `{ "data": { "price": "0.03803", "side": "Buy", "size": "1637", "symbol": "GALAUSDT", "updatedTime": 1673251091822}, "topic": "liquidation.GALAUSDT", "ts": 1673251091822, "type": "snapshot" }`,
"Public LT Kline": `{ "type": "snapshot", "topic": "kline_lt.5.BTCUSDT", "data": [ { "start": 1672325100000, "end": 1672325399999, "interval": "5", "open": "0.416039541212402799", "close": "0.41477848043290448", "high": "0.416039541212402799", "low": "0.409734237314911206", "confirm": false, "timestamp": 1672325322393} ], "ts": 1672325322393}`,
"Public LT Ticker": `{ "topic": "tickers_lt.BTCUSDT", "ts": 1672325446847, "type": "snapshot", "data": { "symbol": "BTCUSDT", "lastPrice": "0.41477848043290448", "highPrice24h": "0.435285472510871305", "lowPrice24h": "0.394601507960931382", "prevPrice24h": "0.431502290172376349", "price24hPcnt": "-0.0388" } }`,
"Public LT Navigation": `{ "topic": "lt.EOS3LUSDT", "ts": 1672325564669, "type": "snapshot", "data": { "symbol": "BTCUSDT", "time": 1672325564554, "nav": "0.413517419653406162", "basketPosition": "1.261060779498318641", "leverage": "2.656197506416192150", "basketLoan": "-0.684866519289629374", "circulation": "72767.309468460367138199", "basket": "91764.000000292013277472" } }`,
"Private Position": `{"id": "59232430b58efe-5fc5-4470-9337-4ce293b68edd", "topic": "position", "creationTime": 1672364174455, "data": [ { "positionIdx": 0, "tradeMode": 0, "riskId": 41, "riskLimitValue": "200000", "symbol": "XRPUSDT", "side": "Buy", "size": "75", "entryPrice": "0.3615", "leverage": "10", "positionValue": "27.1125", "positionBalance": "0", "markPrice": "0.3374", "positionIM": "2.72589075", "positionMM": "0.28576575", "takeProfit": "0", "stopLoss": "0", "trailingStop": "0", "unrealisedPnl": "-1.8075", "cumRealisedPnl": "0.64782276", "createdTime": "1672121182216", "updatedTime": "1672364174449", "tpslMode": "Full", "liqPrice": "", "bustPrice": "", "category": "linear","positionStatus":"Normal","adlRankIndicator":2}]}`,
"Private Order": `{ "id": "5923240c6880ab-c59f-420b-9adb-3639adc9dd90", "topic": "order", "creationTime": 1672364262474, "data": [ { "symbol": "BTCUSDT", "orderId": "5cf98598-39a7-459e-97bf-76ca765ee020", "side": "Sell", "orderType": "Market", "cancelType": "UNKNOWN", "price": "72.5", "qty": "1", "orderIv": "", "timeInForce": "IOC", "orderStatus": "Filled", "orderLinkId": "", "lastPriceOnCreated": "", "reduceOnly": false, "leavesQty": "", "leavesValue": "", "cumExecQty": "1", "cumExecValue": "75", "avgPrice": "75", "blockTradeId": "", "positionIdx": 0, "cumExecFee": "0.358635", "createdTime": "1672364262444", "updatedTime": "1672364262457", "rejectReason": "EC_NoError", "stopOrderType": "", "tpslMode": "", "triggerPrice": "", "takeProfit": "", "stopLoss": "", "tpTriggerBy": "", "slTriggerBy": "", "tpLimitPrice": "", "slLimitPrice": "", "triggerDirection": 0, "triggerBy": "", "closeOnTrigger": false, "category": "option", "placeType": "price", "smpType": "None", "smpGroup": 0, "smpOrderId": "" } ] }`,
"Private Wallet": `{ "id": "5923242c464be9-25ca-483d-a743-c60101fc656f", "topic": "wallet", "creationTime": 1672364262482, "data": [ { "accountIMRate": "0.016", "accountMMRate": "0.003", "totalEquity": "12837.78330098", "totalWalletBalance": "12840.4045924", "totalMarginBalance": "12837.78330188", "totalAvailableBalance": "12632.05767702", "totalPerpUPL": "-2.62129051", "totalInitialMargin": "205.72562486", "totalMaintenanceMargin": "39.42876721", "coin": [ { "coin": "USDC", "equity": "200.62572554", "usdValue": "200.62572554", "walletBalance": "201.34882644", "availableToWithdraw": "0", "availableToBorrow": "1500000", "borrowAmount": "0", "accruedInterest": "0", "totalOrderIM": "0", "totalPositionIM": "202.99874213", "totalPositionMM": "39.14289747", "unrealisedPnl": "74.2768991", "cumRealisedPnl": "-209.1544627", "bonus": "0" }, { "coin": "BTC", "equity": "0.06488393", "usdValue": "1023.08402268", "walletBalance": "0.06488393", "availableToWithdraw": "0.06488393", "availableToBorrow": "2.5", "borrowAmount": "0", "accruedInterest": "0", "totalOrderIM": "0", "totalPositionIM": "0", "totalPositionMM": "0", "unrealisedPnl": "0", "cumRealisedPnl": "0", "bonus": "0" }, { "coin": "ETH", "equity": "0", "usdValue": "0", "walletBalance": "0", "availableToWithdraw": "0", "availableToBorrow": "26", "borrowAmount": "0", "accruedInterest": "0", "totalOrderIM": "0", "totalPositionIM": "0", "totalPositionMM": "0", "unrealisedPnl": "0", "cumRealisedPnl": "0", "bonus": "0" }, { "coin": "USDT", "equity": "11726.64664904", "usdValue": "11613.58597018", "walletBalance": "11728.54414904", "availableToWithdraw": "11723.92075829", "availableToBorrow": "2500000", "borrowAmount": "0", "accruedInterest": "0", "totalOrderIM": "0", "totalPositionIM": "2.72589075", "totalPositionMM": "0.28576575", "unrealisedPnl": "-1.8975", "cumRealisedPnl": "0.64782276", "bonus": "0" }, { "coin": "EOS3L", "equity": "215.0570412", "usdValue": "0", "walletBalance": "215.0570412", "availableToWithdraw": "215.0570412", "availableToBorrow": "0", "borrowAmount": "0", "accruedInterest": "", "totalOrderIM": "0", "totalPositionIM": "0", "totalPositionMM": "0", "unrealisedPnl": "0", "cumRealisedPnl": "0", "bonus": "0" }, { "coin": "BIT", "equity": "1.82", "usdValue": "0.48758257", "walletBalance": "1.82", "availableToWithdraw": "1.82", "availableToBorrow": "0", "borrowAmount": "0", "accruedInterest": "", "totalOrderIM": "0", "totalPositionIM": "0", "totalPositionMM": "0", "unrealisedPnl": "0", "cumRealisedPnl": "0", "bonus": "0" } ], "accountType": "UNIFIED", "accountLTV": "0.017" } ] }`,
"Private Greek": `{ "id": "592324fa945a30-2603-49a5-b865-21668c29f2a6", "topic": "greeks", "creationTime": 1672364262482, "data": [ { "baseCoin": "ETH", "totalDelta": "0.06999986", "totalGamma": "-0.00000001", "totalVega": "-0.00000024", "totalTheta": "0.00001314" } ] }`,
"Execution": `{"id": "592324803b2785-26fa-4214-9963-bdd4727f07be", "topic": "execution", "creationTime": 1672364174455, "data": [ { "category": "linear", "symbol": "XRPUSDT", "execFee": "0.005061", "execId": "7e2ae69c-4edf-5800-a352-893d52b446aa", "execPrice": "0.3374", "execQty": "25", "execType": "Trade", "execValue": "8.435", "isMaker": false, "feeRate": "0.0006", "tradeIv": "", "markIv": "", "blockTradeId": "", "markPrice": "0.3391", "indexPrice": "", "underlyingPrice": "", "leavesQty": "0", "orderId": "f6e324ff-99c2-4e89-9739-3086e47f9381", "orderLinkId": "", "orderPrice": "0.3207", "orderQty":"25","orderType":"Market","stopOrderType":"UNKNOWN","side":"Sell","execTime":"1672364174443","isLeverage": "0","closedSize": "","seq":4688002127}]}`,
}
func TestPushData(t *testing.T) {
t.Parallel()
keys := slices.Collect(maps.Keys(pushDataMap))
slices.Sort(keys)
for x := range keys {
err := b.wsHandleData(asset.Spot, []byte(pushDataMap[keys[x]]))
assert.NoError(t, err, "wsHandleData should not error")
}
}
func TestWsTicker(t *testing.T) {
t.Parallel()
b := new(Bybit) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes
assetRouting := []asset.Item{
asset.Spot, asset.Options, asset.USDTMarginedFutures, asset.USDTMarginedFutures,
asset.USDCMarginedFutures, asset.USDCMarginedFutures, asset.CoinMarginedFutures, asset.CoinMarginedFutures,
}
require.NoError(t, testexch.Setup(b), "Test instance Setup must not error")
testexch.FixtureToDataHandler(t, "testdata/wsTicker.json", func(r []byte) error {
defer slices.Delete(assetRouting, 0, 1)
return b.wsHandleData(assetRouting[0], r)
})
close(b.Websocket.DataHandler)
expected := 8
require.Len(t, b.Websocket.DataHandler, expected, "Should see correct number of tickers")
for resp := range b.Websocket.DataHandler {
switch v := resp.(type) {
case *ticker.Price:
assert.Equal(t, b.Name, v.ExchangeName, "ExchangeName should be correct")
switch expected - len(b.Websocket.DataHandler) {
case 1: // Spot
assert.Equal(t, currency.BTC, v.Pair.Base, "Pair base should be correct")
assert.Equal(t, currency.USDT, v.Pair.Quote, "Pair quote should be correct")
assert.Equal(t, 21109.77, v.Last, "Last should be correct")
assert.Equal(t, 21426.99, v.High, "High should be correct")
assert.Equal(t, 20575.00, v.Low, "Low should be correct")
assert.Equal(t, 6780.866843, v.Volume, "Volume should be correct")
assert.Equal(t, "BTC_USDT", v.Pair.String(), "Pair should be correct")
assert.Equal(t, asset.Spot, v.AssetType, "AssetType should be correct")
assert.Equal(t, int64(1715742949283), v.LastUpdated.UnixMilli(), "LastUpdated should be correct")
case 2: // Option
assert.Equal(t, currency.BTC, v.Pair.Base, "Pair base should be correct")
assert.Equal(t, 3565.00, v.Last, "Last should be correct")
assert.Equal(t, 3715.00, v.High, "High should be correct")
assert.Equal(t, 3555.00, v.Low, "Low should be correct")
assert.Equal(t, 1.62, v.Volume, "Volume should be correct")
assert.Equal(t, 3475.00, v.Bid, "Bid should be correct")
assert.Equal(t, 10.14, v.BidSize, "BidSize should be correct")
assert.Equal(t, 3520.00, v.Ask, "Ask should be correct")
assert.Equal(t, 2.5, v.AskSize, "AskSize should be correct")
assert.Equal(t, 3502.0715721, v.MarkPrice, "MarkPrice should be correct")
assert.Equal(t, 61912.8, v.IndexPrice, "IndexPrice should be correct")
assert.Equal(t, 29.35, v.OpenInterest, "OpenInterest should be correct")
assert.Equal(t, "BTC-28JUN24-60000-P", v.Pair.String(), "Pair should be correct")
assert.Equal(t, asset.Options, v.AssetType, "AssetType should be correct")
assert.Equal(t, int64(1715742949283), v.LastUpdated.UnixMilli(), "LastUpdated should be correct")
case 3: // USDTMargined snapshot
assert.Equal(t, currency.BTC, v.Pair.Base, "Pair base should be correct")
assert.Equal(t, currency.USDT, v.Pair.Quote, "Pair quote should be correct")
assert.Equal(t, 61874.00, v.Last, "Last should be correct")
assert.Equal(t, 62752.90, v.High, "High should be correct")
assert.Equal(t, 61000.10, v.Low, "Low should be correct")
assert.Equal(t, 98430.1050, v.Volume, "Volume should be correct")
assert.Equal(t, 61873.9, v.Bid, "Bid should be correct")
assert.Equal(t, 3.783, v.BidSize, "BidSize should be correct")
assert.Equal(t, 61874.00, v.Ask, "Ask should be correct")
assert.Equal(t, 16.278, v.AskSize, "AskSize should be correct")
assert.Equal(t, 61875.25, v.MarkPrice, "MarkPrice should be correct")
assert.Equal(t, 61903.73, v.IndexPrice, "IndexPrice should be correct")
assert.Equal(t, 58117.022, v.OpenInterest, "OpenInterest should be correct")
assert.Equal(t, asset.USDTMarginedFutures, v.AssetType, "AssetType should be correct")
assert.Equal(t, int64(1715748762463), v.LastUpdated.UnixMilli(), "LastUpdated should be correct")
case 4: // USDTMargined partial
assert.Equal(t, currency.BTC, v.Pair.Base, "Pair base should be correct")
assert.Equal(t, currency.USDT, v.Pair.Quote, "Pair quote should be correct")
assert.Equal(t, 61874.00, v.Last, "Last should be correct")
assert.Equal(t, 62752.90, v.High, "High should be correct")
assert.Equal(t, 61000.10, v.Low, "Low should be correct")
assert.Equal(t, 98430.1050, v.Volume, "Volume should be correct")
assert.Equal(t, 61873.90, v.Bid, "Bid should be correct")
assert.Equal(t, 3.543, v.BidSize, "BidSize should be correct")
assert.Equal(t, 61874.00, v.Ask, "Ask should be correct")
assert.Equal(t, 16.278, v.AskSize, "AskSize should be correct")
assert.Equal(t, 61875.06, v.MarkPrice, "MarkPrice should be correct")
assert.Equal(t, 61903.59, v.IndexPrice, "IndexPrice should be correct")
assert.Equal(t, 58117.022, v.OpenInterest, "OpenInterest should be correct")
assert.Equal(t, asset.USDTMarginedFutures, v.AssetType, "AssetType should be correct")
assert.Equal(t, int64(1715748763063), v.LastUpdated.UnixMilli(), "LastUpdated should be correct")
case 5: // USDCMargined snapshot
assert.Equal(t, currency.BTC, v.Pair.Base, "Pair base should be correct")
assert.Equal(t, currency.PERP, v.Pair.Quote, "Pair quote should be correct")
assert.Equal(t, 61945.70, v.Last, "Last should be correct")
assert.Equal(t, 62242.2, v.High, "High should be correct")
assert.Equal(t, 61059.1, v.Low, "Low should be correct")
assert.Equal(t, 427.375, v.Volume, "Volume should be correct")
assert.Equal(t, 61909.2, v.Bid, "Bid should be correct")
assert.Equal(t, 0.035, v.BidSize, "BidSize should be correct")
assert.Equal(t, 61909.60, v.Ask, "Ask should be correct")
assert.Equal(t, 0.082, v.AskSize, "AskSize should be correct")
assert.Equal(t, 61943.58, v.MarkPrice, "MarkPrice should be correct")
assert.Equal(t, 61942.85, v.IndexPrice, "IndexPrice should be correct")
assert.Equal(t, 526.806, v.OpenInterest, "OpenInterest should be correct")
assert.Equal(t, asset.USDCMarginedFutures, v.AssetType, "AssetType should be correct")
assert.Equal(t, int64(1715756612118), v.LastUpdated.UnixMilli(), "LastUpdated should be correct")
case 6: // USDCMargined partial
assert.Equal(t, currency.BTC, v.Pair.Base, "Pair base should be correct")
assert.Equal(t, currency.PERP, v.Pair.Quote, "Pair quote should be correct")
assert.Equal(t, 61945.70, v.Last, "Last should be correct")
assert.Equal(t, 62242.2, v.High, "High should be correct")
assert.Equal(t, 61059.1, v.Low, "Low should be correct")
assert.Equal(t, 427.375, v.Volume, "Volume should be correct")
assert.Equal(t, 61909.5, v.Bid, "Bid should be correct")
assert.Equal(t, 0.035, v.BidSize, "BidSize should be correct")
assert.Equal(t, 61909.60, v.Ask, "Ask should be correct")
assert.Equal(t, 0.082, v.AskSize, "AskSize should be correct")
assert.Equal(t, 61943.58, v.MarkPrice, "MarkPrice should be correct")
assert.Equal(t, 61942.85, v.IndexPrice, "IndexPrice should be correct")
assert.Equal(t, 526.806, v.OpenInterest, "OpenInterest should be correct")
assert.Equal(t, asset.USDCMarginedFutures, v.AssetType, "AssetType should be correct")
assert.Equal(t, int64(1715756612210), v.LastUpdated.UnixMilli(), "LastUpdated should be correct")
case 7: // CoinMargined snapshot
assert.Equal(t, currency.BTC, v.Pair.Base, "Pair base should be correct")
assert.Equal(t, currency.USD, v.Pair.Quote, "Pair quote should be correct")
assert.Equal(t, 61894.0, v.Last, "Last should be correct")
assert.Equal(t, 62265.5, v.High, "High should be correct")
assert.Equal(t, 61029.5, v.Low, "Low should be correct")
assert.Equal(t, 391976479.0, v.Volume, "Volume should be correct")
assert.Equal(t, 61891.5, v.Bid, "Bid should be correct")
assert.Equal(t, 12667.0, v.BidSize, "BidSize should be correct")
assert.Equal(t, 61892.0, v.Ask, "Ask should be correct")
assert.Equal(t, 60953.0, v.AskSize, "AskSize should be correct")
assert.Equal(t, 61894.0, v.MarkPrice, "MarkPrice should be correct")
assert.Equal(t, 61923.36, v.IndexPrice, "IndexPrice should be correct")
assert.Equal(t, 931760496.0, v.OpenInterest, "OpenInterest should be correct")
assert.Equal(t, asset.CoinMarginedFutures, v.AssetType, "AssetType should be correct")
assert.Equal(t, int64(1715757637952), v.LastUpdated.UnixMilli(), "LastUpdated should be correct")
case 8: // CoinMargined partial
assert.Equal(t, currency.BTC, v.Pair.Base, "Pair base should be correct")
assert.Equal(t, currency.USD, v.Pair.Quote, "Pair quote should be correct")
assert.Equal(t, 61894.0, v.Last, "Last should be correct")
assert.Equal(t, 62265.5, v.High, "High should be correct")
assert.Equal(t, 61029.5, v.Low, "Low should be correct")
assert.Equal(t, 391976479.0, v.Volume, "Volume should be correct")
assert.Equal(t, 61891.5, v.Bid, "Bid should be correct")
assert.Equal(t, 27634.0, v.BidSize, "BidSize should be correct")
assert.Equal(t, 61892.0, v.Ask, "Ask should be correct")
assert.Equal(t, 60953.0, v.AskSize, "AskSize should be correct")
assert.Equal(t, 61894.0, v.MarkPrice, "MarkPrice should be correct")
assert.Equal(t, 61923.36, v.IndexPrice, "IndexPrice should be correct")
assert.Equal(t, 931760496.0, v.OpenInterest, "OpenInterest should be correct")
assert.Equal(t, asset.CoinMarginedFutures, v.AssetType, "AssetType should be correct")
assert.Equal(t, int64(1715757638152), v.LastUpdated.UnixMilli(), "LastUpdated should be correct")
}
case error:
t.Error(v)
default:
t.Errorf("Unexpected type in DataHandler: %T (%s)", v, v)
}
}
}
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
t.Parallel()
feeBuilder := &exchange.FeeBuilder{
Amount: 1,
FeeType: exchange.CryptocurrencyTradeFee,
Pair: spotTradablePair,
PurchasePrice: 1,
FiatCurrency: currency.USD,
BankTransactionType: exchange.WireTransfer,
}
_, err := b.GetFeeByType(context.Background(), feeBuilder)
if err != nil {
t.Fatal(err)
}
feeBuilder.Pair = optionsTradablePair
_, err = b.GetFeeByType(context.Background(), feeBuilder)
if err != nil {
t.Fatal(err)
}
feeBuilder.Pair = usdtMarginedTradablePair
_, err = b.GetFeeByType(context.Background(), feeBuilder)
if err != nil {
t.Fatal(err)
}
feeBuilder.Pair = inverseTradablePair
_, err = b.GetFeeByType(context.Background(), feeBuilder)
if err != nil {
t.Fatal(err)
}
}
func TestSetLeverage(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
ctx := context.Background()
err := b.SetLeverage(ctx, asset.USDTMarginedFutures, usdtMarginedTradablePair, margin.Multi, 5, order.Buy)
if err != nil {
t.Error(err)
}
err = b.SetLeverage(ctx, asset.USDCMarginedFutures, usdcMarginedTradablePair, margin.Multi, 5, order.Buy)
if err != nil {
t.Error(err)
}
err = b.SetLeverage(ctx, asset.CoinMarginedFutures, inverseTradablePair, margin.Isolated, 5, order.UnknownSide)
if !errors.Is(err, order.ErrSideIsInvalid) {
t.Errorf("received '%v', expected '%v'", err, order.ErrSideIsInvalid)
}
err = b.SetLeverage(ctx, asset.USDTMarginedFutures, usdtMarginedTradablePair, margin.Isolated, 5, order.Buy)
if err != nil {
t.Error(err)
}
err = b.SetLeverage(ctx, asset.CoinMarginedFutures, inverseTradablePair, margin.Isolated, 5, order.Sell)
if err != nil {
t.Error(err)
}
err = b.SetLeverage(ctx, asset.USDTMarginedFutures, usdtMarginedTradablePair, margin.Isolated, 5, order.CouldNotBuy)
if !errors.Is(err, order.ErrSideIsInvalid) {
t.Errorf("received '%v', expected '%v'", err, order.ErrSideIsInvalid)
}
err = b.SetLeverage(ctx, asset.Spot, inverseTradablePair, 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 := b.GetFuturesContractDetails(context.Background(), asset.Spot)
if !errors.Is(err, futures.ErrNotFuturesAsset) {
t.Error(err)
}
_, err = b.GetFuturesContractDetails(context.Background(), asset.CoinMarginedFutures)
if !errors.Is(err, nil) {
t.Error(err)
}
_, err = b.GetFuturesContractDetails(context.Background(), asset.USDTMarginedFutures)
if !errors.Is(err, nil) {
t.Error(err)
}
_, err = b.GetFuturesContractDetails(context.Background(), asset.USDCMarginedFutures)
if !errors.Is(err, nil) {
t.Error(err)
}
}
func TestFetchTradablePairs(t *testing.T) {
t.Parallel()
_, err := b.FetchTradablePairs(context.Background(), asset.Spot)
if err != nil {
t.Fatal(err)
}
_, err = b.FetchTradablePairs(context.Background(), asset.CoinMarginedFutures)
if err != nil {
t.Fatal(err)
}
_, err = b.FetchTradablePairs(context.Background(), asset.USDTMarginedFutures)
if err != nil {
t.Fatal(err)
}
_, err = b.FetchTradablePairs(context.Background(), asset.USDCMarginedFutures)
if err != nil {
t.Fatal(err)
}
_, err = b.FetchTradablePairs(context.Background(), asset.Options)
if err != nil {
t.Fatal(err)
}
_, err = b.FetchTradablePairs(context.Background(), asset.Futures)
if !errors.Is(err, asset.ErrNotSupported) {
t.Errorf("expected %v, got %v", asset.ErrNotSupported, err)
}
}
func TestDeltaUpdateOrderbook(t *testing.T) {
t.Parallel()
data := `{"topic":"orderbook.50.WEMIXUSDT","ts":1697573183768,"type":"snapshot","data":{"s":"WEMIXUSDT","b":[["0.9511","260.703"],["0.9677","0"]],"a":[],"u":3119516,"seq":14126848493},"cts":1728966699481}`
err := b.wsHandleData(asset.Spot, []byte(data))
if err != nil {
t.Fatal(err)
}
update := `{"topic":"orderbook.50.WEMIXUSDT","ts":1697573183768,"type":"delta","data":{"s":"WEMIXUSDT","b":[["0.9511","260.703"],["0.9677","0"]],"a":[],"u":3119516,"seq":14126848493},"cts":1728966699481}`
var wsResponse WebsocketResponse
err = json.Unmarshal([]byte(update), &wsResponse)
if err != nil {
t.Fatal(err)
}
err = b.wsProcessOrderbook(asset.Spot, &wsResponse)
if err != nil {
t.Fatal(err)
}
}
func TestGetLongShortRatio(t *testing.T) {
t.Parallel()
_, err := b.GetLongShortRatio(context.Background(), "linear", "BTCUSDT", kline.FiveMin, 0)
if err != nil {
t.Fatal(err)
}
_, err = b.GetLongShortRatio(context.Background(), "inverse", "BTCUSDT", kline.FiveMin, 0)
if err != nil {
t.Fatal(err)
}
_, err = b.GetLongShortRatio(context.Background(), "spot", "BTCUSDT", kline.FiveMin, 0)
if !errors.Is(err, errInvalidCategory) {
t.Fatalf("expected %v, got %v", errInvalidCategory, err)
}
}
func TestStringToOrderStatus(t *testing.T) {
t.Parallel()
input := []struct {
OrderStatus string
Expectation order.Status
}{
{
OrderStatus: "",
Expectation: order.UnknownStatus,
},
{
OrderStatus: "UNKNOWN",
Expectation: order.UnknownStatus,
},
{
OrderStatus: "Cancelled",
Expectation: order.Cancelled,
},
{
OrderStatus: "ACTIVE",
Expectation: order.Active,
},
{
OrderStatus: "NEW",
Expectation: order.New,
},
{
OrderStatus: "FILLED",
Expectation: order.Filled,
},
{
OrderStatus: "UNTRIGGERED",
Expectation: order.Pending,
},
}
var oStatus order.Status
for x := range input {
oStatus = StringToOrderStatus(input[x].OrderStatus)
if oStatus != input[x].Expectation {
t.Fatalf("expected %v, got %v", input[x].Expectation, oStatus)
}
}
}
func TestFetchAccountType(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
val, err := b.FetchAccountType(context.Background())
require.NoError(t, err)
require.NotZero(t, val)
}
func TestAccountTypeString(t *testing.T) {
t.Parallel()
require.Equal(t, "unset", AccountType(0).String())
require.Equal(t, "unified", accountTypeUnified.String())
require.Equal(t, "normal", accountTypeNormal.String())
require.Equal(t, "unknown", AccountType(3).String())
}
func TestRequiresUnifiedAccount(t *testing.T) {
t.Parallel()
if !mockTests {
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
}
err := b.RequiresUnifiedAccount(context.Background())
require.NoError(t, err)
b := &Bybit{} //nolint:govet // Intentional shadow to avoid future copy/paste mistakes. Also stops race below.
b.account.accountType = accountTypeNormal
err = b.RequiresUnifiedAccount(context.Background())
require.ErrorIs(t, err, errAPIKeyIsNotUnified)
}
func TestGetLatestFundingRates(t *testing.T) {
t.Parallel()
_, err := b.GetLatestFundingRates(context.Background(), &fundingrate.LatestRateRequest{
Asset: asset.Futures,
Pair: usdtMarginedTradablePair,
})
if !errors.Is(err, asset.ErrNotSupported) {
t.Error(err)
}
_, err = b.GetLatestFundingRates(context.Background(), &fundingrate.LatestRateRequest{
Asset: asset.Spot,
Pair: spotTradablePair,
})
if !errors.Is(err, asset.ErrNotSupported) {
t.Errorf("expected %v, got %v", asset.ErrNotSupported, err)
}
_, err = b.GetLatestFundingRates(context.Background(), &fundingrate.LatestRateRequest{
Asset: asset.Options,
Pair: optionsTradablePair,
})
if !errors.Is(err, asset.ErrNotSupported) {
t.Errorf("expected %v, got %v", asset.ErrNotSupported, err)
}
_, err = b.GetLatestFundingRates(context.Background(), &fundingrate.LatestRateRequest{
Asset: asset.USDTMarginedFutures,
})
if err != nil {
t.Error(err)
}
_, err = b.GetLatestFundingRates(context.Background(), &fundingrate.LatestRateRequest{
Asset: asset.USDCMarginedFutures,
Pair: usdcMarginedTradablePair,
})
if err != nil {
t.Error(err)
}
}
func TestConstructOrderDetails(t *testing.T) {
t.Parallel()
const data = `[ {"orderId": "fd4300ae-7847-404e-b947-b46980a4d140","orderLinkId": "test-000005","blockTradeId": "","symbol": "ETHUSDT","price": "1600.00","qty": "0.10","side": "Buy","isLeverage": "","positionIdx": 1,"orderStatus": "New","cancelType": "UNKNOWN","rejectReason": "EC_NoError","avgPrice": "0","leavesQty": "0.10","leavesValue": "160","cumExecQty": "0.00","cumExecValue": "0","cumExecFee": "0","timeInForce": "GTC","orderType": "Limit","stopOrderType": "UNKNOWN","orderIv": "","triggerPrice": "0.00","takeProfit": "2500.00","stopLoss": "1500.00","tpTriggerBy": "LastPrice","slTriggerBy": "LastPrice","triggerDirection": 0,"triggerBy": "UNKNOWN","lastPriceOnCreated": "","reduceOnly": false,"closeOnTrigger": false,"smpType": "None", "smpGroup": 0,"smpOrderId": "","tpslMode": "Full","tpLimitPrice": "","slLimitPrice": "","placeType": "","createdTime": "1684738540559","updatedTime": "1684738540561"}]`
var response []TradeOrder
err := json.Unmarshal([]byte(data), &response)
if err != nil {
t.Fatal(err)
}
orders, err := b.ConstructOrderDetails(response, asset.Spot, currency.Pair{Base: currency.BTC, Quote: currency.USDT}, currency.Pairs{})
if err != nil {
t.Fatal(err)
} else if len(orders) > 0 {
t.Errorf("expected order with length 0, got %d", len(orders))
}
orders, err = b.ConstructOrderDetails(response, asset.Spot, currency.EMPTYPAIR, currency.Pairs{})
if err != nil {
t.Fatal(err)
} else if len(orders) != 1 {
t.Errorf("expected order with length 1, got %d", len(orders))
}
}
func TestGetOpenInterest(t *testing.T) {
t.Parallel()
_, err := b.GetOpenInterest(context.Background(), key.PairAsset{
Base: currency.ETH.Item,
Quote: currency.USDT.Item,
Asset: asset.Spot,
})
assert.ErrorIs(t, err, asset.ErrNotSupported)
resp, err := b.GetOpenInterest(context.Background(), key.PairAsset{
Base: usdcMarginedTradablePair.Base.Item,
Quote: usdcMarginedTradablePair.Quote.Item,
Asset: asset.USDCMarginedFutures,
})
assert.NoError(t, err)
assert.NotEmpty(t, resp)
resp, err = b.GetOpenInterest(context.Background(), key.PairAsset{
Base: usdtMarginedTradablePair.Base.Item,
Quote: usdtMarginedTradablePair.Quote.Item,
Asset: asset.USDTMarginedFutures,
})
assert.NoError(t, err)
assert.NotEmpty(t, resp)
resp, err = b.GetOpenInterest(context.Background(), key.PairAsset{
Base: inverseTradablePair.Base.Item,
Quote: inverseTradablePair.Quote.Item,
Asset: asset.CoinMarginedFutures,
})
assert.NoError(t, err)
assert.NotEmpty(t, resp)
resp, err = b.GetOpenInterest(context.Background())
assert.NoError(t, err)
assert.NotEmpty(t, resp)
}
func TestIsPerpetualFutureCurrency(t *testing.T) {
t.Parallel()
is, err := b.IsPerpetualFutureCurrency(asset.Spot, spotTradablePair)
assert.NoError(t, err)
assert.False(t, is)
is, err = b.IsPerpetualFutureCurrency(asset.CoinMarginedFutures, inverseTradablePair)
assert.NoError(t, err)
assert.Truef(t, is, "%s %s should be a perp", asset.CoinMarginedFutures, inverseTradablePair)
is, err = b.IsPerpetualFutureCurrency(asset.USDTMarginedFutures, usdtMarginedTradablePair)
assert.NoError(t, err)
assert.Truef(t, is, "%s %s should be a perp", asset.USDTMarginedFutures, usdtMarginedTradablePair)
is, err = b.IsPerpetualFutureCurrency(asset.USDCMarginedFutures, usdcMarginedTradablePair)
assert.NoError(t, err)
assert.Truef(t, is, "%s %s should be a perp", asset.USDCMarginedFutures, usdcMarginedTradablePair)
}
func TestGetCurrencyTradeURL(t *testing.T) {
t.Parallel()
testexch.UpdatePairsOnce(t, b)
for _, a := range b.GetAssetTypes(false) {
pairs, err := b.CurrencyPairs.GetPairs(a, false)
require.NoError(t, err, "cannot get pairs for %s", a)
require.NotEmpty(t, pairs, "no pairs for %s", a)
resp, err := b.GetCurrencyTradeURL(context.Background(), a, pairs[0])
require.NoError(t, err)
assert.NotEmpty(t, resp)
}
}
// TestGenerateSubscriptions exercises generateSubscriptions
func TestGenerateSubscriptions(t *testing.T) {
t.Parallel()
b := new(Bybit)
require.NoError(t, testexch.Setup(b), "Test instance Setup must not error")
b.Websocket.SetCanUseAuthenticatedEndpoints(true)
subs, err := b.generateSubscriptions()
require.NoError(t, err, "generateSubscriptions must not error")
exp := subscription.List{}
for _, s := range b.Features.Subscriptions {
for _, a := range b.GetAssetTypes(true) {
if s.Asset != asset.All && s.Asset != a {
continue
}
pairs, err := b.GetEnabledPairs(a)
require.NoErrorf(t, err, "GetEnabledPairs %s must not error", a)
pairs = common.SortStrings(pairs).Format(currency.PairFormat{Uppercase: true, Delimiter: ""})
s := s.Clone() //nolint:govet // Intentional lexical scope shadow
s.Asset = a
if isSymbolChannel(channelName(s)) {
for i, p := range pairs {
s := s.Clone() //nolint:govet // Intentional lexical scope shadow
switch s.Channel {
case subscription.CandlesChannel:
s.QualifiedChannel = fmt.Sprintf("%s.%.f.%s", channelName(s), s.Interval.Duration().Minutes(), p)
case subscription.OrderbookChannel:
s.QualifiedChannel = fmt.Sprintf("%s.%d.%s", channelName(s), s.Levels, p)
default:
s.QualifiedChannel = channelName(s) + "." + p.String()
}
s.Pairs = pairs[i : i+1]
exp = append(exp, s)
}
} else {
s.Pairs = pairs
s.QualifiedChannel = channelName(s)
categoryName := getCategoryName(a)
if isCategorisedChannel(s.QualifiedChannel) && categoryName != "" {
s.QualifiedChannel += "." + categoryName
}
exp = append(exp, s)
}
}
}
testsubs.EqualLists(t, exp, subs)
}
func TestSubscribe(t *testing.T) {
t.Parallel()
b := new(Bybit)
require.NoError(t, testexch.Setup(b), "Test instance Setup must not error")
subs, err := b.Features.Subscriptions.ExpandTemplates(b)
require.NoError(t, err, "ExpandTemplates must not error")
b.Features.Subscriptions = subscription.List{}
testexch.SetupWs(t, b)
err = b.Subscribe(subs)
require.NoError(t, err, "Subscribe must not error")
}
func TestAuthSubscribe(t *testing.T) {
t.Parallel()
b := new(Bybit)
require.NoError(t, testexch.Setup(b), "Test instance Setup must not error")
b.Websocket.SetCanUseAuthenticatedEndpoints(true)
subs, err := b.Features.Subscriptions.ExpandTemplates(b)
require.NoError(t, err, "ExpandTemplates must not error")
b.Features.Subscriptions = subscription.List{}
success := true
mock := func(tb testing.TB, msg []byte, w *gws.Conn) error {
tb.Helper()
var req SubscriptionArgument
require.NoError(tb, json.Unmarshal(msg, &req), "Unmarshal must not error")
require.Equal(tb, "subscribe", req.Operation)
msg, err = json.Marshal(SubscriptionResponse{
Success: success,
RetMsg: "Mock Resp Error",
RequestID: req.RequestID,
Operation: req.Operation,
})
require.NoError(tb, err, "Marshal must not error")
return w.WriteMessage(gws.TextMessage, msg)
}
b = testexch.MockWsInstance[Bybit](t, testws.CurryWsMockUpgrader(t, mock))
b.Websocket.AuthConn = b.Websocket.Conn
err = b.Subscribe(subs)
require.NoError(t, err, "Subscribe must not error")
success = false
err = b.Subscribe(subs)
assert.ErrorContains(t, err, "Mock Resp Error", "Subscribe should error containing the returned RetMsg")
}
func TestTransformSymbol(t *testing.T) {
t.Parallel()
tests := []struct {
symbol string
baseCoin string
contractType string
item asset.Item
expectedSymbol string
}{
{
symbol: "POPCATUSDT",
baseCoin: "POPCAT",
item: asset.Spot,
expectedSymbol: "POPCAT_USDT",
},
{
symbol: "BTC26SEP25-300000-P",
item: asset.Options,
baseCoin: "BTC",
expectedSymbol: "BTC-26SEP25-300000-P",
},
{
symbol: "1000000BABYDOGEUSDT",
item: asset.USDTMarginedFutures,
baseCoin: "1000000BABYDOGE",
expectedSymbol: "1000000BABYDOGE-USDT",
},
{
symbol: "BTC-06DEC24",
item: asset.USDCMarginedFutures,
expectedSymbol: "BTC-06DEC24",
contractType: "LinearFutures",
},
{
symbol: "1000PEPEPERP",
baseCoin: "1000PEPE",
item: asset.USDCMarginedFutures,
expectedSymbol: "1000PEPE-PERP",
},
{
symbol: "BTCUSD",
baseCoin: "BTC",
item: asset.CoinMarginedFutures,
expectedSymbol: "BTC_USD",
},
{
symbol: "nothingHappens",
item: asset.CrossMargin,
expectedSymbol: "nothingHappens",
},
}
for i := range tests {
t.Run(tests[i].symbol+" "+tests[i].item.String(), func(t *testing.T) {
t.Parallel()
ii := InstrumentInfo{
Symbol: tests[i].symbol,
ContractType: tests[i].contractType,
BaseCoin: tests[i].baseCoin,
}
assert.Equal(t, tests[i].expectedSymbol, ii.transformSymbol(tests[i].item), "expected symbols to match")
})
}
}