mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 23:16:45 +00:00
kucoin: fix spot order unmarshal bug (#1380)
* kucoin: fix unmarshal bug * kucoin: Add time in force handling * kucoin: fix test * thrasher: nits * kucoin_test: shift skip check down for coverage, rm market testing, change buy price to reduce chance of instant match * kucoin: fix nits and force usage of uuid to rm conflicts --------- Co-authored-by: shazbert <ryan.oharareid@thrasher.io>
This commit is contained in:
@@ -815,6 +815,7 @@ func (ku *Kucoin) GetServiceStatus(ctx context.Context) (*ServiceStatus, error)
|
||||
// Note: use this only for SPOT trades
|
||||
func (ku *Kucoin) PostOrder(ctx context.Context, arg *SpotOrderParam) (string, error) {
|
||||
if arg.ClientOrderID == "" {
|
||||
// NOTE: 128 bit max length character string. UUID recommended.
|
||||
return "", errInvalidClientOrderID
|
||||
}
|
||||
if arg.Side == "" {
|
||||
@@ -841,11 +842,13 @@ func (ku *Kucoin) PostOrder(ctx context.Context, arg *SpotOrderParam) (string, e
|
||||
default:
|
||||
return "", fmt.Errorf("%w %s", order.ErrTypeIsInvalid, arg.OrderType)
|
||||
}
|
||||
resp := struct {
|
||||
OrderID string `json:"orderId"`
|
||||
var resp struct {
|
||||
Data struct {
|
||||
OrderID string `json:"orderId"`
|
||||
} `json:"data"`
|
||||
Error
|
||||
}{}
|
||||
return resp.OrderID, ku.SendAuthHTTPRequest(ctx, exchange.RestSpot, placeOrderEPL, http.MethodPost, kucoinPostOrder, &arg, &resp)
|
||||
}
|
||||
return resp.Data.OrderID, ku.SendAuthHTTPRequest(ctx, exchange.RestSpot, placeOrderEPL, http.MethodPost, kucoinPostOrder, &arg, &resp)
|
||||
}
|
||||
|
||||
// PostMarginOrder used to place two types of margin orders: limit and market
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
@@ -563,7 +564,6 @@ func TestGetServiceStatus(t *testing.T) {
|
||||
|
||||
func TestPostOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
|
||||
|
||||
// default order type is limit
|
||||
_, err := ku.PostOrder(context.Background(), &SpotOrderParam{
|
||||
@@ -571,43 +571,46 @@ func TestPostOrder(t *testing.T) {
|
||||
if !errors.Is(err, errInvalidClientOrderID) {
|
||||
t.Errorf("PostOrder() expected %v, but found %v", errInvalidClientOrderID, err)
|
||||
}
|
||||
|
||||
customID, err := uuid.NewV4()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = ku.PostOrder(context.Background(), &SpotOrderParam{
|
||||
ClientOrderID: "5bd6e9286d99522a52e458de", Symbol: spotTradablePair,
|
||||
ClientOrderID: customID.String(), Symbol: spotTradablePair,
|
||||
OrderType: ""})
|
||||
if !errors.Is(err, order.ErrSideIsInvalid) {
|
||||
t.Errorf("PostOrder() expected %v, but found %v", order.ErrSideIsInvalid, err)
|
||||
}
|
||||
_, err = ku.PostOrder(context.Background(), &SpotOrderParam{
|
||||
ClientOrderID: "5bd6e9286d99522a52e458de", Symbol: currency.EMPTYPAIR,
|
||||
ClientOrderID: customID.String(), Symbol: currency.EMPTYPAIR,
|
||||
Size: 0.1, Side: "buy", Price: 234565})
|
||||
if !errors.Is(err, currency.ErrCurrencyPairEmpty) {
|
||||
t.Errorf("PostOrder() expected %v, but found %v", currency.ErrCurrencyPairEmpty, err)
|
||||
}
|
||||
_, err = ku.PostOrder(context.Background(), &SpotOrderParam{
|
||||
ClientOrderID: "5bd6e9286d99522a52e458de", Side: "buy",
|
||||
ClientOrderID: customID.String(), Side: "buy",
|
||||
Symbol: spotTradablePair,
|
||||
OrderType: "limit", Size: 0.1})
|
||||
if !errors.Is(err, errInvalidPrice) {
|
||||
t.Errorf("PostOrder() expected %v, but found %v", errInvalidPrice, err)
|
||||
}
|
||||
_, err = ku.PostOrder(context.Background(), &SpotOrderParam{
|
||||
ClientOrderID: "5bd6e9286d99522a52e458de", Symbol: spotTradablePair, Side: "buy",
|
||||
ClientOrderID: customID.String(), Symbol: spotTradablePair, Side: "buy",
|
||||
OrderType: "limit", Price: 234565})
|
||||
if !errors.Is(err, errInvalidSize) {
|
||||
t.Errorf("PostOrder() expected %v, but found %v", errInvalidSize, err)
|
||||
}
|
||||
_, err = ku.PostOrder(context.Background(), &SpotOrderParam{
|
||||
ClientOrderID: "5bd6e9286d99522a52e458de", Side: "buy",
|
||||
Symbol: spotTradablePair, OrderType: "limit", Size: 0.1, Price: 234565})
|
||||
if err != nil {
|
||||
t.Error("PostOrder() error", err)
|
||||
}
|
||||
|
||||
// market order
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku, canManipulateRealOrders)
|
||||
_, err = ku.PostOrder(context.Background(), &SpotOrderParam{
|
||||
ClientOrderID: "5bd6e9286d99522a52e458de", Side: "buy",
|
||||
Symbol: spotTradablePair,
|
||||
OrderType: "market", Remark: "remark", Size: 0.1})
|
||||
ClientOrderID: customID.String(),
|
||||
Side: "buy",
|
||||
Symbol: spotTradablePair,
|
||||
OrderType: "limit",
|
||||
Size: 0.005,
|
||||
Price: 1000})
|
||||
if err != nil {
|
||||
t.Error("PostOrder() error", err)
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ var (
|
||||
errMissingOrderbookSequence = errors.New("missing orderbook sequence")
|
||||
errSizeOrFundIsRequired = errors.New("at least one required among size and funds")
|
||||
errInvalidLeverage = errors.New("invalid leverage value")
|
||||
errInvalidClientOrderID = errors.New("invalid client order ID")
|
||||
errInvalidClientOrderID = errors.New("no client order ID supplied, this endpoint requires a UUID or similar string")
|
||||
|
||||
subAccountRegExp = regexp.MustCompile("^[a-zA-Z0-9]{7-32}$")
|
||||
subAccountPassphraseRegExp = regexp.MustCompile("^[a-zA-Z0-9]{7-24}$")
|
||||
|
||||
@@ -761,13 +761,29 @@ func (ku *Kucoin) SubmitOrder(ctx context.Context, s *order.Submit) (*order.Subm
|
||||
}
|
||||
return s.DeriveSubmitResponse(o)
|
||||
case asset.Spot:
|
||||
if s.ClientID != "" && s.ClientOrderID == "" {
|
||||
s.ClientOrderID = s.ClientID
|
||||
timeInForce := ""
|
||||
if s.Type == order.Limit {
|
||||
switch {
|
||||
case s.FillOrKill:
|
||||
timeInForce = "FOK"
|
||||
case s.ImmediateOrCancel:
|
||||
timeInForce = "IOC"
|
||||
case s.PostOnly:
|
||||
default:
|
||||
timeInForce = "GTC"
|
||||
}
|
||||
}
|
||||
o, err := ku.PostOrder(ctx, &SpotOrderParam{
|
||||
ClientOrderID: s.ClientOrderID, Side: sideString,
|
||||
Symbol: s.Pair, OrderType: s.Type.Lower(), Size: s.Amount,
|
||||
Price: s.Price, PostOnly: s.PostOnly, Hidden: s.Hidden})
|
||||
ClientOrderID: s.ClientOrderID,
|
||||
Side: sideString,
|
||||
Symbol: s.Pair,
|
||||
OrderType: s.Type.Lower(),
|
||||
Size: s.Amount,
|
||||
Price: s.Price,
|
||||
PostOnly: s.PostOnly,
|
||||
Hidden: s.Hidden,
|
||||
TimeInForce: timeInForce,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1936,7 +1952,7 @@ func (ku *Kucoin) UpdateOrderExecutionLimits(ctx context.Context, a asset.Item)
|
||||
continue
|
||||
}
|
||||
pair, enabled, err := ku.MatchSymbolCheckEnabled(symbols[x].Symbol, a, true)
|
||||
if err != nil {
|
||||
if err != nil && !errors.Is(err, currency.ErrPairNotFound) {
|
||||
return err
|
||||
}
|
||||
if !enabled {
|
||||
@@ -1962,7 +1978,7 @@ func (ku *Kucoin) UpdateOrderExecutionLimits(ctx context.Context, a asset.Item)
|
||||
limits = make([]order.MinMaxLevel, 0, len(contract))
|
||||
for x := range contract {
|
||||
pair, enabled, err := ku.MatchSymbolCheckEnabled(contract[x].Symbol, a, false)
|
||||
if err != nil {
|
||||
if err != nil && !errors.Is(err, currency.ErrPairNotFound) {
|
||||
return err
|
||||
}
|
||||
if !enabled {
|
||||
|
||||
Reference in New Issue
Block a user