Skip to content

Commit

Permalink
Bitget API becomes appended
Browse files Browse the repository at this point in the history
  • Loading branch information
cranktakular committed Jul 23, 2024
1 parent f482c05 commit d1529aa
Show file tree
Hide file tree
Showing 5 changed files with 811 additions and 88 deletions.
114 changes: 80 additions & 34 deletions exchanges/bitget/bitget.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,16 @@ const (
bitgetAPIURL = "https://api.bitget.com/api/v2/"

// Public endpoints
bitgetPublic = "public/"
bitgetAnnouncements = "annoucements" // sic
bitgetTime = "time"
bitgetMarket = "market/"
bitgetWhaleNetFlow = "whale-net-flow"
bitgetTakerBuySell = "taker-buy-sell"
bitgetPositionLongShort = "position-long-short"
bitgetPublic = "public/"
bitgetAnnouncements = "annoucements" // sic

Check failure on line 30 in exchanges/bitget/bitget.go

View workflow job for this annotation

GitHub Actions / Spell checker

annoucements ==> announcements
bitgetTime = "time"
bitgetMarket = "market/"
bitgetWhaleNetFlow = "whale-net-flow"
bitgetTakerBuySell = "taker-buy-sell"
bitgetPositionLongShort = "position-long-short"
// bitgetLongShortRatio = "long-short-ratio"
// bitgetLoanGrowth = "loan-growth"
// bitgetIsolatedBorrowRate = "isolated-borrow-rate"
bitgetLongShort = "long-short"
bitgetFundFlow = "fund-flow"
bitgetSupportSymbols = "support-symbols"
Expand Down Expand Up @@ -268,6 +271,7 @@ var (
errOrderNotFound = errors.New("order not found")

prodTypes = []string{"USDT-FUTURES", "COIN-FUTURES", "USDC-FUTURES"}
planTypes = []string{"normal_plan", "track_plan", "profit_loss"}
)

// QueryAnnouncement returns announcements from the exchange, filtered by type and time
Expand Down Expand Up @@ -487,35 +491,77 @@ func (bi *Bitget) GetFuturesActiveVolume(ctx context.Context, pair, period strin
}
vals := url.Values{}
vals.Set("symbol", pair)
// See whether this can be unset without causing issues
vals.Set("period", period)
path := bitgetMix + bitgetMarket + bitgetTakerBuySell
var resp *ActiveVolumeResp
return resp, bi.SendHTTPRequest(ctx, exchange.RestSpot, Rate1, path, vals, &resp)
}

