Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 18 additions & 18 deletions exchanges/gateio/gateio.go
Original file line number Diff line number Diff line change
Expand Up @@ -729,7 +729,7 @@ func (e *Exchange) CancelSingleSpotOrder(ctx context.Context, orderID, currencyP
}

// GetMySpotTradingHistory retrieves personal trading history
func (e *Exchange) GetMySpotTradingHistory(ctx context.Context, p currency.Pair, orderID string, page, limit uint64, crossMargin bool, from, to time.Time) ([]SpotPersonalTradeHistory, error) {
func (e *Exchange) GetMySpotTradingHistory(ctx context.Context, p currency.Pair, orderID string, page, limit uint64, from, to time.Time) ([]SpotPersonalTradeHistory, error) {
params := url.Values{}
if p.IsPopulated() {
params.Set("currency_pair", p.String())
Expand All @@ -743,9 +743,6 @@ func (e *Exchange) GetMySpotTradingHistory(ctx context.Context, p currency.Pair,
if page > 0 {
params.Set("page", strconv.FormatUint(page, 10))
}
if crossMargin {
params.Set("account", asset.CrossMargin.String())
}
if !from.IsZero() {
params.Set("from", strconv.FormatInt(from.Unix(), 10))
}
Expand All @@ -767,17 +764,6 @@ func (e *Exchange) GetServerTime(ctx context.Context, _ asset.Item) (time.Time,
return resp.ServerTime.Time(), nil
}

// CountdownCancelorders Countdown cancel orders
// When the timeout set by the user is reached, if there is no cancel or set a new countdown, the related pending orders will be automatically cancelled.
// This endpoint can be called repeatedly to set a new countdown or cancel the countdown.
func (e *Exchange) CountdownCancelorders(ctx context.Context, arg CountdownCancelOrderParam) (*TriggerTimeResponse, error) {
if arg.Timeout <= 0 {
return nil, errInvalidCountdown
}
var response *TriggerTimeResponse
return response, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, spotCountdownCancelEPL, http.MethodPost, gateioSpotAllCountdown, nil, &arg, &response)
}

// CreatePriceTriggeredOrder create a price-triggered order
func (e *Exchange) CreatePriceTriggeredOrder(ctx context.Context, arg *PriceTriggeredOrderParam) (*OrderID, error) {
if arg == nil {
Expand Down Expand Up @@ -2432,16 +2418,30 @@ func (e *Exchange) GetFuturesLiquidationHistory(ctx context.Context, settle curr
return response, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, perpetualLiquidationHistoryEPL, http.MethodGet, futuresPath+settle.Item.Lower+"/liquidates", params, nil, &response)
}

// CountdownCancelOrders represents a trigger time response
func (e *Exchange) CountdownCancelOrders(ctx context.Context, settle currency.Code, arg CountdownParams) (*TriggerTimeResponse, error) {
// CountdownCancelFuturesOrders represents a trigger time response
func (e *Exchange) CountdownCancelFuturesOrders(ctx context.Context, settle currency.Code, arg CountdownParams) (*TriggerTimeResponse, error) {
if settle.IsEmpty() {
return nil, errEmptyOrInvalidSettlementCurrency
}
if arg.Timeout < 0 {
return nil, errInvalidTimeout
}
return e.sendCountdownCancelOrdersRequest(ctx, perpetualCancelTriggerOrdersEPL, futuresPath+settle.Item.Lower+"/countdown_cancel_all", &arg)
}

// CountdownCancelSpotOrders Countdown cancel orders
// When the timeout set by the user is reached, if there is no cancel or set a new countdown, the related pending orders will be automatically cancelled.
// This endpoint can be called repeatedly to set a new countdown or cancel the countdown.
func (e *Exchange) CountdownCancelSpotOrders(ctx context.Context, arg CountdownCancelOrderParam) (*TriggerTimeResponse, error) {
if arg.Timeout <= 0 {
return nil, errInvalidCountdown
}
return e.sendCountdownCancelOrdersRequest(ctx, spotCountdownCancelEPL, gateioSpotAllCountdown, &arg)
}

func (e *Exchange) sendCountdownCancelOrdersRequest(ctx context.Context, epl request.EndpointLimit, path string, arg any) (*TriggerTimeResponse, error) {
var response *TriggerTimeResponse
return response, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, perpetualCancelTriggerOrdersEPL, http.MethodPost, futuresPath+settle.Item.Lower+"/countdown_cancel_all", nil, &arg, &response)
return response, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, epl, http.MethodPost, path, nil, arg, &response)
}

// CreatePriceTriggeredFuturesOrder create a price-triggered order
Expand Down
131 changes: 118 additions & 13 deletions exchanges/gateio/gateio_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ func TestCancelSingleSpotOrder(t *testing.T) {
func TestGetMySpotTradingHistory(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, e)
_, err := e.GetMySpotTradingHistory(t.Context(), currency.Pair{Base: currency.BTC, Quote: currency.USDT, Delimiter: currency.UnderscoreDelimiter}, "", 0, 0, false, time.Time{}, time.Time{})
_, err := e.GetMySpotTradingHistory(t.Context(), currency.Pair{Base: currency.BTC, Quote: currency.USDT, Delimiter: currency.UnderscoreDelimiter}, "", 0, 0, time.Time{}, time.Time{})
require.NoError(t, err)
}

Expand All @@ -378,10 +378,10 @@ func TestGetServerTime(t *testing.T) {
}
}

func TestCountdownCancelorder(t *testing.T) {
func TestCountdownCancelSpotOrders(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wasn't your doing but I noticed that we're missing non-auth error paths we can get test coverage for (timeout <= 0)

if _, err := e.CountdownCancelorders(t.Context(), CountdownCancelOrderParam{
if _, err := e.CountdownCancelSpotOrders(t.Context(), CountdownCancelOrderParam{
Timeout: 10,
CurrencyPair: currency.Pair{Base: currency.BTC, Quote: currency.ETH, Delimiter: currency.UnderscoreDelimiter},
}); err != nil {
Expand Down Expand Up @@ -1291,13 +1291,13 @@ func TestGetFuturesLiquidationHistory(t *testing.T) {
assert.NoError(t, err, "GetFuturesLiquidationHistory should not error")
}

func TestCountdownCancelOrders(t *testing.T) {
func TestCountdownCancelFuturesOrders(t *testing.T) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for here with the settle and timeout params

t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders)
_, err := e.CountdownCancelOrders(t.Context(), currency.BTC, CountdownParams{
_, err := e.CountdownCancelFuturesOrders(t.Context(), currency.BTC, CountdownParams{
Timeout: 8,
})
assert.NoError(t, err, "CountdownCancelOrders should not error")
assert.NoError(t, err, "CountdownCancelFuturesOrders should not error")
}

func TestCreatePriceTriggeredFuturesOrder(t *testing.T) {
Expand Down Expand Up @@ -1891,20 +1891,125 @@ func TestGetActiveOrders(t *testing.T) {
}

func TestGetOrderHistory(t *testing.T) {
sharedtestvalues.SkipTestIfCredentialsUnset(t, e)
t.Parallel()
testexch.UpdatePairsOnce(t, e)
type testCase struct {
name string
requiresAuth bool
request order.MultiOrderRequest
expectedErr error
}

testCases := make([]testCase, 0, len(e.GetAssetTypes(false))*2+1)
for _, a := range e.GetAssetTypes(false) {
enabledPairs := getPairs(t, a)
if len(enabledPairs) > 4 {
enabledPairs = enabledPairs[:4]
}
Comment on lines 1905 to 1908
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
enabledPairs := getPairs(t, a)
if len(enabledPairs) > 4 {
enabledPairs = enabledPairs[:4]
}
enabledPairs := getPairs(t, a)
enabledPairs = enabledPairs[:min(4, len(enabledPairs))]

multiOrderRequest := order.MultiOrderRequest{

withPairs := testCase{
name: a.String() + "/with_pairs",
requiresAuth: true,
request: order.MultiOrderRequest{
Type: order.AnyType,
Side: order.Buy,
Pairs: enabledPairs,
AssetType: a,
},
}
testCases = append(testCases, withPairs)

noPairs := testCase{
name: a.String() + "/without_pairs",
requiresAuth: true,
request: order.MultiOrderRequest{
Type: order.AnyType,
Side: order.Buy,
AssetType: a,
},
}
if a == asset.Options {
noPairs.requiresAuth = false
noPairs.expectedErr = currency.ErrCurrencyPairsEmpty
}
testCases = append(testCases, noPairs)
}

testCases = append(testCases, testCase{
name: "unsupported/default_case_binary",
requiresAuth: false,
request: order.MultiOrderRequest{
Type: order.AnyType,
Side: order.Buy,
Pairs: enabledPairs,
AssetType: a,
}
_, err := e.GetOrderHistory(t.Context(), &multiOrderRequest)
assert.NoErrorf(t, err, "GetOrderHistory should not error for %s", a)
AssetType: asset.Binary,
},
expectedErr: asset.ErrNotSupported,
})

for i := range testCases {
t.Run(testCases[i].name, func(t *testing.T) {
t.Parallel()
if testCases[i].requiresAuth {
sharedtestvalues.SkipTestIfCredentialsUnset(t, e)
}
orders, err := e.GetOrderHistory(t.Context(), &testCases[i].request)
if testCases[i].expectedErr != nil {
assert.ErrorIs(t, err, testCases[i].expectedErr)
return
}
assert.NoError(t, err)
for j := range orders {
assert.Equal(t, testCases[i].request.AssetType, orders[j].AssetType)
assert.Equal(t, e.Name, orders[j].Exchange)
assert.True(t, orders[j].Pair.IsPopulated(), "pair should be populated for order history response")
}
})
}
}

func TestGetOrderHistoryRequestImmutability(t *testing.T) {
t.Parallel()
testexch.UpdatePairsOnce(t, e)
sharedtestvalues.SkipTestIfCredentialsUnset(t, e)
enabledPairs := getPairs(t, asset.Spot)
if len(enabledPairs) > 2 {
enabledPairs = enabledPairs[:2]
}
Comment on lines +1974 to +1977
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
enabledPairs := getPairs(t, asset.Spot)
if len(enabledPairs) > 2 {
enabledPairs = enabledPairs[:2]
}
enabledPairs := getPairs(t, asset.Spot)
enabledPairs = enabledPairs[:min(2, len(enabledPairs))]


type testCase struct {
name string
request order.MultiOrderRequest
}

testCases := []testCase{
{
name: "nil_pairs",
request: order.MultiOrderRequest{
Type: order.AnyType,
Side: order.Buy,
AssetType: asset.Spot,
},
},
{
name: "provided_pairs",
request: order.MultiOrderRequest{
Type: order.AnyType,
Side: order.Buy,
Pairs: append(currency.Pairs(nil), enabledPairs...),
AssetType: asset.Spot,
},
},
}

for i := range testCases {
tc := testCases[i]
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
expectedPairs := append(currency.Pairs(nil), tc.request.Pairs...)
_, err := e.GetOrderHistory(t.Context(), &tc.request)
assert.NoError(t, err)
assert.Equal(t, expectedPairs, tc.request.Pairs)
})
}
Comment on lines +1979 to 2013
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
type testCase struct {
name string
request order.MultiOrderRequest
}
testCases := []testCase{
{
name: "nil_pairs",
request: order.MultiOrderRequest{
Type: order.AnyType,
Side: order.Buy,
AssetType: asset.Spot,
},
},
{
name: "provided_pairs",
request: order.MultiOrderRequest{
Type: order.AnyType,
Side: order.Buy,
Pairs: append(currency.Pairs(nil), enabledPairs...),
AssetType: asset.Spot,
},
},
}
for i := range testCases {
tc := testCases[i]
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
expectedPairs := append(currency.Pairs(nil), tc.request.Pairs...)
_, err := e.GetOrderHistory(t.Context(), &tc.request)
assert.NoError(t, err)
assert.Equal(t, expectedPairs, tc.request.Pairs)
})
}
for _, tc := range []struct {
Name string
request order.MultiOrderRequest
}{
{
Name: "nil_pairs",
request: order.MultiOrderRequest{
Type: order.AnyType,
Side: order.Buy,
AssetType: asset.Spot,
},
},
{
Name: "provided_pairs",
request: order.MultiOrderRequest{
Type: order.AnyType,
Side: order.Buy,
Pairs: slices.Clone(enabledPairs),
AssetType: asset.Spot,
},
},
} {
t.Run(tc.Name, func(t *testing.T) {
t.Parallel()
expectedPairs := slices.Clone(tc.request.Pairs)
_, err := e.GetOrderHistory(t.Context(), &tc.request)
require.NoError(t, err)
assert.Equal(t, expectedPairs, tc.request.Pairs)
})
}
}

}

Expand Down
28 changes: 16 additions & 12 deletions exchanges/gateio/gateio_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -1519,18 +1519,22 @@ type CancelOrderByIDResponse struct {

// SpotPersonalTradeHistory represents personal trading history.
type SpotPersonalTradeHistory struct {
TradeID string `json:"id"`
CreateTime types.Time `json:"create_time_ms"`
CurrencyPair string `json:"currency_pair"`
OrderID string `json:"order_id"`
Side string `json:"side"`
Role string `json:"role"`
Amount types.Number `json:"amount"`
Price types.Number `json:"price"`
Fee types.Number `json:"fee"`
FeeCurrency string `json:"fee_currency"`
PointFee string `json:"point_fee"`
GtFee string `json:"gt_fee"`
TradeID string `json:"id"`
CreateTime types.Time `json:"create_time_ms"`
CurrencyPair currency.Pair `json:"currency_pair"`
OrderID string `json:"order_id"`
Side string `json:"side"`
Role string `json:"role"`
Amount types.Number `json:"amount"`
Price types.Number `json:"price"`
Fee types.Number `json:"fee"`
FeeCurrency currency.Code `json:"fee_currency"`
PointFee types.Number `json:"point_fee"`
GtFee types.Number `json:"gt_fee"`
AmendText string `json:"amend_text"`
SequenceID string `json:"sequence_id"`
Text string `json:"text"`
Deal types.Number `json:"deal"`
}

// CountdownCancelOrderParam represents countdown cancel order params
Expand Down
Loading
Loading