code.vegaprotocol.io/vega@v0.79.0/commands/order_amendment_test.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package commands_test
    17  
    18  import (
    19  	"errors"
    20  	"testing"
    21  	"time"
    22  
    23  	"code.vegaprotocol.io/vega/commands"
    24  	"code.vegaprotocol.io/vega/libs/ptr"
    25  	proto "code.vegaprotocol.io/vega/protos/vega"
    26  	commandspb "code.vegaprotocol.io/vega/protos/vega/commands/v1"
    27  
    28  	"github.com/stretchr/testify/assert"
    29  	"github.com/stretchr/testify/require"
    30  )
    31  
    32  func TestCheckOrderAmendment(t *testing.T) {
    33  	t.Run("Submitting a nil command fails", testNilOrderAmendmentFails)
    34  	t.Run("amend order price - success", testAmendOrderJustPriceSuccess)
    35  	t.Run("amend order reduce size delta - success", testAmendOrderJustReduceSizeDeltaSuccess)
    36  	t.Run("amend order increase size delta - success", testAmendOrderJustIncreaseSizeDeltaSuccess)
    37  	t.Run("amend order setting size delta and size - fails", testAmendOrderSettingSizeDeltaAndSizeFails)
    38  	t.Run("amend order update size - success", testAmendOrderJustUpdateSizeSuccess)
    39  	t.Run("amend order expiry - success", testAmendOrderJustExpirySuccess)
    40  	t.Run("amend order tif - success", testAmendOrderJustTIFSuccess)
    41  	t.Run("amend order expiry before creation time - success", testAmendOrderPastExpiry)
    42  	t.Run("amend order empty - fail", testAmendOrderEmptyFail)
    43  	t.Run("amend order empty - fail", testAmendEmptyFail)
    44  	t.Run("amend order invalid expiry type - fail", testAmendOrderInvalidExpiryFail)
    45  	t.Run("amend order tif to GFA - fail", testAmendOrderToGFA)
    46  	t.Run("amend order tif to GFN - fail", testAmendOrderToGFN)
    47  	t.Run("amend order pegged_offset", testAmendOrderPeggedOffset)
    48  }
    49  
    50  func testNilOrderAmendmentFails(t *testing.T) {
    51  	err := checkOrderAmendment(nil)
    52  
    53  	assert.Contains(t, err.Get("order_amendment"), commands.ErrIsRequired)
    54  }
    55  
    56  func testAmendOrderJustPriceSuccess(t *testing.T) {
    57  	arg := &commandspb.OrderAmendment{
    58  		OrderId:  "08dce6ebf50e34fedee32860b6f459824e4b834762ea66a96504fdc57a9c4741",
    59  		MarketId: "08dce6ebf50e34fedee32860b6f459824e4b834762ea66a96504fdc57a9c4741",
    60  		Price:    ptr.From("1000"),
    61  	}
    62  	err := checkOrderAmendment(arg)
    63  
    64  	assert.NoError(t, err.ErrorOrNil())
    65  }
    66  
    67  func testAmendOrderJustReduceSizeDeltaSuccess(t *testing.T) {
    68  	arg := &commandspb.OrderAmendment{
    69  		OrderId:   "08dce6ebf50e34fedee32860b6f459824e4b834762ea66a96504fdc57a9c4741",
    70  		MarketId:  "08dce6ebf50e34fedee32860b6f459824e4b834762ea66a96504fdc57a9c4741",
    71  		SizeDelta: -10,
    72  	}
    73  	err := checkOrderAmendment(arg)
    74  	assert.NoError(t, err.ErrorOrNil())
    75  }
    76  
    77  func testAmendOrderJustIncreaseSizeDeltaSuccess(t *testing.T) {
    78  	arg := &commandspb.OrderAmendment{
    79  		OrderId:   "08dce6ebf50e34fedee32860b6f459824e4b834762ea66a96504fdc57a9c4741",
    80  		MarketId:  "08dce6ebf50e34fedee32860b6f459824e4b834762ea66a96504fdc57a9c4741",
    81  		SizeDelta: 10,
    82  	}
    83  	err := checkOrderAmendment(arg)
    84  	assert.NoError(t, err.ErrorOrNil())
    85  }
    86  
    87  func testAmendOrderSettingSizeDeltaAndSizeFails(t *testing.T) {
    88  	arg := &commandspb.OrderAmendment{
    89  		OrderId:   "08dce6ebf50e34fedee32860b6f459824e4b834762ea66a96504fdc57a9c4741",
    90  		MarketId:  "08dce6ebf50e34fedee32860b6f459824e4b834762ea66a96504fdc57a9c4741",
    91  		SizeDelta: 10,
    92  		Size:      ptr.From(uint64(10)),
    93  	}
    94  	err := checkOrderAmendment(arg)
    95  	foundErrors := err.Get("order_amendment.size_delta")
    96  	require.Len(t, foundErrors, 1, "expected 1 error on size_delta")
    97  	assert.ErrorIs(t, foundErrors[0], commands.ErrMustBeSetTo0IfSizeSet)
    98  }
    99  
   100  func testAmendOrderJustUpdateSizeSuccess(t *testing.T) {
   101  	arg := &commandspb.OrderAmendment{
   102  		OrderId:  "08dce6ebf50e34fedee32860b6f459824e4b834762ea66a96504fdc57a9c4741",
   103  		MarketId: "08dce6ebf50e34fedee32860b6f459824e4b834762ea66a96504fdc57a9c4741",
   104  		Size:     ptr.From(uint64(10)),
   105  	}
   106  	err := checkOrderAmendment(arg)
   107  	assert.NoError(t, err.ErrorOrNil())
   108  }
   109  
   110  func testAmendOrderJustExpirySuccess(t *testing.T) {
   111  	now := time.Now()
   112  	expires := now.Add(-2 * time.Hour)
   113  	arg := &commandspb.OrderAmendment{
   114  		OrderId:   "08dce6ebf50e34fedee32860b6f459824e4b834762ea66a96504fdc57a9c4741",
   115  		MarketId:  "08dce6ebf50e34fedee32860b6f459824e4b834762ea66a96504fdc57a9c4741",
   116  		ExpiresAt: ptr.From(expires.UnixNano()),
   117  	}
   118  	err := checkOrderAmendment(arg)
   119  	assert.NoError(t, err.ErrorOrNil())
   120  }
   121  
   122  func testAmendOrderJustTIFSuccess(t *testing.T) {
   123  	arg := &commandspb.OrderAmendment{
   124  		OrderId:     "08dce6ebf50e34fedee32860b6f459824e4b834762ea66a96504fdc57a9c4741",
   125  		MarketId:    "08dce6ebf50e34fedee32860b6f459824e4b834762ea66a96504fdc57a9c4741",
   126  		TimeInForce: proto.Order_TIME_IN_FORCE_GTC,
   127  	}
   128  	err := checkOrderAmendment(arg)
   129  	assert.NoError(t, err.ErrorOrNil())
   130  }
   131  
   132  func testAmendOrderEmptyFail(t *testing.T) {
   133  	arg := &commandspb.OrderAmendment{}
   134  	err := checkOrderAmendment(arg)
   135  	assert.Error(t, err)
   136  
   137  	arg2 := &commandspb.OrderAmendment{
   138  		OrderId:  "08dce6ebf50e34fedee32860b6f459824e4b834762ea66a96504fdc57a9c4741",
   139  		MarketId: "08dce6ebf50e34fedee32860b6f459824e4b834762ea66a96504fdc57a9c4741",
   140  	}
   141  	err = checkOrderAmendment(arg2)
   142  	assert.Error(t, err)
   143  }
   144  
   145  func testAmendEmptyFail(t *testing.T) {
   146  	arg := &commandspb.OrderAmendment{
   147  		OrderId:  "08dce6ebf50e34fedee32860b6f459824e4b834762ea66a96504fdc57a9c4741",
   148  		MarketId: "08dce6ebf50e34fedee32860b6f459824e4b834762ea66a96504fdc57a9c4741",
   149  	}
   150  	err := checkOrderAmendment(arg)
   151  	assert.Error(t, err)
   152  }
   153  
   154  func testAmendOrderInvalidExpiryFail(t *testing.T) {
   155  	arg := &commandspb.OrderAmendment{
   156  		OrderId:     "08dce6ebf50e34fedee32860b6f459824e4b834762ea66a96504fdc57a9c4741",
   157  		TimeInForce: proto.Order_TIME_IN_FORCE_GTC,
   158  		ExpiresAt:   ptr.From(int64(10)),
   159  	}
   160  	err := checkOrderAmendment(arg)
   161  	assert.Error(t, err)
   162  
   163  	arg.TimeInForce = proto.Order_TIME_IN_FORCE_FOK
   164  	err = checkOrderAmendment(arg)
   165  	assert.Error(t, err)
   166  
   167  	arg.TimeInForce = proto.Order_TIME_IN_FORCE_IOC
   168  	err = checkOrderAmendment(arg)
   169  	assert.Error(t, err)
   170  }
   171  
   172  func testAmendOrderPeggedOffset(t *testing.T) {
   173  	arg := &commandspb.OrderAmendment{
   174  		OrderId:      "08dce6ebf50e34fedee32860b6f459824e4b834762ea66a96504fdc57a9c4741",
   175  		MarketId:     "08dce6ebf50e34fedee32860b6f459824e4b834762ea66a96504fdc57a9c4741",
   176  		PeggedOffset: "-1789",
   177  		TimeInForce:  proto.Order_TIME_IN_FORCE_GTC, // just here to test the case with empty pegged offset
   178  	}
   179  
   180  	err := checkOrderAmendment(arg)
   181  	assert.Error(t, err.ErrorOrNil())
   182  
   183  	arg.PeggedOffset = ""
   184  	err = checkOrderAmendment(arg)
   185  	assert.NoError(t, err.ErrorOrNil())
   186  
   187  	arg.PeggedOffset = "1000"
   188  	err = checkOrderAmendment(arg)
   189  	assert.NoError(t, err.ErrorOrNil())
   190  }
   191  
   192  /*
   193   * Sending an old expiry date is OK and should not be rejected here.
   194   * The validation should take place inside the core.
   195   */
   196  func testAmendOrderPastExpiry(t *testing.T) {
   197  	arg := &commandspb.OrderAmendment{
   198  		OrderId:     "08dce6ebf50e34fedee32860b6f459824e4b834762ea66a96504fdc57a9c4741",
   199  		MarketId:    "08dce6ebf50e34fedee32860b6f459824e4b834762ea66a96504fdc57a9c4741",
   200  		TimeInForce: proto.Order_TIME_IN_FORCE_GTT,
   201  		ExpiresAt:   ptr.From(int64(10)),
   202  	}
   203  	err := checkOrderAmendment(arg)
   204  	assert.NoError(t, err.ErrorOrNil())
   205  }
   206  
   207  func testAmendOrderToGFN(t *testing.T) {
   208  	arg := &commandspb.OrderAmendment{
   209  		OrderId:     "08dce6ebf50e34fedee32860b6f459824e4b834762ea66a96504fdc57a9c4741",
   210  		TimeInForce: proto.Order_TIME_IN_FORCE_GFN,
   211  		ExpiresAt:   ptr.From(int64(10)),
   212  	}
   213  	err := checkOrderAmendment(arg)
   214  	assert.Error(t, err)
   215  }
   216  
   217  func testAmendOrderToGFA(t *testing.T) {
   218  	arg := &commandspb.OrderAmendment{
   219  		OrderId:     "08dce6ebf50e34fedee32860b6f459824e4b834762ea66a96504fdc57a9c4741",
   220  		TimeInForce: proto.Order_TIME_IN_FORCE_GFA,
   221  		ExpiresAt:   ptr.From(int64(10)),
   222  	}
   223  	err := checkOrderAmendment(arg)
   224  	assert.Error(t, err)
   225  }
   226  
   227  func checkOrderAmendment(cmd *commandspb.OrderAmendment) commands.Errors {
   228  	err := commands.CheckOrderAmendment(cmd)
   229  
   230  	var e commands.Errors
   231  	if ok := errors.As(err, &e); !ok {
   232  		return commands.NewErrors()
   233  	}
   234  
   235  	return e
   236  }