code.vegaprotocol.io/vega@v0.79.0/commands/stop_order_submission_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 22 "code.vegaprotocol.io/vega/commands" 23 "code.vegaprotocol.io/vega/libs/ptr" 24 "code.vegaprotocol.io/vega/protos/vega" 25 commandspb "code.vegaprotocol.io/vega/protos/vega/commands/v1" 26 27 "github.com/stretchr/testify/assert" 28 ) 29 30 func TestCheckStopOrdersStubmission(t *testing.T) { 31 cases := []struct { 32 submission commandspb.StopOrdersSubmission 33 errStr string 34 }{ 35 { 36 submission: commandspb.StopOrdersSubmission{}, 37 errStr: "must have at least one of rises above or falls below", 38 }, 39 { 40 submission: commandspb.StopOrdersSubmission{ 41 RisesAbove: &commandspb.StopOrderSetup{}, 42 }, 43 errStr: "order_submission (is required), stop_orders_submission.rises_below.trigger (must have a stop order trigger)", 44 }, 45 { 46 submission: commandspb.StopOrdersSubmission{ 47 RisesAbove: &commandspb.StopOrderSetup{ 48 Trigger: &commandspb.StopOrderSetup_Price{ 49 Price: "", 50 }, 51 }, 52 }, 53 errStr: "order_submission (is required), stop_orders_submission.rises_below.trigger.price (is required)", 54 }, 55 { 56 submission: commandspb.StopOrdersSubmission{ 57 RisesAbove: &commandspb.StopOrderSetup{ 58 Trigger: &commandspb.StopOrderSetup_Price{ 59 Price: "-1", 60 }, 61 }, 62 }, 63 errStr: "order_submission (is required), stop_orders_submission.rises_below.trigger.price (must be positive)", 64 }, 65 { 66 submission: commandspb.StopOrdersSubmission{ 67 RisesAbove: &commandspb.StopOrderSetup{ 68 Trigger: &commandspb.StopOrderSetup_Price{ 69 Price: "asdsad", 70 }, 71 }, 72 }, 73 errStr: "order_submission (is required), stop_orders_submission.rises_below.trigger.price (not a valid integer)", 74 }, 75 { 76 submission: commandspb.StopOrdersSubmission{ 77 RisesAbove: &commandspb.StopOrderSetup{ 78 Trigger: &commandspb.StopOrderSetup_Price{ 79 Price: "100", 80 }, 81 }, 82 }, 83 errStr: "order_submission (is required)", 84 }, 85 { 86 submission: commandspb.StopOrdersSubmission{ 87 RisesAbove: &commandspb.StopOrderSetup{ 88 Trigger: &commandspb.StopOrderSetup_TrailingPercentOffset{ 89 TrailingPercentOffset: "", 90 }, 91 }, 92 }, 93 errStr: "order_submission (is required), stop_orders_submission.rises_below.trigger.trailing_percent_offset (is required)", 94 }, 95 { 96 submission: commandspb.StopOrdersSubmission{ 97 RisesAbove: &commandspb.StopOrderSetup{ 98 Trigger: &commandspb.StopOrderSetup_TrailingPercentOffset{ 99 TrailingPercentOffset: "0", 100 }, 101 }, 102 }, 103 errStr: "order_submission (is required), stop_orders_submission.rises_below.trigger.trailing_percent_offset (must be between 0 and 1)", 104 }, 105 { 106 submission: commandspb.StopOrdersSubmission{ 107 RisesAbove: &commandspb.StopOrderSetup{ 108 Trigger: &commandspb.StopOrderSetup_TrailingPercentOffset{ 109 TrailingPercentOffset: "1", 110 }, 111 }, 112 }, 113 errStr: "order_submission (is required), stop_orders_submission.rises_below.trigger.trailing_percent_offset (must be between 0 and 1)", 114 }, 115 { 116 submission: commandspb.StopOrdersSubmission{ 117 RisesAbove: &commandspb.StopOrderSetup{ 118 Trigger: &commandspb.StopOrderSetup_TrailingPercentOffset{ 119 TrailingPercentOffset: "0.89", 120 }, 121 }, 122 }, 123 errStr: "order_submission (is required)", 124 }, 125 { 126 submission: commandspb.StopOrdersSubmission{ 127 RisesAbove: &commandspb.StopOrderSetup{ 128 Trigger: &commandspb.StopOrderSetup_TrailingPercentOffset{ 129 TrailingPercentOffset: "132213ds", 130 }, 131 }, 132 }, 133 errStr: "order_submission (is required), stop_orders_submission.rises_below.trigger.trailing_percent_offset (not a valid float)", 134 }, 135 { 136 submission: commandspb.StopOrdersSubmission{ 137 RisesAbove: &commandspb.StopOrderSetup{ 138 ExpiresAt: ptr.From(int64(1000)), 139 Trigger: &commandspb.StopOrderSetup_TrailingPercentOffset{ 140 TrailingPercentOffset: "0.1", 141 }, 142 }, 143 }, 144 errStr: "order_submission (is required), stop_orders_submission.rises_below.expiry_strategy (expiry strategy required when expires_at set)", 145 }, 146 { 147 submission: commandspb.StopOrdersSubmission{ 148 RisesAbove: &commandspb.StopOrderSetup{ 149 ExpiresAt: ptr.From(int64(-1000)), 150 ExpiryStrategy: ptr.From(vega.StopOrder_EXPIRY_STRATEGY_CANCELS), 151 Trigger: &commandspb.StopOrderSetup_TrailingPercentOffset{ 152 TrailingPercentOffset: "0.1", 153 }, 154 }, 155 }, 156 errStr: "order_submission (is required), stop_orders_submission.rises_below.expires_at (must be positive)", 157 }, 158 { 159 submission: commandspb.StopOrdersSubmission{ 160 RisesAbove: &commandspb.StopOrderSetup{ 161 ExpiresAt: ptr.From(int64(1000)), 162 ExpiryStrategy: ptr.From(vega.StopOrder_ExpiryStrategy(-1)), 163 Trigger: &commandspb.StopOrderSetup_TrailingPercentOffset{ 164 TrailingPercentOffset: "0.1", 165 }, 166 }, 167 }, 168 errStr: "order_submission (is required), stop_orders_submission.rises_below.expiry_strategy (is not a valid value)", 169 }, 170 { 171 submission: commandspb.StopOrdersSubmission{ 172 RisesAbove: &commandspb.StopOrderSetup{ 173 ExpiresAt: ptr.From(int64(1000)), 174 ExpiryStrategy: ptr.From(vega.StopOrder_ExpiryStrategy(-1)), 175 Trigger: &commandspb.StopOrderSetup_TrailingPercentOffset{ 176 TrailingPercentOffset: "0.1", 177 }, 178 }, 179 }, 180 errStr: "order_submission (is required), stop_orders_submission.rises_below.expiry_strategy (is not a valid value)", 181 }, 182 { 183 submission: commandspb.StopOrdersSubmission{ 184 RisesAbove: &commandspb.StopOrderSetup{ 185 ExpiresAt: ptr.From(int64(1000)), 186 ExpiryStrategy: ptr.From(vega.StopOrder_EXPIRY_STRATEGY_UNSPECIFIED), 187 Trigger: &commandspb.StopOrderSetup_TrailingPercentOffset{ 188 TrailingPercentOffset: "0.1", 189 }, 190 }, 191 }, 192 errStr: "order_submission (is required), stop_orders_submission.rises_below.expiry_strategy (is required)", 193 }, 194 { 195 submission: commandspb.StopOrdersSubmission{ 196 RisesAbove: &commandspb.StopOrderSetup{ 197 ExpiresAt: ptr.From(int64(1000)), 198 ExpiryStrategy: ptr.From(vega.StopOrder_EXPIRY_STRATEGY_CANCELS), 199 Trigger: &commandspb.StopOrderSetup_TrailingPercentOffset{ 200 TrailingPercentOffset: "0.1", 201 }, 202 }, 203 }, 204 errStr: "order_submission (is required)", 205 }, 206 { 207 submission: commandspb.StopOrdersSubmission{ 208 RisesAbove: &commandspb.StopOrderSetup{ 209 OrderSubmission: &commandspb.OrderSubmission{ 210 MarketId: "f9982447fb4128f9968f9981612c5ea85d19b62058ec2636efc812dcbbc745ca", 211 Side: vega.Side_SIDE_BUY, 212 Size: 100, 213 TimeInForce: vega.Order_TIME_IN_FORCE_IOC, 214 Type: vega.Order_TYPE_MARKET, 215 ReduceOnly: true, 216 }, 217 ExpiresAt: ptr.From(int64(1000)), 218 ExpiryStrategy: ptr.From(vega.StopOrder_EXPIRY_STRATEGY_CANCELS), 219 Trigger: &commandspb.StopOrderSetup_TrailingPercentOffset{ 220 TrailingPercentOffset: "0.1", 221 }, 222 }, 223 FallsBelow: &commandspb.StopOrderSetup{ 224 OrderSubmission: &commandspb.OrderSubmission{ 225 MarketId: "e9982447fb4128f9968f9981612c5ea85d19b62058ec2636efc812dcbbc745ca", 226 Side: vega.Side_SIDE_BUY, 227 Size: 100, 228 TimeInForce: vega.Order_TIME_IN_FORCE_IOC, 229 Type: vega.Order_TYPE_MARKET, 230 ReduceOnly: true, 231 }, 232 ExpiresAt: ptr.From(int64(1000)), 233 ExpiryStrategy: ptr.From(vega.StopOrder_EXPIRY_STRATEGY_CANCELS), 234 Trigger: &commandspb.StopOrderSetup_TrailingPercentOffset{ 235 TrailingPercentOffset: "0.1", 236 }, 237 }, 238 }, 239 errStr: "* (market ID for falls below and rises above must be the same)", 240 }, 241 { 242 submission: commandspb.StopOrdersSubmission{ 243 RisesAbove: &commandspb.StopOrderSetup{ 244 OrderSubmission: &commandspb.OrderSubmission{ 245 MarketId: "f9982447fb4128f9968f9981612c5ea85d19b62058ec2636efc812dcbbc745ca", 246 Side: vega.Side_SIDE_BUY, 247 Size: 100, 248 TimeInForce: vega.Order_TIME_IN_FORCE_IOC, 249 Type: vega.Order_TYPE_MARKET, 250 ReduceOnly: true, 251 }, 252 ExpiresAt: ptr.From(int64(1000)), 253 ExpiryStrategy: ptr.From(vega.StopOrder_EXPIRY_STRATEGY_CANCELS), 254 Trigger: &commandspb.StopOrderSetup_TrailingPercentOffset{ 255 TrailingPercentOffset: "0.1", 256 }, 257 }, 258 }, 259 errStr: "", 260 }, 261 { 262 submission: commandspb.StopOrdersSubmission{ 263 RisesAbove: &commandspb.StopOrderSetup{ 264 OrderSubmission: &commandspb.OrderSubmission{ 265 MarketId: "f9982447fb4128f9968f9981612c5ea85d19b62058ec2636efc812dcbbc745ca", 266 Side: vega.Side_SIDE_BUY, 267 Size: 100, 268 TimeInForce: vega.Order_TIME_IN_FORCE_IOC, 269 Type: vega.Order_TYPE_MARKET, 270 ReduceOnly: true, 271 }, 272 ExpiresAt: ptr.From(int64(1000)), 273 ExpiryStrategy: ptr.From(vega.StopOrder_EXPIRY_STRATEGY_CANCELS), 274 Trigger: &commandspb.StopOrderSetup_TrailingPercentOffset{ 275 TrailingPercentOffset: "0.1", 276 }, 277 SizeOverrideSetting: ptr.From(vega.StopOrder_SIZE_OVERRIDE_SETTING_POSITION), 278 SizeOverrideValue: &vega.StopOrder_SizeOverrideValue{Percentage: "0.5"}, 279 }, 280 }, 281 errStr: "", 282 }, 283 { 284 submission: commandspb.StopOrdersSubmission{ 285 RisesAbove: &commandspb.StopOrderSetup{ 286 OrderSubmission: &commandspb.OrderSubmission{ 287 MarketId: "f9982447fb4128f9968f9981612c5ea85d19b62058ec2636efc812dcbbc745ca", 288 Side: vega.Side_SIDE_BUY, 289 Size: 100, 290 TimeInForce: vega.Order_TIME_IN_FORCE_IOC, 291 Type: vega.Order_TYPE_MARKET, 292 ReduceOnly: true, 293 }, 294 ExpiresAt: ptr.From(int64(1000)), 295 ExpiryStrategy: ptr.From(vega.StopOrder_EXPIRY_STRATEGY_CANCELS), 296 Trigger: &commandspb.StopOrderSetup_TrailingPercentOffset{ 297 TrailingPercentOffset: "0.1", 298 }, 299 SizeOverrideSetting: ptr.From(vega.StopOrder_SIZE_OVERRIDE_SETTING_POSITION), 300 SizeOverrideValue: &vega.StopOrder_SizeOverrideValue{Percentage: "BrokenString"}, 301 }, 302 }, 303 errStr: "stop_orders_submission.rises_above.size_override_value (is not a valid number)", 304 }, 305 { 306 submission: commandspb.StopOrdersSubmission{ 307 RisesAbove: &commandspb.StopOrderSetup{ 308 OrderSubmission: &commandspb.OrderSubmission{ 309 MarketId: "f9982447fb4128f9968f9981612c5ea85d19b62058ec2636efc812dcbbc745ca", 310 Side: vega.Side_SIDE_BUY, 311 Size: 100, 312 TimeInForce: vega.Order_TIME_IN_FORCE_IOC, 313 Type: vega.Order_TYPE_MARKET, 314 ReduceOnly: true, 315 }, 316 ExpiresAt: ptr.From(int64(1000)), 317 ExpiryStrategy: ptr.From(vega.StopOrder_EXPIRY_STRATEGY_CANCELS), 318 Trigger: &commandspb.StopOrderSetup_TrailingPercentOffset{ 319 TrailingPercentOffset: "0.1", 320 }, 321 SizeOverrideSetting: ptr.From(vega.StopOrder_SIZE_OVERRIDE_SETTING_POSITION), 322 SizeOverrideValue: &vega.StopOrder_SizeOverrideValue{Percentage: "0.0"}, 323 }, 324 }, 325 errStr: "stop_orders_submission.rises_above.size_override_value (must be between 0 (excluded) and 1 (included))", 326 }, 327 { 328 submission: commandspb.StopOrdersSubmission{ 329 RisesAbove: &commandspb.StopOrderSetup{ 330 OrderSubmission: &commandspb.OrderSubmission{ 331 MarketId: "f9982447fb4128f9968f9981612c5ea85d19b62058ec2636efc812dcbbc745ca", 332 Side: vega.Side_SIDE_BUY, 333 Size: 100, 334 TimeInForce: vega.Order_TIME_IN_FORCE_IOC, 335 Type: vega.Order_TYPE_MARKET, 336 ReduceOnly: true, 337 }, 338 ExpiresAt: ptr.From(int64(1000)), 339 ExpiryStrategy: ptr.From(vega.StopOrder_EXPIRY_STRATEGY_CANCELS), 340 Trigger: &commandspb.StopOrderSetup_TrailingPercentOffset{ 341 TrailingPercentOffset: "0.1", 342 }, 343 SizeOverrideSetting: ptr.From(vega.StopOrder_SIZE_OVERRIDE_SETTING_POSITION), 344 SizeOverrideValue: &vega.StopOrder_SizeOverrideValue{Percentage: "1.1"}, 345 }, 346 }, 347 errStr: "stop_orders_submission.rises_above.size_override_value (must be between 0 (excluded) and 1 (included))", 348 }, 349 { 350 submission: commandspb.StopOrdersSubmission{ 351 FallsBelow: &commandspb.StopOrderSetup{ 352 OrderSubmission: &commandspb.OrderSubmission{ 353 MarketId: "f9982447fb4128f9968f9981612c5ea85d19b62058ec2636efc812dcbbc745ca", 354 Side: vega.Side_SIDE_BUY, 355 Size: 100, 356 TimeInForce: vega.Order_TIME_IN_FORCE_IOC, 357 Type: vega.Order_TYPE_MARKET, 358 ReduceOnly: true, 359 }, 360 ExpiresAt: ptr.From(int64(1000)), 361 ExpiryStrategy: ptr.From(vega.StopOrder_EXPIRY_STRATEGY_CANCELS), 362 Trigger: &commandspb.StopOrderSetup_TrailingPercentOffset{ 363 TrailingPercentOffset: "0.1", 364 }, 365 SizeOverrideSetting: ptr.From(vega.StopOrder_SIZE_OVERRIDE_SETTING_POSITION), 366 SizeOverrideValue: &vega.StopOrder_SizeOverrideValue{Percentage: "0.5"}, 367 }, 368 }, 369 errStr: "", 370 }, 371 { 372 submission: commandspb.StopOrdersSubmission{ 373 FallsBelow: &commandspb.StopOrderSetup{ 374 OrderSubmission: &commandspb.OrderSubmission{ 375 MarketId: "f9982447fb4128f9968f9981612c5ea85d19b62058ec2636efc812dcbbc745ca", 376 Side: vega.Side_SIDE_BUY, 377 Size: 100, 378 TimeInForce: vega.Order_TIME_IN_FORCE_IOC, 379 Type: vega.Order_TYPE_MARKET, 380 ReduceOnly: true, 381 }, 382 ExpiresAt: ptr.From(int64(1000)), 383 ExpiryStrategy: ptr.From(vega.StopOrder_EXPIRY_STRATEGY_CANCELS), 384 Trigger: &commandspb.StopOrderSetup_TrailingPercentOffset{ 385 TrailingPercentOffset: "0.1", 386 }, 387 SizeOverrideSetting: ptr.From(vega.StopOrder_SIZE_OVERRIDE_SETTING_POSITION), 388 SizeOverrideValue: &vega.StopOrder_SizeOverrideValue{Percentage: "BrokenString"}, 389 }, 390 }, 391 errStr: "stop_orders_submission.falls_below.size_override_value (is not a valid number)", 392 }, 393 { 394 submission: commandspb.StopOrdersSubmission{ 395 FallsBelow: &commandspb.StopOrderSetup{ 396 OrderSubmission: &commandspb.OrderSubmission{ 397 MarketId: "f9982447fb4128f9968f9981612c5ea85d19b62058ec2636efc812dcbbc745ca", 398 Side: vega.Side_SIDE_BUY, 399 Size: 100, 400 TimeInForce: vega.Order_TIME_IN_FORCE_IOC, 401 Type: vega.Order_TYPE_MARKET, 402 ReduceOnly: true, 403 }, 404 ExpiresAt: ptr.From(int64(1000)), 405 ExpiryStrategy: ptr.From(vega.StopOrder_EXPIRY_STRATEGY_CANCELS), 406 Trigger: &commandspb.StopOrderSetup_TrailingPercentOffset{ 407 TrailingPercentOffset: "0.1", 408 }, 409 SizeOverrideSetting: ptr.From(vega.StopOrder_SIZE_OVERRIDE_SETTING_POSITION), 410 SizeOverrideValue: &vega.StopOrder_SizeOverrideValue{Percentage: "0.0"}, 411 }, 412 }, 413 errStr: "stop_orders_submission.falls_below.size_override_value (must be between 0 (excluded) and 1 (included))", 414 }, 415 { 416 submission: commandspb.StopOrdersSubmission{ 417 FallsBelow: &commandspb.StopOrderSetup{ 418 OrderSubmission: &commandspb.OrderSubmission{ 419 MarketId: "f9982447fb4128f9968f9981612c5ea85d19b62058ec2636efc812dcbbc745ca", 420 Side: vega.Side_SIDE_BUY, 421 Size: 100, 422 TimeInForce: vega.Order_TIME_IN_FORCE_IOC, 423 Type: vega.Order_TYPE_MARKET, 424 ReduceOnly: true, 425 }, 426 ExpiresAt: ptr.From(int64(1000)), 427 ExpiryStrategy: ptr.From(vega.StopOrder_EXPIRY_STRATEGY_CANCELS), 428 Trigger: &commandspb.StopOrderSetup_TrailingPercentOffset{ 429 TrailingPercentOffset: "0.1", 430 }, 431 SizeOverrideSetting: ptr.From(vega.StopOrder_SIZE_OVERRIDE_SETTING_POSITION), 432 SizeOverrideValue: &vega.StopOrder_SizeOverrideValue{Percentage: "1.1"}, 433 }, 434 }, 435 errStr: "stop_orders_submission.falls_below.size_override_value (must be between 0 (excluded) and 1 (included))", 436 }, 437 { 438 submission: commandspb.StopOrdersSubmission{ 439 RisesAbove: &commandspb.StopOrderSetup{ 440 OrderSubmission: &commandspb.OrderSubmission{ 441 MarketId: "f9982447fb4128f9968f9981612c5ea85d19b62058ec2636efc812dcbbc745ca", 442 Side: vega.Side_SIDE_BUY, 443 Size: 100, 444 TimeInForce: vega.Order_TIME_IN_FORCE_GFA, 445 Type: vega.Order_TYPE_MARKET, 446 ReduceOnly: true, 447 }, 448 ExpiresAt: ptr.From(int64(1000)), 449 ExpiryStrategy: ptr.From(vega.StopOrder_EXPIRY_STRATEGY_CANCELS), 450 Trigger: &commandspb.StopOrderSetup_TrailingPercentOffset{ 451 TrailingPercentOffset: "0.1", 452 }, 453 }, 454 }, 455 errStr: commands.ErrIsNotValid.Error(), 456 }, 457 { 458 submission: commandspb.StopOrdersSubmission{ 459 FallsBelow: &commandspb.StopOrderSetup{ 460 OrderSubmission: &commandspb.OrderSubmission{ 461 MarketId: "f9982447fb4128f9968f9981612c5ea85d19b62058ec2636efc812dcbbc745ca", 462 Side: vega.Side_SIDE_BUY, 463 Size: 100, 464 TimeInForce: vega.Order_TIME_IN_FORCE_GFA, 465 Type: vega.Order_TYPE_MARKET, 466 ReduceOnly: true, 467 }, 468 ExpiresAt: ptr.From(int64(1000)), 469 ExpiryStrategy: ptr.From(vega.StopOrder_EXPIRY_STRATEGY_CANCELS), 470 Trigger: &commandspb.StopOrderSetup_TrailingPercentOffset{ 471 TrailingPercentOffset: "0.1", 472 }, 473 }, 474 }, 475 errStr: commands.ErrIsNotValid.Error(), 476 }, 477 } 478 479 for n, c := range cases { 480 if len(c.errStr) <= 0 { 481 assert.NoError(t, commands.CheckStopOrdersSubmission(&c.submission), n) 482 continue 483 } 484 485 assert.Contains(t, checkStopOrdersSubmission(&c.submission).Error(), c.errStr, n) 486 } 487 } 488 489 func checkStopOrdersSubmission(cmd *commandspb.StopOrdersSubmission) commands.Errors { 490 err := commands.CheckStopOrdersSubmission(cmd) 491 492 var e commands.Errors 493 if ok := errors.As(err, &e); !ok { 494 return commands.NewErrors() 495 } 496 497 return e 498 }