mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-06-03 23:16:53 +00:00
protocol/order: adds additional fields for trading requirements (#1552)
* Add in initial handling for quote/base currency deployment requirements * include client order ID checking * glorious: suggestions * spell and fix * linter/context/test * rework tests and order side specific requirements * linter * mend panic at the disco * mending more panics at the disco * anudda fix brudda * glorious: NITTTTTT BOOOOOMB * leftover things and stuff * whoops * tie in gateio * glorious: nit fixes life and everything. * thrasher: nits --------- Co-authored-by: Ryan O'Hara-Reid <ryan.oharareid@thrasher.io>
This commit is contained in:
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/validate"
|
||||
)
|
||||
|
||||
@@ -24,9 +25,12 @@ func TestSubmit_Validate(t *testing.T) {
|
||||
t.Parallel()
|
||||
testPair := currency.NewPair(currency.BTC, currency.LTC)
|
||||
tester := []struct {
|
||||
ExpectedErr error
|
||||
Submit *Submit
|
||||
ValidOpts validate.Checker
|
||||
ExpectedErr error
|
||||
Submit *Submit
|
||||
ValidOpts validate.Checker
|
||||
HasToPurchaseWithQuoteAmountSet bool
|
||||
HasToSellWithBaseAmountSet bool
|
||||
RequiresID bool
|
||||
}{
|
||||
{
|
||||
ExpectedErr: ErrSubmissionIsNil,
|
||||
@@ -178,13 +182,72 @@ func TestSubmit_Validate(t *testing.T) {
|
||||
},
|
||||
ValidOpts: validate.Check(func() error { return nil }),
|
||||
}, // valid order!
|
||||
{
|
||||
ExpectedErr: ErrAmountMustBeSet,
|
||||
Submit: &Submit{
|
||||
Exchange: "test",
|
||||
Pair: testPair,
|
||||
Side: Buy,
|
||||
Type: Market,
|
||||
Amount: 1,
|
||||
AssetType: asset.Spot,
|
||||
},
|
||||
HasToPurchaseWithQuoteAmountSet: true,
|
||||
ValidOpts: validate.Check(func() error { return nil }),
|
||||
},
|
||||
{
|
||||
ExpectedErr: ErrAmountMustBeSet,
|
||||
Submit: &Submit{
|
||||
Exchange: "test",
|
||||
Pair: testPair,
|
||||
Side: Sell,
|
||||
Type: Market,
|
||||
QuoteAmount: 1,
|
||||
AssetType: asset.Spot,
|
||||
},
|
||||
HasToSellWithBaseAmountSet: true,
|
||||
ValidOpts: validate.Check(func() error { return nil }),
|
||||
},
|
||||
{
|
||||
ExpectedErr: ErrClientOrderIDMustBeSet,
|
||||
Submit: &Submit{
|
||||
Exchange: "test",
|
||||
Pair: testPair,
|
||||
Side: Buy,
|
||||
Type: Market,
|
||||
Amount: 1,
|
||||
AssetType: asset.Spot,
|
||||
},
|
||||
RequiresID: true,
|
||||
ValidOpts: validate.Check(func() error { return nil }),
|
||||
},
|
||||
{
|
||||
ExpectedErr: nil,
|
||||
Submit: &Submit{
|
||||
Exchange: "test",
|
||||
Pair: testPair,
|
||||
Side: Buy,
|
||||
Type: Market,
|
||||
Amount: 1,
|
||||
AssetType: asset.Spot,
|
||||
ClientOrderID: "69420",
|
||||
},
|
||||
RequiresID: true,
|
||||
ValidOpts: validate.Check(func() error { return nil }),
|
||||
},
|
||||
}
|
||||
|
||||
for x := range tester {
|
||||
err := tester[x].Submit.Validate(tester[x].ValidOpts)
|
||||
if !errors.Is(err, tester[x].ExpectedErr) {
|
||||
t.Fatalf("Unexpected result. %d Got: %v, want: %v", x+1, err, tester[x].ExpectedErr)
|
||||
}
|
||||
for x, tc := range tester {
|
||||
t.Run(strconv.Itoa(x), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
requirements := protocol.TradingRequirements{
|
||||
SpotMarketOrderAmountPurchaseQuotationOnly: tc.HasToPurchaseWithQuoteAmountSet,
|
||||
SpotMarketOrderAmountSellBaseOnly: tc.HasToSellWithBaseAmountSet,
|
||||
ClientOrderID: tc.RequiresID,
|
||||
}
|
||||
err := tc.Submit.Validate(requirements, tc.ValidOpts)
|
||||
assert.ErrorIs(t, err, tc.ExpectedErr)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/validate"
|
||||
"github.com/thrasher-corp/gocryptotrader/log"
|
||||
"golang.org/x/text/cases"
|
||||
@@ -30,16 +31,17 @@ const (
|
||||
notPlaced = InsufficientBalance | MarketUnavailable | Rejected
|
||||
)
|
||||
|
||||
// Public error vars for order package
|
||||
var (
|
||||
// ErrUnableToPlaceOrder defines an error when an order submission has
|
||||
// failed.
|
||||
ErrUnableToPlaceOrder = errors.New("order not placed")
|
||||
// ErrOrderNotFound is returned when no order is found
|
||||
ErrOrderNotFound = errors.New("order not found")
|
||||
|
||||
// ErrUnknownPriceType returned when price type is unknown
|
||||
ErrUnknownPriceType = errors.New("unknown price type")
|
||||
ErrUnableToPlaceOrder = errors.New("order not placed")
|
||||
ErrOrderNotFound = errors.New("order not found")
|
||||
ErrUnknownPriceType = errors.New("unknown price type")
|
||||
ErrAmountMustBeSet = errors.New("amount must be set")
|
||||
ErrClientOrderIDMustBeSet = errors.New("client order ID must be set")
|
||||
ErrUnknownSubmissionAmountType = errors.New("unknown submission amount type")
|
||||
)
|
||||
|
||||
var (
|
||||
errTimeInForceConflict = errors.New("multiple time in force options applied")
|
||||
errUnrecognisedOrderType = errors.New("unrecognised order type")
|
||||
errUnrecognisedOrderStatus = errors.New("unrecognised order status")
|
||||
@@ -56,7 +58,7 @@ func IsValidOrderSubmissionSide(s Side) bool {
|
||||
}
|
||||
|
||||
// Validate checks the supplied data and returns whether it's valid
|
||||
func (s *Submit) Validate(opt ...validate.Checker) error {
|
||||
func (s *Submit) Validate(requirements protocol.TradingRequirements, opt ...validate.Checker) error {
|
||||
if s == nil {
|
||||
return ErrSubmissionIsNil
|
||||
}
|
||||
@@ -105,6 +107,18 @@ func (s *Submit) Validate(opt ...validate.Checker) error {
|
||||
return ErrPriceMustBeSetIfLimitOrder
|
||||
}
|
||||
|
||||
if requirements.ClientOrderID && s.ClientOrderID == "" {
|
||||
return fmt.Errorf("submit validation error %w, client order ID must be set to satisfy submission requirements", ErrClientOrderIDMustBeSet)
|
||||
}
|
||||
|
||||
if requirements.SpotMarketOrderAmountPurchaseQuotationOnly && s.QuoteAmount == 0 && s.Type == Market && s.AssetType == asset.Spot && s.Side.IsLong() {
|
||||
return fmt.Errorf("submit validation error %w, quote amount to be sold must be set to 'QuoteAmount' field to satisfy trading requirements", ErrAmountMustBeSet)
|
||||
}
|
||||
|
||||
if requirements.SpotMarketOrderAmountSellBaseOnly && s.Amount == 0 && s.Type == Market && s.AssetType == asset.Spot && s.Side.IsShort() {
|
||||
return fmt.Errorf("submit validation error %w, base amount being sold must be set to 'Amount' field to satisfy trading requirements", ErrAmountMustBeSet)
|
||||
}
|
||||
|
||||
for _, o := range opt {
|
||||
err := o.Check()
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user