// GetFuturesPositionRatios returns the ratio of long to short positions for a specified pair
func (bi *Bitget) GetFuturesPositionRatios(ctx context.Context, pair, period string) (*PositionRatioResp, error) {
func (bi *Bitget) GetFuturesPositionRatios(ctx context.Context, pair, period string) (*PosRatFutureResp, error) {
if pair == "" {
return nil, errPairEmpty
}
vals := url.Values{}
vals.Set("symbol", pair)
// See whether this can be unset without causing issues
vals.Set("period", period)
path := bitgetMix + bitgetMarket + bitgetPositionLongShort
var resp *PositionRatioResp
var resp *PosRatFutureResp
return resp, bi.SendHTTPRequest(ctx, exchange.RestSpot, Rate1, path, vals, &resp)
}

// When queried, the exchange claims that this endpoint doesn't exist, despite having a documentation page
// // GetMarginPositionRatios returns the ratio of long to short positions for a specified pair in margin accounts
// func (bi *Bitget) GetMarginPositionRatios(ctx context.Context, pair, period, currency string) (*PosRatMarginResp, error) {
// if pair == "" {
// return nil, errPairEmpty
// }
// vals := url.Values{}
// vals.Set("symbol", pair)
// vals.Set("period", period)
// vals.Set("coin", currency)
// path := bitgetMix + bitgetMarket + bitgetLongShortRatio
// var resp *PosRatMarginResp
// return resp, bi.SendHTTPRequest(ctx, exchange.RestSpot, Rate1, path, vals, &resp)
// }

// When queried, the exchange claims that this endpoint doesn't exist, despite having a documentation page
// // GetMarginLoanGrowth returns the growth rate of borrowed funds for a specified pair in margin accounts
// func (bi *Bitget) GetMarginLoanGrowth(ctx context.Context, pair, period, currency string) (*LoanGrowthResp, error) {
// if pair == "" {
// return nil, errPairEmpty
// }
// vals := url.Values{}
// vals.Set("symbol", pair)
// vals.Set("period", period)
// vals.Set("coin", currency)
// path := bitgetMix + bitgetMarket + bitgetLoanGrowth
// var resp *LoanGrowthResp
// return resp, bi.SendHTTPRequest(ctx, exchange.RestSpot, Rate1, path, vals, &resp)
// }

// When queried, the exchange claims that this endpoint doesn't exist, despite having a documentation page
// // GetIsolatedBorrowingRatio returns the ratio of borrowed funds between base and quote currencies, after
// // converting to USDT, within isolated margin accounts
// func (bi *Bitget) GetIsolatedBorrowingRatio(ctx context.Context, pair, period string) (*BorrowRatioResp, error) {
// if pair == "" {
// return nil, errPairEmpty
// }
// vals := url.Values{}
// vals.Set("symbol", pair)
// vals.Set("period", period)
// path := bitgetMix + bitgetMarket + bitgetIsolatedBorrowRate
// var resp *BorrowRatioResp
// return resp, bi.SendHTTPRequest(ctx, exchange.RestSpot, Rate1, path, vals, &resp)
// }

// GetFuturesRatios returns the ratio of long to short positions for a specified pair
func (bi *Bitget) GetFuturesRatios(ctx context.Context, pair, period string) (*RatioResp, error) {
if pair == "" {
return nil, errPairEmpty
}
vals := url.Values{}
vals.Set("symbol", pair)
// See whether this can be unset without causing issues
vals.Set("period", period)
path := bitgetMix + bitgetMarket + bitgetLongShort
var resp *RatioResp
Expand Down Expand Up @@ -561,7 +607,6 @@ func (bi *Bitget) GetFuturesAccountRatios(ctx context.Context, pair, period stri
}
vals := url.Values{}
vals.Set("symbol", pair)
// See whether this can be unset without causing issues
vals.Set("period", period)
path := bitgetMix + bitgetMarket + bitgetAccountLongShort
var resp *AccountRatioResp
Expand Down Expand Up @@ -1315,7 +1360,7 @@ func (bi *Bitget) GetSpotPlanSubOrder(ctx context.Context, orderID string) (*Sub
}

// GetSpotPlanOrderHistory returns the user's plan order history
func (bi *Bitget) GetSpotPlanOrderHistory(ctx context.Context, pair string, startTime, endTime time.Time, limit int32) (*PlanSpotOrderResp, error) {
func (bi *Bitget) GetSpotPlanOrderHistory(ctx context.Context, pair string, startTime, endTime time.Time, limit, pagination int64) (*PlanSpotOrderResp, error) {
if pair == "" {
return nil, errPairEmpty
}
Expand All @@ -1326,6 +1371,9 @@ func (bi *Bitget) GetSpotPlanOrderHistory(ctx context.Context, pair string, star
return nil, err
}
params.Values.Set("symbol", pair)
if pagination != 0 {
params.Values.Set("idLessThan", strconv.FormatInt(pagination, 10))
}
if limit != 0 {
params.Values.Set("limit", strconv.FormatInt(int64(limit), 10))
}
Expand Down Expand Up @@ -2835,24 +2883,6 @@ func (bi *Bitget) ModifyTPSLFuturesOrder(ctx context.Context, orderID int64, cli
&resp)
}

// CancelTriggerFuturesOrders cancels trigger futures orders
func (bi *Bitget) CancelTriggerFuturesOrders(ctx context.Context, orderIDList []OrderIDStruct, pair, productType, marginCoin, planType string) (*BatchOrderResp, error) {
if productType == "" {
return nil, errProductTypeEmpty
}
req := map[string]interface{}{
"productType": productType,
"planType": planType,
"symbol": pair,
"orderIdList": orderIDList,
"marginCoin": marginCoin,
}
path := bitgetMix + bitgetOrder + bitgetCancelPlanOrder
var resp *BatchOrderResp
return resp, bi.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, Rate10, http.MethodPost, path, nil, req,
&resp)
}

// ModifyTriggerFuturesOrder modifies a trigger futures order
func (bi *Bitget) ModifyTriggerFuturesOrder(ctx context.Context, orderID int64, clientOrderID, productType, triggerType, takeProfitTriggerType, stopLossTriggerType string, amount, executePrice, callbackRatio, triggerPrice, takeProfitTriggerPrice, takeProfitExecutePrice, stopLossTriggerPrice, stopLossExecutePrice float64) (*OrderIDResp, error) {
if orderID == 0 && clientOrderID == "" {
Expand Down Expand Up @@ -2926,6 +2956,24 @@ func (bi *Bitget) GetPendingTriggerFuturesOrders(ctx context.Context, orderID, p
nil, &resp)
}

// CancelTriggerFuturesOrders cancels trigger futures orders
func (bi *Bitget) CancelTriggerFuturesOrders(ctx context.Context, orderIDList []OrderIDStruct, pair, productType, marginCoin, planType string) (*BatchOrderResp, error) {
if productType == "" {
return nil, errProductTypeEmpty
}
req := map[string]interface{}{
"productType": productType,
"planType": planType,
"symbol": pair,
"orderIdList": orderIDList,
"marginCoin": marginCoin,
}
path := bitgetMix + bitgetOrder + bitgetCancelPlanOrder
var resp *BatchOrderResp
return resp, bi.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, Rate10, http.MethodPost, path, nil, req,
&resp)
}

// GetHistoricalTriggerFuturesOrders returns information on historical trigger orders
func (bi *Bitget) GetHistoricalTriggerFuturesOrders(ctx context.Context, orderID, pagination, limit int64, clientOrderID, planType, planStatus, pair, productType string, startTime, endTime time.Time) (*HistTriggerFuturesOrdResp, error) {
if planType == "" {
Expand Down Expand Up @@ -4201,8 +4249,6 @@ func (bi *Bitget) GetLoanCurrencyList(ctx context.Context, currency string) (*Lo
vals.Set("coin", currency)
path := bitgetEarn + bitgetLoan + "/" + bitgetPublic + bitgetCoinInfos
var resp *LoanCurList
// return resp, bi.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, Rate10, http.MethodGet, path, vals, nil,
// &resp)
return resp, bi.SendHTTPRequest(ctx, exchange.RestSpot, Rate10, path, vals, &resp)
}

Expand Down
87 changes: 70 additions & 17 deletions exchanges/bitget/bitget_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package bitget

import (
"context"
"fmt"
"log"
"net/url"
"os"
Expand Down Expand Up @@ -230,9 +229,7 @@ func TestGetFuturesActiveVolume(t *testing.T) {
t.Parallel()
_, err := bi.GetFuturesActiveVolume(context.Background(), "", "")
assert.ErrorIs(t, err, errPairEmpty)
// Inexplicably fails with the error "The data fetched by {pair} is empty". The pair is valid, and seems to be
// undergoing trades on the futures market according to their website.
resp, err := bi.GetFuturesActiveVolume(context.Background(), "BTCUSDT", "1d")
resp, err := bi.GetFuturesActiveVolume(context.Background(), testPair.String(), "")
require.NoError(t, err)
assert.NotEmpty(t, resp.Data)
}
Expand All @@ -241,20 +238,46 @@ func TestGetFuturesPositionRatios(t *testing.T) {
t.Parallel()
_, err := bi.GetFuturesPositionRatios(context.Background(), "", "")
assert.ErrorIs(t, err, errPairEmpty)
// Inexplicably fails with the error "The data fetched by {pair} is empty". The pair is valid, and seems to be
// undergoing trades on the futures market according to their website.
resp, err := bi.GetFuturesPositionRatios(context.Background(), "BTCUSDT", "12h")
resp, err := bi.GetFuturesPositionRatios(context.Background(), testPair.String(), "")
require.NoError(t, err)
assert.NotEmpty(t, resp.Data)
}

// Test for an endpoint which doesn't work
// func TestGetMarginPositionRatios(t *testing.T) {
// t.Parallel()
// _, err := bi.GetMarginPositionRatios(context.Background(), "", "", "")
// assert.ErrorIs(t, err, errPairEmpty)
// resp, err := bi.GetMarginPositionRatios(context.Background(), testPair.String(), "", "")
// require.NoError(t, err)
// assert.NotEmpty(t, resp.Data)
// }

// Test for an endpoint which doesn't work
// func TestGetMarginLoanGrowth(t *testing.T) {
// t.Parallel()
// _, err := bi.GetMarginLoanGrowth(context.Background(), "", "", "")
// assert.ErrorIs(t, err, errPairEmpty)
// resp, err := bi.GetMarginLoanGrowth(context.Background(), testPair.String(), "", "")
// require.NoError(t, err)
// assert.NotEmpty(t, resp.Data)
// }

// Test for an endpoint which doesn't work
// func TestGetIsolatedBorrowingRatio(t *testing.T) {
// t.Parallel()
// _, err := bi.GetIsolatedBorrowingRatio(context.Background(), "", "")
// assert.ErrorIs(t, err, errPairEmpty)
// resp, err := bi.GetIsolatedBorrowingRatio(context.Background(), testPair.String(), "")
// require.NoError(t, err)
// assert.NotEmpty(t, resp.Data)
// }

func TestGetFuturesRatios(t *testing.T) {
t.Parallel()
_, err := bi.GetFuturesRatios(context.Background(), "", "")
assert.ErrorIs(t, err, errPairEmpty)
// Inexplicably fails with the error "The data fetched by {pair} is empty". The pair is valid, and seems to be
// undergoing trades on the futures market according to their website.
resp, err := bi.GetFuturesRatios(context.Background(), "BTCUSDT", "12h")
resp, err := bi.GetFuturesRatios(context.Background(), testPair.String(), "")
require.NoError(t, err)
assert.NotEmpty(t, resp.Data)
}
Expand All @@ -278,7 +301,7 @@ func TestGetFuturesAccountRatios(t *testing.T) {
t.Parallel()
_, err := bi.GetFuturesAccountRatios(context.Background(), "", "")
assert.ErrorIs(t, err, errPairEmpty)
resp, err := bi.GetFuturesAccountRatios(context.Background(), testPair.String(), "12h")
resp, err := bi.GetFuturesAccountRatios(context.Background(), testPair.String(), "")
require.NoError(t, err)
assert.NotEmpty(t, resp.Data)
}
Expand Down Expand Up @@ -704,13 +727,13 @@ func TestSpotGetPlanSubOrder(t *testing.T) {

func TestGetSpotPlanOrderHistory(t *testing.T) {
t.Parallel()
_, err := bi.GetSpotPlanOrderHistory(context.Background(), "", time.Time{}, time.Time{}, 0)
_, err := bi.GetSpotPlanOrderHistory(context.Background(), "", time.Time{}, time.Time{}, 0, 0)
assert.ErrorIs(t, err, errPairEmpty)
_, err = bi.GetSpotPlanOrderHistory(context.Background(), "meow", time.Time{}, time.Time{}, 0)
_, err = bi.GetSpotPlanOrderHistory(context.Background(), "meow", time.Time{}, time.Time{}, 0, 0)
assert.ErrorIs(t, err, common.ErrDateUnset)
sharedtestvalues.SkipTestIfCredentialsUnset(t, bi)
_, err = bi.GetSpotPlanOrderHistory(context.Background(), testPair.String(), time.Now().Add(-time.Hour*24*90),
time.Now().Add(-time.Minute), 1<<30)
time.Now().Add(-time.Minute), 2, 1<<62)
assert.NoError(t, err)
}

Expand Down Expand Up @@ -1202,11 +1225,9 @@ func TestGetAllPositions(t *testing.T) {

func TestGetHistoricalPositions(t *testing.T) {
t.Parallel()
fmt.Printf("sending pagination 0\n")
_, err := bi.GetHistoricalPositions(context.Background(), "", "", 0, 0, time.Now().Add(time.Hour), time.Time{})
assert.ErrorIs(t, err, common.ErrStartAfterTimeNow)
sharedtestvalues.SkipTestIfCredentialsUnset(t, bi)
fmt.Printf("sending pagination %v\n", int64(1<<62))
_, err = bi.GetHistoricalPositions(context.Background(), "", "", 1<<62, 5, time.Time{}, time.Time{})
assert.NoError(t, err)
}
Expand Down Expand Up @@ -2607,6 +2628,38 @@ func TestWithdrawFiatFundsToInternationalBank(t *testing.T) {
assert.ErrorIs(t, err, common.ErrFunctionNotSupported)
}

func TestGetActiveOrdrrs(t *testing.T) {
t.Parallel()
var req *order.MultiOrderRequest
_, err := bi.GetActiveOrders(context.Background(), req)
assert.ErrorIs(t, err, order.ErrGetOrdersRequestIsNil)
req = &order.MultiOrderRequest{
AssetType: asset.Binary,
Side: order.Sell,
Type: order.Limit,
Pairs: []currency.Pair{testPair},
}
_, err = bi.GetActiveOrders(context.Background(), req)
assert.ErrorIs(t, err, asset.ErrNotSupported)
sharedtestvalues.SkipTestIfCredentialsUnset(t, bi)
req.AssetType = asset.CrossMargin
_, err = bi.GetActiveOrders(context.Background(), req)
assert.NoError(t, err)
req.AssetType = asset.Margin
_, err = bi.GetActiveOrders(context.Background(), req)
assert.NoError(t, err)
req.AssetType = asset.Futures
_, err = bi.GetActiveOrders(context.Background(), req)
assert.NoError(t, err)
req.AssetType = asset.Spot
_, err = bi.GetActiveOrders(context.Background(), req)
assert.NoError(t, err)
req.Pairs = []currency.Pair{}
_, err = bi.GetActiveOrders(context.Background(), req)
// This is failing since the String() method on these novel pairs returns them with a delimiter for some reason
assert.NoError(t, err)
}

// The following 3 tests aren't parallel due to collisions with each other, and some other plan order-related tests
func TestModifyPlanSpotOrder(t *testing.T) {
_, err := bi.ModifyPlanSpotOrder(context.Background(), 0, "", "", 0, 0, 0)
Expand Down Expand Up @@ -2986,7 +3039,7 @@ type getOneArgResp interface {
}

type getOneArgParam interface {
string | []string | int64 | bool | asset.Item | float64
string | []string | bool | asset.Item
}

type getOneArgGen[R getOneArgResp, P getOneArgParam] func(context.Context, P) (R, error)
Expand Down
Loading

0 comments on commit d1529aa

Please sign in to comment.