-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3459 from vegaprotocol/feature/new-transaction-api-2
Add validation for a couple of commands
- Loading branch information
Showing
13 changed files
with
898 additions
and
75 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
package commands | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"strconv" | ||
|
||
types "code.vegaprotocol.io/vega/proto" | ||
commandspb "code.vegaprotocol.io/vega/proto/commands/v1" | ||
) | ||
|
||
var ( | ||
ErrOrderInShapeWithoutReference = errors.New("order in shape without reference") | ||
ErrOrderInShapeWithoutProportion = errors.New("order in shape without a proportion") | ||
ErrOrderInBuySideShapeWithBestAskPrice = errors.New("order in buy side shape with best ask price reference") | ||
ErrOrderInBuySideShapeOffsetSup0 = errors.New("order in buy side shape offset must be <= 0") | ||
ErrOrderInBuySideShapeOffsetSupEq0 = errors.New("order in buy side shape offset must be < 0") | ||
ErrOrderInSellSideShapeOffsetInf0 = errors.New("order in sell shape offset must be >= 0") | ||
ErrOrderInSellSideShapeWithBestBidPrice = errors.New("order in sell side shape with best bid price reference") | ||
ErrOrderInSellSideShapeOffsetInfEq0 = errors.New("order in sell shape offset must be > 0") | ||
) | ||
|
||
func CheckLiquidityProvisionSubmission(cmd *commandspb.LiquidityProvisionSubmission) error { | ||
return checkLiquidityProvisionSubmission(cmd).ErrorOrNil() | ||
} | ||
|
||
func checkLiquidityProvisionSubmission(cmd *commandspb.LiquidityProvisionSubmission) Errors { | ||
var errs = NewErrors() | ||
|
||
if len(cmd.MarketId) <= 0 { | ||
errs.AddForProperty( | ||
"liquidity_provision_submission.market_id", | ||
ErrIsRequired, | ||
) | ||
} | ||
|
||
if len(cmd.Fee) <= 0 { | ||
errs.AddForProperty( | ||
"liquidity_provision_submission.fee", | ||
ErrIsRequired, | ||
) | ||
} else { | ||
if fee, err := strconv.ParseFloat(cmd.Fee, 64); err != nil { | ||
errs.AddForProperty( | ||
"liquidity_provision_submission.fee", | ||
ErrIsNotValid, | ||
) | ||
} else if fee < 0 { | ||
errs.AddForProperty( | ||
"liquidity_provision_submission.fee", | ||
ErrMustBePositive, | ||
) | ||
} | ||
|
||
} | ||
|
||
errs.Merge(checkLiquidityProvisionShape( | ||
cmd.Buys, types.Side_SIDE_BUY, | ||
)) | ||
errs.Merge(checkLiquidityProvisionShape( | ||
cmd.Sells, types.Side_SIDE_SELL, | ||
)) | ||
|
||
return errs | ||
} | ||
|
||
func checkLiquidityProvisionShape( | ||
sh []*types.LiquidityOrder, side types.Side, | ||
) Errors { | ||
var ( | ||
errs = NewErrors() | ||
shapeSideField = "liquidity_provision_submission.buys" | ||
) | ||
if side == types.Side_SIDE_SELL { | ||
shapeSideField = "liquidity_provision_submission.sells" | ||
} | ||
|
||
if len(sh) <= 0 { | ||
errs.AddForProperty(shapeSideField, errors.New("empty shape")) | ||
return errs | ||
|
||
} | ||
|
||
for idx, lo := range sh { | ||
if lo.Reference == types.PeggedReference_PEGGED_REFERENCE_UNSPECIFIED { | ||
errs.AddForProperty( | ||
fmt.Sprintf("%v[%d].reference", shapeSideField, idx), | ||
ErrOrderInShapeWithoutReference, | ||
) | ||
} | ||
if lo.Proportion == 0 { | ||
errs.AddForProperty( | ||
fmt.Sprintf("%v[%d].proportion", shapeSideField, idx), | ||
ErrOrderInShapeWithoutProportion, | ||
) | ||
} | ||
|
||
if side == types.Side_SIDE_BUY { | ||
switch lo.Reference { | ||
case types.PeggedReference_PEGGED_REFERENCE_BEST_ASK: | ||
errs.AddForProperty( | ||
fmt.Sprintf("%v[%d].reference", shapeSideField, idx), | ||
ErrOrderInBuySideShapeWithBestAskPrice, | ||
) | ||
case types.PeggedReference_PEGGED_REFERENCE_BEST_BID: | ||
if lo.Offset > 0 { | ||
errs.AddForProperty( | ||
fmt.Sprintf("%v[%d].offset", shapeSideField, idx), | ||
ErrOrderInBuySideShapeOffsetSup0, | ||
) | ||
} | ||
case types.PeggedReference_PEGGED_REFERENCE_MID: | ||
if lo.Offset >= 0 { | ||
errs.AddForProperty( | ||
fmt.Sprintf("%v[%d].offset", shapeSideField, idx), | ||
ErrOrderInBuySideShapeOffsetSupEq0, | ||
) | ||
} | ||
} | ||
} else { | ||
switch lo.Reference { | ||
case types.PeggedReference_PEGGED_REFERENCE_BEST_ASK: | ||
if lo.Offset < 0 { | ||
errs.AddForProperty( | ||
fmt.Sprintf("%v[%d].offset", shapeSideField, idx), | ||
ErrOrderInSellSideShapeOffsetInf0, | ||
) | ||
} | ||
case types.PeggedReference_PEGGED_REFERENCE_BEST_BID: | ||
errs.AddForProperty( | ||
fmt.Sprintf("%v[%d].offset", shapeSideField, idx), | ||
ErrOrderInSellSideShapeWithBestBidPrice, | ||
) | ||
case types.PeggedReference_PEGGED_REFERENCE_MID: | ||
if lo.Offset <= 0 { | ||
errs.AddForProperty( | ||
fmt.Sprintf("%v[%d].offset", shapeSideField, idx), | ||
ErrOrderInSellSideShapeOffsetInfEq0, | ||
) | ||
} | ||
} | ||
} | ||
} | ||
return errs | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
package commands_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"code.vegaprotocol.io/vega/commands" | ||
types "code.vegaprotocol.io/vega/proto" | ||
commandspb "code.vegaprotocol.io/vega/proto/commands/v1" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestLiquidityProvisionSubmission(t *testing.T) { | ||
var cases = []struct { | ||
lp commandspb.LiquidityProvisionSubmission | ||
errString string | ||
}{ | ||
{ | ||
lp: commandspb.LiquidityProvisionSubmission{ | ||
CommitmentAmount: 100, | ||
Fee: "abcd", | ||
MarketId: "okmarketid", | ||
Sells: []*types.LiquidityOrder{ | ||
{Reference: types.PeggedReference_PEGGED_REFERENCE_BEST_ASK, Offset: 10, Proportion: 1}, | ||
}, | ||
Buys: []*types.LiquidityOrder{ | ||
{Reference: types.PeggedReference_PEGGED_REFERENCE_BEST_BID, Offset: -10, Proportion: 1}, | ||
}, | ||
}, | ||
errString: "liquidity_provision_submission.fee(is not a valid value)", | ||
}, | ||
{ | ||
lp: commandspb.LiquidityProvisionSubmission{ | ||
CommitmentAmount: 100, | ||
Fee: "-1", | ||
MarketId: "okmarketid", | ||
Sells: []*types.LiquidityOrder{ | ||
{Reference: types.PeggedReference_PEGGED_REFERENCE_BEST_ASK, Offset: 10, Proportion: 1}, | ||
}, | ||
Buys: []*types.LiquidityOrder{ | ||
{Reference: types.PeggedReference_PEGGED_REFERENCE_BEST_BID, Offset: -10, Proportion: 1}, | ||
}, | ||
}, | ||
errString: "liquidity_provision_submission.fee(must be positive)", | ||
}, | ||
{ | ||
lp: commandspb.LiquidityProvisionSubmission{ | ||
CommitmentAmount: 100, | ||
Fee: "0.1", | ||
Sells: []*types.LiquidityOrder{ | ||
{Reference: types.PeggedReference_PEGGED_REFERENCE_BEST_ASK, Offset: 10, Proportion: 1}, | ||
}, | ||
Buys: []*types.LiquidityOrder{ | ||
{Reference: types.PeggedReference_PEGGED_REFERENCE_BEST_BID, Offset: -10, Proportion: 1}, | ||
}, | ||
}, | ||
errString: "liquidity_provision_submission.market_id(is required)", | ||
}, | ||
{ | ||
lp: commandspb.LiquidityProvisionSubmission{ | ||
CommitmentAmount: 100, | ||
Fee: "0.1", | ||
MarketId: "okmarketid", | ||
Sells: []*types.LiquidityOrder{ | ||
{Reference: types.PeggedReference_PEGGED_REFERENCE_BEST_ASK, Offset: 10}, | ||
}, | ||
Buys: []*types.LiquidityOrder{ | ||
{Reference: types.PeggedReference_PEGGED_REFERENCE_BEST_BID, Offset: -10, Proportion: 1}, | ||
}, | ||
}, | ||
errString: "liquidity_provision_submission.sells[0].proportion(order in shape without a proportion)", | ||
}, | ||
{ | ||
lp: commandspb.LiquidityProvisionSubmission{ | ||
CommitmentAmount: 100, | ||
Fee: "0.1", | ||
MarketId: "okmarketid", | ||
Sells: []*types.LiquidityOrder{ | ||
{Reference: types.PeggedReference_PEGGED_REFERENCE_BEST_ASK, Offset: 10, Proportion: 1}, | ||
}, | ||
Buys: []*types.LiquidityOrder{ | ||
{Reference: types.PeggedReference_PEGGED_REFERENCE_BEST_BID, Offset: -10}, | ||
}, | ||
}, | ||
errString: "liquidity_provision_submission.buys[0].proportion(order in shape without a proportion)", | ||
}, | ||
{ | ||
lp: commandspb.LiquidityProvisionSubmission{ | ||
CommitmentAmount: 100, | ||
Fee: "0.1", | ||
MarketId: "okmarketid", | ||
Sells: []*types.LiquidityOrder{ | ||
{Reference: types.PeggedReference_PEGGED_REFERENCE_BEST_ASK, Proportion: 1}, // no offset is ok | ||
}, | ||
Buys: []*types.LiquidityOrder{ | ||
{Reference: types.PeggedReference_PEGGED_REFERENCE_BEST_BID, Proportion: 1}, // no offset is ok | ||
}, | ||
}, | ||
}, | ||
{ | ||
lp: commandspb.LiquidityProvisionSubmission{ | ||
CommitmentAmount: 100, | ||
Fee: "0.1", | ||
MarketId: "okmarketid", | ||
Sells: []*types.LiquidityOrder{ | ||
{Reference: types.PeggedReference_PEGGED_REFERENCE_BEST_ASK, Offset: 10, Proportion: 1}, | ||
}, | ||
Buys: []*types.LiquidityOrder{}, | ||
}, | ||
errString: "liquidity_provision_submission.buys(empty shape)", | ||
}, | ||
{ | ||
lp: commandspb.LiquidityProvisionSubmission{ | ||
CommitmentAmount: 100, | ||
Fee: "0.1", | ||
MarketId: "okmarketid", | ||
Sells: []*types.LiquidityOrder{}, | ||
Buys: []*types.LiquidityOrder{ | ||
{Reference: types.PeggedReference_PEGGED_REFERENCE_BEST_BID, Offset: -10, Proportion: 1}, | ||
}, | ||
}, | ||
errString: "liquidity_provision_submission.sells(empty shape)", | ||
}, | ||
{ | ||
lp: commandspb.LiquidityProvisionSubmission{ | ||
CommitmentAmount: 100, | ||
Fee: "0.1", | ||
MarketId: "okmarketid", | ||
Sells: []*types.LiquidityOrder{ | ||
{Reference: types.PeggedReference_PEGGED_REFERENCE_BEST_BID, Offset: 10, Proportion: 1}, | ||
}, | ||
Buys: []*types.LiquidityOrder{ | ||
{Reference: types.PeggedReference_PEGGED_REFERENCE_BEST_ASK, Offset: -10, Proportion: 1}, | ||
}, | ||
}, | ||
errString: "liquidity_provision_submission.buys[0].reference(order in buy side shape with best ask price reference), liquidity_provision_submission.sells[0].offset(order in sell side shape with best bid price reference)", | ||
}, | ||
{ | ||
lp: commandspb.LiquidityProvisionSubmission{ | ||
CommitmentAmount: 100, | ||
Fee: "0.1", | ||
MarketId: "okmarketid", | ||
Sells: []*types.LiquidityOrder{ | ||
{Reference: types.PeggedReference_PEGGED_REFERENCE_MID, Offset: 0, Proportion: 1}, | ||
{Reference: types.PeggedReference_PEGGED_REFERENCE_BEST_BID, Offset: 0, Proportion: 1}, | ||
{Reference: types.PeggedReference_PEGGED_REFERENCE_BEST_ASK, Offset: -10, Proportion: 1}, | ||
}, | ||
Buys: []*types.LiquidityOrder{ | ||
{Reference: types.PeggedReference_PEGGED_REFERENCE_MID, Offset: 0, Proportion: 1}, | ||
}, | ||
}, | ||
errString: "liquidity_provision_submission.buys[0].offset(order in buy side shape offset must be < 0), liquidity_provision_submission.sells[0].offset(order in sell shape offset must be > 0), liquidity_provision_submission.sells[1].offset(order in sell side shape with best bid price reference), liquidity_provision_submission.sells[2].offset(order in sell shape offset must be >= 0)", | ||
}, | ||
{ | ||
lp: commandspb.LiquidityProvisionSubmission{}, | ||
errString: "liquidity_provision_submission.buys(empty shape), liquidity_provision_submission.fee(is required), liquidity_provision_submission.market_id(is required), liquidity_provision_submission.sells(empty shape)", | ||
}, | ||
} | ||
|
||
for _, c := range cases { | ||
err := commands.CheckLiquidityProvisionSubmission(&c.lp) | ||
if len(c.errString) <= 0 { | ||
assert.NoError(t, err) | ||
continue | ||
} | ||
|
||
assert.Error(t, err) | ||
assert.EqualError(t, err, c.errString) | ||
} | ||
} |
Oops, something went wrong.