code.vegaprotocol.io/vega@v0.79.0/commands/proposal_submission_new_market_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  	"fmt"
    21  	"math"
    22  	"testing"
    23  	"time"
    24  
    25  	"code.vegaprotocol.io/vega/commands"
    26  	dstypes "code.vegaprotocol.io/vega/core/datasource/common"
    27  	"code.vegaprotocol.io/vega/libs/ptr"
    28  	"code.vegaprotocol.io/vega/libs/test"
    29  	"code.vegaprotocol.io/vega/protos/vega"
    30  	protoTypes "code.vegaprotocol.io/vega/protos/vega"
    31  	vegapb "code.vegaprotocol.io/vega/protos/vega"
    32  	commandspb "code.vegaprotocol.io/vega/protos/vega/commands/v1"
    33  	datapb "code.vegaprotocol.io/vega/protos/vega/data/v1"
    34  
    35  	"github.com/stretchr/testify/assert"
    36  )
    37  
    38  func TestCheckProposalSubmissionForNewMarket(t *testing.T) {
    39  	t.Run("Submitting a market change without new market fails", testNewMarketChangeSubmissionWithoutNewMarketFails)
    40  	t.Run("Submitting a market change without changes fails", testNewMarketChangeSubmissionWithoutChangesFails)
    41  	t.Run("Submitting a market change without too many pm trigger fails", testNewMarketChangeSubmissionWithTooManyPMTriggersFails)
    42  	t.Run("Submitting a market change without decimal places succeeds", testNewMarketChangeSubmissionWithoutDecimalPlacesSucceeds)
    43  	t.Run("Submitting a market change with decimal places equal to 0 succeeds", testNewMarketChangeSubmissionWithDecimalPlacesEqualTo0Succeeds)
    44  	t.Run("Submitting a market change with decimal places above or equal to 150 fails", testNewMarketChangeSubmissionWithDecimalPlacesAboveOrEqualTo150Fails)
    45  	t.Run("Submitting a market change with decimal places below 150 succeeds", testNewMarketChangeSubmissionWithDecimalPlacesBelow150Succeeds)
    46  	t.Run("Submitting a market change without decimal places succeeds", testNewMarketChangeSubmissionWithoutDecimalPlacesSucceeds)
    47  	t.Run("Submitting a market change with position decimal places equal to 0 succeeds", testNewMarketChangeSubmissionWithPositionDecimalPlacesEqualTo0Succeeds)
    48  	t.Run("Submitting a market change with position decimal places above or equal to 6 fails", testNewMarketChangeSubmissionWithPositionDecimalPlacesAboveOrEqualTo7Fails)
    49  	t.Run("Submitting a market change with position decimal places below 6 succeeds", testNewMarketChangeSubmissionWithPositionDecimalPlacesBelow7Succeeds)
    50  	t.Run("Submitting a market change with slippage factor 'banana' fails", testNewMarketChangeSubmissionWithSlippageFactorBananaFails)
    51  	t.Run("Submitting a market change with negative slippage factor fails", testNewMarketChangeSubmissionWithSlippageFactorNegativeFails)
    52  	t.Run("Submitting a market change with empty max slippage factor succeeds", testNewMarketChangeSubmissionWithEmptySlippageFactorPasses)
    53  	t.Run("Submitting a market change with too large slippage factor fails", testNewMarketChangeSubmissionWithSlippageFactorTooLargeFails)
    54  	t.Run("Submitting a new capped market with max price succeeds", testNewCappedMarketWithMaxPriceSucceeds)
    55  	t.Run("Submitting a new capped market without max price fails", testNewCappedMarketWithoutMaxPriceFails)
    56  
    57  	t.Run("Submitting a new market without price monitoring succeeds", testNewMarketChangeSubmissionWithoutPriceMonitoringSucceeds)
    58  	t.Run("Submitting a new market with price monitoring succeeds", testNewMarketChangeSubmissionWithPriceMonitoringSucceeds)
    59  	t.Run("Submitting a price monitoring change without triggers succeeds", testPriceMonitoringChangeSubmissionWithoutTriggersSucceeds)
    60  	t.Run("Submitting a price monitoring change with triggers succeeds", testPriceMonitoringChangeSubmissionWithTriggersSucceeds)
    61  	t.Run("Submitting a price monitoring change without trigger horizon fails", testPriceMonitoringChangeSubmissionWithoutTriggerHorizonFails)
    62  	t.Run("Submitting a price monitoring change with trigger horizon succeeds", testPriceMonitoringChangeSubmissionWithTriggerHorizonSucceeds)
    63  	t.Run("Submitting a price monitoring change with wrong trigger probability fails", testPriceMonitoringChangeSubmissionWithWrongTriggerProbabilityFails)
    64  	t.Run("Submitting a price monitoring change with right trigger probability succeeds", testPriceMonitoringChangeSubmissionWithRightTriggerProbabilitySucceeds)
    65  	t.Run("Submitting a price monitoring change without trigger auction extension fails", testPriceMonitoringChangeSubmissionWithoutTriggerAuctionExtensionFails)
    66  	t.Run("Submitting a price monitoring change with trigger auction extension succeeds", testPriceMonitoringChangeSubmissionWithTriggerAuctionExtensionSucceeds)
    67  	t.Run("Submitting a new market without liquidity monitoring fails", testNewMarketChangeSubmissionWithoutLiquidityMonitoringFails)
    68  	t.Run("Submitting a new market with liquidity monitoring succeeds", testNewMarketChangeSubmissionWithLiquidityMonitoringSucceeds)
    69  	t.Run("Submitting a liquidity monitoring change without target stake parameters fails", testLiquidityMonitoringChangeSubmissionWithoutTargetStakeParametersFails)
    70  	t.Run("Submitting a liquidity monitoring change with target stake parameters succeeds", testLiquidityMonitoringChangeSubmissionWithTargetStakeParametersSucceeds)
    71  	t.Run("Submitting a liquidity monitoring change with non-positive time window fails", testLiquidityMonitoringChangeSubmissionWithNonPositiveTimeWindowFails)
    72  	t.Run("Submitting a liquidity monitoring change with positive time window succeeds", testLiquidityMonitoringChangeSubmissionWithPositiveTimeWindowSucceeds)
    73  	t.Run("Submitting a liquidity monitoring change with non-positive scaling factor fails", testLiquidityMonitoringChangeSubmissionWithNonPositiveScalingFactorFails)
    74  	t.Run("Submitting a liquidity monitoring change with positive scaling factor succeeds", testLiquidityMonitoringChangeSubmissionWithPositiveScalingFactorSucceeds)
    75  	t.Run("Submitting a market change without instrument name fails", testNewMarketChangeSubmissionWithoutInstrumentNameFails)
    76  	t.Run("Submitting a market change with instrument name succeeds", testNewMarketChangeSubmissionWithInstrumentNameSucceeds)
    77  	t.Run("Submitting a market change without instrument code fails", testNewMarketChangeSubmissionWithoutInstrumentCodeFails)
    78  	t.Run("Submitting a market change with instrument code succeeds", testNewMarketChangeSubmissionWithInstrumentCodeSucceeds)
    79  	t.Run("Submitting a market change without product fails", testNewMarketChangeSubmissionWithoutProductFails)
    80  	t.Run("Submitting a market change with product succeeds", testNewMarketChangeSubmissionWithProductSucceeds)
    81  	t.Run("Submitting a future market change without future fails", testNewFutureMarketChangeSubmissionWithoutFutureFails)
    82  	t.Run("Submitting a future market change with future succeeds", testNewFutureMarketChangeSubmissionWithFutureSucceeds)
    83  	t.Run("Submitting a future market change without settlement asset fails", testNewFutureMarketChangeSubmissionWithoutSettlementAssetFails)
    84  	t.Run("Submitting a future market change with settlement asset succeeds", testNewFutureMarketChangeSubmissionWithSettlementAssetSucceeds)
    85  	t.Run("Submitting a future market change without quote name fails", testNewFutureMarketChangeSubmissionWithoutQuoteNameFails)
    86  	t.Run("Submitting a future market change with quote name succeeds", testNewFutureMarketChangeSubmissionWithQuoteNameSucceeds)
    87  	t.Run("Submitting a future market change without oracle spec fails", testNewFutureMarketChangeSubmissionWithoutOracleSpecFails)
    88  	t.Run("Submitting a future market change without either of the required oracle spec fails", testNewFutureMarketChangeSubmissionMissingSingleOracleSpecFails)
    89  	t.Run("Submitting a future market change with empty oracle spec fails", testNewFutureMarketChangeSubmissionWithEmptyOracleSpecFails)
    90  	t.Run("Submitting a future market change with empty oracle spec type fails", testNewFutureMarketChangeSubmissionWithEmptyOracleSpecTypeFails)
    91  	t.Run("Submitting a future market change with empty internal spec type fails", testNewFutureMarketChangeSubmissionWithEmptyInternalSpecTypeFails)
    92  	t.Run("Submitting a future market change with wrong pub-keys fails", testNewFutureMarketChangeSubmissionWithWrongPubKeysFails)
    93  	t.Run("Submitting a future market change with bad pubkey or address fails", testNewFutureMarketChangeSubmissionWithBadPubKeysOrderAddressFail)
    94  	t.Run("Submitting a future market change with good pubkey or address succeed", testNewFutureMarketChangeSubmissionWithGoodPubKeysOrderAddressSucceed)
    95  	t.Run("Submitting a future market change without filters fails", testNewFutureMarketChangeSubmissionWithoutFiltersFails)
    96  	t.Run("Submitting a future market change with filters succeeds", testNewFutureMarketChangeSubmissionWithFiltersSucceeds)
    97  	t.Run("Submitting a future market change with filter without key fails", testNewFutureMarketChangeSubmissionWithFilterWithoutKeyFails)
    98  	t.Run("Submitting a future market change with filter with key succeeds", testNewFutureMarketChangeSubmissionWithFilterWithKeySucceeds)
    99  	t.Run("Submitting a future market change with filter without key name fails", testNewFutureMarketChangeSubmissionWithFilterWithoutKeyNameFails)
   100  	t.Run("Submitting a future market change with filter with key name succeeds", testNewFutureMarketChangeSubmissionWithFilterWithKeyNameSucceeds)
   101  	t.Run("Submitting a future market change with filter without key type fails", testNewFutureMarketChangeSubmissionWithFilterWithoutKeyTypeFails)
   102  	t.Run("Submitting a future market change with filter with key type succeeds", testNewFutureMarketChangeSubmissionWithFilterWithKeyTypeSucceeds)
   103  	t.Run("Submitting a future market change with filter without condition succeeds", testNewFutureMarketChangeSubmissionWithFilterWithoutConditionsSucceeds)
   104  	t.Run("Submitting a future market change with filter without condition operator fails", testNewFutureMarketChangeSubmissionWithFilterWithoutConditionOperatorFails)
   105  	t.Run("Submitting a future market change with filter with condition operator succeeds", testNewFutureMarketChangeSubmissionWithFilterWithConditionOperatorSucceeds)
   106  	t.Run("Submitting a future market change with filter without condition value fails", testNewFutureMarketChangeSubmissionWithFilterWithoutConditionValueFails)
   107  	t.Run("Submitting a future market change with filter with condition value succeeds", testNewFutureMarketChangeSubmissionWithFilterWithConditionValueSucceeds)
   108  	t.Run("Submitting a future market change without oracle spec bindings fails", testNewFutureMarketChangeSubmissionWithoutDataSourceSpecBindingFails)
   109  	t.Run("Submitting a future market change with oracle spec binding succeeds", testNewFutureMarketChangeSubmissionWithDataSourceSpecBindingSucceeds)
   110  	t.Run("Submitting a future market change without settlement data property fails", testNewFutureMarketChangeSubmissionWithoutSettlementDataPropertyFails)
   111  	t.Run("Submitting a future market change without pub-keys fails", testNewFutureMarketChangeSubmissionWithoutPubKeysFails)
   112  	t.Run("Submitting a future market change without trading termination property fails", testNewFutureMarketChangeSubmissionWithoutTradingTerminationPropertyFails)
   113  	t.Run("Submitting a future market change with a mismatch between binding property name and filter fails", testNewFutureMarketChangeSubmissionWithMismatchBetweenFilterAndBindingFails)
   114  	t.Run("Submitting a future market change with match between binding property name and filter succeeds", testNewFutureMarketChangeSubmissionWithNoMismatchBetweenFilterAndBindingSucceeds)
   115  	t.Run("Submitting a future market change with settlement data and trading termination properties succeeds", testNewFutureMarketChangeSubmissionWithSettlementDataPropertySucceeds)
   116  	t.Run("Submitting a simple risk parameters change without simple risk parameters fails", testNewSimpleRiskParametersChangeSubmissionWithoutSimpleRiskParametersFails)
   117  	t.Run("Submitting a simple risk parameters change with simple risk parameters succeeds", testNewSimpleRiskParametersChangeSubmissionWithSimpleRiskParametersSucceeds)
   118  	t.Run("Submitting a simple risk parameters change with min move down fails", testNewSimpleRiskParametersChangeSubmissionWithPositiveMinMoveDownFails)
   119  	t.Run("Submitting a simple risk parameters change with min move down succeeds", testNewSimpleRiskParametersChangeSubmissionWithNonPositiveMinMoveDownSucceeds)
   120  	t.Run("Submitting a simple risk parameters change with max move up succeeds", testNewSimpleRiskParametersChangeSubmissionWithNonNegativeMaxMoveUpSucceeds)
   121  	t.Run("Submitting a simple risk parameters change with wrong probability of trading fails", testNewSimpleRiskParametersChangeSubmissionWithWrongProbabilityOfTradingFails)
   122  	t.Run("Submitting a simple risk parameters change with right probability of trading succeeds", testNewSimpleRiskParametersChangeSubmissionWithRightProbabilityOfTradingSucceeds)
   123  	t.Run("Submitting a log normal risk parameters change without log normal risk parameters fails", testNewLogNormalRiskParametersChangeSubmissionWithoutLogNormalRiskParametersFails)
   124  	t.Run("Submitting a log normal risk parameters change with log normal risk parameters succeeds", testNewLogNormalRiskParametersChangeSubmissionWithLogNormalRiskParametersSucceeds)
   125  	t.Run("Submitting a log normal risk parameters change with params fails", testNewLogNormalRiskParametersChangeSubmissionWithoutParamsFails)
   126  	t.Run("Submitting a log normal risk parameters change with invalid risk aversion", testNewLogNormalRiskParametersChangeSubmissionInvalidRiskAversion)
   127  	t.Run("Submitting a log normal risk parameters change with invalid tau", testNewLogNormalRiskParametersChangeSubmissionInvalidTau)
   128  	t.Run("Submitting a log normal risk parameters change with invalid mu", testNewLogNormalRiskParametersChangeSubmissionInvalidMu)
   129  	t.Run("Submitting a log normal risk parameters change with invalid sigma", testNewLogNormalRiskParametersChangeSubmissionInvalidSigma)
   130  	t.Run("Submitting a log normal risk parameters change with invalid r", testNewLogNormalRiskParametersChangeSubmissionInvalidR)
   131  	t.Run("Submitting a new market with a too long reference fails", testNewMarketSubmissionWithTooLongReferenceFails)
   132  	t.Run("Submitting a future market with internal time for trade termination succeeds", testFutureMarketSubmissionWithInternalTimestampForTradingTerminationSucceeds)
   133  	t.Run("Submitting a future market with trade termination from external oracle with no public key fails", testFutureMarketSubmissionWithExternalTradingTerminationNoPublicKeyFails)
   134  	t.Run("Submitting a future market with trading termination from internal source with no public keys succeeds", testFutureMarketSubmissionWithInternalTradingTerminationSucceeds)
   135  	t.Run("Submitting a future market with trading termination from internal source with invalid operator fails", testFutureMarketSubmissionWithInternalTradingInvalidOperatorTerminationFails)
   136  	t.Run("Submitting a future market with trading termination from external source with `vegaprotocol.builtin` key and no public keys fails", testFutureMarketSubmissionWithExternalTradingTerminationBuiltInKeyNoPublicKeyFails)
   137  	t.Run("Submitting a future market with trading settlement from external source with `vegaprotocol.builtin` key and no public keys fails", testFutureMarketSubmissionWithExternalTradingSettlementBuiltInKeyNoPublicKeyFails)
   138  	t.Run("Submitting a future market with trading settlement from external source with one timestamp filter succeeds", testFutureMarketSubmissionWithExternalTradingSettlementTimestampKeySucceeds)
   139  	t.Run("Submitting a future market with trade termination from oracle with no public key fails", testFutureMarketSubmissionWithExternalTradingTerminationNoPublicKeyFails)
   140  	t.Run("Submitting a future market with invalid oracle condition or type", testFutureMarketSubmissionWithInvalidOracleConditionOrType)
   141  	t.Run("Submitting a future market with external data source for termination succeeds", testFutureMarketSubmissionWithExternalTradingTerminationBuiltInKeySucceeds)
   142  	t.Run("Submitting a future market with external data source for termination without signers fails", testFutureMarketSubmissionWithExternalTradingTerminationNoSignerFails)
   143  	t.Run("Submitting a future market with external data source for termination with signers and external settlement data without signers fails", testFutureMarketSubmissionWithExternalSettlementDataNoSignerFails)
   144  	t.Run("Submitting a future market with internal data for settlement fails", testFutureMarketSubmissionWithInternalSettlementDataFails)
   145  	t.Run("Submitting a future market with external data sources for settlement and termination with empty signers fail", testFutureMarketSubmissionWithExternalSettlementDataAndTerminationEmptySignerFails)
   146  	t.Run("Submitting a future market with external data sources for settlement and termination with empty pubKey signer fail", testFutureMarketSubmissionWithExternalSettlementDataAndTerminationEmptyPubKeySignerFails)
   147  	t.Run("Submitting a future market with external data sources for settlement and termination with empty eth address signer fail", testFutureMarketSubmissionWithExternalSettlementDataAndTerminationEmptyEthAddressSignerFails)
   148  	t.Run("Submitting a future market with external data sources for settlement and termination with no signers fail", testFutureMarketSubmissionWithExternalSettlementDataAndTerminationNoSignerFails)
   149  	t.Run("Submitting a future market with internal time trigger termination data fails", testFutureMarketSubmissionWithInternalTimeTriggerTerminationDataFails)
   150  	t.Run("Submitting a future market with internal time trigger settlement data fails", testFutureMarketSubmissionWithInternalTimeTriggerSettlementDataFails)
   151  	t.Run("Submitting a future market with valid liquidation strategy succeeds", testFutureMarketSubmissionWithValidLiquidationStrategySucceeds)
   152  	t.Run("Submitting a future market with invalid liquidation strategy fails", testFutureMarketSubmissionWithInvalidLiquidationStrategyFails)
   153  
   154  	t.Run("Submitting a perps market change without perps fails", testNewPerpsMarketChangeSubmissionWithoutPerpsFails)
   155  	t.Run("Submitting a perps market change with perps succeeds", testNewPerpsMarketChangeSubmissionWithPerpsSucceeds)
   156  	t.Run("Submitting a perps market change without settlement asset fails", testNewPerpsMarketChangeSubmissionWithoutSettlementAssetFails)
   157  	t.Run("Submitting a perps market change with settlement asset succeeds", testNewPerpsMarketChangeSubmissionWithSettlementAssetSucceeds)
   158  	t.Run("Submitting a perps market change without quote name fails", testNewPerpsMarketChangeSubmissionWithoutQuoteNameFails)
   159  	t.Run("Submitting a perps market change with quote name succeeds", testNewPerpsMarketChangeSubmissionWithQuoteNameSucceeds)
   160  	t.Run("Submitting a perps market change without oracle spec fails", testNewPerpsMarketChangeSubmissionWithoutOracleSpecFails)
   161  	t.Run("Submitting a perps market change with oracle spec succeeds", testNewPerpsMarketChangeSubmissionWithOracleSpecSucceeds)
   162  	t.Run("Submitting a perps market change without filters fails", testNewPerpsMarketChangeSubmissionWithoutFiltersFails)
   163  	t.Run("Submitting a perps market change with filters succeeds", testNewPerpsMarketChangeSubmissionWithFiltersSucceeds)
   164  	t.Run("Submitting a perps market change with filter without key fails", testNewPerpsMarketChangeSubmissionWithFilterWithoutKeyFails)
   165  	t.Run("Submitting a perps market change with filter with key succeeds", testNewPerpsMarketChangeSubmissionWithFilterWithKeySucceeds)
   166  	t.Run("Submitting a perps market change with filter without key name fails", testNewPerpsMarketChangeSubmissionWithFilterWithoutKeyNameFails)
   167  	t.Run("Submitting a perps market change with filter with key name succeeds", testNewPerpsMarketChangeSubmissionWithFilterWithKeyNameSucceeds)
   168  	t.Run("Submitting a perps market change with filter without key type fails", testNewPerpsMarketChangeSubmissionWithFilterWithoutKeyTypeFails)
   169  	t.Run("Submitting a perps market change with filter with key type succeeds", testNewPerpsMarketChangeSubmissionWithFilterWithKeyTypeSucceeds)
   170  	t.Run("Submitting a perps market change with filter without condition succeeds", testNewPerpsMarketChangeSubmissionWithFilterWithoutConditionsSucceeds)
   171  	t.Run("Submitting a perps market change with filter without condition operator fails", testNewPerpsMarketChangeSubmissionWithFilterWithoutConditionOperatorFails)
   172  	t.Run("Submitting a perps market change with filter with condition operator succeeds", testNewPerpsMarketChangeSubmissionWithFilterWithConditionOperatorSucceeds)
   173  	t.Run("Submitting a perps market change with filter without condition value fails", testNewPerpsMarketChangeSubmissionWithFilterWithoutConditionValueFails)
   174  	t.Run("Submitting a perps market change with filter with condition value succeeds", testNewPerpsMarketChangeSubmissionWithFilterWithConditionValueSucceeds)
   175  	t.Run("Submitting a perps market change without oracle spec bindings fails", testNewPerpsMarketChangeSubmissionWithoutDataSourceSpecBindingFails)
   176  	t.Run("Submitting a perps market change with oracle spec binding succeeds", testNewPerpsMarketChangeSubmissionWithDataSourceSpecBindingSucceeds)
   177  	t.Run("Submitting a perps market with funding rate modifiers", testNewPerpsMarketWithFundingRateModifiers)
   178  	t.Run("Submitting a perps market change with a mismatch between binding property name and filter fails", testNewPerpsMarketChangeSubmissionWithMismatchBetweenFilterAndBindingFails)
   179  	t.Run("Submitting a perps market change with match between binding property name and filter succeeds", testNewPerpsMarketChangeSubmissionWithNoMismatchBetweenFilterAndBindingSucceeds)
   180  	t.Run("Submitting a perps market change with settlement data and trading termination properties succeeds", testNewPerpsMarketChangeSubmissionWithSettlementDataPropertySucceeds)
   181  	t.Run("Submitting a perps market change with intenal composite price config", testNewPerpsMarketChangeSubmissionWithInternalCompositePriceConfig)
   182  	t.Run("Submitting a new market with invalid SLA price range fails", testNewMarketChangeSubmissionWithInvalidLpRangeFails)
   183  	t.Run("Submitting a new market with valid SLA price range succeeds", testNewMarketChangeSubmissionWithValidLpRangeSucceeds)
   184  	t.Run("Submitting a new market with invalid min time fraction fails", testNewMarketChangeSubmissionWithInvalidMinTimeFractionFails)
   185  	t.Run("Submitting a new market with valid min time fraction succeeds", testNewMarketChangeSubmissionWithValidMinTimeFractionSucceeds)
   186  	t.Run("Submitting a new market with invalid competition factor fails", testNewMarketChangeSubmissionWithInvalidCompetitionFactorFails)
   187  	t.Run("Submitting a new market with valid competition factor succeeds", testNewMarketChangeSubmissionWithValidCompetitionFactorSucceeds)
   188  	t.Run("Submitting a new market with invalid hysteresis epochs fails", testNewMarketChangeSubmissionWithInvalidPerformanceHysteresisEpochsFails)
   189  	t.Run("Submitting a new market with valid hysteresis epochs succeeds", testNewMarketChangeSubmissionWithValidPerformanceHysteresisEpochsSucceeds)
   190  	t.Run("Submitting a new market with invalid liquidity fee settings", testLiquidityFeeSettings)
   191  	t.Run("Submitting a new spot market with invalid liquidity fee settings", testLiquidityFeeSettingsSpot)
   192  	t.Run("Submitting a new market with invalid mark price configuration ", testCompositePriceConfiguration)
   193  	t.Run("Submitting a new market with invalid tick size fails and with valid tick size succeeds", testNewMarketTickSize)
   194  
   195  	t.Run("Log Normal risk factor overrides", testNewLogNormalRiskParametersChangeSubmissionWithOverrides)
   196  }
   197  
   198  type tickSizeCase struct {
   199  	tickSize string
   200  	err      error
   201  }
   202  
   203  func getTickSizeCases() []tickSizeCase {
   204  	return []tickSizeCase{
   205  		{tickSize: "", err: commands.ErrIsRequired},
   206  		{tickSize: "banana", err: commands.ErrNotAValidInteger},
   207  		{tickSize: "-1", err: commands.ErrMustBePositive},
   208  		{tickSize: "0", err: commands.ErrMustBePositive},
   209  		{tickSize: "1", err: nil},
   210  		{tickSize: "123", err: nil},
   211  	}
   212  }
   213  
   214  func testNewMarketTickSize(t *testing.T) {
   215  	cases := getTickSizeCases()
   216  	for _, tsc := range cases {
   217  		err := checkProposalSubmission(&commandspb.ProposalSubmission{
   218  			Terms: &vegapb.ProposalTerms{
   219  				Change: &vegapb.ProposalTerms_NewMarket{
   220  					NewMarket: &vegapb.NewMarket{
   221  						Changes: &vegapb.NewMarketConfiguration{
   222  							TickSize: tsc.tickSize,
   223  						},
   224  					},
   225  				},
   226  			},
   227  		})
   228  		if tsc.err != nil {
   229  			assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.tick_size"), tsc.err)
   230  		} else {
   231  			assert.Empty(t, err.Get("proposal_submission.terms.change.new_market.changes.tick_size"))
   232  		}
   233  	}
   234  }
   235  
   236  func testNewMarketChangeSubmissionWithoutNewMarketFails(t *testing.T) {
   237  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   238  		Terms: &vegapb.ProposalTerms{
   239  			Change: &vegapb.ProposalTerms_NewMarket{},
   240  		},
   241  	})
   242  
   243  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market"), commands.ErrIsRequired)
   244  }
   245  
   246  func testNewMarketChangeSubmissionWithoutChangesFails(t *testing.T) {
   247  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   248  		Terms: &vegapb.ProposalTerms{
   249  			Change: &vegapb.ProposalTerms_NewMarket{
   250  				NewMarket: &vegapb.NewMarket{},
   251  			},
   252  		},
   253  	})
   254  
   255  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes"), commands.ErrIsRequired)
   256  }
   257  
   258  func testNewMarketChangeSubmissionWithoutDecimalPlacesSucceeds(t *testing.T) {
   259  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   260  		Terms: &vegapb.ProposalTerms{
   261  			Change: &vegapb.ProposalTerms_NewMarket{
   262  				NewMarket: &vegapb.NewMarket{
   263  					Changes: &vegapb.NewMarketConfiguration{},
   264  				},
   265  			},
   266  		},
   267  	})
   268  
   269  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.decimal_places"), commands.ErrMustBePositiveOrZero)
   270  }
   271  
   272  func testNewMarketChangeSubmissionWithDecimalPlacesEqualTo0Succeeds(t *testing.T) {
   273  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   274  		Terms: &vegapb.ProposalTerms{
   275  			Change: &vegapb.ProposalTerms_NewMarket{
   276  				NewMarket: &vegapb.NewMarket{
   277  					Changes: &vegapb.NewMarketConfiguration{
   278  						DecimalPlaces: 0,
   279  					},
   280  				},
   281  			},
   282  		},
   283  	})
   284  
   285  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.decimal_places"), commands.ErrMustBePositiveOrZero)
   286  }
   287  
   288  func testNewMarketChangeSubmissionWithDecimalPlacesAboveOrEqualTo150Fails(t *testing.T) {
   289  	testCases := []struct {
   290  		msg   string
   291  		value uint64
   292  	}{
   293  		{
   294  			msg:   "equal to 150",
   295  			value: 150,
   296  		}, {
   297  			msg:   "above 150",
   298  			value: 1000,
   299  		},
   300  	}
   301  	for _, tc := range testCases {
   302  		t.Run(tc.msg, func(t *testing.T) {
   303  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
   304  				Terms: &vegapb.ProposalTerms{
   305  					Change: &vegapb.ProposalTerms_NewMarket{
   306  						NewMarket: &vegapb.NewMarket{
   307  							Changes: &vegapb.NewMarketConfiguration{
   308  								DecimalPlaces: tc.value,
   309  							},
   310  						},
   311  					},
   312  				},
   313  			})
   314  
   315  			assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.decimal_places"), commands.ErrMustBeLessThan150)
   316  		})
   317  	}
   318  }
   319  
   320  func testNewMarketChangeSubmissionWithDecimalPlacesBelow150Succeeds(t *testing.T) {
   321  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   322  		Terms: &vegapb.ProposalTerms{
   323  			Change: &vegapb.ProposalTerms_NewMarket{
   324  				NewMarket: &vegapb.NewMarket{
   325  					Changes: &vegapb.NewMarketConfiguration{
   326  						DecimalPlaces: test.RandomPositiveU64Before(150),
   327  					},
   328  				},
   329  			},
   330  		},
   331  	})
   332  
   333  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.decimal_places"), commands.ErrMustBePositive)
   334  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.decimal_places"), commands.ErrMustBeLessThan150)
   335  }
   336  
   337  func testNewMarketChangeSubmissionWithPositionDecimalPlacesEqualTo0Succeeds(t *testing.T) {
   338  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   339  		Terms: &vegapb.ProposalTerms{
   340  			Change: &vegapb.ProposalTerms_NewMarket{
   341  				NewMarket: &vegapb.NewMarket{
   342  					Changes: &vegapb.NewMarketConfiguration{
   343  						PositionDecimalPlaces: 0,
   344  					},
   345  				},
   346  			},
   347  		},
   348  	})
   349  
   350  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.position_decimal_places"), commands.ErrMustBePositiveOrZero)
   351  }
   352  
   353  func testNewMarketChangeSubmissionWithPositionDecimalPlacesAboveOrEqualTo7Fails(t *testing.T) {
   354  	testCases := []struct {
   355  		msg   string
   356  		value int64
   357  	}{
   358  		{
   359  			msg:   "equal to 7",
   360  			value: 7,
   361  		},
   362  		{
   363  			msg:   "greater than 7",
   364  			value: 8,
   365  		},
   366  		{
   367  			msg:   "equal to -7",
   368  			value: -7,
   369  		},
   370  		{
   371  			msg:   "less than -7",
   372  			value: -8,
   373  		},
   374  	}
   375  	for _, tc := range testCases {
   376  		t.Run(tc.msg, func(t *testing.T) {
   377  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
   378  				Terms: &vegapb.ProposalTerms{
   379  					Change: &vegapb.ProposalTerms_NewMarket{
   380  						NewMarket: &vegapb.NewMarket{
   381  							Changes: &vegapb.NewMarketConfiguration{
   382  								PositionDecimalPlaces: tc.value,
   383  							},
   384  						},
   385  					},
   386  				},
   387  			})
   388  
   389  			assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.position_decimal_places"), commands.ErrMustBeWithinRange7)
   390  		})
   391  	}
   392  }
   393  
   394  func testNewMarketChangeSubmissionWithPositionDecimalPlacesBelow7Succeeds(t *testing.T) {
   395  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   396  		Terms: &vegapb.ProposalTerms{
   397  			Change: &vegapb.ProposalTerms_NewMarket{
   398  				NewMarket: &vegapb.NewMarket{
   399  					Changes: &vegapb.NewMarketConfiguration{
   400  						PositionDecimalPlaces: test.RandomPositiveI64Before(7),
   401  					},
   402  				},
   403  			},
   404  		},
   405  	})
   406  
   407  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.position_decimal_places"), commands.ErrMustBeWithinRange7)
   408  }
   409  
   410  func testNewMarketChangeSubmissionWithSlippageFactorBananaFails(t *testing.T) {
   411  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   412  		Terms: &vegapb.ProposalTerms{
   413  			Change: &vegapb.ProposalTerms_NewMarket{
   414  				NewMarket: &vegapb.NewMarket{
   415  					Changes: &vegapb.NewMarketConfiguration{
   416  						LinearSlippageFactor: "banana",
   417  					},
   418  				},
   419  			},
   420  		},
   421  	})
   422  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.linear_slippage_factor"), commands.ErrIsNotValidNumber)
   423  }
   424  
   425  func testNewMarketChangeSubmissionWithSlippageFactorNegativeFails(t *testing.T) {
   426  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   427  		Terms: &vegapb.ProposalTerms{
   428  			Change: &vegapb.ProposalTerms_NewMarket{
   429  				NewMarket: &vegapb.NewMarket{
   430  					Changes: &vegapb.NewMarketConfiguration{
   431  						LinearSlippageFactor: "-0.1",
   432  					},
   433  				},
   434  			},
   435  		},
   436  	})
   437  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.linear_slippage_factor"), commands.ErrMustBePositiveOrZero)
   438  }
   439  
   440  func testNewMarketChangeSubmissionWithSlippageFactorTooLargeFails(t *testing.T) {
   441  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   442  		Terms: &vegapb.ProposalTerms{
   443  			Change: &vegapb.ProposalTerms_NewMarket{
   444  				NewMarket: &vegapb.NewMarket{
   445  					Changes: &vegapb.NewMarketConfiguration{
   446  						LinearSlippageFactor: "1000000.000001",
   447  					},
   448  				},
   449  			},
   450  		},
   451  	})
   452  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.linear_slippage_factor"), commands.ErrMustBeAtMost1M)
   453  }
   454  
   455  func testNewMarketChangeSubmissionWithEmptySlippageFactorPasses(t *testing.T) {
   456  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   457  		Terms: &vegapb.ProposalTerms{
   458  			Change: &vegapb.ProposalTerms_NewMarket{
   459  				NewMarket: &vegapb.NewMarket{
   460  					Changes: &vegapb.NewMarketConfiguration{},
   461  				},
   462  			},
   463  		},
   464  	})
   465  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.linear_slippage_factor"), commands.ErrIsNotValidNumber)
   466  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.quadratic_slippage_factor"), commands.ErrIsNotValidNumber)
   467  }
   468  
   469  func testNewMarketChangeSubmissionWithoutLiquidityMonitoringFails(t *testing.T) {
   470  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   471  		Terms: &vegapb.ProposalTerms{
   472  			Change: &vegapb.ProposalTerms_NewMarket{
   473  				NewMarket: &vegapb.NewMarket{
   474  					Changes: &vegapb.NewMarketConfiguration{},
   475  				},
   476  			},
   477  		},
   478  	})
   479  
   480  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.liquidity_monitoring_parameters"), commands.ErrIsRequired)
   481  }
   482  
   483  func testNewMarketChangeSubmissionWithLiquidityMonitoringSucceeds(t *testing.T) {
   484  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   485  		Terms: &vegapb.ProposalTerms{
   486  			Change: &vegapb.ProposalTerms_NewMarket{
   487  				NewMarket: &vegapb.NewMarket{
   488  					Changes: &vegapb.NewMarketConfiguration{
   489  						LiquidityMonitoringParameters: &vegapb.LiquidityMonitoringParameters{},
   490  					},
   491  				},
   492  			},
   493  		},
   494  	})
   495  
   496  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.liquidity_monitoring_parameters"), commands.ErrIsRequired)
   497  }
   498  
   499  func testLiquidityMonitoringChangeSubmissionWithoutTargetStakeParametersFails(t *testing.T) {
   500  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   501  		Terms: &vegapb.ProposalTerms{
   502  			Change: &vegapb.ProposalTerms_NewMarket{
   503  				NewMarket: &vegapb.NewMarket{
   504  					Changes: &vegapb.NewMarketConfiguration{
   505  						LiquidityMonitoringParameters: &vegapb.LiquidityMonitoringParameters{},
   506  					},
   507  				},
   508  			},
   509  		},
   510  	})
   511  
   512  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.liquidity_monitoring_parameters.target_stake_parameters"), commands.ErrIsRequired)
   513  }
   514  
   515  func testLiquidityMonitoringChangeSubmissionWithTargetStakeParametersSucceeds(t *testing.T) {
   516  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   517  		Terms: &vegapb.ProposalTerms{
   518  			Change: &vegapb.ProposalTerms_NewMarket{
   519  				NewMarket: &vegapb.NewMarket{
   520  					Changes: &vegapb.NewMarketConfiguration{
   521  						LiquidityMonitoringParameters: &vegapb.LiquidityMonitoringParameters{
   522  							TargetStakeParameters: &vegapb.TargetStakeParameters{},
   523  						},
   524  					},
   525  				},
   526  			},
   527  		},
   528  	})
   529  
   530  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.liquidity_monitoring_parameters.target_stake_parameters"), commands.ErrIsRequired)
   531  }
   532  
   533  func testLiquidityMonitoringChangeSubmissionWithNonPositiveTimeWindowFails(t *testing.T) {
   534  	testCases := []struct {
   535  		msg   string
   536  		value int64
   537  	}{
   538  		{
   539  			msg:   "with ratio of 0",
   540  			value: 0,
   541  		}, {
   542  			msg:   "with ratio of -1",
   543  			value: test.RandomNegativeI64(),
   544  		},
   545  	}
   546  	for _, tc := range testCases {
   547  		t.Run(tc.msg, func(t *testing.T) {
   548  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
   549  				Terms: &vegapb.ProposalTerms{
   550  					Change: &vegapb.ProposalTerms_NewMarket{
   551  						NewMarket: &vegapb.NewMarket{
   552  							Changes: &vegapb.NewMarketConfiguration{
   553  								LiquidityMonitoringParameters: &vegapb.LiquidityMonitoringParameters{
   554  									TargetStakeParameters: &vegapb.TargetStakeParameters{
   555  										TimeWindow: tc.value,
   556  									},
   557  								},
   558  							},
   559  						},
   560  					},
   561  				},
   562  			})
   563  
   564  			assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.liquidity_monitoring_parameters.target_stake_parameters.time_window"), commands.ErrMustBePositive)
   565  		})
   566  	}
   567  }
   568  
   569  func testLiquidityMonitoringChangeSubmissionWithPositiveTimeWindowSucceeds(t *testing.T) {
   570  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   571  		Terms: &vegapb.ProposalTerms{
   572  			Change: &vegapb.ProposalTerms_NewMarket{
   573  				NewMarket: &vegapb.NewMarket{
   574  					Changes: &vegapb.NewMarketConfiguration{
   575  						LiquidityMonitoringParameters: &vegapb.LiquidityMonitoringParameters{
   576  							TargetStakeParameters: &vegapb.TargetStakeParameters{
   577  								TimeWindow: test.RandomPositiveI64(),
   578  							},
   579  						},
   580  					},
   581  				},
   582  			},
   583  		},
   584  	})
   585  
   586  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.liquidity_monitoring_parameters.target_stake_parameters.time_window"), commands.ErrMustBePositive)
   587  }
   588  
   589  func testLiquidityMonitoringChangeSubmissionWithNonPositiveScalingFactorFails(t *testing.T) {
   590  	testCases := []struct {
   591  		msg   string
   592  		value float64
   593  	}{
   594  		{
   595  			msg:   "with ratio of 0",
   596  			value: 0,
   597  		}, {
   598  			msg:   "with ratio of -1.5",
   599  			value: -1.5,
   600  		},
   601  	}
   602  	for _, tc := range testCases {
   603  		t.Run(tc.msg, func(t *testing.T) {
   604  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
   605  				Terms: &vegapb.ProposalTerms{
   606  					Change: &vegapb.ProposalTerms_NewMarket{
   607  						NewMarket: &vegapb.NewMarket{
   608  							Changes: &vegapb.NewMarketConfiguration{
   609  								LiquidityMonitoringParameters: &vegapb.LiquidityMonitoringParameters{
   610  									TargetStakeParameters: &vegapb.TargetStakeParameters{
   611  										ScalingFactor: tc.value,
   612  									},
   613  								},
   614  							},
   615  						},
   616  					},
   617  				},
   618  			})
   619  
   620  			assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.liquidity_monitoring_parameters.target_stake_parameters.scaling_factor"), commands.ErrMustBePositive)
   621  		})
   622  	}
   623  }
   624  
   625  func testLiquidityMonitoringChangeSubmissionWithPositiveScalingFactorSucceeds(t *testing.T) {
   626  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   627  		Terms: &vegapb.ProposalTerms{
   628  			Change: &vegapb.ProposalTerms_NewMarket{
   629  				NewMarket: &vegapb.NewMarket{
   630  					Changes: &vegapb.NewMarketConfiguration{
   631  						LiquidityMonitoringParameters: &vegapb.LiquidityMonitoringParameters{
   632  							TargetStakeParameters: &vegapb.TargetStakeParameters{
   633  								ScalingFactor: 1.5,
   634  							},
   635  						},
   636  					},
   637  				},
   638  			},
   639  		},
   640  	})
   641  
   642  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.liquidity_monitoring_parameters.target_stake_parameters.scaling_factor"), commands.ErrMustBePositive)
   643  }
   644  
   645  func testPriceMonitoringChangeSubmissionWithoutTriggersSucceeds(t *testing.T) {
   646  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   647  		Terms: &vegapb.ProposalTerms{
   648  			Change: &vegapb.ProposalTerms_NewMarket{
   649  				NewMarket: &vegapb.NewMarket{
   650  					Changes: &vegapb.NewMarketConfiguration{
   651  						PriceMonitoringParameters: &vegapb.PriceMonitoringParameters{
   652  							Triggers: []*vegapb.PriceMonitoringTrigger{},
   653  						},
   654  					},
   655  				},
   656  			},
   657  		},
   658  	})
   659  
   660  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.price_monitoring_parameters.triggers"), commands.ErrIsRequired)
   661  }
   662  
   663  func testPriceMonitoringChangeSubmissionWithTriggersSucceeds(t *testing.T) {
   664  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   665  		Terms: &vegapb.ProposalTerms{
   666  			Change: &vegapb.ProposalTerms_NewMarket{
   667  				NewMarket: &vegapb.NewMarket{
   668  					Changes: &vegapb.NewMarketConfiguration{
   669  						PriceMonitoringParameters: &vegapb.PriceMonitoringParameters{
   670  							Triggers: []*vegapb.PriceMonitoringTrigger{
   671  								{},
   672  								{},
   673  							},
   674  						},
   675  					},
   676  				},
   677  			},
   678  		},
   679  	})
   680  
   681  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.price_monitoring_parameters.triggers"), commands.ErrIsRequired)
   682  }
   683  
   684  func testNewMarketChangeSubmissionWithTooManyPMTriggersFails(t *testing.T) {
   685  	triggers := []*vegapb.PriceMonitoringTrigger{}
   686  	for i := 0; i <= 100; i++ {
   687  		triggers = append(triggers, &vegapb.PriceMonitoringTrigger{})
   688  	}
   689  
   690  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   691  		Terms: &vegapb.ProposalTerms{
   692  			Change: &vegapb.ProposalTerms_NewMarket{
   693  				NewMarket: &vegapb.NewMarket{
   694  					Changes: &vegapb.NewMarketConfiguration{
   695  						PriceMonitoringParameters: &vegapb.PriceMonitoringParameters{
   696  							Triggers: triggers,
   697  						},
   698  					},
   699  				},
   700  			},
   701  		},
   702  	})
   703  
   704  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.price_monitoring_parameters.triggers"), errors.New("maximum 100 triggers allowed"))
   705  }
   706  
   707  func testPriceMonitoringChangeSubmissionWithoutTriggerHorizonFails(t *testing.T) {
   708  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   709  		Terms: &vegapb.ProposalTerms{
   710  			Change: &vegapb.ProposalTerms_NewMarket{
   711  				NewMarket: &vegapb.NewMarket{
   712  					Changes: &vegapb.NewMarketConfiguration{
   713  						PriceMonitoringParameters: &vegapb.PriceMonitoringParameters{
   714  							Triggers: []*vegapb.PriceMonitoringTrigger{
   715  								{},
   716  								{},
   717  							},
   718  						},
   719  					},
   720  				},
   721  			},
   722  		},
   723  	})
   724  
   725  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.price_monitoring_parameters.triggers.0.horizon"), commands.ErrMustBePositive)
   726  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.price_monitoring_parameters.triggers.1.horizon"), commands.ErrMustBePositive)
   727  }
   728  
   729  func testPriceMonitoringChangeSubmissionWithTriggerHorizonSucceeds(t *testing.T) {
   730  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   731  		Terms: &vegapb.ProposalTerms{
   732  			Change: &vegapb.ProposalTerms_NewMarket{
   733  				NewMarket: &vegapb.NewMarket{
   734  					Changes: &vegapb.NewMarketConfiguration{
   735  						PriceMonitoringParameters: &vegapb.PriceMonitoringParameters{
   736  							Triggers: []*vegapb.PriceMonitoringTrigger{
   737  								{
   738  									Horizon: test.RandomPositiveI64(),
   739  								},
   740  								{
   741  									Horizon: test.RandomPositiveI64(),
   742  								},
   743  							},
   744  						},
   745  					},
   746  				},
   747  			},
   748  		},
   749  	})
   750  
   751  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.price_monitoring_parameters.triggers.0.horizon"), commands.ErrMustBePositive)
   752  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.price_monitoring_parameters.triggers.1.horizon"), commands.ErrMustBePositive)
   753  }
   754  
   755  func testPriceMonitoringChangeSubmissionWithWrongTriggerProbabilityFails(t *testing.T) {
   756  	testCases := []struct {
   757  		msg   string
   758  		value float64
   759  	}{
   760  		{
   761  			msg:   "with probability of -1",
   762  			value: -1,
   763  		}, {
   764  			msg:   "with probability of 0",
   765  			value: 0,
   766  		}, {
   767  			msg:   "with probability of 1",
   768  			value: 1,
   769  		}, {
   770  			msg:   "with probability of 2",
   771  			value: 2,
   772  		},
   773  	}
   774  	for _, tc := range testCases {
   775  		t.Run(tc.msg, func(t *testing.T) {
   776  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
   777  				Terms: &vegapb.ProposalTerms{
   778  					Change: &vegapb.ProposalTerms_NewMarket{
   779  						NewMarket: &vegapb.NewMarket{
   780  							Changes: &vegapb.NewMarketConfiguration{
   781  								PriceMonitoringParameters: &vegapb.PriceMonitoringParameters{
   782  									Triggers: []*vegapb.PriceMonitoringTrigger{
   783  										{
   784  											Probability: fmt.Sprintf("%f", tc.value),
   785  										},
   786  										{
   787  											Probability: fmt.Sprintf("%f", tc.value),
   788  										},
   789  									},
   790  								},
   791  							},
   792  						},
   793  					},
   794  				},
   795  			})
   796  
   797  			assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.price_monitoring_parameters.triggers.0.probability"),
   798  				errors.New("should be between 0.9 (exclusive) and 1 (exclusive)"))
   799  			assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.price_monitoring_parameters.triggers.1.probability"),
   800  				errors.New("should be between 0.9 (exclusive) and 1 (exclusive)"))
   801  		})
   802  	}
   803  }
   804  
   805  func testPriceMonitoringChangeSubmissionWithRightTriggerProbabilitySucceeds(t *testing.T) {
   806  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   807  		Terms: &vegapb.ProposalTerms{
   808  			Change: &vegapb.ProposalTerms_NewMarket{
   809  				NewMarket: &vegapb.NewMarket{
   810  					Changes: &vegapb.NewMarketConfiguration{
   811  						PriceMonitoringParameters: &vegapb.PriceMonitoringParameters{
   812  							Triggers: []*vegapb.PriceMonitoringTrigger{
   813  								{
   814  									Probability: "0.01",
   815  								},
   816  								{
   817  									Probability: "0.9",
   818  								},
   819  							},
   820  						},
   821  					},
   822  				},
   823  			},
   824  		},
   825  	})
   826  
   827  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.price_monitoring_parameters.triggers.0.probability"),
   828  		errors.New("should be between 0 (exclusive) and 1 (exclusive)"))
   829  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.price_monitoring_parameters.triggers.1.probability"),
   830  		errors.New("should be between 0 (exclusive) and 1 (exclusive)"))
   831  }
   832  
   833  func testPriceMonitoringChangeSubmissionWithoutTriggerAuctionExtensionFails(t *testing.T) {
   834  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   835  		Terms: &vegapb.ProposalTerms{
   836  			Change: &vegapb.ProposalTerms_NewMarket{
   837  				NewMarket: &vegapb.NewMarket{
   838  					Changes: &vegapb.NewMarketConfiguration{
   839  						PriceMonitoringParameters: &vegapb.PriceMonitoringParameters{
   840  							Triggers: []*vegapb.PriceMonitoringTrigger{
   841  								{},
   842  								{},
   843  							},
   844  						},
   845  					},
   846  				},
   847  			},
   848  		},
   849  	})
   850  
   851  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.price_monitoring_parameters.triggers.0.auction_extension"), commands.ErrMustBePositive)
   852  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.price_monitoring_parameters.triggers.1.auction_extension"), commands.ErrMustBePositive)
   853  }
   854  
   855  func testPriceMonitoringChangeSubmissionWithTriggerAuctionExtensionSucceeds(t *testing.T) {
   856  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   857  		Terms: &vegapb.ProposalTerms{
   858  			Change: &vegapb.ProposalTerms_NewMarket{
   859  				NewMarket: &vegapb.NewMarket{
   860  					Changes: &vegapb.NewMarketConfiguration{
   861  						PriceMonitoringParameters: &vegapb.PriceMonitoringParameters{
   862  							Triggers: []*vegapb.PriceMonitoringTrigger{
   863  								{
   864  									AuctionExtension: test.RandomPositiveI64(),
   865  								},
   866  								{
   867  									AuctionExtension: test.RandomPositiveI64(),
   868  								},
   869  							},
   870  						},
   871  					},
   872  				},
   873  			},
   874  		},
   875  	})
   876  
   877  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.price_monitoring_parameters.triggers.0.auction_extension"), commands.ErrMustBePositive)
   878  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.price_monitoring_parameters.triggers.1.auction_extension"), commands.ErrMustBePositive)
   879  }
   880  
   881  func testNewCappedMarketWithMaxPriceSucceeds(t *testing.T) {
   882  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   883  		Terms: &vegapb.ProposalTerms{
   884  			Change: &vegapb.ProposalTerms_NewMarket{
   885  				NewMarket: &vegapb.NewMarket{
   886  					Changes: &vegapb.NewMarketConfiguration{
   887  						Instrument: &vegapb.InstrumentConfiguration{
   888  							Product: &vegapb.InstrumentConfiguration_Future{
   889  								Future: &vegapb.FutureProduct{
   890  									Cap: &vegapb.FutureCap{
   891  										MaxPrice: "100",
   892  									},
   893  								},
   894  							},
   895  						},
   896  						TickSize: "10", // ensure tick size is fine, too
   897  					},
   898  				},
   899  			},
   900  		},
   901  	})
   902  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.cap.max_price"), commands.ErrMustBePositive)
   903  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.cap.max_price"), commands.ErrIsRequired)
   904  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.cap.max_price"), commands.ErrMaxPriceMustRespectTickSize)
   905  }
   906  
   907  func testNewCappedMarketWithoutMaxPriceFails(t *testing.T) {
   908  	fCap := &vegapb.FutureCap{
   909  		MaxPrice: "",
   910  	}
   911  	nmConf := &vegapb.NewMarketConfiguration{
   912  		Instrument: &vegapb.InstrumentConfiguration{
   913  			Product: &vegapb.InstrumentConfiguration_Future{
   914  				Future: &vegapb.FutureProduct{
   915  					Cap: fCap,
   916  				},
   917  			},
   918  		},
   919  	}
   920  	cmd := &commandspb.ProposalSubmission{
   921  		Terms: &vegapb.ProposalTerms{
   922  			Change: &vegapb.ProposalTerms_NewMarket{
   923  				NewMarket: &vegapb.NewMarket{
   924  					Changes: nmConf,
   925  				},
   926  			},
   927  		},
   928  	}
   929  	// submit with empty string:
   930  	err := checkProposalSubmission(cmd)
   931  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.cap.max_price"), commands.ErrIsRequired)
   932  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.cap.max_price"), commands.ErrMaxPriceMustRespectTickSize)
   933  	fCap.MaxPrice = "foobar" // invalid input
   934  	err = checkProposalSubmission(cmd)
   935  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.cap.max_price"), commands.ErrMustBePositive)
   936  	// submit with invalid value relative to tick size
   937  	fCap.MaxPrice = "123"
   938  	nmConf.TickSize = "10"
   939  	err = checkProposalSubmission(cmd)
   940  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.cap.max_price"), commands.ErrMaxPriceMustRespectTickSize)
   941  
   942  	// submit with no max price but other fields set (0019-MCAL-170)
   943  	fCap.MaxPrice = ""
   944  	fCap.BinarySettlement = ptr.From(true)
   945  	fCap.FullyCollateralised = nil
   946  	err = checkProposalSubmission(cmd)
   947  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.cap.max_price"), commands.ErrIsRequired)
   948  
   949  	// submit with no max price but other fields set (0019-MCAL-171)
   950  	fCap.MaxPrice = ""
   951  	fCap.BinarySettlement = nil
   952  	fCap.FullyCollateralised = ptr.From(true)
   953  	err = checkProposalSubmission(cmd)
   954  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.cap.max_price"), commands.ErrIsRequired)
   955  
   956  	// max cap of zero is rejected
   957  	fCap.MaxPrice = "0"
   958  	fCap.BinarySettlement = nil
   959  	fCap.FullyCollateralised = ptr.From(true)
   960  	err = checkProposalSubmission(cmd)
   961  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.cap.max_price"), commands.ErrMustBePositive)
   962  }
   963  
   964  func testNewMarketChangeSubmissionWithoutPriceMonitoringSucceeds(t *testing.T) {
   965  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   966  		Terms: &vegapb.ProposalTerms{
   967  			Change: &vegapb.ProposalTerms_NewMarket{
   968  				NewMarket: &vegapb.NewMarket{
   969  					Changes: &vegapb.NewMarketConfiguration{},
   970  				},
   971  			},
   972  		},
   973  	})
   974  
   975  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.price_monitoring_parameters"), commands.ErrIsRequired)
   976  }
   977  
   978  func testNewMarketChangeSubmissionWithPriceMonitoringSucceeds(t *testing.T) {
   979  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   980  		Terms: &vegapb.ProposalTerms{
   981  			Change: &vegapb.ProposalTerms_NewMarket{
   982  				NewMarket: &vegapb.NewMarket{
   983  					Changes: &vegapb.NewMarketConfiguration{
   984  						PriceMonitoringParameters: &vegapb.PriceMonitoringParameters{},
   985  					},
   986  				},
   987  			},
   988  		},
   989  	})
   990  
   991  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.price_monitoring_parameters"), commands.ErrIsRequired)
   992  }
   993  
   994  func testNewMarketChangeSubmissionWithoutInstrumentNameFails(t *testing.T) {
   995  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   996  		Terms: &vegapb.ProposalTerms{
   997  			Change: &vegapb.ProposalTerms_NewMarket{
   998  				NewMarket: &vegapb.NewMarket{
   999  					Changes: &vegapb.NewMarketConfiguration{
  1000  						Instrument: &vegapb.InstrumentConfiguration{
  1001  							Name: "",
  1002  						},
  1003  					},
  1004  				},
  1005  			},
  1006  		},
  1007  	})
  1008  
  1009  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.name"), commands.ErrIsRequired)
  1010  }
  1011  
  1012  func testNewMarketChangeSubmissionWithInstrumentNameSucceeds(t *testing.T) {
  1013  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1014  		Terms: &vegapb.ProposalTerms{
  1015  			Change: &vegapb.ProposalTerms_NewMarket{
  1016  				NewMarket: &vegapb.NewMarket{
  1017  					Changes: &vegapb.NewMarketConfiguration{
  1018  						Instrument: &vegapb.InstrumentConfiguration{
  1019  							Name: "My name",
  1020  						},
  1021  					},
  1022  				},
  1023  			},
  1024  		},
  1025  	})
  1026  
  1027  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.name"), commands.ErrIsRequired)
  1028  }
  1029  
  1030  func testNewMarketChangeSubmissionWithoutInstrumentCodeFails(t *testing.T) {
  1031  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1032  		Terms: &vegapb.ProposalTerms{
  1033  			Change: &vegapb.ProposalTerms_NewMarket{
  1034  				NewMarket: &vegapb.NewMarket{
  1035  					Changes: &vegapb.NewMarketConfiguration{
  1036  						Instrument: &vegapb.InstrumentConfiguration{
  1037  							Code: "",
  1038  						},
  1039  					},
  1040  				},
  1041  			},
  1042  		},
  1043  	})
  1044  
  1045  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.code"), commands.ErrIsRequired)
  1046  }
  1047  
  1048  func testNewMarketChangeSubmissionWithInstrumentCodeSucceeds(t *testing.T) {
  1049  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1050  		Terms: &vegapb.ProposalTerms{
  1051  			Change: &vegapb.ProposalTerms_NewMarket{
  1052  				NewMarket: &vegapb.NewMarket{
  1053  					Changes: &vegapb.NewMarketConfiguration{
  1054  						Instrument: &vegapb.InstrumentConfiguration{
  1055  							Code: "My code",
  1056  						},
  1057  					},
  1058  				},
  1059  			},
  1060  		},
  1061  	})
  1062  
  1063  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.code"), commands.ErrIsRequired)
  1064  }
  1065  
  1066  func testNewMarketChangeSubmissionWithoutProductFails(t *testing.T) {
  1067  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1068  		Terms: &vegapb.ProposalTerms{
  1069  			Change: &vegapb.ProposalTerms_NewMarket{
  1070  				NewMarket: &vegapb.NewMarket{
  1071  					Changes: &vegapb.NewMarketConfiguration{
  1072  						Instrument: &vegapb.InstrumentConfiguration{},
  1073  					},
  1074  				},
  1075  			},
  1076  		},
  1077  	})
  1078  
  1079  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product"), commands.ErrIsRequired)
  1080  }
  1081  
  1082  func testNewMarketChangeSubmissionWithProductSucceeds(t *testing.T) {
  1083  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1084  		Terms: &vegapb.ProposalTerms{
  1085  			Change: &vegapb.ProposalTerms_NewMarket{
  1086  				NewMarket: &vegapb.NewMarket{
  1087  					Changes: &vegapb.NewMarketConfiguration{
  1088  						Instrument: &vegapb.InstrumentConfiguration{
  1089  							Product: &vegapb.InstrumentConfiguration_Future{},
  1090  						},
  1091  					},
  1092  				},
  1093  			},
  1094  		},
  1095  	})
  1096  
  1097  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product"), commands.ErrIsRequired)
  1098  }
  1099  
  1100  func testNewFutureMarketChangeSubmissionWithoutFutureFails(t *testing.T) {
  1101  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1102  		Terms: &vegapb.ProposalTerms{
  1103  			Change: &vegapb.ProposalTerms_NewMarket{
  1104  				NewMarket: &vegapb.NewMarket{
  1105  					Changes: &vegapb.NewMarketConfiguration{
  1106  						Instrument: &vegapb.InstrumentConfiguration{
  1107  							Product: &vegapb.InstrumentConfiguration_Future{},
  1108  						},
  1109  					},
  1110  				},
  1111  			},
  1112  		},
  1113  	})
  1114  
  1115  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future"), commands.ErrIsRequired)
  1116  }
  1117  
  1118  func testNewFutureMarketChangeSubmissionWithFutureSucceeds(t *testing.T) {
  1119  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1120  		Terms: &vegapb.ProposalTerms{
  1121  			Change: &vegapb.ProposalTerms_NewMarket{
  1122  				NewMarket: &vegapb.NewMarket{
  1123  					Changes: &vegapb.NewMarketConfiguration{
  1124  						Instrument: &vegapb.InstrumentConfiguration{
  1125  							Product: &vegapb.InstrumentConfiguration_Future{
  1126  								Future: &vegapb.FutureProduct{},
  1127  							},
  1128  						},
  1129  					},
  1130  				},
  1131  			},
  1132  		},
  1133  	})
  1134  
  1135  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future"), commands.ErrIsRequired)
  1136  }
  1137  
  1138  func testNewFutureMarketChangeSubmissionWithoutSettlementAssetFails(t *testing.T) {
  1139  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1140  		Terms: &vegapb.ProposalTerms{
  1141  			Change: &vegapb.ProposalTerms_NewMarket{
  1142  				NewMarket: &vegapb.NewMarket{
  1143  					Changes: &vegapb.NewMarketConfiguration{
  1144  						Instrument: &vegapb.InstrumentConfiguration{
  1145  							Product: &vegapb.InstrumentConfiguration_Future{
  1146  								Future: &vegapb.FutureProduct{
  1147  									SettlementAsset: "",
  1148  								},
  1149  							},
  1150  						},
  1151  					},
  1152  				},
  1153  			},
  1154  		},
  1155  	})
  1156  
  1157  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.settlement_asset"), commands.ErrIsRequired)
  1158  }
  1159  
  1160  func testNewFutureMarketChangeSubmissionWithSettlementAssetSucceeds(t *testing.T) {
  1161  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1162  		Terms: &vegapb.ProposalTerms{
  1163  			Change: &vegapb.ProposalTerms_NewMarket{
  1164  				NewMarket: &vegapb.NewMarket{
  1165  					Changes: &vegapb.NewMarketConfiguration{
  1166  						Instrument: &vegapb.InstrumentConfiguration{
  1167  							Product: &vegapb.InstrumentConfiguration_Future{
  1168  								Future: &vegapb.FutureProduct{
  1169  									SettlementAsset: "BTC",
  1170  								},
  1171  							},
  1172  						},
  1173  					},
  1174  				},
  1175  			},
  1176  		},
  1177  	})
  1178  
  1179  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.settlement_asset"), commands.ErrIsRequired)
  1180  }
  1181  
  1182  func testNewFutureMarketChangeSubmissionWithoutQuoteNameFails(t *testing.T) {
  1183  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1184  		Terms: &vegapb.ProposalTerms{
  1185  			Change: &vegapb.ProposalTerms_NewMarket{
  1186  				NewMarket: &vegapb.NewMarket{
  1187  					Changes: &vegapb.NewMarketConfiguration{
  1188  						Instrument: &vegapb.InstrumentConfiguration{
  1189  							Product: &vegapb.InstrumentConfiguration_Future{
  1190  								Future: &vegapb.FutureProduct{
  1191  									QuoteName: "",
  1192  								},
  1193  							},
  1194  						},
  1195  					},
  1196  				},
  1197  			},
  1198  		},
  1199  	})
  1200  
  1201  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.quote_name"), commands.ErrIsRequired)
  1202  }
  1203  
  1204  func testNewFutureMarketChangeSubmissionWithQuoteNameSucceeds(t *testing.T) {
  1205  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1206  		Terms: &vegapb.ProposalTerms{
  1207  			Change: &vegapb.ProposalTerms_NewMarket{
  1208  				NewMarket: &vegapb.NewMarket{
  1209  					Changes: &vegapb.NewMarketConfiguration{
  1210  						Instrument: &vegapb.InstrumentConfiguration{
  1211  							Product: &vegapb.InstrumentConfiguration_Future{
  1212  								Future: &vegapb.FutureProduct{
  1213  									QuoteName: "BTC",
  1214  								},
  1215  							},
  1216  						},
  1217  					},
  1218  				},
  1219  			},
  1220  		},
  1221  	})
  1222  
  1223  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.quote_name"), commands.ErrIsRequired)
  1224  }
  1225  
  1226  func testNewFutureMarketChangeSubmissionWithoutOracleSpecFails(t *testing.T) {
  1227  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1228  		Terms: &vegapb.ProposalTerms{
  1229  			Change: &vegapb.ProposalTerms_NewMarket{
  1230  				NewMarket: &vegapb.NewMarket{
  1231  					Changes: &vegapb.NewMarketConfiguration{
  1232  						Instrument: &vegapb.InstrumentConfiguration{
  1233  							Product: &vegapb.InstrumentConfiguration_Future{
  1234  								Future: &vegapb.FutureProduct{},
  1235  							},
  1236  						},
  1237  					},
  1238  				},
  1239  			},
  1240  		},
  1241  	})
  1242  
  1243  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data"), commands.ErrIsRequired)
  1244  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_trading_termination"), commands.ErrIsRequired)
  1245  }
  1246  
  1247  func testNewFutureMarketChangeSubmissionMissingSingleOracleSpecFails(t *testing.T) {
  1248  	testNewFutureMarketChangeSubmissionWithoutEitherOracleSpecFails(t, "data_source_spec_for_settlement_data")
  1249  	testNewFutureMarketChangeSubmissionWithoutEitherOracleSpecFails(t, "data_source_spec_for_trading_termination")
  1250  }
  1251  
  1252  func testNewFutureMarketChangeSubmissionWithoutEitherOracleSpecFails(t *testing.T, oracleSpecName string) {
  1253  	t.Helper()
  1254  	future := &vegapb.FutureProduct{}
  1255  	if oracleSpecName == "data_source_spec_for_settlement_data" {
  1256  		future.DataSourceSpecForTradingTermination = &vegapb.DataSourceDefinition{}
  1257  	} else {
  1258  		future.DataSourceSpecForSettlementData = &vegapb.DataSourceDefinition{}
  1259  	}
  1260  
  1261  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1262  		Terms: &vegapb.ProposalTerms{
  1263  			Change: &vegapb.ProposalTerms_NewMarket{
  1264  				NewMarket: &vegapb.NewMarket{
  1265  					Changes: &vegapb.NewMarketConfiguration{
  1266  						Instrument: &vegapb.InstrumentConfiguration{
  1267  							Product: &vegapb.InstrumentConfiguration_Future{
  1268  								Future: &vegapb.FutureProduct{},
  1269  							},
  1270  						},
  1271  					},
  1272  				},
  1273  			},
  1274  		},
  1275  	})
  1276  
  1277  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future."+oracleSpecName), commands.ErrIsRequired)
  1278  }
  1279  
  1280  func testNewFutureMarketChangeSubmissionWithEmptyOracleSpecFails(t *testing.T) {
  1281  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1282  		Terms: &vegapb.ProposalTerms{
  1283  			Change: &vegapb.ProposalTerms_NewMarket{
  1284  				NewMarket: &vegapb.NewMarket{
  1285  					Changes: &vegapb.NewMarketConfiguration{
  1286  						Instrument: &vegapb.InstrumentConfiguration{
  1287  							Product: &vegapb.InstrumentConfiguration_Future{
  1288  								Future: &vegapb.FutureProduct{
  1289  									DataSourceSpecForSettlementData:     &vegapb.DataSourceDefinition{},
  1290  									DataSourceSpecForTradingTermination: &vegapb.DataSourceDefinition{},
  1291  								},
  1292  							},
  1293  						},
  1294  					},
  1295  				},
  1296  			},
  1297  		},
  1298  	})
  1299  
  1300  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.source_type"), commands.ErrIsRequired)
  1301  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_trading_termination.source_type"), commands.ErrIsRequired)
  1302  }
  1303  
  1304  func testNewFutureMarketChangeSubmissionWithEmptyOracleSpecTypeFails(t *testing.T) {
  1305  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1306  		Terms: &vegapb.ProposalTerms{
  1307  			Change: &vegapb.ProposalTerms_NewMarket{
  1308  				NewMarket: &vegapb.NewMarket{
  1309  					Changes: &vegapb.NewMarketConfiguration{
  1310  						Instrument: &vegapb.InstrumentConfiguration{
  1311  							Product: &vegapb.InstrumentConfiguration_Future{
  1312  								Future: &vegapb.FutureProduct{
  1313  									DataSourceSpecForSettlementData: &vegapb.DataSourceDefinition{
  1314  										SourceType: &vegapb.DataSourceDefinition_External{
  1315  											External: &vegapb.DataSourceDefinitionExternal{
  1316  												SourceType: &vegapb.DataSourceDefinitionExternal_Oracle{
  1317  													Oracle: nil,
  1318  												},
  1319  											},
  1320  										},
  1321  									},
  1322  									DataSourceSpecForTradingTermination: &vegapb.DataSourceDefinition{
  1323  										SourceType: &vegapb.DataSourceDefinition_External{
  1324  											External: &vegapb.DataSourceDefinitionExternal{
  1325  												SourceType: &vegapb.DataSourceDefinitionExternal_Oracle{
  1326  													Oracle: nil,
  1327  												},
  1328  											},
  1329  										},
  1330  									},
  1331  								},
  1332  							},
  1333  						},
  1334  					},
  1335  				},
  1336  			},
  1337  		},
  1338  	})
  1339  
  1340  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle"), commands.ErrIsRequired)
  1341  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_trading_termination.external.oracle"), commands.ErrIsRequired)
  1342  }
  1343  
  1344  func testNewFutureMarketChangeSubmissionWithEmptyInternalSpecTypeFails(t *testing.T) {
  1345  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1346  		Terms: &vegapb.ProposalTerms{
  1347  			Change: &vegapb.ProposalTerms_NewMarket{
  1348  				NewMarket: &vegapb.NewMarket{
  1349  					Changes: &vegapb.NewMarketConfiguration{
  1350  						Instrument: &vegapb.InstrumentConfiguration{
  1351  							Product: &vegapb.InstrumentConfiguration_Future{
  1352  								Future: &vegapb.FutureProduct{
  1353  									DataSourceSpecForSettlementData: &vegapb.DataSourceDefinition{
  1354  										SourceType: &vegapb.DataSourceDefinition_Internal{
  1355  											Internal: &vegapb.DataSourceDefinitionInternal{
  1356  												SourceType: &vegapb.DataSourceDefinitionInternal_Time{
  1357  													Time: nil,
  1358  												},
  1359  											},
  1360  										},
  1361  									},
  1362  									DataSourceSpecForTradingTermination: &vegapb.DataSourceDefinition{
  1363  										SourceType: &vegapb.DataSourceDefinition_Internal{
  1364  											Internal: &vegapb.DataSourceDefinitionInternal{
  1365  												SourceType: &vegapb.DataSourceDefinitionInternal_Time{
  1366  													Time: nil,
  1367  												},
  1368  											},
  1369  										},
  1370  									},
  1371  								},
  1372  							},
  1373  						},
  1374  					},
  1375  				},
  1376  			},
  1377  		},
  1378  	})
  1379  
  1380  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data"), commands.ErrIsNotValid)
  1381  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_trading_termination.internal.time"), commands.ErrIsRequired)
  1382  }
  1383  
  1384  func testNewFutureMarketChangeSubmissionWithoutPubKeysFails(t *testing.T) {
  1385  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1386  		Terms: &vegapb.ProposalTerms{
  1387  			Change: &vegapb.ProposalTerms_NewMarket{
  1388  				NewMarket: &vegapb.NewMarket{
  1389  					Changes: &vegapb.NewMarketConfiguration{
  1390  						Instrument: &vegapb.InstrumentConfiguration{
  1391  							Product: &vegapb.InstrumentConfiguration_Future{
  1392  								Future: &vegapb.FutureProduct{
  1393  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(vegapb.DataSourceContentTypeOracle),
  1394  								},
  1395  							},
  1396  						},
  1397  					},
  1398  				},
  1399  			},
  1400  		},
  1401  	})
  1402  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers"), commands.ErrIsRequired)
  1403  }
  1404  
  1405  func testNewFutureMarketChangeSubmissionWithWrongPubKeysFails(t *testing.T) {
  1406  	pubKeys := []*dstypes.Signer{
  1407  		dstypes.CreateSignerFromString("0xDEADBEEF", dstypes.SignerTypePubKey),
  1408  		dstypes.CreateSignerFromString("", dstypes.SignerTypePubKey),
  1409  	}
  1410  
  1411  	testCases := []struct {
  1412  		msg   string
  1413  		value []*datapb.Signer
  1414  	}{
  1415  		{
  1416  			msg:   "with empty signers",
  1417  			value: dstypes.SignersIntoProto(pubKeys),
  1418  		}, {
  1419  			msg:   "with blank signers",
  1420  			value: dstypes.SignersIntoProto(pubKeys),
  1421  		},
  1422  	}
  1423  	for _, tc := range testCases {
  1424  		t.Run(tc.msg, func(t *testing.T) {
  1425  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1426  				Terms: &vegapb.ProposalTerms{
  1427  					Change: &vegapb.ProposalTerms_NewMarket{
  1428  						NewMarket: &vegapb.NewMarket{
  1429  							Changes: &vegapb.NewMarketConfiguration{
  1430  								Instrument: &vegapb.InstrumentConfiguration{
  1431  									Product: &vegapb.InstrumentConfiguration_Future{
  1432  										Future: &vegapb.FutureProduct{
  1433  											DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1434  												vegapb.DataSourceContentTypeOracle,
  1435  											).SetOracleConfig(
  1436  												&vegapb.DataSourceDefinitionExternal_Oracle{
  1437  													Oracle: &vegapb.DataSourceSpecConfiguration{
  1438  														Signers: tc.value,
  1439  													},
  1440  												},
  1441  											),
  1442  										},
  1443  									},
  1444  								},
  1445  							},
  1446  						},
  1447  					},
  1448  				},
  1449  			})
  1450  
  1451  			assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers.1"), commands.ErrIsNotValid)
  1452  		})
  1453  	}
  1454  }
  1455  
  1456  func testNewFutureMarketChangeSubmissionWithBadPubKeysOrderAddressFail(t *testing.T) {
  1457  	pubKeys := []*dstypes.Signer{
  1458  		dstypes.CreateSignerFromString("0xDEADBEEF", dstypes.SignerTypePubKey),
  1459  		dstypes.CreateSignerFromString("0xCAFEDUDE", dstypes.SignerTypePubKey),
  1460  		dstypes.CreateSignerFromString("0xCAFEDUDE", dstypes.SignerTypeEthAddress),
  1461  		dstypes.CreateSignerFromString("36393436346533356263623865386132393030636130663837616361663235326435306366326162326663373336393438343561313662376338613064633666", dstypes.SignerTypePubKey),
  1462  	}
  1463  
  1464  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1465  		Terms: &vegapb.ProposalTerms{
  1466  			Change: &vegapb.ProposalTerms_NewMarket{
  1467  				NewMarket: &vegapb.NewMarket{
  1468  					Changes: &vegapb.NewMarketConfiguration{
  1469  						Instrument: &vegapb.InstrumentConfiguration{
  1470  							Product: &vegapb.InstrumentConfiguration_Future{
  1471  								Future: &vegapb.FutureProduct{
  1472  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1473  										vegapb.DataSourceContentTypeOracle,
  1474  									).SetOracleConfig(
  1475  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1476  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1477  												Signers: dstypes.SignersIntoProto(pubKeys),
  1478  											},
  1479  										},
  1480  									),
  1481  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  1482  										vegapb.DataSourceContentTypeOracle,
  1483  									).SetOracleConfig(
  1484  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1485  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1486  												Signers: dstypes.SignersIntoProto(pubKeys),
  1487  											},
  1488  										},
  1489  									),
  1490  								},
  1491  							},
  1492  						},
  1493  					},
  1494  				},
  1495  			},
  1496  		},
  1497  	})
  1498  
  1499  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers"), commands.ErrIsRequired)
  1500  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers.0"), commands.ErrIsNotValid)
  1501  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers.1"), commands.ErrIsNotValid)
  1502  
  1503  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers.3"), commands.ErrIsNotValidVegaPubkey)
  1504  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers.2"), commands.ErrIsNotValidEthereumAddress)
  1505  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers.1"), commands.ErrIsNotValidVegaPubkey)
  1506  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers.0"), commands.ErrIsNotValidVegaPubkey)
  1507  }
  1508  
  1509  func testNewFutureMarketChangeSubmissionWithGoodPubKeysOrderAddressSucceed(t *testing.T) {
  1510  	pubKeys := []*dstypes.Signer{
  1511  		dstypes.CreateSignerFromString("0x8565a19c49bcD6Fa7b6EB0221a50606F9c9cC683", dstypes.SignerTypeEthAddress),
  1512  		dstypes.CreateSignerFromString("bd069246503a57271375f1995c46e03db88c4e1a564077b33a9872f905650dc4", dstypes.SignerTypePubKey),
  1513  	}
  1514  
  1515  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1516  		Terms: &vegapb.ProposalTerms{
  1517  			Change: &vegapb.ProposalTerms_NewMarket{
  1518  				NewMarket: &vegapb.NewMarket{
  1519  					Changes: &vegapb.NewMarketConfiguration{
  1520  						Instrument: &vegapb.InstrumentConfiguration{
  1521  							Product: &vegapb.InstrumentConfiguration_Future{
  1522  								Future: &vegapb.FutureProduct{
  1523  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1524  										vegapb.DataSourceContentTypeOracle,
  1525  									).SetOracleConfig(
  1526  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1527  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1528  												Signers: dstypes.SignersIntoProto(pubKeys),
  1529  											},
  1530  										},
  1531  									),
  1532  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  1533  										vegapb.DataSourceContentTypeOracle,
  1534  									).SetOracleConfig(
  1535  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1536  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1537  												Signers: dstypes.SignersIntoProto(pubKeys),
  1538  											},
  1539  										},
  1540  									),
  1541  								},
  1542  							},
  1543  						},
  1544  					},
  1545  				},
  1546  			},
  1547  		},
  1548  	})
  1549  
  1550  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers"), commands.ErrIsRequired)
  1551  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers.0"), commands.ErrIsNotValid)
  1552  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers.1"), commands.ErrIsNotValid)
  1553  
  1554  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers.1"), commands.ErrIsNotValidEthereumAddress)
  1555  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers.0"), commands.ErrIsNotValidVegaPubkey)
  1556  }
  1557  
  1558  func testNewFutureMarketChangeSubmissionWithoutFiltersFails(t *testing.T) {
  1559  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1560  		Terms: &vegapb.ProposalTerms{
  1561  			Change: &vegapb.ProposalTerms_NewMarket{
  1562  				NewMarket: &vegapb.NewMarket{
  1563  					Changes: &vegapb.NewMarketConfiguration{
  1564  						Instrument: &vegapb.InstrumentConfiguration{
  1565  							Product: &vegapb.InstrumentConfiguration_Future{
  1566  								Future: &vegapb.FutureProduct{
  1567  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1568  										vegapb.DataSourceContentTypeOracle,
  1569  									),
  1570  								},
  1571  							},
  1572  						},
  1573  					},
  1574  				},
  1575  			},
  1576  		},
  1577  	})
  1578  
  1579  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters"), commands.ErrIsRequired)
  1580  }
  1581  
  1582  func testNewFutureMarketChangeSubmissionWithFiltersSucceeds(t *testing.T) {
  1583  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1584  		Terms: &vegapb.ProposalTerms{
  1585  			Change: &vegapb.ProposalTerms_NewMarket{
  1586  				NewMarket: &vegapb.NewMarket{
  1587  					Changes: &vegapb.NewMarketConfiguration{
  1588  						Instrument: &vegapb.InstrumentConfiguration{
  1589  							Product: &vegapb.InstrumentConfiguration_Future{
  1590  								Future: &vegapb.FutureProduct{
  1591  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1592  										vegapb.DataSourceContentTypeOracle,
  1593  									).SetOracleConfig(
  1594  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1595  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1596  												Filters: []*datapb.Filter{
  1597  													{},
  1598  												},
  1599  											},
  1600  										},
  1601  									),
  1602  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  1603  										vegapb.DataSourceContentTypeOracle,
  1604  									).SetOracleConfig(
  1605  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1606  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1607  												Filters: []*datapb.Filter{
  1608  													{},
  1609  												},
  1610  											},
  1611  										},
  1612  									),
  1613  								},
  1614  							},
  1615  						},
  1616  					},
  1617  				},
  1618  			},
  1619  		},
  1620  	})
  1621  
  1622  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters"), commands.ErrIsRequired)
  1623  }
  1624  
  1625  func testNewFutureMarketChangeSubmissionWithFilterWithoutKeyFails(t *testing.T) {
  1626  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1627  		Terms: &vegapb.ProposalTerms{
  1628  			Change: &vegapb.ProposalTerms_NewMarket{
  1629  				NewMarket: &vegapb.NewMarket{
  1630  					Changes: &vegapb.NewMarketConfiguration{
  1631  						Instrument: &vegapb.InstrumentConfiguration{
  1632  							Product: &vegapb.InstrumentConfiguration_Future{
  1633  								Future: &vegapb.FutureProduct{
  1634  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1635  										vegapb.DataSourceContentTypeOracle,
  1636  									).SetOracleConfig(
  1637  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1638  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1639  												Filters: []*datapb.Filter{
  1640  													{}, {},
  1641  												},
  1642  											},
  1643  										},
  1644  									),
  1645  								},
  1646  							},
  1647  						},
  1648  					},
  1649  				},
  1650  			},
  1651  		},
  1652  	})
  1653  
  1654  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters.0.key"), commands.ErrIsNotValid)
  1655  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters.1.key"), commands.ErrIsNotValid)
  1656  }
  1657  
  1658  func testNewFutureMarketChangeSubmissionWithFilterWithKeySucceeds(t *testing.T) {
  1659  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1660  		Terms: &vegapb.ProposalTerms{
  1661  			Change: &vegapb.ProposalTerms_NewMarket{
  1662  				NewMarket: &vegapb.NewMarket{
  1663  					Changes: &vegapb.NewMarketConfiguration{
  1664  						Instrument: &vegapb.InstrumentConfiguration{
  1665  							Product: &vegapb.InstrumentConfiguration_Future{
  1666  								Future: &vegapb.FutureProduct{
  1667  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1668  										vegapb.DataSourceContentTypeOracle,
  1669  									).SetOracleConfig(
  1670  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1671  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1672  												Filters: []*datapb.Filter{
  1673  													{
  1674  														Key: &datapb.PropertyKey{},
  1675  													}, {
  1676  														Key: &datapb.PropertyKey{},
  1677  													},
  1678  												},
  1679  											},
  1680  										},
  1681  									),
  1682  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  1683  										vegapb.DataSourceContentTypeOracle,
  1684  									).SetOracleConfig(
  1685  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1686  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1687  												Filters: []*datapb.Filter{
  1688  													{
  1689  														Key: &datapb.PropertyKey{},
  1690  													}, {
  1691  														Key: &datapb.PropertyKey{},
  1692  													},
  1693  												},
  1694  											},
  1695  										},
  1696  									),
  1697  								},
  1698  							},
  1699  						},
  1700  					},
  1701  				},
  1702  			},
  1703  		},
  1704  	})
  1705  
  1706  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters.0.key"), commands.ErrIsNotValid)
  1707  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters.1.key"), commands.ErrIsNotValid)
  1708  }
  1709  
  1710  func testNewFutureMarketChangeSubmissionWithFilterWithoutKeyNameFails(t *testing.T) {
  1711  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1712  		Terms: &vegapb.ProposalTerms{
  1713  			Change: &vegapb.ProposalTerms_NewMarket{
  1714  				NewMarket: &vegapb.NewMarket{
  1715  					Changes: &vegapb.NewMarketConfiguration{
  1716  						Instrument: &vegapb.InstrumentConfiguration{
  1717  							Product: &vegapb.InstrumentConfiguration_Future{
  1718  								Future: &vegapb.FutureProduct{
  1719  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1720  										vegapb.DataSourceContentTypeOracle,
  1721  									).SetOracleConfig(
  1722  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1723  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1724  												Filters: []*datapb.Filter{
  1725  													{
  1726  														Key: &datapb.PropertyKey{
  1727  															Name: "",
  1728  														},
  1729  													}, {
  1730  														Key: &datapb.PropertyKey{
  1731  															Name: "",
  1732  														},
  1733  													},
  1734  												},
  1735  											},
  1736  										},
  1737  									),
  1738  								},
  1739  							},
  1740  						},
  1741  					},
  1742  				},
  1743  			},
  1744  		},
  1745  	})
  1746  
  1747  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters.0.key.name"), commands.ErrIsRequired)
  1748  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters.1.key.name"), commands.ErrIsRequired)
  1749  }
  1750  
  1751  func testNewFutureMarketChangeSubmissionWithFilterWithKeyNameSucceeds(t *testing.T) {
  1752  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1753  		Terms: &vegapb.ProposalTerms{
  1754  			Change: &vegapb.ProposalTerms_NewMarket{
  1755  				NewMarket: &vegapb.NewMarket{
  1756  					Changes: &vegapb.NewMarketConfiguration{
  1757  						Instrument: &vegapb.InstrumentConfiguration{
  1758  							Product: &vegapb.InstrumentConfiguration_Future{
  1759  								Future: &vegapb.FutureProduct{
  1760  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1761  										vegapb.DataSourceContentTypeOracle,
  1762  									).SetOracleConfig(
  1763  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1764  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1765  												Filters: []*datapb.Filter{
  1766  													{
  1767  														Key: &datapb.PropertyKey{
  1768  															Name: "key1",
  1769  														},
  1770  													}, {
  1771  														Key: &datapb.PropertyKey{
  1772  															Name: "key2",
  1773  														},
  1774  													},
  1775  												},
  1776  											},
  1777  										},
  1778  									),
  1779  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  1780  										vegapb.DataSourceContentTypeOracle,
  1781  									).SetOracleConfig(
  1782  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1783  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1784  												Filters: []*datapb.Filter{
  1785  													{
  1786  														Key: &datapb.PropertyKey{
  1787  															Name: "key1",
  1788  														},
  1789  													}, {
  1790  														Key: &datapb.PropertyKey{
  1791  															Name: "key2",
  1792  														},
  1793  													},
  1794  												},
  1795  											},
  1796  										},
  1797  									),
  1798  								},
  1799  							},
  1800  						},
  1801  					},
  1802  				},
  1803  			},
  1804  		},
  1805  	})
  1806  
  1807  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters.0.key.name"), commands.ErrIsRequired)
  1808  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters.1.key.name"), commands.ErrIsRequired)
  1809  }
  1810  
  1811  func testNewFutureMarketChangeSubmissionWithFilterWithoutKeyTypeFails(t *testing.T) {
  1812  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1813  		Terms: &vegapb.ProposalTerms{
  1814  			Change: &vegapb.ProposalTerms_NewMarket{
  1815  				NewMarket: &vegapb.NewMarket{
  1816  					Changes: &vegapb.NewMarketConfiguration{
  1817  						Instrument: &vegapb.InstrumentConfiguration{
  1818  							Product: &vegapb.InstrumentConfiguration_Future{
  1819  								Future: &vegapb.FutureProduct{
  1820  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1821  										vegapb.DataSourceContentTypeOracle,
  1822  									).SetOracleConfig(
  1823  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1824  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1825  												Filters: []*datapb.Filter{
  1826  													{
  1827  														Key: &datapb.PropertyKey{
  1828  															Type: datapb.PropertyKey_TYPE_UNSPECIFIED,
  1829  														},
  1830  													}, {
  1831  														Key: &datapb.PropertyKey{},
  1832  													},
  1833  												},
  1834  											},
  1835  										},
  1836  									),
  1837  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  1838  										vegapb.DataSourceContentTypeOracle,
  1839  									).SetOracleConfig(
  1840  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1841  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1842  												Filters: []*datapb.Filter{
  1843  													{
  1844  														Key: &datapb.PropertyKey{
  1845  															Type: datapb.PropertyKey_TYPE_UNSPECIFIED,
  1846  														},
  1847  													}, {
  1848  														Key: &datapb.PropertyKey{},
  1849  													},
  1850  												},
  1851  											},
  1852  										},
  1853  									),
  1854  								},
  1855  							},
  1856  						},
  1857  					},
  1858  				},
  1859  			},
  1860  		},
  1861  	})
  1862  
  1863  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters.0.key.type"), commands.ErrIsRequired)
  1864  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters.1.key.type"), commands.ErrIsRequired)
  1865  }
  1866  
  1867  func testNewFutureMarketChangeSubmissionWithFilterWithKeyTypeSucceeds(t *testing.T) {
  1868  	testCases := []struct {
  1869  		msg   string
  1870  		value datapb.PropertyKey_Type
  1871  	}{
  1872  		{
  1873  			msg:   "with EMPTY",
  1874  			value: datapb.PropertyKey_TYPE_EMPTY,
  1875  		}, {
  1876  			msg:   "with INTEGER",
  1877  			value: datapb.PropertyKey_TYPE_INTEGER,
  1878  		}, {
  1879  			msg:   "with STRING",
  1880  			value: datapb.PropertyKey_TYPE_STRING,
  1881  		}, {
  1882  			msg:   "with BOOLEAN",
  1883  			value: datapb.PropertyKey_TYPE_BOOLEAN,
  1884  		}, {
  1885  			msg:   "with DECIMAL",
  1886  			value: datapb.PropertyKey_TYPE_DECIMAL,
  1887  		}, {
  1888  			msg:   "with TIMESTAMP",
  1889  			value: datapb.PropertyKey_TYPE_TIMESTAMP,
  1890  		},
  1891  	}
  1892  	for _, tc := range testCases {
  1893  		t.Run(tc.msg, func(t *testing.T) {
  1894  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1895  				Terms: &vegapb.ProposalTerms{
  1896  					Change: &vegapb.ProposalTerms_NewMarket{
  1897  						NewMarket: &vegapb.NewMarket{
  1898  							Changes: &vegapb.NewMarketConfiguration{
  1899  								Instrument: &vegapb.InstrumentConfiguration{
  1900  									Product: &vegapb.InstrumentConfiguration_Future{
  1901  										Future: &vegapb.FutureProduct{
  1902  											DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1903  												vegapb.DataSourceContentTypeOracle,
  1904  											).SetOracleConfig(
  1905  												&vegapb.DataSourceDefinitionExternal_Oracle{
  1906  													Oracle: &vegapb.DataSourceSpecConfiguration{
  1907  														Filters: []*datapb.Filter{
  1908  															{
  1909  																Key: &datapb.PropertyKey{
  1910  																	Type: tc.value,
  1911  																},
  1912  															}, {
  1913  																Key: &datapb.PropertyKey{
  1914  																	Type: tc.value,
  1915  																},
  1916  															},
  1917  														},
  1918  													},
  1919  												},
  1920  											),
  1921  										},
  1922  									},
  1923  								},
  1924  							},
  1925  						},
  1926  					},
  1927  				},
  1928  			})
  1929  
  1930  			assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec.external.oracle.filters.0.key.type"), commands.ErrIsRequired)
  1931  			assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec.external.oracle.filters.1.key.type"), commands.ErrIsRequired)
  1932  		})
  1933  	}
  1934  }
  1935  
  1936  func testNewFutureMarketChangeSubmissionWithFilterWithoutConditionsSucceeds(t *testing.T) {
  1937  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1938  		Terms: &vegapb.ProposalTerms{
  1939  			Change: &vegapb.ProposalTerms_NewMarket{
  1940  				NewMarket: &vegapb.NewMarket{
  1941  					Changes: &vegapb.NewMarketConfiguration{
  1942  						Instrument: &vegapb.InstrumentConfiguration{
  1943  							Product: &vegapb.InstrumentConfiguration_Future{
  1944  								Future: &vegapb.FutureProduct{
  1945  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1946  										vegapb.DataSourceContentTypeOracle,
  1947  									).SetOracleConfig(
  1948  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1949  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1950  												Filters: []*datapb.Filter{
  1951  													{
  1952  														Conditions: []*datapb.Condition{},
  1953  													},
  1954  												},
  1955  											},
  1956  										},
  1957  									),
  1958  								},
  1959  							},
  1960  						},
  1961  					},
  1962  				},
  1963  			},
  1964  		},
  1965  	})
  1966  
  1967  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec.external.oracle.filters.0.conditions"), commands.ErrIsRequired)
  1968  }
  1969  
  1970  func testNewFutureMarketChangeSubmissionWithFilterWithoutConditionOperatorFails(t *testing.T) {
  1971  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1972  		Terms: &vegapb.ProposalTerms{
  1973  			Change: &vegapb.ProposalTerms_NewMarket{
  1974  				NewMarket: &vegapb.NewMarket{
  1975  					Changes: &vegapb.NewMarketConfiguration{
  1976  						Instrument: &vegapb.InstrumentConfiguration{
  1977  							Product: &vegapb.InstrumentConfiguration_Future{
  1978  								Future: &vegapb.FutureProduct{
  1979  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1980  										vegapb.DataSourceContentTypeOracle,
  1981  									).SetOracleConfig(
  1982  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1983  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1984  												Filters: []*datapb.Filter{
  1985  													{
  1986  														Conditions: []*datapb.Condition{
  1987  															{
  1988  																Operator: datapb.Condition_OPERATOR_UNSPECIFIED,
  1989  															},
  1990  															{},
  1991  														},
  1992  													},
  1993  												},
  1994  											},
  1995  										},
  1996  									),
  1997  								},
  1998  							},
  1999  						},
  2000  					},
  2001  				},
  2002  			},
  2003  		},
  2004  	})
  2005  
  2006  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters.0.conditions.0.operator"), commands.ErrIsRequired)
  2007  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters.0.conditions.1.operator"), commands.ErrIsRequired)
  2008  }
  2009  
  2010  func testNewFutureMarketChangeSubmissionWithFilterWithConditionOperatorSucceeds(t *testing.T) {
  2011  	testCases := []struct {
  2012  		msg   string
  2013  		value datapb.Condition_Operator
  2014  	}{
  2015  		{
  2016  			msg:   "with EQUALS",
  2017  			value: datapb.Condition_OPERATOR_EQUALS,
  2018  		}, {
  2019  			msg:   "with GREATER_THAN",
  2020  			value: datapb.Condition_OPERATOR_GREATER_THAN,
  2021  		}, {
  2022  			msg:   "with GREATER_THAN_OR_EQUAL",
  2023  			value: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  2024  		}, {
  2025  			msg:   "with LESS_THAN",
  2026  			value: datapb.Condition_OPERATOR_LESS_THAN,
  2027  		}, {
  2028  			msg:   "with LESS_THAN_OR_EQUAL",
  2029  			value: datapb.Condition_OPERATOR_LESS_THAN_OR_EQUAL,
  2030  		},
  2031  	}
  2032  	for _, tc := range testCases {
  2033  		t.Run(tc.msg, func(t *testing.T) {
  2034  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2035  				Terms: &vegapb.ProposalTerms{
  2036  					Change: &vegapb.ProposalTerms_NewMarket{
  2037  						NewMarket: &vegapb.NewMarket{
  2038  							Changes: &vegapb.NewMarketConfiguration{
  2039  								Instrument: &vegapb.InstrumentConfiguration{
  2040  									Product: &vegapb.InstrumentConfiguration_Future{
  2041  										Future: &vegapb.FutureProduct{
  2042  											DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  2043  												vegapb.DataSourceContentTypeOracle,
  2044  											).SetOracleConfig(
  2045  												&vegapb.DataSourceDefinitionExternal_Oracle{
  2046  													Oracle: &vegapb.DataSourceSpecConfiguration{
  2047  														Filters: []*datapb.Filter{
  2048  															{
  2049  																Conditions: []*datapb.Condition{
  2050  																	{
  2051  																		Operator: tc.value,
  2052  																	},
  2053  																	{
  2054  																		Operator: tc.value,
  2055  																	},
  2056  																},
  2057  															},
  2058  														},
  2059  													},
  2060  												},
  2061  											),
  2062  										},
  2063  									},
  2064  								},
  2065  							},
  2066  						},
  2067  					},
  2068  				},
  2069  			})
  2070  
  2071  			assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec.external.oracle.filters.0.conditions.0.operator"), commands.ErrIsRequired)
  2072  			assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec.external.oracle.filters.1.conditions.0.operator"), commands.ErrIsRequired)
  2073  		})
  2074  	}
  2075  }
  2076  
  2077  func testNewFutureMarketChangeSubmissionWithFilterWithoutConditionValueFails(t *testing.T) {
  2078  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2079  		Terms: &vegapb.ProposalTerms{
  2080  			Change: &vegapb.ProposalTerms_NewMarket{
  2081  				NewMarket: &vegapb.NewMarket{
  2082  					Changes: &vegapb.NewMarketConfiguration{
  2083  						Instrument: &vegapb.InstrumentConfiguration{
  2084  							Product: &vegapb.InstrumentConfiguration_Future{
  2085  								Future: &vegapb.FutureProduct{
  2086  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  2087  										vegapb.DataSourceContentTypeOracle,
  2088  									).SetOracleConfig(
  2089  										&vegapb.DataSourceDefinitionExternal_Oracle{
  2090  											Oracle: &vegapb.DataSourceSpecConfiguration{
  2091  												Filters: []*datapb.Filter{
  2092  													{
  2093  														Conditions: []*datapb.Condition{
  2094  															{
  2095  																Value: "",
  2096  															},
  2097  															{
  2098  																Value: "",
  2099  															},
  2100  														},
  2101  													},
  2102  												},
  2103  											},
  2104  										},
  2105  									),
  2106  								},
  2107  							},
  2108  						},
  2109  					},
  2110  				},
  2111  			},
  2112  		},
  2113  	})
  2114  
  2115  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters.0.conditions.0.value"), commands.ErrIsRequired)
  2116  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters.0.conditions.1.value"), commands.ErrIsRequired)
  2117  }
  2118  
  2119  func testNewFutureMarketChangeSubmissionWithFilterWithConditionValueSucceeds(t *testing.T) {
  2120  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2121  		Terms: &vegapb.ProposalTerms{
  2122  			Change: &vegapb.ProposalTerms_NewMarket{
  2123  				NewMarket: &vegapb.NewMarket{
  2124  					Changes: &vegapb.NewMarketConfiguration{
  2125  						Instrument: &vegapb.InstrumentConfiguration{
  2126  							Product: &vegapb.InstrumentConfiguration_Future{
  2127  								Future: &vegapb.FutureProduct{
  2128  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  2129  										vegapb.DataSourceContentTypeOracle,
  2130  									).SetOracleConfig(
  2131  										&vegapb.DataSourceDefinitionExternal_Oracle{
  2132  											Oracle: &vegapb.DataSourceSpecConfiguration{
  2133  												Filters: []*datapb.Filter{
  2134  													{
  2135  														Conditions: []*datapb.Condition{
  2136  															{
  2137  																Value: "value 1",
  2138  															},
  2139  															{
  2140  																Value: "value 2",
  2141  															},
  2142  														},
  2143  													},
  2144  												},
  2145  											},
  2146  										},
  2147  									),
  2148  								},
  2149  							},
  2150  						},
  2151  					},
  2152  				},
  2153  			},
  2154  		},
  2155  	})
  2156  
  2157  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec.external.oracle.filters.0.conditions.0.value"), commands.ErrIsRequired)
  2158  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec.external.oracle.filters.0.conditions.1.value"), commands.ErrIsRequired)
  2159  }
  2160  
  2161  func testNewFutureMarketChangeSubmissionWithoutDataSourceSpecBindingFails(t *testing.T) {
  2162  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2163  		Terms: &vegapb.ProposalTerms{
  2164  			Change: &vegapb.ProposalTerms_NewMarket{
  2165  				NewMarket: &vegapb.NewMarket{
  2166  					Changes: &vegapb.NewMarketConfiguration{
  2167  						Instrument: &vegapb.InstrumentConfiguration{
  2168  							Product: &vegapb.InstrumentConfiguration_Future{
  2169  								Future: &vegapb.FutureProduct{},
  2170  							},
  2171  						},
  2172  					},
  2173  				},
  2174  			},
  2175  		},
  2176  	})
  2177  
  2178  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_binding"), commands.ErrIsRequired)
  2179  }
  2180  
  2181  func testNewFutureMarketChangeSubmissionWithDataSourceSpecBindingSucceeds(t *testing.T) {
  2182  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2183  		Terms: &vegapb.ProposalTerms{
  2184  			Change: &vegapb.ProposalTerms_NewMarket{
  2185  				NewMarket: &vegapb.NewMarket{
  2186  					Changes: &vegapb.NewMarketConfiguration{
  2187  						Instrument: &vegapb.InstrumentConfiguration{
  2188  							Product: &vegapb.InstrumentConfiguration_Future{
  2189  								Future: &vegapb.FutureProduct{
  2190  									DataSourceSpecBinding: &vegapb.DataSourceSpecToFutureBinding{},
  2191  								},
  2192  							},
  2193  						},
  2194  					},
  2195  				},
  2196  			},
  2197  		},
  2198  	})
  2199  
  2200  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_binding"), commands.ErrIsRequired)
  2201  }
  2202  
  2203  func testNewFutureMarketChangeSubmissionMissingOracleBindingPropertyFails(t *testing.T, property string) {
  2204  	t.Helper()
  2205  	var binding *vegapb.DataSourceSpecToFutureBinding
  2206  	if property == "settlement_data_property" {
  2207  		binding = &vegapb.DataSourceSpecToFutureBinding{
  2208  			SettlementDataProperty: "",
  2209  		}
  2210  	} else {
  2211  		binding = &vegapb.DataSourceSpecToFutureBinding{
  2212  			TradingTerminationProperty: "",
  2213  		}
  2214  	}
  2215  
  2216  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2217  		Terms: &vegapb.ProposalTerms{
  2218  			Change: &vegapb.ProposalTerms_NewMarket{
  2219  				NewMarket: &vegapb.NewMarket{
  2220  					Changes: &vegapb.NewMarketConfiguration{
  2221  						Instrument: &vegapb.InstrumentConfiguration{
  2222  							Product: &vegapb.InstrumentConfiguration_Future{
  2223  								Future: &vegapb.FutureProduct{
  2224  									DataSourceSpecBinding: binding,
  2225  								},
  2226  							},
  2227  						},
  2228  					},
  2229  				},
  2230  			},
  2231  		},
  2232  	})
  2233  
  2234  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_binding."+property), commands.ErrIsRequired)
  2235  }
  2236  
  2237  func testNewFutureMarketChangeSubmissionWithoutTradingTerminationPropertyFails(t *testing.T) {
  2238  	testNewFutureMarketChangeSubmissionMissingOracleBindingPropertyFails(t, "trading_termination_property")
  2239  }
  2240  
  2241  func testNewFutureMarketChangeSubmissionWithoutSettlementDataPropertyFails(t *testing.T) {
  2242  	testNewFutureMarketChangeSubmissionMissingOracleBindingPropertyFails(t, "settlement_data_property")
  2243  }
  2244  
  2245  func testNewFutureMarketChangeSubmissionWithNoMismatchBetweenFilterAndBindingSucceeds(t *testing.T) {
  2246  	testNewFutureMarketChangeSubmissionWithNoMismatchBetweenFilterAndBindingForSpecSucceeds(t, &vegapb.DataSourceSpecToFutureBinding{SettlementDataProperty: "key1"}, "settlement_data_property", "key1")
  2247  	testNewFutureMarketChangeSubmissionWithNoMismatchBetweenFilterAndBindingForSpecSucceeds(t, &vegapb.DataSourceSpecToFutureBinding{TradingTerminationProperty: "key2"}, "settlement_data_property", "key2")
  2248  }
  2249  
  2250  func testNewFutureMarketChangeSubmissionWithNoMismatchBetweenFilterAndBindingForSpecSucceeds(t *testing.T, binding *vegapb.DataSourceSpecToFutureBinding, bindingName string, bindingKey string) {
  2251  	t.Helper()
  2252  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2253  		Terms: &vegapb.ProposalTerms{
  2254  			Change: &vegapb.ProposalTerms_NewMarket{
  2255  				NewMarket: &vegapb.NewMarket{
  2256  					Changes: &vegapb.NewMarketConfiguration{
  2257  						Instrument: &vegapb.InstrumentConfiguration{
  2258  							Product: &vegapb.InstrumentConfiguration_Future{
  2259  								Future: &vegapb.FutureProduct{
  2260  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  2261  										vegapb.DataSourceContentTypeOracle,
  2262  									).SetOracleConfig(
  2263  										&vegapb.DataSourceDefinitionExternal_Oracle{
  2264  											Oracle: &vegapb.DataSourceSpecConfiguration{
  2265  												Filters: []*datapb.Filter{
  2266  													{
  2267  														Key: &datapb.PropertyKey{
  2268  															Name: bindingKey,
  2269  														},
  2270  													}, {
  2271  														Key: &datapb.PropertyKey{},
  2272  													},
  2273  												},
  2274  											},
  2275  										},
  2276  									),
  2277  									DataSourceSpecBinding: binding,
  2278  								},
  2279  							},
  2280  						},
  2281  					},
  2282  				},
  2283  			},
  2284  		},
  2285  	})
  2286  
  2287  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_binding."+bindingName), commands.ErrIsMismatching)
  2288  }
  2289  
  2290  func testNewFutureMarketChangeSubmissionWithMismatchBetweenFilterAndBindingForSpecFails(t *testing.T, binding *vegapb.DataSourceSpecToFutureBinding, bindingName string) {
  2291  	t.Helper()
  2292  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2293  		Terms: &vegapb.ProposalTerms{
  2294  			Change: &vegapb.ProposalTerms_NewMarket{
  2295  				NewMarket: &vegapb.NewMarket{
  2296  					Changes: &vegapb.NewMarketConfiguration{
  2297  						Instrument: &vegapb.InstrumentConfiguration{
  2298  							Product: &vegapb.InstrumentConfiguration_Future{
  2299  								Future: &vegapb.FutureProduct{
  2300  									DataSourceSpecBinding: binding,
  2301  								},
  2302  							},
  2303  						},
  2304  					},
  2305  				},
  2306  			},
  2307  		},
  2308  	})
  2309  
  2310  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_binding."+bindingName), commands.ErrIsMismatching)
  2311  }
  2312  
  2313  func testNewFutureMarketChangeSubmissionWithMismatchBetweenFilterAndBindingFails(t *testing.T) {
  2314  	testNewFutureMarketChangeSubmissionWithMismatchBetweenFilterAndBindingForSpecFails(t, &vegapb.DataSourceSpecToFutureBinding{SettlementDataProperty: "My property"}, "settlement_data_property")
  2315  	testNewFutureMarketChangeSubmissionWithMismatchBetweenFilterAndBindingForSpecFails(t, &vegapb.DataSourceSpecToFutureBinding{TradingTerminationProperty: "My property"}, "trading_termination_property")
  2316  }
  2317  
  2318  func testNewFutureMarketChangeSubmissionWithSettlementDataPropertySucceeds(t *testing.T) {
  2319  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2320  		Terms: &vegapb.ProposalTerms{
  2321  			Change: &vegapb.ProposalTerms_NewMarket{
  2322  				NewMarket: &vegapb.NewMarket{
  2323  					Changes: &vegapb.NewMarketConfiguration{
  2324  						Instrument: &vegapb.InstrumentConfiguration{
  2325  							Product: &vegapb.InstrumentConfiguration_Future{
  2326  								Future: &vegapb.FutureProduct{
  2327  									DataSourceSpecBinding: &vegapb.DataSourceSpecToFutureBinding{
  2328  										SettlementDataProperty: "My property",
  2329  									},
  2330  								},
  2331  							},
  2332  						},
  2333  					},
  2334  				},
  2335  			},
  2336  		},
  2337  	})
  2338  
  2339  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_binding.settlement_data_property"), commands.ErrIsRequired)
  2340  }
  2341  
  2342  func testNewSimpleRiskParametersChangeSubmissionWithoutSimpleRiskParametersFails(t *testing.T) {
  2343  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2344  		Terms: &vegapb.ProposalTerms{
  2345  			Change: &vegapb.ProposalTerms_NewMarket{
  2346  				NewMarket: &vegapb.NewMarket{
  2347  					Changes: &vegapb.NewMarketConfiguration{
  2348  						RiskParameters: &vegapb.NewMarketConfiguration_Simple{},
  2349  					},
  2350  				},
  2351  			},
  2352  		},
  2353  	})
  2354  
  2355  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.simple"), commands.ErrIsRequired)
  2356  }
  2357  
  2358  func testNewSimpleRiskParametersChangeSubmissionWithSimpleRiskParametersSucceeds(t *testing.T) {
  2359  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2360  		Terms: &vegapb.ProposalTerms{
  2361  			Change: &vegapb.ProposalTerms_NewMarket{
  2362  				NewMarket: &vegapb.NewMarket{
  2363  					Changes: &vegapb.NewMarketConfiguration{
  2364  						RiskParameters: &vegapb.NewMarketConfiguration_Simple{
  2365  							Simple: &vegapb.SimpleModelParams{},
  2366  						},
  2367  					},
  2368  				},
  2369  			},
  2370  		},
  2371  	})
  2372  
  2373  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.simple"), commands.ErrIsRequired)
  2374  }
  2375  
  2376  func testNewSimpleRiskParametersChangeSubmissionWithPositiveMinMoveDownFails(t *testing.T) {
  2377  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2378  		Terms: &vegapb.ProposalTerms{
  2379  			Change: &vegapb.ProposalTerms_NewMarket{
  2380  				NewMarket: &vegapb.NewMarket{
  2381  					Changes: &vegapb.NewMarketConfiguration{
  2382  						RiskParameters: &vegapb.NewMarketConfiguration_Simple{
  2383  							Simple: &vegapb.SimpleModelParams{
  2384  								MinMoveDown: 1,
  2385  							},
  2386  						},
  2387  					},
  2388  				},
  2389  			},
  2390  		},
  2391  	})
  2392  
  2393  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.simple.min_move_down"), commands.ErrMustBeNegativeOrZero)
  2394  }
  2395  
  2396  func testNewSimpleRiskParametersChangeSubmissionWithNonPositiveMinMoveDownSucceeds(t *testing.T) {
  2397  	testCases := []struct {
  2398  		msg   string
  2399  		value float64
  2400  	}{
  2401  		{
  2402  			msg:   "with min move down of 0",
  2403  			value: 0,
  2404  		}, {
  2405  			msg:   "with min move down of -1",
  2406  			value: -1,
  2407  		},
  2408  	}
  2409  	for _, tc := range testCases {
  2410  		t.Run(tc.msg, func(t *testing.T) {
  2411  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2412  				Terms: &vegapb.ProposalTerms{
  2413  					Change: &vegapb.ProposalTerms_NewMarket{
  2414  						NewMarket: &vegapb.NewMarket{
  2415  							Changes: &vegapb.NewMarketConfiguration{
  2416  								RiskParameters: &vegapb.NewMarketConfiguration_Simple{
  2417  									Simple: &vegapb.SimpleModelParams{
  2418  										MinMoveDown: tc.value,
  2419  									},
  2420  								},
  2421  							},
  2422  						},
  2423  					},
  2424  				},
  2425  			})
  2426  
  2427  			assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.simple.min_move_down"), commands.ErrMustBeNegativeOrZero)
  2428  		})
  2429  	}
  2430  }
  2431  
  2432  func testNewSimpleRiskParametersChangeSubmissionWithNonNegativeMaxMoveUpSucceeds(t *testing.T) {
  2433  	testCases := []struct {
  2434  		msg   string
  2435  		value float64
  2436  	}{
  2437  		{
  2438  			msg:   "with max move up of 0",
  2439  			value: 0,
  2440  		}, {
  2441  			msg:   "with max move up of 1",
  2442  			value: 1,
  2443  		},
  2444  	}
  2445  	for _, tc := range testCases {
  2446  		t.Run(tc.msg, func(t *testing.T) {
  2447  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2448  				Terms: &vegapb.ProposalTerms{
  2449  					Change: &vegapb.ProposalTerms_NewMarket{
  2450  						NewMarket: &vegapb.NewMarket{
  2451  							Changes: &vegapb.NewMarketConfiguration{
  2452  								RiskParameters: &vegapb.NewMarketConfiguration_Simple{
  2453  									Simple: &vegapb.SimpleModelParams{
  2454  										MaxMoveUp: tc.value,
  2455  									},
  2456  								},
  2457  							},
  2458  						},
  2459  					},
  2460  				},
  2461  			})
  2462  
  2463  			assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.simple.max_move_up"), commands.ErrMustBePositiveOrZero)
  2464  		})
  2465  	}
  2466  }
  2467  
  2468  func testNewSimpleRiskParametersChangeSubmissionWithWrongProbabilityOfTradingFails(t *testing.T) {
  2469  	testCases := []struct {
  2470  		msg   string
  2471  		value float64
  2472  	}{
  2473  		{
  2474  			msg:   "with probability of trading of -1",
  2475  			value: -1,
  2476  		}, {
  2477  			msg:   "with probability of trading of 2",
  2478  			value: 2,
  2479  		},
  2480  	}
  2481  	for _, tc := range testCases {
  2482  		t.Run(tc.msg, func(t *testing.T) {
  2483  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2484  				Terms: &vegapb.ProposalTerms{
  2485  					Change: &vegapb.ProposalTerms_NewMarket{
  2486  						NewMarket: &vegapb.NewMarket{
  2487  							Changes: &vegapb.NewMarketConfiguration{
  2488  								RiskParameters: &vegapb.NewMarketConfiguration_Simple{
  2489  									Simple: &vegapb.SimpleModelParams{
  2490  										ProbabilityOfTrading: tc.value,
  2491  									},
  2492  								},
  2493  							},
  2494  						},
  2495  					},
  2496  				},
  2497  			})
  2498  
  2499  			assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.simple.probability_of_trading"),
  2500  				errors.New("should be between 0 (inclusive) and 1 (inclusive)"))
  2501  		})
  2502  	}
  2503  }
  2504  
  2505  func testNewSimpleRiskParametersChangeSubmissionWithRightProbabilityOfTradingSucceeds(t *testing.T) {
  2506  	testCases := []struct {
  2507  		msg   string
  2508  		value float64
  2509  	}{
  2510  		{
  2511  			msg:   "with probability of trading of 0",
  2512  			value: 0,
  2513  		}, {
  2514  			msg:   "with probability of trading of 1",
  2515  			value: 1,
  2516  		}, {
  2517  			msg:   "with probability of trading of 0.5",
  2518  			value: 0.5,
  2519  		},
  2520  	}
  2521  	for _, tc := range testCases {
  2522  		t.Run(tc.msg, func(t *testing.T) {
  2523  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2524  				Terms: &vegapb.ProposalTerms{
  2525  					Change: &vegapb.ProposalTerms_NewMarket{
  2526  						NewMarket: &vegapb.NewMarket{
  2527  							Changes: &vegapb.NewMarketConfiguration{
  2528  								RiskParameters: &vegapb.NewMarketConfiguration_Simple{
  2529  									Simple: &vegapb.SimpleModelParams{
  2530  										ProbabilityOfTrading: tc.value,
  2531  									},
  2532  								},
  2533  							},
  2534  						},
  2535  					},
  2536  				},
  2537  			})
  2538  
  2539  			assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.simple.probability_of_trading"),
  2540  				errors.New("should be between 0 (inclusive) and 1 (inclusive)"))
  2541  		})
  2542  	}
  2543  }
  2544  
  2545  func testNewLogNormalRiskParametersChangeSubmissionWithoutLogNormalRiskParametersFails(t *testing.T) {
  2546  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2547  		Terms: &vegapb.ProposalTerms{
  2548  			Change: &vegapb.ProposalTerms_NewMarket{
  2549  				NewMarket: &vegapb.NewMarket{
  2550  					Changes: &vegapb.NewMarketConfiguration{
  2551  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{},
  2552  					},
  2553  				},
  2554  			},
  2555  		},
  2556  	})
  2557  
  2558  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal"), commands.ErrIsRequired)
  2559  }
  2560  
  2561  func testNewLogNormalRiskParametersChangeSubmissionWithLogNormalRiskParametersSucceeds(t *testing.T) {
  2562  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2563  		Terms: &vegapb.ProposalTerms{
  2564  			Change: &vegapb.ProposalTerms_NewMarket{
  2565  				NewMarket: &vegapb.NewMarket{
  2566  					Changes: &vegapb.NewMarketConfiguration{
  2567  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  2568  							LogNormal: &vegapb.LogNormalRiskModel{
  2569  								RiskAversionParameter: 1,
  2570  								Tau:                   2,
  2571  								Params: &vegapb.LogNormalModelParams{
  2572  									Mu:    0,
  2573  									Sigma: 0.1,
  2574  									R:     0,
  2575  								},
  2576  							},
  2577  						},
  2578  					},
  2579  				},
  2580  			},
  2581  		},
  2582  	})
  2583  
  2584  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal"), commands.ErrIsRequired)
  2585  }
  2586  
  2587  func testNewLogNormalRiskParametersChangeSubmissionWithOverrides(t *testing.T) {
  2588  	cases := []struct {
  2589  		desc     string
  2590  		get      string
  2591  		override *vegapb.RiskFactorOverride
  2592  		err      string
  2593  	}{
  2594  		{
  2595  			desc:     "no override is valid",
  2596  			get:      "proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.risk_factor_override",
  2597  			override: nil,
  2598  			err:      "",
  2599  		},
  2600  		{
  2601  			desc:     "non nil, but with empty short",
  2602  			get:      "proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.risk_factor_override.short",
  2603  			override: &vegapb.RiskFactorOverride{},
  2604  			err:      "is required",
  2605  		},
  2606  		{
  2607  			desc: "non nil, but with bad value short",
  2608  			get:  "proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.risk_factor_override.short",
  2609  			override: &vegapb.RiskFactorOverride{
  2610  				Short: "asd",
  2611  			},
  2612  			err: "is not a valid number",
  2613  		},
  2614  		{
  2615  			desc: "non nil, but with negative short",
  2616  			get:  "proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.risk_factor_override.short",
  2617  			override: &vegapb.RiskFactorOverride{
  2618  				Short: "-1",
  2619  			},
  2620  			err: "must be positive",
  2621  		},
  2622  		{
  2623  			desc: "non nil, but with 0 short",
  2624  			get:  "proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.risk_factor_override.short",
  2625  			override: &vegapb.RiskFactorOverride{
  2626  				Short: "0",
  2627  			},
  2628  			err: "must be positive",
  2629  		},
  2630  		{
  2631  			desc: "non nil, but with empty long",
  2632  			get:  "proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.risk_factor_override.long",
  2633  			override: &vegapb.RiskFactorOverride{
  2634  				Short: "0.1",
  2635  			},
  2636  			err: "is required",
  2637  		},
  2638  		{
  2639  			desc: "non nil, but with bad value long",
  2640  			get:  "proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.risk_factor_override.long",
  2641  			override: &vegapb.RiskFactorOverride{
  2642  				Short: "0.1",
  2643  				Long:  "asd",
  2644  			},
  2645  			err: "is not a valid number",
  2646  		},
  2647  		{
  2648  			desc: "non nil, but with negative long",
  2649  			get:  "proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.risk_factor_override.long",
  2650  			override: &vegapb.RiskFactorOverride{
  2651  				Short: "0.1",
  2652  				Long:  "-1",
  2653  			},
  2654  			err: "must be positive",
  2655  		},
  2656  		{
  2657  			desc: "non nil, but with 0 long",
  2658  			get:  "proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.risk_factor_override.long",
  2659  			override: &vegapb.RiskFactorOverride{
  2660  				Short: "0.1",
  2661  				Long:  "0",
  2662  			},
  2663  			err: "must be positive",
  2664  		},
  2665  		{
  2666  			desc: "both valid",
  2667  			get:  "proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.risk_factor_override",
  2668  			override: &vegapb.RiskFactorOverride{
  2669  				Short: "0.1",
  2670  				Long:  "0.1",
  2671  			},
  2672  			err: "",
  2673  		},
  2674  	}
  2675  
  2676  	for _, c := range cases {
  2677  		err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2678  			Terms: &vegapb.ProposalTerms{
  2679  				Change: &vegapb.ProposalTerms_NewMarket{
  2680  					NewMarket: &vegapb.NewMarket{
  2681  						Changes: &vegapb.NewMarketConfiguration{
  2682  							RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  2683  								LogNormal: &vegapb.LogNormalRiskModel{
  2684  									RiskAversionParameter: 0.1,
  2685  									Tau:                   1,
  2686  									Params: &vegapb.LogNormalModelParams{
  2687  										Mu:    0,
  2688  										Sigma: 0.1,
  2689  										R:     0,
  2690  									},
  2691  									RiskFactorOverride: c.override,
  2692  								},
  2693  							},
  2694  						},
  2695  					},
  2696  				},
  2697  			},
  2698  		})
  2699  
  2700  		if len(c.err) <= 0 {
  2701  			// no error
  2702  			assert.Len(t, err.Get(c.get), 0, c.desc)
  2703  			continue
  2704  		}
  2705  
  2706  		assert.Contains(t, err.Get(c.get), errors.New(c.err), "test: %v, err: %v", c.desc, err)
  2707  	}
  2708  }
  2709  
  2710  func testNewLogNormalRiskParametersChangeSubmissionWithoutParamsFails(t *testing.T) {
  2711  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2712  		Terms: &vegapb.ProposalTerms{
  2713  			Change: &vegapb.ProposalTerms_NewMarket{
  2714  				NewMarket: &vegapb.NewMarket{
  2715  					Changes: &vegapb.NewMarketConfiguration{
  2716  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  2717  							LogNormal: &vegapb.LogNormalRiskModel{},
  2718  						},
  2719  					},
  2720  				},
  2721  			},
  2722  		},
  2723  	})
  2724  
  2725  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.params"), commands.ErrIsRequired)
  2726  }
  2727  
  2728  func testNewLogNormalRiskParametersChangeSubmissionInvalidRiskAversion(t *testing.T) {
  2729  	cTooSmall := &commandspb.ProposalSubmission{
  2730  		Terms: &vegapb.ProposalTerms{
  2731  			Change: &vegapb.ProposalTerms_NewMarket{
  2732  				NewMarket: &vegapb.NewMarket{
  2733  					Changes: &vegapb.NewMarketConfiguration{
  2734  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  2735  							LogNormal: &vegapb.LogNormalRiskModel{
  2736  								RiskAversionParameter: 5e-9,
  2737  								Tau:                   1.0,
  2738  								Params: &vegapb.LogNormalModelParams{
  2739  									Mu:    0.0,
  2740  									Sigma: 0.1,
  2741  									R:     0,
  2742  								},
  2743  							},
  2744  						},
  2745  					},
  2746  				},
  2747  			},
  2748  		},
  2749  	}
  2750  	err := checkProposalSubmission(cTooSmall)
  2751  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.risk_aversion_parameter"), errors.New("must be between [1e-8, 0.1]"))
  2752  
  2753  	cNeg := &commandspb.ProposalSubmission{
  2754  		Terms: &vegapb.ProposalTerms{
  2755  			Change: &vegapb.ProposalTerms_NewMarket{
  2756  				NewMarket: &vegapb.NewMarket{
  2757  					Changes: &vegapb.NewMarketConfiguration{
  2758  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  2759  							LogNormal: &vegapb.LogNormalRiskModel{
  2760  								RiskAversionParameter: 1e-9,
  2761  								Tau:                   2,
  2762  								Params: &vegapb.LogNormalModelParams{
  2763  									Mu:    0,
  2764  									Sigma: 0.1,
  2765  									R:     0,
  2766  								},
  2767  							},
  2768  						},
  2769  					},
  2770  				},
  2771  			},
  2772  		},
  2773  	}
  2774  	err = checkProposalSubmission(cNeg)
  2775  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.risk_aversion_parameter"), errors.New("must be between [1e-8, 0.1]"))
  2776  
  2777  	cTooBig := &commandspb.ProposalSubmission{
  2778  		Terms: &vegapb.ProposalTerms{
  2779  			Change: &vegapb.ProposalTerms_NewMarket{
  2780  				NewMarket: &vegapb.NewMarket{
  2781  					Changes: &vegapb.NewMarketConfiguration{
  2782  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  2783  							LogNormal: &vegapb.LogNormalRiskModel{
  2784  								RiskAversionParameter: 0.1 + 1e-8,
  2785  								Tau:                   2,
  2786  								Params: &vegapb.LogNormalModelParams{
  2787  									Mu:    0,
  2788  									Sigma: 0.1,
  2789  									R:     0,
  2790  								},
  2791  							},
  2792  						},
  2793  					},
  2794  				},
  2795  			},
  2796  		},
  2797  	}
  2798  	err = checkProposalSubmission(cTooBig)
  2799  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.risk_aversion_parameter"), errors.New("must be between [1e-8, 0.1]"))
  2800  
  2801  	cJustAboutRight1 := &commandspb.ProposalSubmission{
  2802  		Terms: &vegapb.ProposalTerms{
  2803  			Change: &vegapb.ProposalTerms_NewMarket{
  2804  				NewMarket: &vegapb.NewMarket{
  2805  					Changes: &vegapb.NewMarketConfiguration{
  2806  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  2807  							LogNormal: &vegapb.LogNormalRiskModel{
  2808  								RiskAversionParameter: 1e-8,
  2809  								Tau:                   2,
  2810  								Params: &vegapb.LogNormalModelParams{
  2811  									Mu:    0,
  2812  									Sigma: 0.1,
  2813  									R:     0,
  2814  								},
  2815  							},
  2816  						},
  2817  					},
  2818  				},
  2819  			},
  2820  		},
  2821  	}
  2822  	err = checkProposalSubmission(cJustAboutRight1)
  2823  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.risk_aversion_parameter"), errors.New("must be between [1e-8, 1)"))
  2824  
  2825  	cJustAboutRight2 := &commandspb.ProposalSubmission{
  2826  		Terms: &vegapb.ProposalTerms{
  2827  			Change: &vegapb.ProposalTerms_NewMarket{
  2828  				NewMarket: &vegapb.NewMarket{
  2829  					Changes: &vegapb.NewMarketConfiguration{
  2830  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  2831  							LogNormal: &vegapb.LogNormalRiskModel{
  2832  								RiskAversionParameter: 1 - 1e-12,
  2833  								Tau:                   2,
  2834  								Params: &vegapb.LogNormalModelParams{
  2835  									Mu:    0,
  2836  									Sigma: 0.1,
  2837  									R:     0,
  2838  								},
  2839  							},
  2840  						},
  2841  					},
  2842  				},
  2843  			},
  2844  		},
  2845  	}
  2846  	err = checkProposalSubmission(cJustAboutRight2)
  2847  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.risk_aversion_parameter"), errors.New("must be between [1e-8, 1)"))
  2848  }
  2849  
  2850  func testNewLogNormalRiskParametersChangeSubmissionInvalidTau(t *testing.T) {
  2851  	cZero := &commandspb.ProposalSubmission{
  2852  		Terms: &vegapb.ProposalTerms{
  2853  			Change: &vegapb.ProposalTerms_NewMarket{
  2854  				NewMarket: &vegapb.NewMarket{
  2855  					Changes: &vegapb.NewMarketConfiguration{
  2856  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  2857  							LogNormal: &vegapb.LogNormalRiskModel{
  2858  								RiskAversionParameter: 0.1,
  2859  								Tau:                   0,
  2860  								Params: &vegapb.LogNormalModelParams{
  2861  									Mu:    0,
  2862  									Sigma: 0.1,
  2863  									R:     0,
  2864  								},
  2865  							},
  2866  						},
  2867  					},
  2868  				},
  2869  			},
  2870  		},
  2871  	}
  2872  	err := checkProposalSubmission(cZero)
  2873  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.tau"), errors.New("must be between [1e-8, 1]"))
  2874  
  2875  	cNeg := &commandspb.ProposalSubmission{
  2876  		Terms: &vegapb.ProposalTerms{
  2877  			Change: &vegapb.ProposalTerms_NewMarket{
  2878  				NewMarket: &vegapb.NewMarket{
  2879  					Changes: &vegapb.NewMarketConfiguration{
  2880  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  2881  							LogNormal: &vegapb.LogNormalRiskModel{
  2882  								RiskAversionParameter: 0.1,
  2883  								Tau:                   1e-9,
  2884  								Params: &vegapb.LogNormalModelParams{
  2885  									Mu:    0,
  2886  									Sigma: 0.1,
  2887  									R:     0,
  2888  								},
  2889  							},
  2890  						},
  2891  					},
  2892  				},
  2893  			},
  2894  		},
  2895  	}
  2896  	err = checkProposalSubmission(cNeg)
  2897  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.tau"), errors.New("must be between [1e-8, 1]"))
  2898  
  2899  	cTooLarge := &commandspb.ProposalSubmission{
  2900  		Terms: &vegapb.ProposalTerms{
  2901  			Change: &vegapb.ProposalTerms_NewMarket{
  2902  				NewMarket: &vegapb.NewMarket{
  2903  					Changes: &vegapb.NewMarketConfiguration{
  2904  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  2905  							LogNormal: &vegapb.LogNormalRiskModel{
  2906  								RiskAversionParameter: 0.1,
  2907  								Tau:                   1 + 1e-12,
  2908  								Params: &vegapb.LogNormalModelParams{
  2909  									Mu:    0,
  2910  									Sigma: 0.1,
  2911  									R:     0,
  2912  								},
  2913  							},
  2914  						},
  2915  					},
  2916  				},
  2917  			},
  2918  		},
  2919  	}
  2920  	err = checkProposalSubmission(cTooLarge)
  2921  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.tau"), errors.New("must be between [1e-8, 1]"))
  2922  
  2923  	cJustAboutRight1 := &commandspb.ProposalSubmission{
  2924  		Terms: &vegapb.ProposalTerms{
  2925  			Change: &vegapb.ProposalTerms_NewMarket{
  2926  				NewMarket: &vegapb.NewMarket{
  2927  					Changes: &vegapb.NewMarketConfiguration{
  2928  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  2929  							LogNormal: &vegapb.LogNormalRiskModel{
  2930  								RiskAversionParameter: 0.1,
  2931  								Tau:                   1e-12,
  2932  								Params: &vegapb.LogNormalModelParams{
  2933  									Mu:    0,
  2934  									Sigma: 0.1,
  2935  									R:     0,
  2936  								},
  2937  							},
  2938  						},
  2939  					},
  2940  				},
  2941  			},
  2942  		},
  2943  	}
  2944  	err = checkProposalSubmission(cJustAboutRight1)
  2945  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.tau"), errors.New("must be between (0, 1]"))
  2946  
  2947  	cJustAboutRight2 := &commandspb.ProposalSubmission{
  2948  		Terms: &vegapb.ProposalTerms{
  2949  			Change: &vegapb.ProposalTerms_NewMarket{
  2950  				NewMarket: &vegapb.NewMarket{
  2951  					Changes: &vegapb.NewMarketConfiguration{
  2952  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  2953  							LogNormal: &vegapb.LogNormalRiskModel{
  2954  								RiskAversionParameter: 0.1,
  2955  								Tau:                   1,
  2956  								Params: &vegapb.LogNormalModelParams{
  2957  									Mu:    0,
  2958  									Sigma: 0.1,
  2959  									R:     0,
  2960  								},
  2961  							},
  2962  						},
  2963  					},
  2964  				},
  2965  			},
  2966  		},
  2967  	}
  2968  	err = checkProposalSubmission(cJustAboutRight2)
  2969  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.tau"), errors.New("must be between (0, 1]"))
  2970  }
  2971  
  2972  func testNewLogNormalRiskParametersChangeSubmissionInvalidMu(t *testing.T) {
  2973  	cNaN := &commandspb.ProposalSubmission{
  2974  		Terms: &vegapb.ProposalTerms{
  2975  			Change: &vegapb.ProposalTerms_NewMarket{
  2976  				NewMarket: &vegapb.NewMarket{
  2977  					Changes: &vegapb.NewMarketConfiguration{
  2978  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  2979  							LogNormal: &vegapb.LogNormalRiskModel{
  2980  								RiskAversionParameter: 0.1,
  2981  								Tau:                   0.2,
  2982  								Params: &vegapb.LogNormalModelParams{
  2983  									Mu:    math.NaN(),
  2984  									Sigma: 0.1,
  2985  									R:     0,
  2986  								},
  2987  							},
  2988  						},
  2989  					},
  2990  				},
  2991  			},
  2992  		},
  2993  	}
  2994  	err := checkProposalSubmission(cNaN)
  2995  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.params.mu"), commands.ErrIsNotValidNumber)
  2996  
  2997  	cTooSmall := &commandspb.ProposalSubmission{
  2998  		Terms: &vegapb.ProposalTerms{
  2999  			Change: &vegapb.ProposalTerms_NewMarket{
  3000  				NewMarket: &vegapb.NewMarket{
  3001  					Changes: &vegapb.NewMarketConfiguration{
  3002  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  3003  							LogNormal: &vegapb.LogNormalRiskModel{
  3004  								RiskAversionParameter: 0.1,
  3005  								Tau:                   0.2,
  3006  								Params: &vegapb.LogNormalModelParams{
  3007  									Mu:    -1e-6 - 1e-12,
  3008  									Sigma: 0.1,
  3009  									R:     0,
  3010  								},
  3011  							},
  3012  						},
  3013  					},
  3014  				},
  3015  			},
  3016  		},
  3017  	}
  3018  	err = checkProposalSubmission(cTooSmall)
  3019  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.params.mu"), errors.New("must be between [-1e-6,1e-6]"))
  3020  
  3021  	cTooLarge := &commandspb.ProposalSubmission{
  3022  		Terms: &vegapb.ProposalTerms{
  3023  			Change: &vegapb.ProposalTerms_NewMarket{
  3024  				NewMarket: &vegapb.NewMarket{
  3025  					Changes: &vegapb.NewMarketConfiguration{
  3026  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  3027  							LogNormal: &vegapb.LogNormalRiskModel{
  3028  								RiskAversionParameter: 0.1,
  3029  								Tau:                   0.2,
  3030  								Params: &vegapb.LogNormalModelParams{
  3031  									Mu:    1e-6 + 1e-12,
  3032  									Sigma: 0.1,
  3033  									R:     0,
  3034  								},
  3035  							},
  3036  						},
  3037  					},
  3038  				},
  3039  			},
  3040  		},
  3041  	}
  3042  	err = checkProposalSubmission(cTooLarge)
  3043  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.params.mu"), errors.New("must be between [-1e-6,1e-6]"))
  3044  
  3045  	cJustAboutRight1 := &commandspb.ProposalSubmission{
  3046  		Terms: &vegapb.ProposalTerms{
  3047  			Change: &vegapb.ProposalTerms_NewMarket{
  3048  				NewMarket: &vegapb.NewMarket{
  3049  					Changes: &vegapb.NewMarketConfiguration{
  3050  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  3051  							LogNormal: &vegapb.LogNormalRiskModel{
  3052  								RiskAversionParameter: 0.1,
  3053  								Tau:                   0.2,
  3054  								Params: &vegapb.LogNormalModelParams{
  3055  									Mu:    -20,
  3056  									Sigma: 0.1,
  3057  									R:     0,
  3058  								},
  3059  							},
  3060  						},
  3061  					},
  3062  				},
  3063  			},
  3064  		},
  3065  	}
  3066  	err = checkProposalSubmission(cJustAboutRight1)
  3067  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.params.mu"), errors.New("must be between [-20,20]"))
  3068  
  3069  	cJustAboutRight2 := &commandspb.ProposalSubmission{
  3070  		Terms: &vegapb.ProposalTerms{
  3071  			Change: &vegapb.ProposalTerms_NewMarket{
  3072  				NewMarket: &vegapb.NewMarket{
  3073  					Changes: &vegapb.NewMarketConfiguration{
  3074  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  3075  							LogNormal: &vegapb.LogNormalRiskModel{
  3076  								RiskAversionParameter: 0.1,
  3077  								Tau:                   0.2,
  3078  								Params: &vegapb.LogNormalModelParams{
  3079  									Mu:    20,
  3080  									Sigma: 0.1,
  3081  									R:     0,
  3082  								},
  3083  							},
  3084  						},
  3085  					},
  3086  				},
  3087  			},
  3088  		},
  3089  	}
  3090  	err = checkProposalSubmission(cJustAboutRight2)
  3091  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.params.mu"), errors.New("must be between [-20,20]"))
  3092  }
  3093  
  3094  func testNewLogNormalRiskParametersChangeSubmissionInvalidR(t *testing.T) {
  3095  	cNaN := &commandspb.ProposalSubmission{
  3096  		Terms: &vegapb.ProposalTerms{
  3097  			Change: &vegapb.ProposalTerms_NewMarket{
  3098  				NewMarket: &vegapb.NewMarket{
  3099  					Changes: &vegapb.NewMarketConfiguration{
  3100  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  3101  							LogNormal: &vegapb.LogNormalRiskModel{
  3102  								RiskAversionParameter: 0.1,
  3103  								Tau:                   0.2,
  3104  								Params: &vegapb.LogNormalModelParams{
  3105  									Mu:    0.0,
  3106  									Sigma: 0.1,
  3107  									R:     math.NaN(),
  3108  								},
  3109  							},
  3110  						},
  3111  					},
  3112  				},
  3113  			},
  3114  		},
  3115  	}
  3116  	err := checkProposalSubmission(cNaN)
  3117  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.params.r"), commands.ErrIsNotValidNumber)
  3118  
  3119  	cTooSmall := &commandspb.ProposalSubmission{
  3120  		Terms: &vegapb.ProposalTerms{
  3121  			Change: &vegapb.ProposalTerms_NewMarket{
  3122  				NewMarket: &vegapb.NewMarket{
  3123  					Changes: &vegapb.NewMarketConfiguration{
  3124  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  3125  							LogNormal: &vegapb.LogNormalRiskModel{
  3126  								RiskAversionParameter: 0.1,
  3127  								Tau:                   0.2,
  3128  								Params: &vegapb.LogNormalModelParams{
  3129  									Mu:    0.0,
  3130  									Sigma: 0.1,
  3131  									R:     -1 - 1e-12,
  3132  								},
  3133  							},
  3134  						},
  3135  					},
  3136  				},
  3137  			},
  3138  		},
  3139  	}
  3140  	err = checkProposalSubmission(cTooSmall)
  3141  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.params.r"), errors.New("must be between [-1,1]"))
  3142  
  3143  	cTooLarge := &commandspb.ProposalSubmission{
  3144  		Terms: &vegapb.ProposalTerms{
  3145  			Change: &vegapb.ProposalTerms_NewMarket{
  3146  				NewMarket: &vegapb.NewMarket{
  3147  					Changes: &vegapb.NewMarketConfiguration{
  3148  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  3149  							LogNormal: &vegapb.LogNormalRiskModel{
  3150  								RiskAversionParameter: 0.1,
  3151  								Tau:                   0.2,
  3152  								Params: &vegapb.LogNormalModelParams{
  3153  									Mu:    0.0,
  3154  									Sigma: 0.1,
  3155  									R:     1 + 1e-12,
  3156  								},
  3157  							},
  3158  						},
  3159  					},
  3160  				},
  3161  			},
  3162  		},
  3163  	}
  3164  	err = checkProposalSubmission(cTooLarge)
  3165  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.params.r"), errors.New("must be between [-1,1]"))
  3166  
  3167  	cJustAboutRight1 := &commandspb.ProposalSubmission{
  3168  		Terms: &vegapb.ProposalTerms{
  3169  			Change: &vegapb.ProposalTerms_NewMarket{
  3170  				NewMarket: &vegapb.NewMarket{
  3171  					Changes: &vegapb.NewMarketConfiguration{
  3172  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  3173  							LogNormal: &vegapb.LogNormalRiskModel{
  3174  								RiskAversionParameter: 0.1,
  3175  								Tau:                   0.2,
  3176  								Params: &vegapb.LogNormalModelParams{
  3177  									Mu:    0.0,
  3178  									Sigma: 0.1,
  3179  									R:     -20,
  3180  								},
  3181  							},
  3182  						},
  3183  					},
  3184  				},
  3185  			},
  3186  		},
  3187  	}
  3188  	err = checkProposalSubmission(cJustAboutRight1)
  3189  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.params.r"), errors.New("must be between [-20,20]"))
  3190  
  3191  	cJustAboutRight2 := &commandspb.ProposalSubmission{
  3192  		Terms: &vegapb.ProposalTerms{
  3193  			Change: &vegapb.ProposalTerms_NewMarket{
  3194  				NewMarket: &vegapb.NewMarket{
  3195  					Changes: &vegapb.NewMarketConfiguration{
  3196  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  3197  							LogNormal: &vegapb.LogNormalRiskModel{
  3198  								RiskAversionParameter: 0.1,
  3199  								Tau:                   0.2,
  3200  								Params: &vegapb.LogNormalModelParams{
  3201  									Mu:    0.0,
  3202  									Sigma: 0.1,
  3203  									R:     20,
  3204  								},
  3205  							},
  3206  						},
  3207  					},
  3208  				},
  3209  			},
  3210  		},
  3211  	}
  3212  	err = checkProposalSubmission(cJustAboutRight2)
  3213  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.params.r"), errors.New("must be between [-20,20]"))
  3214  }
  3215  
  3216  func testNewLogNormalRiskParametersChangeSubmissionInvalidSigma(t *testing.T) {
  3217  	cNaN := &commandspb.ProposalSubmission{
  3218  		Terms: &vegapb.ProposalTerms{
  3219  			Change: &vegapb.ProposalTerms_NewMarket{
  3220  				NewMarket: &vegapb.NewMarket{
  3221  					Changes: &vegapb.NewMarketConfiguration{
  3222  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  3223  							LogNormal: &vegapb.LogNormalRiskModel{
  3224  								RiskAversionParameter: 0.1,
  3225  								Tau:                   0.2,
  3226  								Params: &vegapb.LogNormalModelParams{
  3227  									Mu:    0.0,
  3228  									Sigma: math.NaN(),
  3229  									R:     0,
  3230  								},
  3231  							},
  3232  						},
  3233  					},
  3234  				},
  3235  			},
  3236  		},
  3237  	}
  3238  	err := checkProposalSubmission(cNaN)
  3239  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.params.sigma"), commands.ErrIsNotValidNumber)
  3240  
  3241  	cNeg := &commandspb.ProposalSubmission{
  3242  		Terms: &vegapb.ProposalTerms{
  3243  			Change: &vegapb.ProposalTerms_NewMarket{
  3244  				NewMarket: &vegapb.NewMarket{
  3245  					Changes: &vegapb.NewMarketConfiguration{
  3246  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  3247  							LogNormal: &vegapb.LogNormalRiskModel{
  3248  								RiskAversionParameter: 0.1,
  3249  								Tau:                   0.2,
  3250  								Params: &vegapb.LogNormalModelParams{
  3251  									Mu:    0.0,
  3252  									Sigma: 1e-4,
  3253  									R:     0,
  3254  								},
  3255  							},
  3256  						},
  3257  					},
  3258  				},
  3259  			},
  3260  		},
  3261  	}
  3262  	err = checkProposalSubmission(cNeg)
  3263  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.params.sigma"), errors.New("must be between [1e-3,50]"))
  3264  
  3265  	cTooSmall := &commandspb.ProposalSubmission{
  3266  		Terms: &vegapb.ProposalTerms{
  3267  			Change: &vegapb.ProposalTerms_NewMarket{
  3268  				NewMarket: &vegapb.NewMarket{
  3269  					Changes: &vegapb.NewMarketConfiguration{
  3270  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  3271  							LogNormal: &vegapb.LogNormalRiskModel{
  3272  								RiskAversionParameter: 0.1,
  3273  								Tau:                   0.2,
  3274  								Params: &vegapb.LogNormalModelParams{
  3275  									Mu:    0.0,
  3276  									Sigma: 1e-3 - 1e-12,
  3277  									R:     0,
  3278  								},
  3279  							},
  3280  						},
  3281  					},
  3282  				},
  3283  			},
  3284  		},
  3285  	}
  3286  	err = checkProposalSubmission(cTooSmall)
  3287  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.params.sigma"), errors.New("must be between [1e-3,50]"))
  3288  
  3289  	cTooLarge := &commandspb.ProposalSubmission{
  3290  		Terms: &vegapb.ProposalTerms{
  3291  			Change: &vegapb.ProposalTerms_NewMarket{
  3292  				NewMarket: &vegapb.NewMarket{
  3293  					Changes: &vegapb.NewMarketConfiguration{
  3294  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  3295  							LogNormal: &vegapb.LogNormalRiskModel{
  3296  								RiskAversionParameter: 0.1,
  3297  								Tau:                   0.2,
  3298  								Params: &vegapb.LogNormalModelParams{
  3299  									Mu:    0.0,
  3300  									Sigma: 50 + 1e-12,
  3301  									R:     0,
  3302  								},
  3303  							},
  3304  						},
  3305  					},
  3306  				},
  3307  			},
  3308  		},
  3309  	}
  3310  	err = checkProposalSubmission(cTooLarge)
  3311  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.params.sigma"), errors.New("must be between [1e-3,50]"))
  3312  
  3313  	cJustAboutRight1 := &commandspb.ProposalSubmission{
  3314  		Terms: &vegapb.ProposalTerms{
  3315  			Change: &vegapb.ProposalTerms_NewMarket{
  3316  				NewMarket: &vegapb.NewMarket{
  3317  					Changes: &vegapb.NewMarketConfiguration{
  3318  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  3319  							LogNormal: &vegapb.LogNormalRiskModel{
  3320  								RiskAversionParameter: 0.1,
  3321  								Tau:                   0.2,
  3322  								Params: &vegapb.LogNormalModelParams{
  3323  									Mu:    0.0,
  3324  									Sigma: 1e-4,
  3325  									R:     0,
  3326  								},
  3327  							},
  3328  						},
  3329  					},
  3330  				},
  3331  			},
  3332  		},
  3333  	}
  3334  	err = checkProposalSubmission(cJustAboutRight1)
  3335  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.params.sigma"), errors.New("must be between [1e-4,100]"))
  3336  
  3337  	cJustAboutRight2 := &commandspb.ProposalSubmission{
  3338  		Terms: &vegapb.ProposalTerms{
  3339  			Change: &vegapb.ProposalTerms_NewMarket{
  3340  				NewMarket: &vegapb.NewMarket{
  3341  					Changes: &vegapb.NewMarketConfiguration{
  3342  						RiskParameters: &vegapb.NewMarketConfiguration_LogNormal{
  3343  							LogNormal: &vegapb.LogNormalRiskModel{
  3344  								RiskAversionParameter: 0.1,
  3345  								Tau:                   0.2,
  3346  								Params: &vegapb.LogNormalModelParams{
  3347  									Mu:    0.0,
  3348  									Sigma: 50,
  3349  									R:     0,
  3350  								},
  3351  							},
  3352  						},
  3353  					},
  3354  				},
  3355  			},
  3356  		},
  3357  	}
  3358  	err = checkProposalSubmission(cJustAboutRight2)
  3359  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.risk_parameters.log_normal.params.sigma"), errors.New("must be between [1e-4,100]"))
  3360  }
  3361  
  3362  func testNewMarketSubmissionWithTooLongReferenceFails(t *testing.T) {
  3363  	ref := make([]byte, 101)
  3364  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  3365  		Reference: string(ref),
  3366  	})
  3367  	assert.Contains(t, err.Get("proposal_submission.reference"), commands.ErrReferenceTooLong)
  3368  }
  3369  
  3370  func testFutureMarketSubmissionWithInternalTimestampForTradingTerminationSucceeds(t *testing.T) {
  3371  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  3372  		Terms: &vegapb.ProposalTerms{
  3373  			Change: &vegapb.ProposalTerms_NewMarket{
  3374  				NewMarket: &vegapb.NewMarket{
  3375  					Changes: &vegapb.NewMarketConfiguration{
  3376  						Instrument: &vegapb.InstrumentConfiguration{
  3377  							Product: &vegapb.InstrumentConfiguration_Future{
  3378  								Future: &vegapb.FutureProduct{
  3379  									DataSourceSpecForTradingTermination: &vegapb.DataSourceDefinition{
  3380  										SourceType: &vegapb.DataSourceDefinition_Internal{
  3381  											Internal: &vegapb.DataSourceDefinitionInternal{
  3382  												SourceType: &vegapb.DataSourceDefinitionInternal_Time{
  3383  													Time: &vegapb.DataSourceSpecConfigurationTime{
  3384  														Conditions: []*datapb.Condition{
  3385  															{
  3386  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  3387  																Value:    fmt.Sprintf("%d", time.Now().Add(time.Hour*24*365).UnixNano()),
  3388  															},
  3389  														},
  3390  													},
  3391  												},
  3392  											},
  3393  										},
  3394  									},
  3395  								},
  3396  							},
  3397  						},
  3398  					},
  3399  				},
  3400  			},
  3401  		},
  3402  	})
  3403  
  3404  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_trading_termination.external.oracle.signers"), commands.ErrIsRequired)
  3405  }
  3406  
  3407  func testFutureMarketSubmissionWithInvalidOracleConditionOrType(t *testing.T) {
  3408  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  3409  		Terms: &vegapb.ProposalTerms{
  3410  			Change: &vegapb.ProposalTerms_NewMarket{
  3411  				NewMarket: &vegapb.NewMarket{
  3412  					Changes: &vegapb.NewMarketConfiguration{
  3413  						Instrument: &vegapb.InstrumentConfiguration{
  3414  							Product: &vegapb.InstrumentConfiguration_Future{
  3415  								Future: &vegapb.FutureProduct{
  3416  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  3417  										vegapb.DataSourceContentTypeOracle,
  3418  									).SetOracleConfig(
  3419  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3420  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3421  												Signers: []*datapb.Signer{},
  3422  												Filters: []*datapb.Filter{
  3423  													{
  3424  														Key: &datapb.PropertyKey{
  3425  															Name: "trading.terminated",
  3426  															Type: datapb.PropertyKey_Type(10000),
  3427  														},
  3428  														Conditions: []*datapb.Condition{
  3429  															{
  3430  																Operator: datapb.Condition_Operator(10000),
  3431  															},
  3432  														},
  3433  													},
  3434  												},
  3435  											},
  3436  										},
  3437  									),
  3438  								},
  3439  							},
  3440  						},
  3441  					},
  3442  				},
  3443  			},
  3444  		},
  3445  	})
  3446  
  3447  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_trading_termination.external.oracle.filters.0.conditions.0.operator"), commands.ErrIsNotValid)
  3448  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_trading_termination.external.oracle.filters.0.key.type"), commands.ErrIsNotValid)
  3449  }
  3450  
  3451  func testFutureMarketSubmissionWithExternalTradingTerminationNoPublicKeyFails(t *testing.T) {
  3452  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  3453  		Terms: &vegapb.ProposalTerms{
  3454  			Change: &vegapb.ProposalTerms_NewMarket{
  3455  				NewMarket: &vegapb.NewMarket{
  3456  					Changes: &vegapb.NewMarketConfiguration{
  3457  						Instrument: &vegapb.InstrumentConfiguration{
  3458  							Product: &vegapb.InstrumentConfiguration_Future{
  3459  								Future: &vegapb.FutureProduct{
  3460  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  3461  										vegapb.DataSourceContentTypeOracle,
  3462  									).SetOracleConfig(
  3463  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3464  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3465  												Signers: []*datapb.Signer{},
  3466  												Filters: []*datapb.Filter{
  3467  													{
  3468  														Key: &datapb.PropertyKey{
  3469  															Name: "trading.terminated",
  3470  															Type: datapb.PropertyKey_TYPE_BOOLEAN,
  3471  														},
  3472  														Conditions: []*datapb.Condition{},
  3473  													},
  3474  												},
  3475  											},
  3476  										},
  3477  									),
  3478  								},
  3479  							},
  3480  						},
  3481  					},
  3482  				},
  3483  			},
  3484  		},
  3485  	})
  3486  
  3487  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_trading_termination.external.oracle.signers"), commands.ErrIsRequired)
  3488  }
  3489  
  3490  func testFutureMarketSubmissionWithInternalTradingTerminationSucceeds(t *testing.T) {
  3491  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  3492  		Terms: &vegapb.ProposalTerms{
  3493  			Change: &vegapb.ProposalTerms_NewMarket{
  3494  				NewMarket: &vegapb.NewMarket{
  3495  					Changes: &vegapb.NewMarketConfiguration{
  3496  						Instrument: &vegapb.InstrumentConfiguration{
  3497  							Product: &vegapb.InstrumentConfiguration_Future{
  3498  								Future: &vegapb.FutureProduct{
  3499  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  3500  										vegapb.DataSourceContentTypeInternalTimeTermination,
  3501  									).SetOracleConfig(
  3502  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3503  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3504  												Signers: []*datapb.Signer{},
  3505  												Filters: []*datapb.Filter{
  3506  													{
  3507  														Conditions: []*datapb.Condition{
  3508  															{
  3509  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  3510  																Value:    fmt.Sprintf("%d", time.Now().Add(time.Hour*24*365).UnixNano()),
  3511  															},
  3512  														},
  3513  													},
  3514  												},
  3515  											},
  3516  										},
  3517  									),
  3518  								},
  3519  							},
  3520  						},
  3521  					},
  3522  				},
  3523  			},
  3524  		},
  3525  	})
  3526  
  3527  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_trading_termination.external.oracle.signers"), commands.ErrIsRequired)
  3528  }
  3529  
  3530  func testFutureMarketSubmissionWithInternalTradingInvalidOperatorTerminationFails(t *testing.T) {
  3531  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  3532  		Terms: &vegapb.ProposalTerms{
  3533  			Change: &vegapb.ProposalTerms_NewMarket{
  3534  				NewMarket: &vegapb.NewMarket{
  3535  					Changes: &vegapb.NewMarketConfiguration{
  3536  						Instrument: &vegapb.InstrumentConfiguration{
  3537  							Product: &vegapb.InstrumentConfiguration_Future{
  3538  								Future: &vegapb.FutureProduct{
  3539  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  3540  										vegapb.DataSourceContentTypeInternalTimeTermination,
  3541  									).SetOracleConfig(
  3542  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3543  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3544  												Signers: []*datapb.Signer{},
  3545  												Filters: []*datapb.Filter{
  3546  													{
  3547  														Conditions: []*datapb.Condition{
  3548  															{
  3549  																Operator: datapb.Condition_OPERATOR_UNSPECIFIED,
  3550  																Value:    "value 1",
  3551  															},
  3552  														},
  3553  													},
  3554  												},
  3555  											},
  3556  										},
  3557  									),
  3558  								},
  3559  							},
  3560  						},
  3561  					},
  3562  				},
  3563  			},
  3564  		},
  3565  	})
  3566  
  3567  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_trading_termination.internal.time.conditions"), commands.ErrIsRequired)
  3568  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data"), commands.ErrIsRequired)
  3569  
  3570  	err = checkProposalSubmission(&commandspb.ProposalSubmission{
  3571  		Terms: &vegapb.ProposalTerms{
  3572  			Change: &vegapb.ProposalTerms_NewMarket{
  3573  				NewMarket: &vegapb.NewMarket{
  3574  					Changes: &vegapb.NewMarketConfiguration{
  3575  						Instrument: &vegapb.InstrumentConfiguration{
  3576  							Product: &vegapb.InstrumentConfiguration_Future{
  3577  								Future: &vegapb.FutureProduct{
  3578  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  3579  										vegapb.DataSourceContentTypeInternalTimeTermination,
  3580  									).SetTimeTriggerConditionConfig(
  3581  										[]*datapb.Condition{
  3582  											{
  3583  												Operator: datapb.Condition_OPERATOR_UNSPECIFIED,
  3584  												Value:    "value 1",
  3585  											},
  3586  										},
  3587  									),
  3588  								},
  3589  							},
  3590  						},
  3591  					},
  3592  				},
  3593  			},
  3594  		},
  3595  	})
  3596  
  3597  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_trading_termination.internal.time.conditions.0.operator"), commands.ErrIsRequired)
  3598  }
  3599  
  3600  func testFutureMarketSubmissionWithExternalTradingTerminationBuiltInKeyNoPublicKeyFails(t *testing.T) {
  3601  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  3602  		Terms: &vegapb.ProposalTerms{
  3603  			Change: &vegapb.ProposalTerms_NewMarket{
  3604  				NewMarket: &vegapb.NewMarket{
  3605  					Changes: &vegapb.NewMarketConfiguration{
  3606  						Instrument: &vegapb.InstrumentConfiguration{
  3607  							Product: &vegapb.InstrumentConfiguration_Future{
  3608  								Future: &vegapb.FutureProduct{
  3609  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  3610  										vegapb.DataSourceContentTypeOracle,
  3611  									).SetOracleConfig(
  3612  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3613  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3614  												Signers: []*datapb.Signer{},
  3615  												Filters: []*datapb.Filter{
  3616  													{
  3617  														Key: &datapb.PropertyKey{
  3618  															Name: "vegaprotocol.builtin.timestamp",
  3619  															Type: datapb.PropertyKey_TYPE_TIMESTAMP,
  3620  														},
  3621  														Conditions: []*datapb.Condition{
  3622  															{
  3623  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  3624  																Value:    fmt.Sprintf("%d", time.Now().Add(time.Hour*24*365).UnixNano()),
  3625  															},
  3626  														},
  3627  													},
  3628  												},
  3629  											},
  3630  										},
  3631  									),
  3632  								},
  3633  							},
  3634  						},
  3635  					},
  3636  				},
  3637  			},
  3638  		},
  3639  	})
  3640  
  3641  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_trading_termination.external.oracle.signers"), commands.ErrIsRequired)
  3642  }
  3643  
  3644  func testFutureMarketSubmissionWithExternalTradingSettlementBuiltInKeyNoPublicKeyFails(t *testing.T) {
  3645  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  3646  		Terms: &vegapb.ProposalTerms{
  3647  			Change: &vegapb.ProposalTerms_NewMarket{
  3648  				NewMarket: &vegapb.NewMarket{
  3649  					Changes: &vegapb.NewMarketConfiguration{
  3650  						Instrument: &vegapb.InstrumentConfiguration{
  3651  							Product: &vegapb.InstrumentConfiguration_Future{
  3652  								Future: &vegapb.FutureProduct{
  3653  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  3654  										vegapb.DataSourceContentTypeOracle,
  3655  									).SetOracleConfig(
  3656  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3657  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3658  												Signers: []*datapb.Signer{},
  3659  												Filters: []*datapb.Filter{
  3660  													{
  3661  														Key: &datapb.PropertyKey{
  3662  															Name: "vegaprotocol.builtin.timestamp",
  3663  															Type: datapb.PropertyKey_TYPE_TIMESTAMP,
  3664  														},
  3665  														Conditions: []*datapb.Condition{
  3666  															{
  3667  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  3668  																Value:    fmt.Sprintf("%d", time.Now().Add(time.Hour*24*365).UnixNano()),
  3669  															},
  3670  														},
  3671  													},
  3672  												},
  3673  											},
  3674  										},
  3675  									),
  3676  								},
  3677  							},
  3678  						},
  3679  					},
  3680  				},
  3681  			},
  3682  		},
  3683  	})
  3684  
  3685  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data"), commands.ErrIsNotValid)
  3686  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers"), commands.ErrIsRequired)
  3687  }
  3688  
  3689  func testFutureMarketSubmissionWithExternalTradingSettlementTimestampKeySucceeds(t *testing.T) {
  3690  	pubKeys := []*dstypes.Signer{
  3691  		dstypes.CreateSignerFromString("0xDEADBEEF", dstypes.SignerTypePubKey),
  3692  		dstypes.CreateSignerFromString("", dstypes.SignerTypePubKey),
  3693  	}
  3694  
  3695  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  3696  		Terms: &vegapb.ProposalTerms{
  3697  			Change: &vegapb.ProposalTerms_NewMarket{
  3698  				NewMarket: &vegapb.NewMarket{
  3699  					Changes: &vegapb.NewMarketConfiguration{
  3700  						Instrument: &vegapb.InstrumentConfiguration{
  3701  							Product: &vegapb.InstrumentConfiguration_Future{
  3702  								Future: &vegapb.FutureProduct{
  3703  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  3704  										vegapb.DataSourceContentTypeOracle,
  3705  									).SetOracleConfig(
  3706  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3707  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3708  												Signers: dstypes.SignersIntoProto(pubKeys),
  3709  												Filters: []*datapb.Filter{
  3710  													{
  3711  														Key: &datapb.PropertyKey{
  3712  															Name: "price.BTC.value",
  3713  															Type: datapb.PropertyKey_TYPE_INTEGER,
  3714  														},
  3715  														Conditions: []*datapb.Condition{
  3716  															{
  3717  																Operator: datapb.Condition_OPERATOR_EQUALS,
  3718  																Value:    "15",
  3719  															},
  3720  														},
  3721  													},
  3722  													{
  3723  														Key: &datapb.PropertyKey{
  3724  															Name: "price.BTC.timestamp",
  3725  															Type: datapb.PropertyKey_TYPE_TIMESTAMP,
  3726  														},
  3727  														Conditions: []*datapb.Condition{
  3728  															{
  3729  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  3730  																Value:    fmt.Sprintf("%d", time.Now().Add(time.Hour*24*365).UnixNano()),
  3731  															},
  3732  														},
  3733  													},
  3734  												},
  3735  											},
  3736  										},
  3737  									),
  3738  								},
  3739  							},
  3740  						},
  3741  					},
  3742  				},
  3743  			},
  3744  		},
  3745  	})
  3746  
  3747  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data"), commands.ErrIsNotValid)
  3748  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers"), commands.ErrIsRequired)
  3749  }
  3750  
  3751  func testFutureMarketSubmissionWithExternalTradingTerminationBuiltInKeySucceeds(t *testing.T) {
  3752  	pubKey := []*dstypes.Signer{
  3753  		dstypes.CreateSignerFromString("bd069246503a57271375f1995c46e03db88c4e1a564077b33a9872f905650dc4", dstypes.SignerTypePubKey),
  3754  	}
  3755  
  3756  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  3757  		Terms: &vegapb.ProposalTerms{
  3758  			Change: &vegapb.ProposalTerms_NewMarket{
  3759  				NewMarket: &vegapb.NewMarket{
  3760  					Changes: &vegapb.NewMarketConfiguration{
  3761  						Instrument: &vegapb.InstrumentConfiguration{
  3762  							Product: &vegapb.InstrumentConfiguration_Future{
  3763  								Future: &vegapb.FutureProduct{
  3764  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  3765  										vegapb.DataSourceContentTypeOracle,
  3766  									).SetOracleConfig(
  3767  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3768  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3769  												Signers: dstypes.SignersIntoProto(pubKey),
  3770  												Filters: []*datapb.Filter{
  3771  													{
  3772  														Key: &datapb.PropertyKey{
  3773  															Name: "prices.ETH.value",
  3774  															Type: datapb.PropertyKey_TYPE_INTEGER,
  3775  														},
  3776  														Conditions: []*datapb.Condition{
  3777  															{
  3778  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  3779  															},
  3780  														},
  3781  													},
  3782  												},
  3783  											},
  3784  										},
  3785  									),
  3786  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  3787  										vegapb.DataSourceContentTypeOracle,
  3788  									).SetOracleConfig(
  3789  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3790  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3791  												Signers: dstypes.SignersIntoProto(pubKey),
  3792  												Filters: []*datapb.Filter{
  3793  													{
  3794  														Key: &datapb.PropertyKey{
  3795  															Name: "vegaprotocol.builtin.timestamp",
  3796  															Type: datapb.PropertyKey_TYPE_TIMESTAMP,
  3797  														},
  3798  														Conditions: []*datapb.Condition{
  3799  															{
  3800  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  3801  																Value:    fmt.Sprintf("%d", time.Now().Add(time.Hour*24*365).UnixNano()),
  3802  															},
  3803  														},
  3804  													},
  3805  												},
  3806  											},
  3807  										},
  3808  									),
  3809  								},
  3810  							},
  3811  						},
  3812  					},
  3813  				},
  3814  			},
  3815  		},
  3816  	})
  3817  
  3818  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers"), commands.ErrIsRequired)
  3819  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_trading_termination.external.oracle.signers"), commands.ErrIsRequired)
  3820  }
  3821  
  3822  func testFutureMarketSubmissionWithExternalTradingTerminationNoSignerFails(t *testing.T) {
  3823  	pubKey := []*dstypes.Signer{
  3824  		dstypes.CreateSignerFromString("bd069246503a57271375f1995c46e03db88c4e1a564077b33a9872f905650dc4", dstypes.SignerTypePubKey),
  3825  	}
  3826  
  3827  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  3828  		Terms: &vegapb.ProposalTerms{
  3829  			Change: &vegapb.ProposalTerms_NewMarket{
  3830  				NewMarket: &vegapb.NewMarket{
  3831  					Changes: &vegapb.NewMarketConfiguration{
  3832  						Instrument: &vegapb.InstrumentConfiguration{
  3833  							Product: &vegapb.InstrumentConfiguration_Future{
  3834  								Future: &vegapb.FutureProduct{
  3835  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  3836  										vegapb.DataSourceContentTypeOracle,
  3837  									).SetOracleConfig(
  3838  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3839  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3840  												Signers: dstypes.SignersIntoProto(pubKey),
  3841  												Filters: []*datapb.Filter{
  3842  													{
  3843  														Key: &datapb.PropertyKey{
  3844  															Name: "vegaprotocol.builtin.prices.ETH.value",
  3845  															Type: datapb.PropertyKey_TYPE_INTEGER,
  3846  														},
  3847  														Conditions: []*datapb.Condition{
  3848  															{
  3849  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  3850  															},
  3851  														},
  3852  													},
  3853  												},
  3854  											},
  3855  										},
  3856  									),
  3857  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  3858  										vegapb.DataSourceContentTypeOracle,
  3859  									).SetOracleConfig(
  3860  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3861  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3862  												Filters: []*datapb.Filter{
  3863  													{
  3864  														Key: &datapb.PropertyKey{
  3865  															Name: "trading.terminated",
  3866  															Type: datapb.PropertyKey_TYPE_BOOLEAN,
  3867  														},
  3868  														Conditions: []*datapb.Condition{},
  3869  													},
  3870  												},
  3871  											},
  3872  										},
  3873  									),
  3874  								},
  3875  							},
  3876  						},
  3877  					},
  3878  				},
  3879  			},
  3880  		},
  3881  	})
  3882  
  3883  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers"), commands.ErrIsRequired)
  3884  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_trading_termination.external.oracle.signers"), commands.ErrIsRequired)
  3885  }
  3886  
  3887  func testFutureMarketSubmissionWithExternalSettlementDataNoSignerFails(t *testing.T) {
  3888  	pubKey := []*dstypes.Signer{
  3889  		dstypes.CreateSignerFromString("bd069246503a57271375f1995c46e03db88c4e1a564077b33a9872f905650dc4", dstypes.SignerTypePubKey),
  3890  	}
  3891  
  3892  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  3893  		Terms: &vegapb.ProposalTerms{
  3894  			Change: &vegapb.ProposalTerms_NewMarket{
  3895  				NewMarket: &vegapb.NewMarket{
  3896  					Changes: &vegapb.NewMarketConfiguration{
  3897  						Instrument: &vegapb.InstrumentConfiguration{
  3898  							Product: &vegapb.InstrumentConfiguration_Future{
  3899  								Future: &vegapb.FutureProduct{
  3900  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  3901  										vegapb.DataSourceContentTypeOracle,
  3902  									).SetOracleConfig(
  3903  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3904  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3905  												Filters: []*datapb.Filter{
  3906  													{
  3907  														Key: &datapb.PropertyKey{
  3908  															Name: "vegaprotocol.builtin.prices.ETH.value",
  3909  															Type: datapb.PropertyKey_TYPE_INTEGER,
  3910  														},
  3911  														Conditions: []*datapb.Condition{
  3912  															{
  3913  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  3914  															},
  3915  														},
  3916  													},
  3917  												},
  3918  											},
  3919  										},
  3920  									),
  3921  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  3922  										vegapb.DataSourceContentTypeOracle,
  3923  									).SetOracleConfig(
  3924  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3925  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3926  												Signers: dstypes.SignersIntoProto(pubKey),
  3927  												Filters: []*datapb.Filter{
  3928  													{
  3929  														Key: &datapb.PropertyKey{
  3930  															Name: "trading.terminated",
  3931  															Type: datapb.PropertyKey_TYPE_BOOLEAN,
  3932  														},
  3933  														Conditions: []*datapb.Condition{},
  3934  													},
  3935  												},
  3936  											},
  3937  										},
  3938  									),
  3939  								},
  3940  							},
  3941  						},
  3942  					},
  3943  				},
  3944  			},
  3945  		},
  3946  	})
  3947  
  3948  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers"), commands.ErrIsRequired)
  3949  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_trading_termination.external.oracle.signers"), commands.ErrIsRequired)
  3950  }
  3951  
  3952  func testFutureMarketSubmissionWithInternalSettlementDataFails(t *testing.T) {
  3953  	pubKey := []*dstypes.Signer{
  3954  		dstypes.CreateSignerFromString("bd069246503a57271375f1995c46e03db88c4e1a564077b33a9872f905650dc4", dstypes.SignerTypePubKey),
  3955  	}
  3956  
  3957  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  3958  		Terms: &vegapb.ProposalTerms{
  3959  			Change: &vegapb.ProposalTerms_NewMarket{
  3960  				NewMarket: &vegapb.NewMarket{
  3961  					Changes: &vegapb.NewMarketConfiguration{
  3962  						Instrument: &vegapb.InstrumentConfiguration{
  3963  							Product: &vegapb.InstrumentConfiguration_Future{
  3964  								Future: &vegapb.FutureProduct{
  3965  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  3966  										vegapb.DataSourceContentTypeInternalTimeTermination,
  3967  									).SetTimeTriggerConditionConfig(
  3968  										[]*datapb.Condition{
  3969  											{
  3970  												// It does not matter what conditions are set here
  3971  												Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  3972  											},
  3973  										},
  3974  									),
  3975  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  3976  										vegapb.DataSourceContentTypeOracle,
  3977  									).SetOracleConfig(
  3978  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3979  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3980  												Signers: dstypes.SignersIntoProto(pubKey),
  3981  												Filters: []*datapb.Filter{
  3982  													{
  3983  														Key: &datapb.PropertyKey{
  3984  															Name: "trading.terminated",
  3985  															Type: datapb.PropertyKey_TYPE_BOOLEAN,
  3986  														},
  3987  														Conditions: []*datapb.Condition{},
  3988  													},
  3989  												},
  3990  											},
  3991  										},
  3992  									),
  3993  								},
  3994  							},
  3995  						},
  3996  					},
  3997  				},
  3998  			},
  3999  		},
  4000  	})
  4001  
  4002  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data"), commands.ErrIsNotValid)
  4003  }
  4004  
  4005  func testFutureMarketSubmissionWithExternalSettlementDataAndTerminationEmptySignerFails(t *testing.T) {
  4006  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  4007  		Terms: &vegapb.ProposalTerms{
  4008  			Change: &vegapb.ProposalTerms_NewMarket{
  4009  				NewMarket: &vegapb.NewMarket{
  4010  					Changes: &vegapb.NewMarketConfiguration{
  4011  						Instrument: &vegapb.InstrumentConfiguration{
  4012  							Product: &vegapb.InstrumentConfiguration_Future{
  4013  								Future: &vegapb.FutureProduct{
  4014  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  4015  										vegapb.DataSourceContentTypeOracle,
  4016  									).SetOracleConfig(
  4017  										&vegapb.DataSourceDefinitionExternal_Oracle{
  4018  											Oracle: &vegapb.DataSourceSpecConfiguration{
  4019  												Signers: []*datapb.Signer{},
  4020  												Filters: []*datapb.Filter{
  4021  													{
  4022  														Key: &datapb.PropertyKey{
  4023  															Name: "vegaprotocol.builtin.prices.ETH.value",
  4024  															Type: datapb.PropertyKey_TYPE_INTEGER,
  4025  														},
  4026  														Conditions: []*datapb.Condition{
  4027  															{
  4028  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  4029  															},
  4030  														},
  4031  													},
  4032  												},
  4033  											},
  4034  										},
  4035  									),
  4036  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  4037  										vegapb.DataSourceContentTypeOracle,
  4038  									).SetOracleConfig(
  4039  										&vegapb.DataSourceDefinitionExternal_Oracle{
  4040  											Oracle: &vegapb.DataSourceSpecConfiguration{
  4041  												Signers: []*datapb.Signer{},
  4042  												Filters: []*datapb.Filter{
  4043  													{
  4044  														Key: &datapb.PropertyKey{
  4045  															Name: "trading.terminated",
  4046  															Type: datapb.PropertyKey_TYPE_BOOLEAN,
  4047  														},
  4048  														Conditions: []*datapb.Condition{},
  4049  													},
  4050  												},
  4051  											},
  4052  										},
  4053  									),
  4054  								},
  4055  							},
  4056  						},
  4057  					},
  4058  				},
  4059  			},
  4060  		},
  4061  	})
  4062  
  4063  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers"), commands.ErrIsRequired)
  4064  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_trading_termination.external.oracle.signers"), commands.ErrIsRequired)
  4065  }
  4066  
  4067  func testFutureMarketSubmissionWithExternalSettlementDataAndTerminationNoSignerFails(t *testing.T) {
  4068  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  4069  		Terms: &vegapb.ProposalTerms{
  4070  			Change: &vegapb.ProposalTerms_NewMarket{
  4071  				NewMarket: &vegapb.NewMarket{
  4072  					Changes: &vegapb.NewMarketConfiguration{
  4073  						Instrument: &vegapb.InstrumentConfiguration{
  4074  							Product: &vegapb.InstrumentConfiguration_Future{
  4075  								Future: &vegapb.FutureProduct{
  4076  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  4077  										vegapb.DataSourceContentTypeOracle,
  4078  									).SetOracleConfig(
  4079  										&vegapb.DataSourceDefinitionExternal_Oracle{
  4080  											Oracle: &vegapb.DataSourceSpecConfiguration{
  4081  												Filters: []*datapb.Filter{
  4082  													{
  4083  														Key: &datapb.PropertyKey{
  4084  															Name: "vegaprotocol.builtin.prices.ETH.value",
  4085  															Type: datapb.PropertyKey_TYPE_INTEGER,
  4086  														},
  4087  														Conditions: []*datapb.Condition{
  4088  															{
  4089  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  4090  															},
  4091  														},
  4092  													},
  4093  												},
  4094  											},
  4095  										},
  4096  									),
  4097  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  4098  										vegapb.DataSourceContentTypeOracle,
  4099  									).SetOracleConfig(
  4100  										&vegapb.DataSourceDefinitionExternal_Oracle{
  4101  											Oracle: &vegapb.DataSourceSpecConfiguration{
  4102  												Filters: []*datapb.Filter{
  4103  													{
  4104  														Key: &datapb.PropertyKey{
  4105  															Name: "trading.terminated",
  4106  															Type: datapb.PropertyKey_TYPE_BOOLEAN,
  4107  														},
  4108  														Conditions: []*datapb.Condition{},
  4109  													},
  4110  												},
  4111  											},
  4112  										},
  4113  									),
  4114  								},
  4115  							},
  4116  						},
  4117  					},
  4118  				},
  4119  			},
  4120  		},
  4121  	})
  4122  
  4123  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers"), commands.ErrIsRequired)
  4124  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_trading_termination.external.oracle.signers"), commands.ErrIsRequired)
  4125  }
  4126  
  4127  func testFutureMarketSubmissionWithExternalSettlementDataAndTerminationEmptyPubKeySignerFails(t *testing.T) {
  4128  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  4129  		Terms: &vegapb.ProposalTerms{
  4130  			Change: &vegapb.ProposalTerms_NewMarket{
  4131  				NewMarket: &vegapb.NewMarket{
  4132  					Changes: &vegapb.NewMarketConfiguration{
  4133  						Instrument: &vegapb.InstrumentConfiguration{
  4134  							Product: &vegapb.InstrumentConfiguration_Future{
  4135  								Future: &vegapb.FutureProduct{
  4136  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  4137  										vegapb.DataSourceContentTypeOracle,
  4138  									).SetOracleConfig(
  4139  										&vegapb.DataSourceDefinitionExternal_Oracle{
  4140  											Oracle: &vegapb.DataSourceSpecConfiguration{
  4141  												Signers: []*datapb.Signer{
  4142  													{
  4143  														Signer: &datapb.Signer_PubKey{
  4144  															PubKey: &datapb.PubKey{
  4145  																Key: "",
  4146  															},
  4147  														},
  4148  													},
  4149  												},
  4150  												Filters: []*datapb.Filter{
  4151  													{
  4152  														Key: &datapb.PropertyKey{
  4153  															Name: "vegaprotocol.builtin.prices.ETH.value",
  4154  															Type: datapb.PropertyKey_TYPE_INTEGER,
  4155  														},
  4156  														Conditions: []*datapb.Condition{
  4157  															{
  4158  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  4159  															},
  4160  														},
  4161  													},
  4162  												},
  4163  											},
  4164  										},
  4165  									),
  4166  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  4167  										vegapb.DataSourceContentTypeOracle,
  4168  									).SetOracleConfig(
  4169  										&vegapb.DataSourceDefinitionExternal_Oracle{
  4170  											Oracle: &vegapb.DataSourceSpecConfiguration{
  4171  												Signers: []*datapb.Signer{
  4172  													{
  4173  														Signer: &datapb.Signer_PubKey{
  4174  															PubKey: &datapb.PubKey{},
  4175  														},
  4176  													},
  4177  												},
  4178  												Filters: []*datapb.Filter{
  4179  													{
  4180  														Key: &datapb.PropertyKey{
  4181  															Name: "trading.terminated",
  4182  															Type: datapb.PropertyKey_TYPE_BOOLEAN,
  4183  														},
  4184  														Conditions: []*datapb.Condition{},
  4185  													},
  4186  												},
  4187  											},
  4188  										},
  4189  									),
  4190  								},
  4191  							},
  4192  						},
  4193  					},
  4194  				},
  4195  			},
  4196  		},
  4197  	})
  4198  
  4199  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers.0"), commands.ErrIsNotValid)
  4200  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_trading_termination.external.oracle.signers.0"), commands.ErrIsNotValid)
  4201  }
  4202  
  4203  func testFutureMarketSubmissionWithExternalSettlementDataAndTerminationEmptyEthAddressSignerFails(t *testing.T) {
  4204  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  4205  		Terms: &vegapb.ProposalTerms{
  4206  			Change: &vegapb.ProposalTerms_NewMarket{
  4207  				NewMarket: &vegapb.NewMarket{
  4208  					Changes: &vegapb.NewMarketConfiguration{
  4209  						Instrument: &vegapb.InstrumentConfiguration{
  4210  							Product: &vegapb.InstrumentConfiguration_Future{
  4211  								Future: &vegapb.FutureProduct{
  4212  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  4213  										vegapb.DataSourceContentTypeOracle,
  4214  									).SetOracleConfig(
  4215  										&vegapb.DataSourceDefinitionExternal_Oracle{
  4216  											Oracle: &vegapb.DataSourceSpecConfiguration{
  4217  												Signers: []*datapb.Signer{
  4218  													{
  4219  														Signer: &datapb.Signer_EthAddress{
  4220  															EthAddress: &datapb.ETHAddress{
  4221  																Address: "",
  4222  															},
  4223  														},
  4224  													},
  4225  												},
  4226  												Filters: []*datapb.Filter{
  4227  													{
  4228  														Key: &datapb.PropertyKey{
  4229  															Name: "vegaprotocol.builtin.prices.ETH.value",
  4230  															Type: datapb.PropertyKey_TYPE_INTEGER,
  4231  														},
  4232  														Conditions: []*datapb.Condition{
  4233  															{
  4234  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  4235  															},
  4236  														},
  4237  													},
  4238  												},
  4239  											},
  4240  										},
  4241  									),
  4242  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  4243  										vegapb.DataSourceContentTypeOracle,
  4244  									).SetOracleConfig(
  4245  										&vegapb.DataSourceDefinitionExternal_Oracle{
  4246  											Oracle: &vegapb.DataSourceSpecConfiguration{
  4247  												Signers: []*datapb.Signer{
  4248  													{
  4249  														Signer: &datapb.Signer_EthAddress{
  4250  															EthAddress: &datapb.ETHAddress{},
  4251  														},
  4252  													},
  4253  												},
  4254  												Filters: []*datapb.Filter{
  4255  													{
  4256  														Key: &datapb.PropertyKey{
  4257  															Name: "trading.terminated",
  4258  															Type: datapb.PropertyKey_TYPE_BOOLEAN,
  4259  														},
  4260  														Conditions: []*datapb.Condition{},
  4261  													},
  4262  												},
  4263  											},
  4264  										},
  4265  									),
  4266  								},
  4267  							},
  4268  						},
  4269  					},
  4270  				},
  4271  			},
  4272  		},
  4273  	})
  4274  
  4275  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers.0"), commands.ErrIsNotValid)
  4276  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_trading_termination.external.oracle.signers.0"), commands.ErrIsNotValid)
  4277  }
  4278  
  4279  func testNewPerpsMarketChangeSubmissionWithoutPerpsFails(t *testing.T) {
  4280  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  4281  		Terms: &vegapb.ProposalTerms{
  4282  			Change: &vegapb.ProposalTerms_NewMarket{
  4283  				NewMarket: &vegapb.NewMarket{
  4284  					Changes: &vegapb.NewMarketConfiguration{
  4285  						Instrument: &vegapb.InstrumentConfiguration{
  4286  							Product: &vegapb.InstrumentConfiguration_Perpetual{},
  4287  						},
  4288  					},
  4289  				},
  4290  			},
  4291  		},
  4292  	})
  4293  
  4294  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps"), commands.ErrIsRequired)
  4295  }
  4296  
  4297  func testNewPerpsMarketChangeSubmissionWithPerpsSucceeds(t *testing.T) {
  4298  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  4299  		Terms: &vegapb.ProposalTerms{
  4300  			Change: &vegapb.ProposalTerms_NewMarket{
  4301  				NewMarket: &vegapb.NewMarket{
  4302  					Changes: &vegapb.NewMarketConfiguration{
  4303  						Instrument: &vegapb.InstrumentConfiguration{
  4304  							Product: &vegapb.InstrumentConfiguration_Perpetual{
  4305  								Perpetual: &vegapb.PerpetualProduct{},
  4306  							},
  4307  						},
  4308  					},
  4309  				},
  4310  			},
  4311  		},
  4312  	})
  4313  
  4314  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps"), commands.ErrIsRequired)
  4315  }
  4316  
  4317  func testNewPerpsMarketChangeSubmissionWithoutSettlementAssetFails(t *testing.T) {
  4318  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  4319  		Terms: &vegapb.ProposalTerms{
  4320  			Change: &vegapb.ProposalTerms_NewMarket{
  4321  				NewMarket: &vegapb.NewMarket{
  4322  					Changes: &vegapb.NewMarketConfiguration{
  4323  						Instrument: &vegapb.InstrumentConfiguration{
  4324  							Product: &vegapb.InstrumentConfiguration_Perpetual{
  4325  								Perpetual: &vegapb.PerpetualProduct{
  4326  									SettlementAsset: "",
  4327  								},
  4328  							},
  4329  						},
  4330  					},
  4331  				},
  4332  			},
  4333  		},
  4334  	})
  4335  
  4336  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.settlement_asset"), commands.ErrIsRequired)
  4337  }
  4338  
  4339  func testNewPerpsMarketChangeSubmissionWithSettlementAssetSucceeds(t *testing.T) {
  4340  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  4341  		Terms: &vegapb.ProposalTerms{
  4342  			Change: &vegapb.ProposalTerms_NewMarket{
  4343  				NewMarket: &vegapb.NewMarket{
  4344  					Changes: &vegapb.NewMarketConfiguration{
  4345  						Instrument: &vegapb.InstrumentConfiguration{
  4346  							Product: &vegapb.InstrumentConfiguration_Perpetual{
  4347  								Perpetual: &vegapb.PerpetualProduct{
  4348  									SettlementAsset: "BTC",
  4349  								},
  4350  							},
  4351  						},
  4352  					},
  4353  				},
  4354  			},
  4355  		},
  4356  	})
  4357  
  4358  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.settlement_asset"), commands.ErrIsRequired)
  4359  }
  4360  
  4361  func testNewPerpsMarketChangeSubmissionWithoutQuoteNameFails(t *testing.T) {
  4362  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  4363  		Terms: &vegapb.ProposalTerms{
  4364  			Change: &vegapb.ProposalTerms_NewMarket{
  4365  				NewMarket: &vegapb.NewMarket{
  4366  					Changes: &vegapb.NewMarketConfiguration{
  4367  						Instrument: &vegapb.InstrumentConfiguration{
  4368  							Product: &vegapb.InstrumentConfiguration_Perpetual{
  4369  								Perpetual: &vegapb.PerpetualProduct{
  4370  									QuoteName: "",
  4371  								},
  4372  							},
  4373  						},
  4374  					},
  4375  				},
  4376  			},
  4377  		},
  4378  	})
  4379  
  4380  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.quote_name"), commands.ErrIsRequired)
  4381  }
  4382  
  4383  func testNewPerpsMarketChangeSubmissionWithQuoteNameSucceeds(t *testing.T) {
  4384  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  4385  		Terms: &vegapb.ProposalTerms{
  4386  			Change: &vegapb.ProposalTerms_NewMarket{
  4387  				NewMarket: &vegapb.NewMarket{
  4388  					Changes: &vegapb.NewMarketConfiguration{
  4389  						Instrument: &vegapb.InstrumentConfiguration{
  4390  							Product: &vegapb.InstrumentConfiguration_Perpetual{
  4391  								Perpetual: &vegapb.PerpetualProduct{
  4392  									QuoteName: "BTC",
  4393  								},
  4394  							},
  4395  						},
  4396  					},
  4397  				},
  4398  			},
  4399  		},
  4400  	})
  4401  
  4402  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.quote_name"), commands.ErrIsRequired)
  4403  }
  4404  
  4405  func testNewPerpsMarketChangeSubmissionWithoutOracleSpecFails(t *testing.T) {
  4406  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  4407  		Terms: &vegapb.ProposalTerms{
  4408  			Change: &vegapb.ProposalTerms_NewMarket{
  4409  				NewMarket: &vegapb.NewMarket{
  4410  					Changes: &vegapb.NewMarketConfiguration{
  4411  						Instrument: &vegapb.InstrumentConfiguration{
  4412  							Product: &vegapb.InstrumentConfiguration_Perpetual{
  4413  								Perpetual: &vegapb.PerpetualProduct{},
  4414  							},
  4415  						},
  4416  					},
  4417  				},
  4418  			},
  4419  		},
  4420  	})
  4421  
  4422  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec_for_settlement_data"), commands.ErrIsRequired)
  4423  }
  4424  
  4425  func testNewPerpsMarketChangeSubmissionWithOracleSpecSucceeds(t *testing.T) {
  4426  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  4427  		Terms: &vegapb.ProposalTerms{
  4428  			Change: &vegapb.ProposalTerms_NewMarket{
  4429  				NewMarket: &vegapb.NewMarket{
  4430  					Changes: &vegapb.NewMarketConfiguration{
  4431  						Instrument: &vegapb.InstrumentConfiguration{
  4432  							Product: &vegapb.InstrumentConfiguration_Perpetual{
  4433  								Perpetual: &vegapb.PerpetualProduct{
  4434  									DataSourceSpecForSettlementData: &vegapb.DataSourceDefinition{},
  4435  								},
  4436  							},
  4437  						},
  4438  					},
  4439  				},
  4440  			},
  4441  		},
  4442  	})
  4443  
  4444  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec_for_settlement_data"), commands.ErrIsRequired)
  4445  }
  4446  
  4447  func testNewPerpsMarketChangeSubmissionWithoutFiltersFails(t *testing.T) {
  4448  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  4449  		Terms: &vegapb.ProposalTerms{
  4450  			Change: &vegapb.ProposalTerms_NewMarket{
  4451  				NewMarket: &vegapb.NewMarket{
  4452  					Changes: &vegapb.NewMarketConfiguration{
  4453  						Instrument: &vegapb.InstrumentConfiguration{
  4454  							Product: &vegapb.InstrumentConfiguration_Perpetual{
  4455  								Perpetual: &vegapb.PerpetualProduct{
  4456  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  4457  										vegapb.DataSourceContentTypeEthOracle,
  4458  									),
  4459  								},
  4460  							},
  4461  						},
  4462  					},
  4463  				},
  4464  			},
  4465  		},
  4466  	})
  4467  
  4468  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec_for_settlement_data.external.ethoracle.filters"), commands.ErrIsRequired)
  4469  }
  4470  
  4471  func testNewPerpsMarketChangeSubmissionWithFiltersSucceeds(t *testing.T) {
  4472  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  4473  		Terms: &vegapb.ProposalTerms{
  4474  			Change: &vegapb.ProposalTerms_NewMarket{
  4475  				NewMarket: &vegapb.NewMarket{
  4476  					Changes: &vegapb.NewMarketConfiguration{
  4477  						Instrument: &vegapb.InstrumentConfiguration{
  4478  							Product: &vegapb.InstrumentConfiguration_Perpetual{
  4479  								Perpetual: &vegapb.PerpetualProduct{
  4480  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  4481  										vegapb.DataSourceContentTypeEthOracle,
  4482  									).SetOracleConfig(
  4483  										&vegapb.DataSourceDefinitionExternal_EthOracle{
  4484  											EthOracle: &vegapb.EthCallSpec{
  4485  												Filters: []*datapb.Filter{
  4486  													{},
  4487  												},
  4488  											},
  4489  										},
  4490  									),
  4491  								},
  4492  							},
  4493  						},
  4494  					},
  4495  				},
  4496  			},
  4497  		},
  4498  	})
  4499  
  4500  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec_for_settlement_data.external.ethoracle.filters"), commands.ErrIsRequired)
  4501  }
  4502  
  4503  func testNewPerpsMarketChangeSubmissionWithFilterWithoutKeyFails(t *testing.T) {
  4504  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  4505  		Terms: &vegapb.ProposalTerms{
  4506  			Change: &vegapb.ProposalTerms_NewMarket{
  4507  				NewMarket: &vegapb.NewMarket{
  4508  					Changes: &vegapb.NewMarketConfiguration{
  4509  						Instrument: &vegapb.InstrumentConfiguration{
  4510  							Product: &vegapb.InstrumentConfiguration_Perpetual{
  4511  								Perpetual: &vegapb.PerpetualProduct{
  4512  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  4513  										vegapb.DataSourceContentTypeEthOracle,
  4514  									).SetOracleConfig(
  4515  										&vegapb.DataSourceDefinitionExternal_EthOracle{
  4516  											EthOracle: &vegapb.EthCallSpec{
  4517  												Filters: []*datapb.Filter{
  4518  													{}, {},
  4519  												},
  4520  											},
  4521  										},
  4522  									),
  4523  								},
  4524  							},
  4525  						},
  4526  					},
  4527  				},
  4528  			},
  4529  		},
  4530  	})
  4531  
  4532  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec_for_settlement_data.external.ethoracle.filters.0.key"), commands.ErrIsNotValid)
  4533  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec_for_settlement_data.external.ethoracle.filters.1.key"), commands.ErrIsNotValid)
  4534  }
  4535  
  4536  func testNewPerpsMarketChangeSubmissionWithFilterWithKeySucceeds(t *testing.T) {
  4537  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  4538  		Terms: &vegapb.ProposalTerms{
  4539  			Change: &vegapb.ProposalTerms_NewMarket{
  4540  				NewMarket: &vegapb.NewMarket{
  4541  					Changes: &vegapb.NewMarketConfiguration{
  4542  						Instrument: &vegapb.InstrumentConfiguration{
  4543  							Product: &vegapb.InstrumentConfiguration_Perpetual{
  4544  								Perpetual: &vegapb.PerpetualProduct{
  4545  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  4546  										vegapb.DataSourceContentTypeEthOracle,
  4547  									).SetOracleConfig(
  4548  										&vegapb.DataSourceDefinitionExternal_EthOracle{
  4549  											EthOracle: &vegapb.EthCallSpec{
  4550  												Filters: []*datapb.Filter{
  4551  													{
  4552  														Key: &datapb.PropertyKey{},
  4553  													}, {
  4554  														Key: &datapb.PropertyKey{},
  4555  													},
  4556  												},
  4557  											},
  4558  										},
  4559  									),
  4560  								},
  4561  							},
  4562  						},
  4563  					},
  4564  				},
  4565  			},
  4566  		},
  4567  	})
  4568  
  4569  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec_for_settlement_data.external.ethoracle.filters.0.key"), commands.ErrIsNotValid)
  4570  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec_for_settlement_data.external.ethoracle.filters.1.key"), commands.ErrIsNotValid)
  4571  }
  4572  
  4573  func testNewPerpsMarketChangeSubmissionWithFilterWithoutKeyNameFails(t *testing.T) {
  4574  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  4575  		Terms: &vegapb.ProposalTerms{
  4576  			Change: &vegapb.ProposalTerms_NewMarket{
  4577  				NewMarket: &vegapb.NewMarket{
  4578  					Changes: &vegapb.NewMarketConfiguration{
  4579  						Instrument: &vegapb.InstrumentConfiguration{
  4580  							Product: &vegapb.InstrumentConfiguration_Perpetual{
  4581  								Perpetual: &vegapb.PerpetualProduct{
  4582  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  4583  										vegapb.DataSourceContentTypeEthOracle,
  4584  									).SetOracleConfig(
  4585  										&vegapb.DataSourceDefinitionExternal_EthOracle{
  4586  											EthOracle: &vegapb.EthCallSpec{
  4587  												Filters: []*datapb.Filter{
  4588  													{
  4589  														Key: &datapb.PropertyKey{
  4590  															Name: "",
  4591  														},
  4592  													}, {
  4593  														Key: &datapb.PropertyKey{
  4594  															Name: "",
  4595  														},
  4596  													},
  4597  												},
  4598  											},
  4599  										},
  4600  									),
  4601  								},
  4602  							},
  4603  						},
  4604  					},
  4605  				},
  4606  			},
  4607  		},
  4608  	})
  4609  
  4610  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec_for_settlement_data.external.ethoracle.filters.0.key.name"), commands.ErrIsRequired)
  4611  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec_for_settlement_data.external.ethoracle.filters.1.key.name"), commands.ErrIsRequired)
  4612  }
  4613  
  4614  func testNewPerpsMarketChangeSubmissionWithFilterWithKeyNameSucceeds(t *testing.T) {
  4615  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  4616  		Terms: &vegapb.ProposalTerms{
  4617  			Change: &vegapb.ProposalTerms_NewMarket{
  4618  				NewMarket: &vegapb.NewMarket{
  4619  					Changes: &vegapb.NewMarketConfiguration{
  4620  						Instrument: &vegapb.InstrumentConfiguration{
  4621  							Product: &vegapb.InstrumentConfiguration_Perpetual{
  4622  								Perpetual: &vegapb.PerpetualProduct{
  4623  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  4624  										vegapb.DataSourceContentTypeEthOracle,
  4625  									).SetOracleConfig(
  4626  										&vegapb.DataSourceDefinitionExternal_EthOracle{
  4627  											EthOracle: &vegapb.EthCallSpec{
  4628  												Filters: []*datapb.Filter{
  4629  													{
  4630  														Key: &datapb.PropertyKey{
  4631  															Name: "key1",
  4632  														},
  4633  													}, {
  4634  														Key: &datapb.PropertyKey{
  4635  															Name: "key2",
  4636  														},
  4637  													},
  4638  												},
  4639  											},
  4640  										},
  4641  									),
  4642  								},
  4643  							},
  4644  						},
  4645  					},
  4646  				},
  4647  			},
  4648  		},
  4649  	})
  4650  
  4651  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec_for_settlement_data.external.ethoracle.filters.0.key.name"), commands.ErrIsRequired)
  4652  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec_for_settlement_data.external.ethoracle.filters.1.key.name"), commands.ErrIsRequired)
  4653  }
  4654  
  4655  func testNewPerpsMarketChangeSubmissionWithFilterWithoutKeyTypeFails(t *testing.T) {
  4656  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  4657  		Terms: &vegapb.ProposalTerms{
  4658  			Change: &vegapb.ProposalTerms_NewMarket{
  4659  				NewMarket: &vegapb.NewMarket{
  4660  					Changes: &vegapb.NewMarketConfiguration{
  4661  						Instrument: &vegapb.InstrumentConfiguration{
  4662  							Product: &vegapb.InstrumentConfiguration_Perpetual{
  4663  								Perpetual: &vegapb.PerpetualProduct{
  4664  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  4665  										vegapb.DataSourceContentTypeEthOracle,
  4666  									).SetOracleConfig(
  4667  										&vegapb.DataSourceDefinitionExternal_EthOracle{
  4668  											EthOracle: &vegapb.EthCallSpec{
  4669  												Filters: []*datapb.Filter{
  4670  													{
  4671  														Key: &datapb.PropertyKey{
  4672  															Type: datapb.PropertyKey_TYPE_UNSPECIFIED,
  4673  														},
  4674  													}, {
  4675  														Key: &datapb.PropertyKey{},
  4676  													},
  4677  												},
  4678  											},
  4679  										},
  4680  									),
  4681  								},
  4682  							},
  4683  						},
  4684  					},
  4685  				},
  4686  			},
  4687  		},
  4688  	})
  4689  
  4690  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec_for_settlement_data.external.ethoracle.filters.0.key.type"), commands.ErrIsRequired)
  4691  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec_for_settlement_data.external.ethoracle.filters.1.key.type"), commands.ErrIsRequired)
  4692  }
  4693  
  4694  func testNewPerpsMarketChangeSubmissionWithFilterWithKeyTypeSucceeds(t *testing.T) {
  4695  	testCases := []struct {
  4696  		msg   string
  4697  		value datapb.PropertyKey_Type
  4698  	}{
  4699  		{
  4700  			msg:   "with EMPTY",
  4701  			value: datapb.PropertyKey_TYPE_EMPTY,
  4702  		}, {
  4703  			msg:   "with INTEGER",
  4704  			value: datapb.PropertyKey_TYPE_INTEGER,
  4705  		}, {
  4706  			msg:   "with STRING",
  4707  			value: datapb.PropertyKey_TYPE_STRING,
  4708  		}, {
  4709  			msg:   "with BOOLEAN",
  4710  			value: datapb.PropertyKey_TYPE_BOOLEAN,
  4711  		}, {
  4712  			msg:   "with DECIMAL",
  4713  			value: datapb.PropertyKey_TYPE_DECIMAL,
  4714  		}, {
  4715  			msg:   "with TIMESTAMP",
  4716  			value: datapb.PropertyKey_TYPE_TIMESTAMP,
  4717  		},
  4718  	}
  4719  	for _, tc := range testCases {
  4720  		t.Run(tc.msg, func(t *testing.T) {
  4721  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
  4722  				Terms: &vegapb.ProposalTerms{
  4723  					Change: &vegapb.ProposalTerms_NewMarket{
  4724  						NewMarket: &vegapb.NewMarket{
  4725  							Changes: &vegapb.NewMarketConfiguration{
  4726  								Instrument: &vegapb.InstrumentConfiguration{
  4727  									Product: &vegapb.InstrumentConfiguration_Perpetual{
  4728  										Perpetual: &vegapb.PerpetualProduct{
  4729  											DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  4730  												vegapb.DataSourceContentTypeEthOracle,
  4731  											).SetOracleConfig(
  4732  												&vegapb.DataSourceDefinitionExternal_EthOracle{
  4733  													EthOracle: &vegapb.EthCallSpec{
  4734  														Filters: []*datapb.Filter{
  4735  															{
  4736  																Key: &datapb.PropertyKey{
  4737  																	Type: tc.value,
  4738  																},
  4739  															}, {
  4740  																Key: &datapb.PropertyKey{
  4741  																	Type: tc.value,
  4742  																},
  4743  															},
  4744  														},
  4745  													},
  4746  												},
  4747  											),
  4748  										},
  4749  									},
  4750  								},
  4751  							},
  4752  						},
  4753  					},
  4754  				},
  4755  			})
  4756  
  4757  			assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec.external.ethoracle.filters.0.key.type"), commands.ErrIsRequired)
  4758  			assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec.external.ethoracle.filters.1.key.type"), commands.ErrIsRequired)
  4759  		})
  4760  	}
  4761  }
  4762  
  4763  func testNewPerpsMarketChangeSubmissionWithFilterWithoutConditionsSucceeds(t *testing.T) {
  4764  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  4765  		Terms: &vegapb.ProposalTerms{
  4766  			Change: &vegapb.ProposalTerms_NewMarket{
  4767  				NewMarket: &vegapb.NewMarket{
  4768  					Changes: &vegapb.NewMarketConfiguration{
  4769  						Instrument: &vegapb.InstrumentConfiguration{
  4770  							Product: &vegapb.InstrumentConfiguration_Perpetual{
  4771  								Perpetual: &vegapb.PerpetualProduct{
  4772  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  4773  										vegapb.DataSourceContentTypeEthOracle,
  4774  									).SetOracleConfig(
  4775  										&vegapb.DataSourceDefinitionExternal_EthOracle{
  4776  											EthOracle: &vegapb.EthCallSpec{
  4777  												Filters: []*datapb.Filter{
  4778  													{
  4779  														Conditions: []*datapb.Condition{},
  4780  													},
  4781  												},
  4782  											},
  4783  										},
  4784  									),
  4785  								},
  4786  							},
  4787  						},
  4788  					},
  4789  				},
  4790  			},
  4791  		},
  4792  	})
  4793  
  4794  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec.external.ethoracle.filters.0.conditions"), commands.ErrIsRequired)
  4795  }
  4796  
  4797  func testNewPerpsMarketChangeSubmissionWithFilterWithoutConditionOperatorFails(t *testing.T) {
  4798  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  4799  		Terms: &vegapb.ProposalTerms{
  4800  			Change: &vegapb.ProposalTerms_NewMarket{
  4801  				NewMarket: &vegapb.NewMarket{
  4802  					Changes: &vegapb.NewMarketConfiguration{
  4803  						Instrument: &vegapb.InstrumentConfiguration{
  4804  							Product: &vegapb.InstrumentConfiguration_Perpetual{
  4805  								Perpetual: &vegapb.PerpetualProduct{
  4806  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  4807  										vegapb.DataSourceContentTypeEthOracle,
  4808  									).SetOracleConfig(
  4809  										&vegapb.DataSourceDefinitionExternal_EthOracle{
  4810  											EthOracle: &vegapb.EthCallSpec{
  4811  												Filters: []*datapb.Filter{
  4812  													{
  4813  														Conditions: []*datapb.Condition{
  4814  															{
  4815  																Operator: datapb.Condition_OPERATOR_UNSPECIFIED,
  4816  															},
  4817  															{},
  4818  														},
  4819  													},
  4820  												},
  4821  											},
  4822  										},
  4823  									),
  4824  								},
  4825  							},
  4826  						},
  4827  					},
  4828  				},
  4829  			},
  4830  		},
  4831  	})
  4832  
  4833  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec_for_settlement_data.external.ethoracle.filters.0.conditions.0.operator"), commands.ErrIsRequired)
  4834  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec_for_settlement_data.external.ethoracle.filters.0.conditions.1.operator"), commands.ErrIsRequired)
  4835  }
  4836  
  4837  func testNewPerpsMarketChangeSubmissionWithFilterWithConditionOperatorSucceeds(t *testing.T) {
  4838  	testCases := []struct {
  4839  		msg   string
  4840  		value datapb.Condition_Operator
  4841  	}{
  4842  		{
  4843  			msg:   "with EQUALS",
  4844  			value: datapb.Condition_OPERATOR_EQUALS,
  4845  		}, {
  4846  			msg:   "with GREATER_THAN",
  4847  			value: datapb.Condition_OPERATOR_GREATER_THAN,
  4848  		}, {
  4849  			msg:   "with GREATER_THAN_OR_EQUAL",
  4850  			value: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  4851  		}, {
  4852  			msg:   "with LESS_THAN",
  4853  			value: datapb.Condition_OPERATOR_LESS_THAN,
  4854  		}, {
  4855  			msg:   "with LESS_THAN_OR_EQUAL",
  4856  			value: datapb.Condition_OPERATOR_LESS_THAN_OR_EQUAL,
  4857  		},
  4858  	}
  4859  	for _, tc := range testCases {
  4860  		t.Run(tc.msg, func(t *testing.T) {
  4861  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
  4862  				Terms: &vegapb.ProposalTerms{
  4863  					Change: &vegapb.ProposalTerms_NewMarket{
  4864  						NewMarket: &vegapb.NewMarket{
  4865  							Changes: &vegapb.NewMarketConfiguration{
  4866  								Instrument: &vegapb.InstrumentConfiguration{
  4867  									Product: &vegapb.InstrumentConfiguration_Perpetual{
  4868  										Perpetual: &vegapb.PerpetualProduct{
  4869  											DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  4870  												vegapb.DataSourceContentTypeEthOracle,
  4871  											).SetOracleConfig(
  4872  												&vegapb.DataSourceDefinitionExternal_EthOracle{
  4873  													EthOracle: &vegapb.EthCallSpec{
  4874  														Filters: []*datapb.Filter{
  4875  															{
  4876  																Conditions: []*datapb.Condition{
  4877  																	{
  4878  																		Operator: tc.value,
  4879  																	},
  4880  																	{
  4881  																		Operator: tc.value,
  4882  																	},
  4883  																},
  4884  															},
  4885  														},
  4886  													},
  4887  												},
  4888  											),
  4889  										},
  4890  									},
  4891  								},
  4892  							},
  4893  						},
  4894  					},
  4895  				},
  4896  			})
  4897  
  4898  			assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec.external.ethoracle.filters.0.conditions.0.operator"), commands.ErrIsRequired)
  4899  			assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec.external.ethoracle.filters.1.conditions.0.operator"), commands.ErrIsRequired)
  4900  		})
  4901  	}
  4902  }
  4903  
  4904  func testNewPerpsMarketChangeSubmissionWithFilterWithoutConditionValueFails(t *testing.T) {
  4905  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  4906  		Terms: &vegapb.ProposalTerms{
  4907  			Change: &vegapb.ProposalTerms_NewMarket{
  4908  				NewMarket: &vegapb.NewMarket{
  4909  					Changes: &vegapb.NewMarketConfiguration{
  4910  						Instrument: &vegapb.InstrumentConfiguration{
  4911  							Product: &vegapb.InstrumentConfiguration_Perpetual{
  4912  								Perpetual: &vegapb.PerpetualProduct{
  4913  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  4914  										vegapb.DataSourceContentTypeEthOracle,
  4915  									).SetOracleConfig(
  4916  										&vegapb.DataSourceDefinitionExternal_EthOracle{
  4917  											EthOracle: &vegapb.EthCallSpec{
  4918  												Filters: []*datapb.Filter{
  4919  													{
  4920  														Conditions: []*datapb.Condition{
  4921  															{
  4922  																Value: "",
  4923  															},
  4924  															{
  4925  																Value: "",
  4926  															},
  4927  														},
  4928  													},
  4929  												},
  4930  											},
  4931  										},
  4932  									),
  4933  								},
  4934  							},
  4935  						},
  4936  					},
  4937  				},
  4938  			},
  4939  		},
  4940  	})
  4941  
  4942  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec_for_settlement_data.external.ethoracle.filters.0.conditions.0.value"), commands.ErrIsRequired)
  4943  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec_for_settlement_data.external.ethoracle.filters.0.conditions.1.value"), commands.ErrIsRequired)
  4944  }
  4945  
  4946  func testNewPerpsMarketChangeSubmissionWithFilterWithConditionValueSucceeds(t *testing.T) {
  4947  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  4948  		Terms: &vegapb.ProposalTerms{
  4949  			Change: &vegapb.ProposalTerms_NewMarket{
  4950  				NewMarket: &vegapb.NewMarket{
  4951  					Changes: &vegapb.NewMarketConfiguration{
  4952  						Instrument: &vegapb.InstrumentConfiguration{
  4953  							Product: &vegapb.InstrumentConfiguration_Perpetual{
  4954  								Perpetual: &vegapb.PerpetualProduct{
  4955  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  4956  										vegapb.DataSourceContentTypeEthOracle,
  4957  									).SetOracleConfig(
  4958  										&vegapb.DataSourceDefinitionExternal_EthOracle{
  4959  											EthOracle: &vegapb.EthCallSpec{
  4960  												Filters: []*datapb.Filter{
  4961  													{
  4962  														Conditions: []*datapb.Condition{
  4963  															{
  4964  																Value: "value 1",
  4965  															},
  4966  															{
  4967  																Value: "value 2",
  4968  															},
  4969  														},
  4970  													},
  4971  												},
  4972  											},
  4973  										},
  4974  									),
  4975  								},
  4976  							},
  4977  						},
  4978  					},
  4979  				},
  4980  			},
  4981  		},
  4982  	})
  4983  
  4984  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec.external.ethoracle.filters.0.conditions.0.value"), commands.ErrIsRequired)
  4985  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec.external.ethoracle.filters.0.conditions.1.value"), commands.ErrIsRequired)
  4986  }
  4987  
  4988  func testNewPerpsMarketChangeSubmissionWithoutDataSourceSpecBindingFails(t *testing.T) {
  4989  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  4990  		Terms: &vegapb.ProposalTerms{
  4991  			Change: &vegapb.ProposalTerms_NewMarket{
  4992  				NewMarket: &vegapb.NewMarket{
  4993  					Changes: &vegapb.NewMarketConfiguration{
  4994  						Instrument: &vegapb.InstrumentConfiguration{
  4995  							Product: &vegapb.InstrumentConfiguration_Perpetual{
  4996  								Perpetual: &vegapb.PerpetualProduct{},
  4997  							},
  4998  						},
  4999  					},
  5000  				},
  5001  			},
  5002  		},
  5003  	})
  5004  
  5005  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec_binding"), commands.ErrIsRequired)
  5006  }
  5007  
  5008  func testNewPerpsMarketChangeSubmissionWithDataSourceSpecBindingSucceeds(t *testing.T) {
  5009  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  5010  		Terms: &vegapb.ProposalTerms{
  5011  			Change: &vegapb.ProposalTerms_NewMarket{
  5012  				NewMarket: &vegapb.NewMarket{
  5013  					Changes: &vegapb.NewMarketConfiguration{
  5014  						Instrument: &vegapb.InstrumentConfiguration{
  5015  							Product: &vegapb.InstrumentConfiguration_Perpetual{
  5016  								Perpetual: &vegapb.PerpetualProduct{
  5017  									DataSourceSpecBinding: &vegapb.DataSourceSpecToPerpetualBinding{},
  5018  								},
  5019  							},
  5020  						},
  5021  					},
  5022  				},
  5023  			},
  5024  		},
  5025  	})
  5026  
  5027  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec_binding"), commands.ErrIsRequired)
  5028  }
  5029  
  5030  func testNewPerpsMarketChangeSubmissionWithNoMismatchBetweenFilterAndBindingSucceeds(t *testing.T) {
  5031  	testNewPerpsMarketChangeSubmissionWithNoMismatchBetweenFilterAndBindingForSpecSucceeds(t, &vegapb.DataSourceSpecToPerpetualBinding{SettlementDataProperty: "key1"}, "settlement_data_property", "key1")
  5032  }
  5033  
  5034  func testNewPerpsMarketChangeSubmissionWithNoMismatchBetweenFilterAndBindingForSpecSucceeds(t *testing.T, binding *vegapb.DataSourceSpecToPerpetualBinding, bindingName string, bindingKey string) {
  5035  	t.Helper()
  5036  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  5037  		Terms: &vegapb.ProposalTerms{
  5038  			Change: &vegapb.ProposalTerms_NewMarket{
  5039  				NewMarket: &vegapb.NewMarket{
  5040  					Changes: &vegapb.NewMarketConfiguration{
  5041  						Instrument: &vegapb.InstrumentConfiguration{
  5042  							Product: &vegapb.InstrumentConfiguration_Perpetual{
  5043  								Perpetual: &vegapb.PerpetualProduct{
  5044  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  5045  										vegapb.DataSourceContentTypeEthOracle,
  5046  									).SetOracleConfig(
  5047  										&vegapb.DataSourceDefinitionExternal_EthOracle{
  5048  											EthOracle: &vegapb.EthCallSpec{
  5049  												Filters: []*datapb.Filter{
  5050  													{
  5051  														Key: &datapb.PropertyKey{
  5052  															Name: bindingKey,
  5053  														},
  5054  													}, {
  5055  														Key: &datapb.PropertyKey{},
  5056  													},
  5057  												},
  5058  											},
  5059  										},
  5060  									),
  5061  									DataSourceSpecBinding: binding,
  5062  								},
  5063  							},
  5064  						},
  5065  					},
  5066  				},
  5067  			},
  5068  		},
  5069  	})
  5070  
  5071  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec_binding."+bindingName), commands.ErrIsMismatching)
  5072  }
  5073  
  5074  func testNewPerpsMarketChangeSubmissionWithMismatchBetweenFilterAndBindingForSpecFails(t *testing.T, binding *vegapb.DataSourceSpecToPerpetualBinding, bindingName string) {
  5075  	t.Helper()
  5076  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  5077  		Terms: &vegapb.ProposalTerms{
  5078  			Change: &vegapb.ProposalTerms_NewMarket{
  5079  				NewMarket: &vegapb.NewMarket{
  5080  					Changes: &vegapb.NewMarketConfiguration{
  5081  						Instrument: &vegapb.InstrumentConfiguration{
  5082  							Product: &vegapb.InstrumentConfiguration_Perpetual{
  5083  								Perpetual: &vegapb.PerpetualProduct{
  5084  									DataSourceSpecBinding: binding,
  5085  								},
  5086  							},
  5087  						},
  5088  					},
  5089  				},
  5090  			},
  5091  		},
  5092  	})
  5093  
  5094  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec_binding."+bindingName), commands.ErrIsMismatching)
  5095  }
  5096  
  5097  func testNewPerpsMarketChangeSubmissionWithMismatchBetweenFilterAndBindingFails(t *testing.T) {
  5098  	testNewPerpsMarketChangeSubmissionWithMismatchBetweenFilterAndBindingForSpecFails(t, &vegapb.DataSourceSpecToPerpetualBinding{SettlementDataProperty: "My property"}, "settlement_data_property")
  5099  }
  5100  
  5101  func testNewPerpsMarketChangeSubmissionWithSettlementDataPropertySucceeds(t *testing.T) {
  5102  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  5103  		Terms: &vegapb.ProposalTerms{
  5104  			Change: &vegapb.ProposalTerms_NewMarket{
  5105  				NewMarket: &vegapb.NewMarket{
  5106  					Changes: &vegapb.NewMarketConfiguration{
  5107  						Instrument: &vegapb.InstrumentConfiguration{
  5108  							Product: &vegapb.InstrumentConfiguration_Perpetual{
  5109  								Perpetual: &vegapb.PerpetualProduct{
  5110  									DataSourceSpecBinding: &vegapb.DataSourceSpecToPerpetualBinding{
  5111  										SettlementDataProperty: "My property",
  5112  									},
  5113  								},
  5114  							},
  5115  						},
  5116  					},
  5117  				},
  5118  			},
  5119  		},
  5120  	})
  5121  
  5122  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec_binding.settlement_data_property"), commands.ErrIsRequired)
  5123  }
  5124  
  5125  func testNewPerpsMarketChangeSubmissionWithInternalCompositePriceConfig(t *testing.T) {
  5126  	cases := getCompositePriceConfigurationCases()
  5127  	for _, c := range cases {
  5128  		err := checkProposalSubmission(&commandspb.ProposalSubmission{
  5129  			Terms: &vegapb.ProposalTerms{
  5130  				Change: &vegapb.ProposalTerms_NewMarket{
  5131  					NewMarket: &vegapb.NewMarket{
  5132  						Changes: &vegapb.NewMarketConfiguration{
  5133  							Instrument: &vegapb.InstrumentConfiguration{
  5134  								Product: &vegapb.InstrumentConfiguration_Perpetual{
  5135  									Perpetual: &vegapb.PerpetualProduct{
  5136  										DataSourceSpecBinding: &vegapb.DataSourceSpecToPerpetualBinding{
  5137  											SettlementDataProperty: "My property",
  5138  										},
  5139  										InternalCompositePriceConfiguration: c.mpc,
  5140  									},
  5141  								},
  5142  							},
  5143  						},
  5144  					},
  5145  				},
  5146  			},
  5147  		})
  5148  		if len(c.field) > 0 {
  5149  			if c.err != nil {
  5150  				assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.internal_composite_price_configuration."+c.field), c.err)
  5151  			} else {
  5152  				assert.Empty(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.internal_composite_price_configuration."+c.field))
  5153  			}
  5154  		} else {
  5155  			assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.internal_composite_price_configuration"), c.err)
  5156  		}
  5157  	}
  5158  }
  5159  
  5160  func TestNewPerpsMarketChangeSubmissionProductParameters(t *testing.T) {
  5161  	cases := []struct {
  5162  		product vegapb.PerpetualProduct
  5163  		err     error
  5164  		path    string
  5165  		desc    string
  5166  	}{
  5167  		// margin_funding_factor
  5168  		{
  5169  			product: vegapb.PerpetualProduct{
  5170  				MarginFundingFactor: "",
  5171  			},
  5172  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.margin_funding_factor",
  5173  			err:  commands.ErrIsRequired,
  5174  			desc: "margin_funding_factor is empty",
  5175  		},
  5176  		{
  5177  			product: vegapb.PerpetualProduct{
  5178  				MarginFundingFactor: "nope",
  5179  			},
  5180  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.margin_funding_factor",
  5181  			err:  commands.ErrIsNotValidNumber,
  5182  			desc: "margin_funding_factor is not a valid number",
  5183  		},
  5184  		{
  5185  			product: vegapb.PerpetualProduct{
  5186  				MarginFundingFactor: "-10",
  5187  			},
  5188  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.margin_funding_factor",
  5189  			err:  commands.ErrMustBeWithinRange01,
  5190  			desc: "margin_funding_factor is not within range (< 0)",
  5191  		},
  5192  		{
  5193  			product: vegapb.PerpetualProduct{
  5194  				MarginFundingFactor: "10",
  5195  			},
  5196  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.margin_funding_factor",
  5197  			err:  commands.ErrMustBeWithinRange01,
  5198  			desc: "margin_funding_factor is not within range (> 1)",
  5199  		},
  5200  		{
  5201  			product: vegapb.PerpetualProduct{
  5202  				MarginFundingFactor: "0.5",
  5203  			},
  5204  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.margin_funding_factor",
  5205  			desc: "margin_funding_factor is valid",
  5206  		},
  5207  		// interest_rate
  5208  		{
  5209  			product: vegapb.PerpetualProduct{
  5210  				InterestRate: "",
  5211  			},
  5212  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.interest_rate",
  5213  			err:  commands.ErrIsRequired,
  5214  			desc: "interest_rate is empty",
  5215  		},
  5216  		{
  5217  			product: vegapb.PerpetualProduct{
  5218  				InterestRate: "nope",
  5219  			},
  5220  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.interest_rate",
  5221  			err:  commands.ErrIsNotValidNumber,
  5222  			desc: "interest_rate is not a valid number",
  5223  		},
  5224  		{
  5225  			product: vegapb.PerpetualProduct{
  5226  				InterestRate: "-10",
  5227  			},
  5228  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.interest_rate",
  5229  			err:  commands.ErrMustBeWithinRange11,
  5230  			desc: "interest_rate is not within range (< -1)",
  5231  		},
  5232  		{
  5233  			product: vegapb.PerpetualProduct{
  5234  				InterestRate: "10",
  5235  			},
  5236  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.interest_rate",
  5237  			err:  commands.ErrMustBeWithinRange11,
  5238  			desc: "interest_rate is not within range (> 1)",
  5239  		},
  5240  		{
  5241  			product: vegapb.PerpetualProduct{
  5242  				InterestRate: "0.5",
  5243  			},
  5244  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.interest_rate",
  5245  			desc: "interest_rate is valid",
  5246  		},
  5247  		{
  5248  			product: vegapb.PerpetualProduct{
  5249  				InterestRate: "-0.5",
  5250  			},
  5251  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.interest_rate",
  5252  			desc: "interest_rate is valid",
  5253  		},
  5254  		// clamp_lower_bound (0053-PERP-042)
  5255  		{
  5256  			product: vegapb.PerpetualProduct{
  5257  				ClampLowerBound: "",
  5258  			},
  5259  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.clamp_lower_bound",
  5260  			err:  commands.ErrIsRequired,
  5261  			desc: "clamp_lower_bound is empty",
  5262  		},
  5263  		{
  5264  			product: vegapb.PerpetualProduct{
  5265  				ClampLowerBound: "nope",
  5266  			},
  5267  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.clamp_lower_bound",
  5268  			err:  commands.ErrIsNotValidNumber,
  5269  			desc: "clamp_lower_bound is not a valid number",
  5270  		},
  5271  		{
  5272  			product: vegapb.PerpetualProduct{
  5273  				ClampLowerBound: "-10",
  5274  			},
  5275  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.clamp_lower_bound",
  5276  			err:  commands.ErrMustBeWithinRange11,
  5277  			desc: "clamp_lower_bound is not within range (< -1)",
  5278  		},
  5279  		{
  5280  			product: vegapb.PerpetualProduct{
  5281  				ClampLowerBound: "10",
  5282  			},
  5283  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.clamp_lower_bound",
  5284  			err:  commands.ErrMustBeWithinRange11,
  5285  			desc: "clamp_lower_bound is not within range (> 1)",
  5286  		},
  5287  		{
  5288  			product: vegapb.PerpetualProduct{
  5289  				ClampLowerBound: "0.5",
  5290  			},
  5291  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.clamp_lower_bound",
  5292  			desc: "clamp_lower_bound is valid",
  5293  		},
  5294  		{
  5295  			product: vegapb.PerpetualProduct{
  5296  				ClampLowerBound: "-0.5",
  5297  			},
  5298  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.clamp_lower_bound",
  5299  			desc: "clamp_lower_bound is valid",
  5300  		},
  5301  		// clamp_upper_bound (0053-PERP-042)
  5302  		{
  5303  			product: vegapb.PerpetualProduct{
  5304  				ClampUpperBound: "",
  5305  			},
  5306  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.clamp_upper_bound",
  5307  			err:  commands.ErrIsRequired,
  5308  			desc: "clamp_upper_bound is empty",
  5309  		},
  5310  		{
  5311  			product: vegapb.PerpetualProduct{
  5312  				ClampUpperBound: "nope",
  5313  			},
  5314  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.clamp_upper_bound",
  5315  			err:  commands.ErrIsNotValidNumber,
  5316  			desc: "clamp_upper_bound is not a valid number",
  5317  		},
  5318  		{
  5319  			product: vegapb.PerpetualProduct{
  5320  				ClampUpperBound: "-10",
  5321  			},
  5322  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.clamp_upper_bound",
  5323  			err:  commands.ErrMustBeWithinRange11,
  5324  			desc: "clamp_upper_bound is not within range (< -1)",
  5325  		},
  5326  		{
  5327  			product: vegapb.PerpetualProduct{
  5328  				ClampUpperBound: "10",
  5329  			},
  5330  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.clamp_upper_bound",
  5331  			err:  commands.ErrMustBeWithinRange11,
  5332  			desc: "clamp_upper_bound is not within range (> 1)",
  5333  		},
  5334  		{
  5335  			product: vegapb.PerpetualProduct{
  5336  				ClampUpperBound: "0.5",
  5337  			},
  5338  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.clamp_upper_bound",
  5339  			desc: "clamp_upper_bound is valid",
  5340  		},
  5341  		{
  5342  			product: vegapb.PerpetualProduct{
  5343  				ClampUpperBound: "-0.5",
  5344  			},
  5345  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.clamp_upper_bound",
  5346  			desc: "clamp_upper_bound is valid",
  5347  		},
  5348  		// clamp lower and upper (0053-PERP-042)
  5349  		{
  5350  			product: vegapb.PerpetualProduct{
  5351  				ClampLowerBound: "0.5",
  5352  				ClampUpperBound: "0.5",
  5353  			},
  5354  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.clamp_upper_bound",
  5355  			desc: "clamp_upper_bound == clamp_lower_bound is valid",
  5356  		},
  5357  		{
  5358  			product: vegapb.PerpetualProduct{
  5359  				ClampLowerBound: "0.4",
  5360  				ClampUpperBound: "0.5",
  5361  			},
  5362  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.clamp_upper_bound",
  5363  			desc: "clamp_upper_bound > clamp_lower_bound is valid",
  5364  		},
  5365  		{
  5366  			product: vegapb.PerpetualProduct{
  5367  				ClampLowerBound: "0.5",
  5368  				ClampUpperBound: "0.4",
  5369  			},
  5370  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.clamp_upper_bound",
  5371  			err:  commands.ErrMustBeGTEClampLowerBound,
  5372  			desc: "clamp_upper_bound < clamp_lower_bound is invalid",
  5373  		},
  5374  	}
  5375  
  5376  	for _, v := range cases {
  5377  		t.Run(v.desc, func(t *testing.T) {
  5378  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
  5379  				Terms: &vegapb.ProposalTerms{
  5380  					Change: &vegapb.ProposalTerms_NewMarket{
  5381  						NewMarket: &vegapb.NewMarket{
  5382  							Changes: &vegapb.NewMarketConfiguration{
  5383  								Instrument: &vegapb.InstrumentConfiguration{
  5384  									Product: &vegapb.InstrumentConfiguration_Perpetual{
  5385  										Perpetual: &v.product,
  5386  									},
  5387  								},
  5388  							},
  5389  						},
  5390  					},
  5391  				},
  5392  			})
  5393  
  5394  			errs := err.Get(v.path)
  5395  
  5396  			// no errors expected
  5397  			if v.err == nil {
  5398  				assert.Len(t, errs, 0, v.desc)
  5399  				return
  5400  			}
  5401  
  5402  			assert.Contains(t, errs, v.err, v.desc)
  5403  		})
  5404  	}
  5405  }
  5406  
  5407  func testNewPerpsMarketWithFundingRateModifiers(t *testing.T) {
  5408  	cases := []struct {
  5409  		product vegapb.PerpetualProduct
  5410  		err     error
  5411  		path    string
  5412  		desc    string
  5413  	}{
  5414  		{
  5415  			product: vegapb.PerpetualProduct{
  5416  				FundingRateScalingFactor: ptr.From("hello"),
  5417  			},
  5418  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.funding_rate_scaling_factor",
  5419  			err:  commands.ErrIsNotValidNumber,
  5420  		},
  5421  		{
  5422  			product: vegapb.PerpetualProduct{
  5423  				FundingRateScalingFactor: ptr.From("-10"),
  5424  			},
  5425  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.funding_rate_scaling_factor",
  5426  			err:  commands.ErrMustBePositiveOrZero,
  5427  		},
  5428  		{
  5429  			product: vegapb.PerpetualProduct{
  5430  				FundingRateScalingFactor: ptr.From("0.1"),
  5431  			},
  5432  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.funding_rate_scaling_factor",
  5433  		},
  5434  		{
  5435  			product: vegapb.PerpetualProduct{
  5436  				FundingRateLowerBound: ptr.From("hello"),
  5437  			},
  5438  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.funding_rate_lower_bound",
  5439  			err:  commands.ErrIsNotValidNumber,
  5440  		},
  5441  		{
  5442  			product: vegapb.PerpetualProduct{
  5443  				FundingRateLowerBound: ptr.From("-100"),
  5444  			},
  5445  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.funding_rate_lower_bound",
  5446  		},
  5447  		{
  5448  			product: vegapb.PerpetualProduct{
  5449  				FundingRateUpperBound: ptr.From("hello"),
  5450  			},
  5451  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.funding_rate_upper_bound",
  5452  			err:  commands.ErrIsNotValidNumber,
  5453  		},
  5454  		{
  5455  			product: vegapb.PerpetualProduct{
  5456  				FundingRateUpperBound: ptr.From("100"),
  5457  			},
  5458  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.funding_rate_upper_bound",
  5459  		},
  5460  		{
  5461  			product: vegapb.PerpetualProduct{
  5462  				FundingRateUpperBound: ptr.From("100"),
  5463  				FundingRateLowerBound: ptr.From("200"),
  5464  			},
  5465  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.funding_rate_lower_bound",
  5466  			err:  commands.ErrIsNotValid,
  5467  		},
  5468  	}
  5469  
  5470  	for _, v := range cases {
  5471  		t.Run(v.desc, func(t *testing.T) {
  5472  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
  5473  				Terms: &vegapb.ProposalTerms{
  5474  					Change: &vegapb.ProposalTerms_NewMarket{
  5475  						NewMarket: &vegapb.NewMarket{
  5476  							Changes: &vegapb.NewMarketConfiguration{
  5477  								Instrument: &vegapb.InstrumentConfiguration{
  5478  									Product: &vegapb.InstrumentConfiguration_Perpetual{
  5479  										Perpetual: &v.product,
  5480  									},
  5481  								},
  5482  							},
  5483  						},
  5484  					},
  5485  				},
  5486  			})
  5487  			errs := err.Get(v.path)
  5488  
  5489  			// no errors expected
  5490  			if v.err == nil {
  5491  				assert.Len(t, errs, 0, v.desc)
  5492  				return
  5493  			}
  5494  			assert.Contains(t, errs, v.err, v.desc)
  5495  		})
  5496  	}
  5497  }
  5498  
  5499  func TestNewPerpsMarketChangeSubmissionSettlementSchedule(t *testing.T) {
  5500  	cases := []struct {
  5501  		product vegapb.PerpetualProduct
  5502  		err     error
  5503  		path    string
  5504  		desc    string
  5505  	}{
  5506  		{
  5507  			product: vegapb.PerpetualProduct{
  5508  				DataSourceSpecForSettlementSchedule: &vegapb.DataSourceDefinition{
  5509  					SourceType: &vegapb.DataSourceDefinition_Internal{
  5510  						Internal: &vega.DataSourceDefinitionInternal{
  5511  							SourceType: &vegapb.DataSourceDefinitionInternal_TimeTrigger{
  5512  								TimeTrigger: &vegapb.DataSourceSpecConfigurationTimeTrigger{
  5513  									Triggers: []*datapb.InternalTimeTrigger{
  5514  										{
  5515  											Initial: nil,
  5516  											Every:   0,
  5517  										},
  5518  									},
  5519  								},
  5520  							},
  5521  						},
  5522  					},
  5523  				},
  5524  			},
  5525  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec_for_settlement_schedule.internal.timetrigger.triggers.0.every",
  5526  			err:  commands.ErrIsNotValid,
  5527  			desc: "not a valid every",
  5528  		},
  5529  		{
  5530  			product: vegapb.PerpetualProduct{
  5531  				DataSourceSpecForSettlementSchedule: &vegapb.DataSourceDefinition{
  5532  					SourceType: &vegapb.DataSourceDefinition_Internal{
  5533  						Internal: &vega.DataSourceDefinitionInternal{
  5534  							SourceType: &vegapb.DataSourceDefinitionInternal_TimeTrigger{
  5535  								TimeTrigger: &vegapb.DataSourceSpecConfigurationTimeTrigger{
  5536  									Triggers: []*datapb.InternalTimeTrigger{
  5537  										{
  5538  											Initial: nil,
  5539  											Every:   -1,
  5540  										},
  5541  									},
  5542  								},
  5543  							},
  5544  						},
  5545  					},
  5546  				},
  5547  			},
  5548  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec_for_settlement_schedule.internal.timetrigger.triggers.0.every",
  5549  			err:  commands.ErrIsNotValid,
  5550  			desc: "not a valid every",
  5551  		},
  5552  		{
  5553  			product: vegapb.PerpetualProduct{
  5554  				DataSourceSpecForSettlementSchedule: &vegapb.DataSourceDefinition{
  5555  					SourceType: &vegapb.DataSourceDefinition_Internal{
  5556  						Internal: &vega.DataSourceDefinitionInternal{
  5557  							SourceType: &vegapb.DataSourceDefinitionInternal_TimeTrigger{
  5558  								TimeTrigger: &vegapb.DataSourceSpecConfigurationTimeTrigger{
  5559  									Triggers: []*datapb.InternalTimeTrigger{
  5560  										{
  5561  											Initial: ptr.From(int64(-1)),
  5562  											Every:   100,
  5563  										},
  5564  									},
  5565  								},
  5566  							},
  5567  						},
  5568  					},
  5569  				},
  5570  			},
  5571  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec_for_settlement_schedule.internal.timetrigger.triggers.0.initial",
  5572  			err:  commands.ErrIsNotValid,
  5573  			desc: "not a valid every",
  5574  		},
  5575  		{
  5576  			product: vegapb.PerpetualProduct{
  5577  				DataSourceSpecForSettlementSchedule: &vegapb.DataSourceDefinition{
  5578  					SourceType: &vegapb.DataSourceDefinition_Internal{
  5579  						Internal: &vega.DataSourceDefinitionInternal{
  5580  							SourceType: &vegapb.DataSourceDefinitionInternal_TimeTrigger{
  5581  								TimeTrigger: &vegapb.DataSourceSpecConfigurationTimeTrigger{
  5582  									Triggers: []*datapb.InternalTimeTrigger{
  5583  										{
  5584  											Initial: nil,
  5585  											Every:   100,
  5586  										},
  5587  									},
  5588  								},
  5589  							},
  5590  						},
  5591  					},
  5592  				},
  5593  			},
  5594  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec_for_settlement_schedule.internal.timetrigger",
  5595  			desc: "valid with initial nil",
  5596  		},
  5597  		{
  5598  			product: vegapb.PerpetualProduct{
  5599  				DataSourceSpecForSettlementSchedule: &vegapb.DataSourceDefinition{
  5600  					SourceType: &vegapb.DataSourceDefinition_Internal{
  5601  						Internal: &vega.DataSourceDefinitionInternal{
  5602  							SourceType: &vegapb.DataSourceDefinitionInternal_TimeTrigger{
  5603  								TimeTrigger: &vegapb.DataSourceSpecConfigurationTimeTrigger{
  5604  									Triggers: []*datapb.InternalTimeTrigger{
  5605  										{
  5606  											Initial: ptr.From(int64(100)),
  5607  											Every:   100,
  5608  										},
  5609  									},
  5610  								},
  5611  							},
  5612  						},
  5613  					},
  5614  				},
  5615  			},
  5616  			path: "proposal_submission.terms.change.new_market.changes.instrument.product.perps.data_source_spec_for_settlement_schedule.internal.timetrigger",
  5617  			desc: "valid",
  5618  		},
  5619  	}
  5620  
  5621  	for _, v := range cases {
  5622  		t.Run(v.desc, func(t *testing.T) {
  5623  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
  5624  				Terms: &vegapb.ProposalTerms{
  5625  					Change: &vegapb.ProposalTerms_NewMarket{
  5626  						NewMarket: &vegapb.NewMarket{
  5627  							Changes: &vegapb.NewMarketConfiguration{
  5628  								Instrument: &vegapb.InstrumentConfiguration{
  5629  									Product: &vegapb.InstrumentConfiguration_Perpetual{
  5630  										Perpetual: &v.product,
  5631  									},
  5632  								},
  5633  							},
  5634  						},
  5635  					},
  5636  				},
  5637  			})
  5638  
  5639  			errs := err.Get(v.path)
  5640  
  5641  			// no errors expected
  5642  			if v.err == nil {
  5643  				assert.Len(t, errs, 0, v.desc)
  5644  				return
  5645  			}
  5646  
  5647  			assert.Contains(t, errs, v.err, v.desc)
  5648  		})
  5649  	}
  5650  }
  5651  
  5652  func testFutureMarketSubmissionWithInternalTimeTriggerTerminationDataFails(t *testing.T) {
  5653  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  5654  		Terms: &vegapb.ProposalTerms{
  5655  			Change: &vegapb.ProposalTerms_NewMarket{
  5656  				NewMarket: &vegapb.NewMarket{
  5657  					Changes: &vegapb.NewMarketConfiguration{
  5658  						Instrument: &vegapb.InstrumentConfiguration{
  5659  							Product: &vegapb.InstrumentConfiguration_Future{
  5660  								Future: &vegapb.FutureProduct{
  5661  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  5662  										vegapb.DataSourceContentTypeOracle,
  5663  									).SetOracleConfig(
  5664  										&vegapb.DataSourceDefinitionExternal_Oracle{
  5665  											Oracle: &vegapb.DataSourceSpecConfiguration{
  5666  												Signers: []*datapb.Signer{
  5667  													{
  5668  														Signer: &datapb.Signer_EthAddress{
  5669  															EthAddress: &datapb.ETHAddress{
  5670  																Address: "",
  5671  															},
  5672  														},
  5673  													},
  5674  												},
  5675  												Filters: []*datapb.Filter{
  5676  													{
  5677  														Key: &datapb.PropertyKey{
  5678  															Name: "vegaprotocol.builtin.prices.ETH.value",
  5679  															Type: datapb.PropertyKey_TYPE_INTEGER,
  5680  														},
  5681  														Conditions: []*datapb.Condition{
  5682  															{
  5683  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  5684  															},
  5685  														},
  5686  													},
  5687  												},
  5688  											},
  5689  										},
  5690  									),
  5691  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  5692  										vegapb.DataSourceContentTypeInternalTimeTriggerTermination,
  5693  									).SetTimeTriggerConditionConfig(
  5694  										[]*datapb.Condition{
  5695  											{
  5696  												// It does not matter what conditions are set here
  5697  												Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  5698  											},
  5699  										},
  5700  									),
  5701  								},
  5702  							},
  5703  						},
  5704  					},
  5705  				},
  5706  			},
  5707  		},
  5708  	})
  5709  
  5710  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_trading_termination.internal.timetrigger"), commands.ErrIsNotValid)
  5711  }
  5712  
  5713  func testFutureMarketSubmissionWithInternalTimeTriggerSettlementDataFails(t *testing.T) {
  5714  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  5715  		Terms: &vegapb.ProposalTerms{
  5716  			Change: &vegapb.ProposalTerms_NewMarket{
  5717  				NewMarket: &vegapb.NewMarket{
  5718  					Changes: &vegapb.NewMarketConfiguration{
  5719  						Instrument: &vegapb.InstrumentConfiguration{
  5720  							Product: &vegapb.InstrumentConfiguration_Future{
  5721  								Future: &vegapb.FutureProduct{
  5722  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  5723  										vegapb.DataSourceContentTypeInternalTimeTriggerTermination,
  5724  									).SetTimeTriggerConditionConfig(
  5725  										[]*datapb.Condition{
  5726  											{
  5727  												// It does not matter what conditions are set here
  5728  												Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  5729  											},
  5730  										},
  5731  									),
  5732  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  5733  										vegapb.DataSourceContentTypeInternalTimeTriggerTermination,
  5734  									).SetTimeTriggerConditionConfig(
  5735  										[]*datapb.Condition{
  5736  											{
  5737  												// It does not matter what conditions are set here
  5738  												Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  5739  											},
  5740  										},
  5741  									),
  5742  								},
  5743  							},
  5744  						},
  5745  					},
  5746  				},
  5747  			},
  5748  		},
  5749  	})
  5750  
  5751  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data.internal.timetrigger"), commands.ErrIsNotValid)
  5752  }
  5753  
  5754  func TestNewMarketChangeSubmissionWithInvalidLpRangeFails(t *testing.T) {
  5755  	priceRanges := []string{"banana", "-1", "0", "101"}
  5756  	errors := []error{commands.ErrIsNotValidNumber, commands.ErrMustBeWithinRangeGT0LT20, commands.ErrMustBeWithinRangeGT0LT20, commands.ErrMustBeWithinRangeGT0LT20}
  5757  
  5758  	for i, v := range priceRanges {
  5759  		err := checkProposalSubmission(&commandspb.ProposalSubmission{
  5760  			Terms: &protoTypes.ProposalTerms{
  5761  				Change: &protoTypes.ProposalTerms_NewMarket{
  5762  					NewMarket: &protoTypes.NewMarket{
  5763  						Changes: &protoTypes.NewMarketConfiguration{
  5764  							Instrument: &protoTypes.InstrumentConfiguration{
  5765  								Product: &protoTypes.InstrumentConfiguration_Future{},
  5766  							},
  5767  							LiquiditySlaParameters: &protoTypes.LiquiditySLAParameters{
  5768  								PriceRange: v,
  5769  							},
  5770  						},
  5771  					},
  5772  				},
  5773  			},
  5774  		})
  5775  		assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.sla_params.price_range"), errors[i])
  5776  	}
  5777  }
  5778  
  5779  func TestNewMarketChangeSubmissionWithInvalidMinTimeFractionFails(t *testing.T) {
  5780  	minTimeFraction := []string{"banana", "-1", "-1.1", "1.1", "100"}
  5781  	errors := []error{commands.ErrIsNotValidNumber, commands.ErrMustBeWithinRange01, commands.ErrMustBeWithinRange01, commands.ErrMustBeWithinRange01, commands.ErrMustBeWithinRange01}
  5782  
  5783  	for i, v := range minTimeFraction {
  5784  		err := checkProposalSubmission(&commandspb.ProposalSubmission{
  5785  			Terms: &protoTypes.ProposalTerms{
  5786  				Change: &protoTypes.ProposalTerms_NewMarket{
  5787  					NewMarket: &protoTypes.NewMarket{
  5788  						Changes: &protoTypes.NewMarketConfiguration{
  5789  							Instrument: &protoTypes.InstrumentConfiguration{
  5790  								Product: &protoTypes.InstrumentConfiguration_Future{},
  5791  							},
  5792  							LiquiditySlaParameters: &protoTypes.LiquiditySLAParameters{
  5793  								CommitmentMinTimeFraction: v,
  5794  							},
  5795  						},
  5796  					},
  5797  				},
  5798  			},
  5799  		})
  5800  		assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.sla_params.commitment_min_time_fraction"), errors[i])
  5801  	}
  5802  }
  5803  
  5804  func TestNewMarketChangeSubmissionWithValidMinTimeFractionSucceeds(t *testing.T) {
  5805  	minTimeFraction := []string{"0", "0.1", "0.99", "1"}
  5806  
  5807  	for _, v := range minTimeFraction {
  5808  		err := checkProposalSubmission(&commandspb.ProposalSubmission{
  5809  			Terms: &protoTypes.ProposalTerms{
  5810  				Change: &protoTypes.ProposalTerms_NewMarket{
  5811  					NewMarket: &protoTypes.NewMarket{
  5812  						Changes: &protoTypes.NewMarketConfiguration{
  5813  							Instrument: &protoTypes.InstrumentConfiguration{
  5814  								Product: &protoTypes.InstrumentConfiguration_Future{},
  5815  							},
  5816  							LiquiditySlaParameters: &protoTypes.LiquiditySLAParameters{
  5817  								CommitmentMinTimeFraction: v,
  5818  							},
  5819  						},
  5820  					},
  5821  				},
  5822  			},
  5823  		})
  5824  
  5825  		errors := []error{commands.ErrIsNotValidNumber, commands.ErrMustBeWithinRange01}
  5826  		for _, e := range errors {
  5827  			assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.sla_params.commitment_min_time_fraction"), e)
  5828  		}
  5829  	}
  5830  }
  5831  
  5832  func TestNewMarketChangeSubmissionWithInvalidCompetitionFactorFails(t *testing.T) {
  5833  	competitionFactors := []string{"banana", "-1", "-1.1", "1.1", "100"}
  5834  	errors := []error{commands.ErrIsNotValidNumber, commands.ErrMustBeWithinRange01, commands.ErrMustBeWithinRange01, commands.ErrMustBeWithinRange01, commands.ErrMustBeWithinRange01}
  5835  
  5836  	for i, v := range competitionFactors {
  5837  		err := checkProposalSubmission(&commandspb.ProposalSubmission{
  5838  			Terms: &protoTypes.ProposalTerms{
  5839  				Change: &protoTypes.ProposalTerms_NewMarket{
  5840  					NewMarket: &protoTypes.NewMarket{
  5841  						Changes: &protoTypes.NewMarketConfiguration{
  5842  							Instrument: &protoTypes.InstrumentConfiguration{
  5843  								Product: &protoTypes.InstrumentConfiguration_Future{},
  5844  							},
  5845  							LiquiditySlaParameters: &protoTypes.LiquiditySLAParameters{
  5846  								SlaCompetitionFactor: v,
  5847  							},
  5848  						},
  5849  					},
  5850  				},
  5851  			},
  5852  		})
  5853  		assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.sla_params.sla_competition_factor"), errors[i])
  5854  	}
  5855  }
  5856  
  5857  func TestNewMarketChangeSubmissionWithValidCompetitionFactorSucceeds(t *testing.T) {
  5858  	minTimeFraction := []string{"0", "0.1", "0.99", "1"}
  5859  
  5860  	for _, v := range minTimeFraction {
  5861  		err := checkProposalSubmission(&commandspb.ProposalSubmission{
  5862  			Terms: &protoTypes.ProposalTerms{
  5863  				Change: &protoTypes.ProposalTerms_NewMarket{
  5864  					NewMarket: &protoTypes.NewMarket{
  5865  						Changes: &protoTypes.NewMarketConfiguration{
  5866  							Instrument: &protoTypes.InstrumentConfiguration{
  5867  								Product: &protoTypes.InstrumentConfiguration_Future{},
  5868  							},
  5869  							LiquiditySlaParameters: &protoTypes.LiquiditySLAParameters{
  5870  								SlaCompetitionFactor: v,
  5871  							},
  5872  						},
  5873  					},
  5874  				},
  5875  			},
  5876  		})
  5877  
  5878  		errors := []error{commands.ErrIsNotValidNumber, commands.ErrMustBeWithinRange01}
  5879  		for _, e := range errors {
  5880  			assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.sla_params.sla_competition_factor"), e)
  5881  		}
  5882  	}
  5883  }
  5884  
  5885  func TestNewMarketChangeSubmissionWithInvalidPerformanceHysteresisEpochsFails(t *testing.T) {
  5886  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  5887  		Terms: &protoTypes.ProposalTerms{
  5888  			Change: &protoTypes.ProposalTerms_NewMarket{
  5889  				NewMarket: &protoTypes.NewMarket{
  5890  					Changes: &protoTypes.NewMarketConfiguration{
  5891  						Instrument: &protoTypes.InstrumentConfiguration{
  5892  							Product: &protoTypes.InstrumentConfiguration_Future{},
  5893  						},
  5894  						LiquiditySlaParameters: &protoTypes.LiquiditySLAParameters{
  5895  							PerformanceHysteresisEpochs: 367,
  5896  						},
  5897  					},
  5898  				},
  5899  			},
  5900  		},
  5901  	})
  5902  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.sla_params.performance_hysteresis_epochs"), commands.ErrMustBeLessThen366)
  5903  }
  5904  
  5905  func TestNewMarketChangeSubmissionWithValidPerformanceHysteresisEpochsSucceeds(t *testing.T) {
  5906  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  5907  		Terms: &protoTypes.ProposalTerms{
  5908  			Change: &protoTypes.ProposalTerms_NewMarket{
  5909  				NewMarket: &protoTypes.NewMarket{
  5910  					Changes: &protoTypes.NewMarketConfiguration{
  5911  						Instrument: &protoTypes.InstrumentConfiguration{
  5912  							Product: &protoTypes.InstrumentConfiguration_Future{},
  5913  						},
  5914  						LiquiditySlaParameters: &protoTypes.LiquiditySLAParameters{
  5915  							PerformanceHysteresisEpochs: 1,
  5916  						},
  5917  					},
  5918  				},
  5919  			},
  5920  		},
  5921  	})
  5922  
  5923  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.sla_params.performance_hysteresis_epochs"), commands.ErrMustBePositive)
  5924  }
  5925  
  5926  func testNewMarketChangeSubmissionWithInvalidLpRangeFails(t *testing.T) {
  5927  	priceRanges := []string{"banana", "-1", "0", "101"}
  5928  	errors := []error{commands.ErrIsNotValidNumber, commands.ErrMustBeWithinRangeGT0LT20, commands.ErrMustBeWithinRangeGT0LT20, commands.ErrMustBeWithinRangeGT0LT20}
  5929  
  5930  	for i, v := range priceRanges {
  5931  		err := checkProposalSubmission(&commandspb.ProposalSubmission{
  5932  			Terms: &protoTypes.ProposalTerms{
  5933  				Change: &protoTypes.ProposalTerms_NewMarket{
  5934  					NewMarket: &protoTypes.NewMarket{
  5935  						Changes: &protoTypes.NewMarketConfiguration{
  5936  							Instrument: &protoTypes.InstrumentConfiguration{
  5937  								Product: &protoTypes.InstrumentConfiguration_Future{},
  5938  							},
  5939  							LiquiditySlaParameters: &protoTypes.LiquiditySLAParameters{
  5940  								PriceRange: v,
  5941  							},
  5942  						},
  5943  					},
  5944  				},
  5945  			},
  5946  		})
  5947  		assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.sla_params.price_range"), errors[i])
  5948  	}
  5949  }
  5950  
  5951  func testNewMarketChangeSubmissionWithValidLpRangeSucceeds(t *testing.T) {
  5952  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  5953  		Terms: &protoTypes.ProposalTerms{
  5954  			Change: &protoTypes.ProposalTerms_NewMarket{
  5955  				NewMarket: &protoTypes.NewMarket{
  5956  					Changes: &protoTypes.NewMarketConfiguration{
  5957  						Instrument: &protoTypes.InstrumentConfiguration{
  5958  							Product: &protoTypes.InstrumentConfiguration_Future{},
  5959  						},
  5960  						LiquiditySlaParameters: &protoTypes.LiquiditySLAParameters{
  5961  							PriceRange: "50",
  5962  						},
  5963  					},
  5964  				},
  5965  			},
  5966  		},
  5967  	})
  5968  	errors := []error{commands.ErrIsNotValidNumber, commands.ErrMustBePositive, commands.ErrMustBePositive, commands.ErrMustBeAtMost100}
  5969  	for _, e := range errors {
  5970  		assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.sla_params.price_range"), e)
  5971  	}
  5972  }
  5973  
  5974  func testNewMarketChangeSubmissionWithInvalidMinTimeFractionFails(t *testing.T) {
  5975  	minTimeFraction := []string{"banana", "-1", "-1.1", "1.1", "100"}
  5976  	errors := []error{commands.ErrIsNotValidNumber, commands.ErrMustBeWithinRange01, commands.ErrMustBeWithinRange01, commands.ErrMustBeWithinRange01, commands.ErrMustBeWithinRange01}
  5977  
  5978  	for i, v := range minTimeFraction {
  5979  		err := checkProposalSubmission(&commandspb.ProposalSubmission{
  5980  			Terms: &protoTypes.ProposalTerms{
  5981  				Change: &protoTypes.ProposalTerms_NewMarket{
  5982  					NewMarket: &protoTypes.NewMarket{
  5983  						Changes: &protoTypes.NewMarketConfiguration{
  5984  							Instrument: &protoTypes.InstrumentConfiguration{
  5985  								Product: &protoTypes.InstrumentConfiguration_Future{},
  5986  							},
  5987  							LiquiditySlaParameters: &protoTypes.LiquiditySLAParameters{
  5988  								CommitmentMinTimeFraction: v,
  5989  							},
  5990  						},
  5991  					},
  5992  				},
  5993  			},
  5994  		})
  5995  		assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.sla_params.commitment_min_time_fraction"), errors[i])
  5996  	}
  5997  }
  5998  
  5999  func testNewMarketChangeSubmissionWithValidMinTimeFractionSucceeds(t *testing.T) {
  6000  	minTimeFraction := []string{"0", "0.1", "0.99", "1"}
  6001  
  6002  	for _, v := range minTimeFraction {
  6003  		err := checkProposalSubmission(&commandspb.ProposalSubmission{
  6004  			Terms: &protoTypes.ProposalTerms{
  6005  				Change: &protoTypes.ProposalTerms_NewMarket{
  6006  					NewMarket: &protoTypes.NewMarket{
  6007  						Changes: &protoTypes.NewMarketConfiguration{
  6008  							Instrument: &protoTypes.InstrumentConfiguration{
  6009  								Product: &protoTypes.InstrumentConfiguration_Future{},
  6010  							},
  6011  							LiquiditySlaParameters: &protoTypes.LiquiditySLAParameters{
  6012  								CommitmentMinTimeFraction: v,
  6013  							},
  6014  						},
  6015  					},
  6016  				},
  6017  			},
  6018  		})
  6019  
  6020  		errors := []error{commands.ErrIsNotValidNumber, commands.ErrMustBeWithinRange01}
  6021  		for _, e := range errors {
  6022  			assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.sla_params.commitment_min_time_fraction"), e)
  6023  		}
  6024  	}
  6025  }
  6026  
  6027  func testNewMarketChangeSubmissionWithInvalidCompetitionFactorFails(t *testing.T) {
  6028  	competitionFactors := []string{"banana", "-1", "-1.1", "1.1", "100"}
  6029  	errors := []error{commands.ErrIsNotValidNumber, commands.ErrMustBeWithinRange01, commands.ErrMustBeWithinRange01, commands.ErrMustBeWithinRange01, commands.ErrMustBeWithinRange01}
  6030  
  6031  	for i, v := range competitionFactors {
  6032  		err := checkProposalSubmission(&commandspb.ProposalSubmission{
  6033  			Terms: &protoTypes.ProposalTerms{
  6034  				Change: &protoTypes.ProposalTerms_NewMarket{
  6035  					NewMarket: &protoTypes.NewMarket{
  6036  						Changes: &protoTypes.NewMarketConfiguration{
  6037  							Instrument: &protoTypes.InstrumentConfiguration{
  6038  								Product: &protoTypes.InstrumentConfiguration_Future{},
  6039  							},
  6040  							LiquiditySlaParameters: &protoTypes.LiquiditySLAParameters{
  6041  								SlaCompetitionFactor: v,
  6042  							},
  6043  						},
  6044  					},
  6045  				},
  6046  			},
  6047  		})
  6048  		assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.sla_params.sla_competition_factor"), errors[i])
  6049  	}
  6050  }
  6051  
  6052  func testNewMarketChangeSubmissionWithValidCompetitionFactorSucceeds(t *testing.T) {
  6053  	minTimeFraction := []string{"0", "0.1", "0.99", "1"}
  6054  
  6055  	for _, v := range minTimeFraction {
  6056  		err := checkProposalSubmission(&commandspb.ProposalSubmission{
  6057  			Terms: &protoTypes.ProposalTerms{
  6058  				Change: &protoTypes.ProposalTerms_NewMarket{
  6059  					NewMarket: &protoTypes.NewMarket{
  6060  						Changes: &protoTypes.NewMarketConfiguration{
  6061  							Instrument: &protoTypes.InstrumentConfiguration{
  6062  								Product: &protoTypes.InstrumentConfiguration_Future{},
  6063  							},
  6064  							LiquiditySlaParameters: &protoTypes.LiquiditySLAParameters{
  6065  								SlaCompetitionFactor: v,
  6066  							},
  6067  						},
  6068  					},
  6069  				},
  6070  			},
  6071  		})
  6072  
  6073  		errors := []error{commands.ErrIsNotValidNumber, commands.ErrMustBeWithinRange01}
  6074  		for _, e := range errors {
  6075  			assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.sla_params.sla_competition_factor"), e)
  6076  		}
  6077  	}
  6078  }
  6079  
  6080  func testNewMarketChangeSubmissionWithInvalidPerformanceHysteresisEpochsFails(t *testing.T) {
  6081  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  6082  		Terms: &protoTypes.ProposalTerms{
  6083  			Change: &protoTypes.ProposalTerms_NewMarket{
  6084  				NewMarket: &protoTypes.NewMarket{
  6085  					Changes: &protoTypes.NewMarketConfiguration{
  6086  						Instrument: &protoTypes.InstrumentConfiguration{
  6087  							Product: &protoTypes.InstrumentConfiguration_Future{},
  6088  						},
  6089  						LiquiditySlaParameters: &protoTypes.LiquiditySLAParameters{
  6090  							PerformanceHysteresisEpochs: 367,
  6091  						},
  6092  					},
  6093  				},
  6094  			},
  6095  		},
  6096  	})
  6097  	assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.sla_params.performance_hysteresis_epochs"), commands.ErrMustBeLessThen366)
  6098  }
  6099  
  6100  func testNewMarketChangeSubmissionWithValidPerformanceHysteresisEpochsSucceeds(t *testing.T) {
  6101  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  6102  		Terms: &protoTypes.ProposalTerms{
  6103  			Change: &protoTypes.ProposalTerms_NewMarket{
  6104  				NewMarket: &protoTypes.NewMarket{
  6105  					Changes: &protoTypes.NewMarketConfiguration{
  6106  						Instrument: &protoTypes.InstrumentConfiguration{
  6107  							Product: &protoTypes.InstrumentConfiguration_Future{},
  6108  						},
  6109  						LiquiditySlaParameters: &protoTypes.LiquiditySLAParameters{
  6110  							PerformanceHysteresisEpochs: 1,
  6111  						},
  6112  					},
  6113  				},
  6114  			},
  6115  		},
  6116  	})
  6117  
  6118  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.sla_params.performance_hysteresis_epochs"), commands.ErrMustBePositive)
  6119  }
  6120  
  6121  func testLiquidityFeeSettings(t *testing.T) {
  6122  	cases := []struct {
  6123  		lfs   *vega.LiquidityFeeSettings
  6124  		field string
  6125  		err   error
  6126  	}{
  6127  		{
  6128  			lfs: &vega.LiquidityFeeSettings{
  6129  				Method:      vegapb.LiquidityFeeSettings_METHOD_MARGINAL_COST,
  6130  				FeeConstant: ptr.From("0.1"),
  6131  			},
  6132  			field: "method",
  6133  			err:   commands.ErrIsNotValid,
  6134  		},
  6135  		{
  6136  			lfs: &vega.LiquidityFeeSettings{
  6137  				Method:      vegapb.LiquidityFeeSettings_METHOD_WEIGHTED_AVERAGE,
  6138  				FeeConstant: ptr.From("0.1"),
  6139  			},
  6140  			field: "method",
  6141  			err:   commands.ErrIsNotValid,
  6142  		},
  6143  		{
  6144  			lfs: &vega.LiquidityFeeSettings{
  6145  				Method:      vegapb.LiquidityFeeSettings_METHOD_CONSTANT,
  6146  				FeeConstant: nil,
  6147  			},
  6148  			field: "fee_constant",
  6149  			err:   commands.ErrIsRequired,
  6150  		},
  6151  		{
  6152  			lfs: &vega.LiquidityFeeSettings{
  6153  				Method:      vegapb.LiquidityFeeSettings_METHOD_CONSTANT,
  6154  				FeeConstant: ptr.From("hello"),
  6155  			},
  6156  			field: "fee_constant",
  6157  			err:   commands.ErrIsNotValidNumber,
  6158  		},
  6159  		{
  6160  			lfs: &vega.LiquidityFeeSettings{
  6161  				Method:      vegapb.LiquidityFeeSettings_METHOD_CONSTANT,
  6162  				FeeConstant: ptr.From("-0.1"), // (0042-LIQF-060)
  6163  			},
  6164  			field: "fee_constant",
  6165  			err:   commands.ErrMustBePositiveOrZero,
  6166  		},
  6167  		{
  6168  			lfs: &vega.LiquidityFeeSettings{
  6169  				Method:      vegapb.LiquidityFeeSettings_METHOD_CONSTANT,
  6170  				FeeConstant: ptr.From("1.1"), // (0042-LIQF-060)
  6171  			},
  6172  			field: "fee_constant",
  6173  			err:   commands.ErrMustBeWithinRange01,
  6174  		},
  6175  		{
  6176  			lfs: &vega.LiquidityFeeSettings{
  6177  				Method: vegapb.LiquidityFeeSettings_METHOD_UNSPECIFIED,
  6178  			},
  6179  			field: "method",
  6180  			err:   commands.ErrIsRequired,
  6181  		},
  6182  		{
  6183  			lfs: &vega.LiquidityFeeSettings{
  6184  				Method: vegapb.LiquidityFeeSettings_Method(int32(100)),
  6185  			},
  6186  			field: "method",
  6187  			err:   commands.ErrIsNotValid,
  6188  		},
  6189  	}
  6190  
  6191  	for _, c := range cases {
  6192  		err := checkProposalSubmission(&commandspb.ProposalSubmission{
  6193  			Terms: &vegapb.ProposalTerms{
  6194  				Change: &vegapb.ProposalTerms_NewMarket{
  6195  					NewMarket: &vegapb.NewMarket{
  6196  						Changes: &vegapb.NewMarketConfiguration{
  6197  							Instrument: &vegapb.InstrumentConfiguration{
  6198  								Product: &vegapb.InstrumentConfiguration_Perpetual{
  6199  									Perpetual: &vegapb.PerpetualProduct{},
  6200  								},
  6201  							},
  6202  							LiquidityFeeSettings: c.lfs,
  6203  						},
  6204  					},
  6205  				},
  6206  			},
  6207  		})
  6208  		assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.liquidity_fee_settings."+c.field), c.err)
  6209  	}
  6210  }
  6211  
  6212  func testLiquidityFeeSettingsSpot(t *testing.T) {
  6213  	cases := []struct {
  6214  		lfs   *vega.LiquidityFeeSettings
  6215  		field string
  6216  		err   error
  6217  	}{
  6218  		{
  6219  			lfs: &vega.LiquidityFeeSettings{
  6220  				Method:      vegapb.LiquidityFeeSettings_METHOD_MARGINAL_COST,
  6221  				FeeConstant: ptr.From("0.1"),
  6222  			},
  6223  			field: "method",
  6224  			err:   commands.ErrIsNotValid,
  6225  		},
  6226  		{
  6227  			lfs: &vega.LiquidityFeeSettings{
  6228  				Method:      vegapb.LiquidityFeeSettings_METHOD_WEIGHTED_AVERAGE,
  6229  				FeeConstant: ptr.From("0.1"),
  6230  			},
  6231  			field: "method",
  6232  			err:   commands.ErrIsNotValid,
  6233  		},
  6234  		{
  6235  			lfs: &vega.LiquidityFeeSettings{
  6236  				Method:      vegapb.LiquidityFeeSettings_METHOD_CONSTANT,
  6237  				FeeConstant: nil,
  6238  			},
  6239  			field: "fee_constant",
  6240  			err:   commands.ErrIsRequired,
  6241  		},
  6242  		{
  6243  			lfs: &vega.LiquidityFeeSettings{
  6244  				Method:      vegapb.LiquidityFeeSettings_METHOD_CONSTANT,
  6245  				FeeConstant: ptr.From("hello"),
  6246  			},
  6247  			field: "fee_constant",
  6248  			err:   commands.ErrIsNotValidNumber,
  6249  		},
  6250  		{
  6251  			lfs: &vega.LiquidityFeeSettings{
  6252  				Method:      vegapb.LiquidityFeeSettings_METHOD_CONSTANT,
  6253  				FeeConstant: ptr.From("-0.1"), // (0042-LIQF-072)
  6254  			},
  6255  			field: "fee_constant",
  6256  			err:   commands.ErrMustBePositiveOrZero,
  6257  		},
  6258  		{
  6259  			lfs: &vega.LiquidityFeeSettings{
  6260  				Method:      vegapb.LiquidityFeeSettings_METHOD_CONSTANT,
  6261  				FeeConstant: ptr.From("1.1"), // (0042-LIQF-072)
  6262  			},
  6263  			field: "fee_constant",
  6264  			err:   commands.ErrMustBeWithinRange01,
  6265  		},
  6266  		{
  6267  			lfs: &vega.LiquidityFeeSettings{
  6268  				Method: vegapb.LiquidityFeeSettings_METHOD_UNSPECIFIED,
  6269  			},
  6270  			field: "method",
  6271  			err:   commands.ErrIsRequired,
  6272  		},
  6273  		{
  6274  			lfs: &vega.LiquidityFeeSettings{
  6275  				Method: vegapb.LiquidityFeeSettings_Method(int32(100)),
  6276  			},
  6277  			field: "method",
  6278  			err:   commands.ErrIsNotValid,
  6279  		},
  6280  	}
  6281  
  6282  	for _, c := range cases {
  6283  		err := checkProposalSubmission(&commandspb.ProposalSubmission{
  6284  			Terms: &vegapb.ProposalTerms{
  6285  				Change: &vegapb.ProposalTerms_NewSpotMarket{
  6286  					NewSpotMarket: &vegapb.NewSpotMarket{
  6287  						Changes: &vegapb.NewSpotMarketConfiguration{
  6288  							Instrument: &vegapb.InstrumentConfiguration{
  6289  								Product: &vegapb.InstrumentConfiguration_Spot{
  6290  									Spot: &vegapb.SpotProduct{},
  6291  								},
  6292  							},
  6293  							LiquidityFeeSettings: c.lfs,
  6294  						},
  6295  					},
  6296  				},
  6297  			},
  6298  		})
  6299  		assert.Contains(t, err.Get("proposal_submission.terms.change.new_spot_market.changes.liquidity_fee_settings."+c.field), c.err)
  6300  	}
  6301  }
  6302  
  6303  func testFutureMarketSubmissionWithValidLiquidationStrategySucceeds(t *testing.T) {
  6304  	pubKey := []*dstypes.Signer{
  6305  		dstypes.CreateSignerFromString("bd069246503a57271375f1995c46e03db88c4e1a564077b33a9872f905650dc4", dstypes.SignerTypePubKey),
  6306  	}
  6307  
  6308  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  6309  		Terms: &vegapb.ProposalTerms{
  6310  			Change: &vegapb.ProposalTerms_NewMarket{
  6311  				NewMarket: &vegapb.NewMarket{
  6312  					Changes: &vegapb.NewMarketConfiguration{
  6313  						Instrument: &vegapb.InstrumentConfiguration{
  6314  							Product: &vegapb.InstrumentConfiguration_Future{
  6315  								Future: &vegapb.FutureProduct{
  6316  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  6317  										vegapb.DataSourceContentTypeOracle,
  6318  									).SetOracleConfig(
  6319  										&vegapb.DataSourceDefinitionExternal_Oracle{
  6320  											Oracle: &vegapb.DataSourceSpecConfiguration{
  6321  												Signers: dstypes.SignersIntoProto(pubKey),
  6322  												Filters: []*datapb.Filter{
  6323  													{
  6324  														Key: &datapb.PropertyKey{
  6325  															Name: "prices.ETH.value",
  6326  															Type: datapb.PropertyKey_TYPE_INTEGER,
  6327  														},
  6328  														Conditions: []*datapb.Condition{
  6329  															{
  6330  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  6331  															},
  6332  														},
  6333  													},
  6334  												},
  6335  											},
  6336  										},
  6337  									),
  6338  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  6339  										vegapb.DataSourceContentTypeOracle,
  6340  									).SetOracleConfig(
  6341  										&vegapb.DataSourceDefinitionExternal_Oracle{
  6342  											Oracle: &vegapb.DataSourceSpecConfiguration{
  6343  												Signers: dstypes.SignersIntoProto(pubKey),
  6344  												Filters: []*datapb.Filter{
  6345  													{
  6346  														Key: &datapb.PropertyKey{
  6347  															Name: "vegaprotocol.builtin.timestamp",
  6348  															Type: datapb.PropertyKey_TYPE_TIMESTAMP,
  6349  														},
  6350  														Conditions: []*datapb.Condition{
  6351  															{
  6352  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  6353  																Value:    fmt.Sprintf("%d", time.Now().Add(time.Hour*24*365).UnixNano()),
  6354  															},
  6355  														},
  6356  													},
  6357  												},
  6358  											},
  6359  										},
  6360  									),
  6361  								},
  6362  							},
  6363  						},
  6364  						LiquidationStrategy: &vegapb.LiquidationStrategy{
  6365  							DisposalTimeStep:      20,
  6366  							DisposalFraction:      "0.05",
  6367  							FullDisposalSize:      20,
  6368  							MaxFractionConsumed:   "0.01",
  6369  							DisposalSlippageRange: "0.1",
  6370  						},
  6371  					},
  6372  				},
  6373  			},
  6374  		},
  6375  	})
  6376  
  6377  	assert.Empty(t, err.Get("proposal_submission.terms.change.new_market.changes.liquidation_strategy.disposal_fraction"))
  6378  	assert.Empty(t, err.Get("proposal_submission.terms.change.new_market.changes.liquidation_strategy.max_fraction_consumed"))
  6379  	assert.Empty(t, err.Get("proposal_submission.terms.change.new_market.changes.liquidation_strategy.disposal_time_step"))
  6380  	assert.Empty(t, err.Get("proposal_submission.terms.change.new_market.changes.liquidation_strategy.disposal_slippage_range"))
  6381  }
  6382  
  6383  type compositePriceConfigCase struct {
  6384  	mpc   *vega.CompositePriceConfiguration
  6385  	field string
  6386  	err   error
  6387  }
  6388  
  6389  func getCompositePriceConfigurationCases() []compositePriceConfigCase {
  6390  	cases := []compositePriceConfigCase{
  6391  		{
  6392  			mpc:   &vega.CompositePriceConfiguration{},
  6393  			field: "composite_price_type",
  6394  			err:   commands.ErrIsRequired,
  6395  		},
  6396  		{
  6397  			mpc: &vega.CompositePriceConfiguration{
  6398  				CompositePriceType: 0,
  6399  			},
  6400  			field: "composite_price_type",
  6401  			err:   commands.ErrIsRequired,
  6402  		},
  6403  		{
  6404  			mpc: &vega.CompositePriceConfiguration{
  6405  				CompositePriceType: 4,
  6406  			},
  6407  			field: "composite_price_type",
  6408  			err:   commands.ErrIsNotValid,
  6409  		},
  6410  		{
  6411  			mpc: &vega.CompositePriceConfiguration{
  6412  				CompositePriceType: 2,
  6413  				DecayWeight:        "",
  6414  			},
  6415  			field: "decay_weight",
  6416  			err:   commands.ErrIsRequired,
  6417  		},
  6418  		{
  6419  			mpc: &vega.CompositePriceConfiguration{
  6420  				CompositePriceType: 2,
  6421  				DecayWeight:        "banana",
  6422  			},
  6423  			field: "decay_weight",
  6424  			err:   commands.ErrIsNotValidNumber,
  6425  		},
  6426  		{
  6427  			mpc: &vega.CompositePriceConfiguration{
  6428  				CompositePriceType: 2,
  6429  				DecayWeight:        "-1",
  6430  			},
  6431  			field: "decay_weight",
  6432  			err:   commands.ErrMustBeWithinRange01,
  6433  		},
  6434  		{
  6435  			mpc: &vega.CompositePriceConfiguration{
  6436  				CompositePriceType: 2,
  6437  				DecayWeight:        "1.1",
  6438  			},
  6439  			field: "decay_weight",
  6440  			err:   commands.ErrMustBeWithinRange01,
  6441  		},
  6442  		{
  6443  			mpc: &vega.CompositePriceConfiguration{
  6444  				CompositePriceType: 3,
  6445  				DecayWeight:        "",
  6446  			},
  6447  			field: "decay_weight",
  6448  			err:   nil,
  6449  		},
  6450  		{
  6451  			mpc: &vega.CompositePriceConfiguration{
  6452  				CompositePriceType: 2,
  6453  				DecayPower:         4,
  6454  			},
  6455  			field: "decay_power",
  6456  			err:   fmt.Errorf("must be in {1, 2, 3}"),
  6457  		},
  6458  		{
  6459  			mpc: &vega.CompositePriceConfiguration{
  6460  				CompositePriceType: 2,
  6461  				DecayPower:         0,
  6462  			},
  6463  			field: "decay_power",
  6464  			err:   fmt.Errorf("must be in {1, 2, 3}"),
  6465  		},
  6466  		{
  6467  			mpc: &vega.CompositePriceConfiguration{
  6468  				CompositePriceType: 3,
  6469  				DecayPower:         0,
  6470  			},
  6471  			field: "decay_power",
  6472  			err:   nil,
  6473  		},
  6474  		{
  6475  			mpc: &vega.CompositePriceConfiguration{
  6476  				CompositePriceType: 2,
  6477  				CashAmount:         "",
  6478  			},
  6479  			field: "cash_amount",
  6480  			err:   commands.ErrIsRequired,
  6481  		},
  6482  		{
  6483  			mpc: &vega.CompositePriceConfiguration{
  6484  				CompositePriceType: 2,
  6485  				CashAmount:         "banana",
  6486  			},
  6487  			field: "cash_amount",
  6488  			err:   commands.ErrIsNotValidNumber,
  6489  		},
  6490  		{
  6491  			mpc: &vega.CompositePriceConfiguration{
  6492  				CompositePriceType: 2,
  6493  				CashAmount:         "-1",
  6494  			},
  6495  			field: "cash_amount",
  6496  			err:   commands.ErrIsNotValidNumber,
  6497  		},
  6498  		{
  6499  			mpc: &vega.CompositePriceConfiguration{
  6500  				CompositePriceType: 2,
  6501  				CashAmount:         "1.2",
  6502  			},
  6503  			field: "cash_amount",
  6504  			err:   commands.ErrIsNotValidNumber,
  6505  		},
  6506  		{
  6507  			mpc: &vega.CompositePriceConfiguration{
  6508  				CompositePriceType: 3,
  6509  				CashAmount:         "",
  6510  			},
  6511  			field: "cash_amount",
  6512  			err:   nil,
  6513  		},
  6514  		{
  6515  			mpc: &vega.CompositePriceConfiguration{
  6516  				SourceWeights:      []string{"1", "2", "3"},
  6517  				CompositePriceType: protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_MEDIAN,
  6518  			},
  6519  			field: "source_weights",
  6520  			err:   fmt.Errorf("must be empty if composite price type is not weighted"),
  6521  		},
  6522  		{
  6523  			mpc: &vega.CompositePriceConfiguration{
  6524  				SourceWeights:      []string{"1", "2", "3"},
  6525  				CompositePriceType: protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_LAST_TRADE,
  6526  			},
  6527  			field: "source_weights",
  6528  			err:   fmt.Errorf("must be empty if composite price type is not weighted"),
  6529  		},
  6530  		{
  6531  			mpc: &vega.CompositePriceConfiguration{
  6532  				SourceWeights:      []string{"", "", ""},
  6533  				CompositePriceType: protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_WEIGHTED,
  6534  				DataSourcesSpec: []*protoTypes.DataSourceDefinition{
  6535  					{SourceType: &vegapb.DataSourceDefinition_External{}},
  6536  					{SourceType: &vegapb.DataSourceDefinition_External{}},
  6537  					{SourceType: &vegapb.DataSourceDefinition_External{}},
  6538  				},
  6539  			},
  6540  			field: "source_weights",
  6541  			err:   fmt.Errorf("must be defined for all price sources"),
  6542  		},
  6543  		{
  6544  			mpc: &vega.CompositePriceConfiguration{
  6545  				CompositePriceType:       protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_WEIGHTED,
  6546  				SourceStalenessTolerance: []string{"1", "2", "3", "4", "5"},
  6547  				DataSourcesSpec: []*protoTypes.DataSourceDefinition{
  6548  					{SourceType: &vegapb.DataSourceDefinition_External{}},
  6549  					{SourceType: &vegapb.DataSourceDefinition_External{}},
  6550  					{SourceType: &vegapb.DataSourceDefinition_External{}},
  6551  				},
  6552  			},
  6553  			field: "source_staleness_tolerance",
  6554  			err:   fmt.Errorf("must included staleness information for all price sources"),
  6555  		},
  6556  		{
  6557  			mpc: &vega.CompositePriceConfiguration{
  6558  				CompositePriceType:       protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_WEIGHTED,
  6559  				SourceStalenessTolerance: []string{"1", "2", "3", "4", "5", "6", "7"},
  6560  				DataSourcesSpec: []*protoTypes.DataSourceDefinition{
  6561  					{SourceType: &vegapb.DataSourceDefinition_External{}},
  6562  					{SourceType: &vegapb.DataSourceDefinition_External{}},
  6563  				},
  6564  			},
  6565  			field: "source_staleness_tolerance",
  6566  			err:   fmt.Errorf("must included staleness information for all price sources"),
  6567  		},
  6568  		{
  6569  			mpc: &vega.CompositePriceConfiguration{
  6570  				CompositePriceType: protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_MEDIAN,
  6571  				DataSourcesSpec: []*protoTypes.DataSourceDefinition{
  6572  					{SourceType: &vegapb.DataSourceDefinition_External{}},
  6573  					{SourceType: &vegapb.DataSourceDefinition_External{}},
  6574  				},
  6575  			},
  6576  			field: "source_staleness_tolerance",
  6577  			err:   fmt.Errorf("must included staleness information for all price sources"),
  6578  		},
  6579  		{
  6580  			mpc: &vega.CompositePriceConfiguration{
  6581  				CompositePriceType: protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_WEIGHTED,
  6582  				DataSourcesSpec: []*protoTypes.DataSourceDefinition{
  6583  					{SourceType: &vegapb.DataSourceDefinition_External{}},
  6584  					{SourceType: &vegapb.DataSourceDefinition_External{}},
  6585  				},
  6586  			},
  6587  			field: "source_staleness_tolerance",
  6588  			err:   fmt.Errorf("must included staleness information for all price sources"),
  6589  		},
  6590  		{
  6591  			mpc: &vega.CompositePriceConfiguration{
  6592  				CompositePriceType:       protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_WEIGHTED,
  6593  				SourceStalenessTolerance: []string{"1s", "2s", "3s"},
  6594  				SourceWeights:            []string{"1", "2", "3"},
  6595  			},
  6596  			field: "source_staleness_tolerance",
  6597  			err:   nil,
  6598  		},
  6599  		{
  6600  			mpc: &vega.CompositePriceConfiguration{
  6601  				CompositePriceType:       protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_MEDIAN,
  6602  				SourceStalenessTolerance: []string{"1s", "2s", "3s"},
  6603  			},
  6604  			field: "source_staleness_tolerance",
  6605  			err:   nil,
  6606  		},
  6607  		{
  6608  			mpc: &vega.CompositePriceConfiguration{
  6609  				CompositePriceType:       protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_WEIGHTED,
  6610  				SourceStalenessTolerance: []string{"1s", "2s", "3s"},
  6611  				DataSourcesSpec: []*protoTypes.DataSourceDefinition{
  6612  					{SourceType: &vegapb.DataSourceDefinition_External{}},
  6613  					{SourceType: &vegapb.DataSourceDefinition_External{}},
  6614  				},
  6615  			},
  6616  			field: "source_staleness_tolerance",
  6617  			err:   fmt.Errorf("must included staleness information for all price sources"),
  6618  		},
  6619  		{
  6620  			mpc: &vega.CompositePriceConfiguration{
  6621  				CompositePriceType:       protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_MEDIAN,
  6622  				SourceStalenessTolerance: []string{"1s", "2s", "3s"},
  6623  				DataSourcesSpec: []*protoTypes.DataSourceDefinition{
  6624  					{SourceType: &vegapb.DataSourceDefinition_External{}},
  6625  					{SourceType: &vegapb.DataSourceDefinition_External{}},
  6626  				},
  6627  			},
  6628  			field: "source_staleness_tolerance",
  6629  			err:   fmt.Errorf("must included staleness information for all price sources"),
  6630  		},
  6631  		{
  6632  			mpc: &vega.CompositePriceConfiguration{
  6633  				CompositePriceType:       protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_LAST_TRADE,
  6634  				SourceStalenessTolerance: nil,
  6635  			},
  6636  			field: "source_staleness_tolerance",
  6637  			err:   nil,
  6638  		},
  6639  		{
  6640  			mpc: &vega.CompositePriceConfiguration{
  6641  				SourceWeights:            []string{"", "", "", ""},
  6642  				SourceStalenessTolerance: []string{"", "", "", "", ""},
  6643  				CompositePriceType:       protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_WEIGHTED,
  6644  			},
  6645  			field: "source_staleness_tolerance",
  6646  			err:   fmt.Errorf("must have the same length as source_weights"),
  6647  		},
  6648  		{
  6649  			mpc: &vega.CompositePriceConfiguration{
  6650  				CompositePriceType: protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_WEIGHTED,
  6651  				SourceWeights:      []string{"0", "0", "0", "0"},
  6652  			},
  6653  			field: "source_weights",
  6654  			err:   fmt.Errorf("must have at least one none zero weight"),
  6655  		},
  6656  		{
  6657  			mpc: &vega.CompositePriceConfiguration{
  6658  				CompositePriceType: protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_MEDIAN,
  6659  				SourceWeights:      []string{"0", "0", "0", "0"},
  6660  			},
  6661  			field: "source_weights",
  6662  			err:   fmt.Errorf("must be empty if composite price type is not weighted"),
  6663  		},
  6664  		{
  6665  			mpc: &vega.CompositePriceConfiguration{
  6666  				SourceWeights: []string{"", "banana", "-1", ""},
  6667  			},
  6668  			field: "source_weights.0",
  6669  			err:   commands.ErrIsNotValidNumber,
  6670  		},
  6671  		{
  6672  			mpc: &vega.CompositePriceConfiguration{
  6673  				SourceWeights: []string{"", "banana", "-1", ""},
  6674  			},
  6675  			field: "source_weights.1",
  6676  			err:   commands.ErrIsNotValidNumber,
  6677  		},
  6678  		{
  6679  			mpc: &vega.CompositePriceConfiguration{
  6680  				SourceWeights: []string{"", "banana", "-1", ""},
  6681  			},
  6682  			field: "source_weights.2",
  6683  			err:   commands.ErrMustBePositiveOrZero,
  6684  		},
  6685  		{
  6686  			mpc: &vega.CompositePriceConfiguration{
  6687  				SourceStalenessTolerance: []string{"", "banana", "-1", ""},
  6688  			},
  6689  			field: "source_staleness_tolerance.0",
  6690  			err:   fmt.Errorf("must be a valid duration"),
  6691  		},
  6692  		{
  6693  			mpc: &vega.CompositePriceConfiguration{
  6694  				SourceStalenessTolerance: []string{"", "banana", "-1", ""},
  6695  			},
  6696  			field: "source_staleness_tolerance.1",
  6697  			err:   fmt.Errorf("must be a valid duration"),
  6698  		},
  6699  	}
  6700  	return cases
  6701  }
  6702  
  6703  func testCompositePriceConfiguration(t *testing.T) {
  6704  	cases := getCompositePriceConfigurationCases()
  6705  	cases = append(cases, compositePriceConfigCase{
  6706  		mpc:   nil,
  6707  		field: "",
  6708  		err:   commands.ErrIsRequired,
  6709  	})
  6710  
  6711  	for _, c := range cases {
  6712  		err := checkProposalSubmission(&commandspb.ProposalSubmission{
  6713  			Terms: &vegapb.ProposalTerms{
  6714  				Change: &vegapb.ProposalTerms_NewMarket{
  6715  					NewMarket: &vegapb.NewMarket{
  6716  						Changes: &vegapb.NewMarketConfiguration{
  6717  							Instrument: &vegapb.InstrumentConfiguration{
  6718  								Product: &vegapb.InstrumentConfiguration_Perpetual{
  6719  									Perpetual: &vegapb.PerpetualProduct{},
  6720  								},
  6721  							},
  6722  							MarkPriceConfiguration: c.mpc,
  6723  						},
  6724  					},
  6725  				},
  6726  			},
  6727  		})
  6728  		if len(c.field) > 0 {
  6729  			if c.err != nil {
  6730  				assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.mark_price_configuration."+c.field), c.err)
  6731  			} else {
  6732  				assert.Empty(t, err.Get("proposal_submission.terms.change.new_market.changes.mark_price_configuration."+c.field))
  6733  			}
  6734  		} else {
  6735  			assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.mark_price_configuration"), c.err)
  6736  		}
  6737  	}
  6738  }
  6739  
  6740  func testFutureMarketSubmissionWithInvalidLiquidationStrategyFails(t *testing.T) {
  6741  	pubKey := []*dstypes.Signer{
  6742  		dstypes.CreateSignerFromString("bd069246503a57271375f1995c46e03db88c4e1a564077b33a9872f905650dc4", dstypes.SignerTypePubKey),
  6743  	}
  6744  
  6745  	submission := &commandspb.ProposalSubmission{
  6746  		Terms: &vegapb.ProposalTerms{
  6747  			Change: &vegapb.ProposalTerms_NewMarket{
  6748  				NewMarket: &vegapb.NewMarket{
  6749  					Changes: &vegapb.NewMarketConfiguration{
  6750  						Instrument: &vegapb.InstrumentConfiguration{
  6751  							Product: &vegapb.InstrumentConfiguration_Future{
  6752  								Future: &vegapb.FutureProduct{
  6753  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  6754  										vegapb.DataSourceContentTypeOracle,
  6755  									).SetOracleConfig(
  6756  										&vegapb.DataSourceDefinitionExternal_Oracle{
  6757  											Oracle: &vegapb.DataSourceSpecConfiguration{
  6758  												Signers: dstypes.SignersIntoProto(pubKey),
  6759  												Filters: []*datapb.Filter{
  6760  													{
  6761  														Key: &datapb.PropertyKey{
  6762  															Name: "prices.ETH.value",
  6763  															Type: datapb.PropertyKey_TYPE_INTEGER,
  6764  														},
  6765  														Conditions: []*datapb.Condition{
  6766  															{
  6767  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  6768  															},
  6769  														},
  6770  													},
  6771  												},
  6772  											},
  6773  										},
  6774  									),
  6775  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  6776  										vegapb.DataSourceContentTypeOracle,
  6777  									).SetOracleConfig(
  6778  										&vegapb.DataSourceDefinitionExternal_Oracle{
  6779  											Oracle: &vegapb.DataSourceSpecConfiguration{
  6780  												Signers: dstypes.SignersIntoProto(pubKey),
  6781  												Filters: []*datapb.Filter{
  6782  													{
  6783  														Key: &datapb.PropertyKey{
  6784  															Name: "vegaprotocol.builtin.timestamp",
  6785  															Type: datapb.PropertyKey_TYPE_TIMESTAMP,
  6786  														},
  6787  														Conditions: []*datapb.Condition{
  6788  															{
  6789  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  6790  																Value:    fmt.Sprintf("%d", time.Now().Add(time.Hour*24*365).UnixNano()),
  6791  															},
  6792  														},
  6793  													},
  6794  												},
  6795  											},
  6796  										},
  6797  									),
  6798  								},
  6799  							},
  6800  						},
  6801  						LiquidationStrategy: &vegapb.LiquidationStrategy{
  6802  							DisposalTimeStep:      20,
  6803  							DisposalFraction:      "0.05",
  6804  							FullDisposalSize:      20,
  6805  							MaxFractionConsumed:   "0.01",
  6806  							DisposalSlippageRange: "0.1",
  6807  						},
  6808  					},
  6809  				},
  6810  			},
  6811  		},
  6812  	}
  6813  
  6814  	data := map[string]struct {
  6815  		ls  *vegapb.LiquidationStrategy
  6816  		err error
  6817  	}{
  6818  		"proposal_submission.terms.change.new_market.changes.liquidation_strategy.disposal_fraction": {
  6819  			ls: &vegapb.LiquidationStrategy{
  6820  				DisposalTimeStep:      20,
  6821  				DisposalFraction:      "123",
  6822  				FullDisposalSize:      20,
  6823  				MaxFractionConsumed:   "0.01",
  6824  				DisposalSlippageRange: "0.1",
  6825  			},
  6826  			err: commands.ErrMustBeBetween01,
  6827  		},
  6828  		"proposal_submission.terms.change.new_market.changes.liquidation_strategy.max_fraction_consumed": {
  6829  			ls: &vegapb.LiquidationStrategy{
  6830  				DisposalTimeStep:      20,
  6831  				DisposalFraction:      "0.1",
  6832  				FullDisposalSize:      20,
  6833  				MaxFractionConsumed:   "-0.1",
  6834  				DisposalSlippageRange: "100", // large values are fine
  6835  			},
  6836  			err: commands.ErrMustBeBetween01,
  6837  		},
  6838  		"proposal_submission.terms.change.new_market.changes.liquidation_strategy.disposal_time_step": {
  6839  			ls: &vegapb.LiquidationStrategy{
  6840  				DisposalTimeStep:      0,
  6841  				DisposalFraction:      "0.1",
  6842  				FullDisposalSize:      20,
  6843  				MaxFractionConsumed:   "0.1",
  6844  				DisposalSlippageRange: "0.5",
  6845  			},
  6846  			err: commands.ErrMustBePositive,
  6847  		},
  6848  		"proposal_submission.terms.change.new_market.changes.liquidation_strategy.disposal_slippage_range": {
  6849  			ls: &vegapb.LiquidationStrategy{
  6850  				DisposalTimeStep:      5,
  6851  				DisposalFraction:      "0.1",
  6852  				FullDisposalSize:      20,
  6853  				MaxFractionConsumed:   "0.1",
  6854  				DisposalSlippageRange: "-0.5",
  6855  			},
  6856  			err: commands.ErrMustBePositive,
  6857  		},
  6858  	}
  6859  	checks := []string{
  6860  		"proposal_submission.terms.change.new_market.changes.liquidation_strategy.disposal_fraction",
  6861  		"proposal_submission.terms.change.new_market.changes.liquidation_strategy.max_fraction_consumed",
  6862  		"proposal_submission.terms.change.new_market.changes.liquidation_strategy.disposal_time_step",
  6863  		"proposal_submission.terms.change.new_market.changes.liquidation_strategy.disposal_slippage_range",
  6864  	}
  6865  	for ec, exp := range data {
  6866  		nm := submission.Terms.GetNewMarket()
  6867  		nm.Changes.LiquidationStrategy = exp.ls
  6868  		submission.Terms.Change = &vegapb.ProposalTerms_NewMarket{
  6869  			NewMarket: nm,
  6870  		}
  6871  		err := checkProposalSubmission(submission)
  6872  		for _, k := range checks {
  6873  			if k != ec {
  6874  				assert.Empty(t, err.Get(k))
  6875  			} else {
  6876  				assert.Contains(t, err.Get(k), exp.err)
  6877  			}
  6878  		}
  6879  	}
  6880  	// pretty much the same as above, only this time set the disposal fraction to a negative value
  6881  	// and max fraction consumed to a large positive
  6882  	// finally set the disposal time step to a large int value, this changes the error
  6883  	data = map[string]struct {
  6884  		ls  *vegapb.LiquidationStrategy
  6885  		err error
  6886  	}{
  6887  		"proposal_submission.terms.change.new_market.changes.liquidation_strategy.disposal_fraction": {
  6888  			ls: &vegapb.LiquidationStrategy{
  6889  				DisposalTimeStep:      20,
  6890  				DisposalFraction:      "-2",
  6891  				FullDisposalSize:      20,
  6892  				MaxFractionConsumed:   "0.01",
  6893  				DisposalSlippageRange: "0.5",
  6894  			},
  6895  			err: commands.ErrMustBeBetween01,
  6896  		},
  6897  		"proposal_submission.terms.change.new_market.changes.liquidation_strategy.max_fraction_consumed": {
  6898  			ls: &vegapb.LiquidationStrategy{
  6899  				DisposalTimeStep:      20,
  6900  				DisposalFraction:      "0.1",
  6901  				FullDisposalSize:      20,
  6902  				MaxFractionConsumed:   "2",
  6903  				DisposalSlippageRange: "0.5",
  6904  			},
  6905  			err: commands.ErrMustBeBetween01,
  6906  		},
  6907  		"proposal_submission.terms.change.new_market.changes.liquidation_strategy.disposal_time_step": {
  6908  			ls: &vegapb.LiquidationStrategy{
  6909  				DisposalTimeStep:      3601,
  6910  				DisposalFraction:      "0.1",
  6911  				FullDisposalSize:      20,
  6912  				MaxFractionConsumed:   "0.1",
  6913  				DisposalSlippageRange: "0.5",
  6914  			},
  6915  			err: commands.ErrMustBeAtMost3600,
  6916  		},
  6917  		"proposal_submission.terms.change.new_market.changes.liquidation_strategy.disposal_slippage_range": {
  6918  			ls: &vegapb.LiquidationStrategy{
  6919  				DisposalTimeStep:      5,
  6920  				DisposalFraction:      "0.1",
  6921  				FullDisposalSize:      20,
  6922  				MaxFractionConsumed:   "0.1",
  6923  				DisposalSlippageRange: "0", // zero or missing values fail, too
  6924  			},
  6925  			err: commands.ErrMustBePositive,
  6926  		},
  6927  	}
  6928  	for ec, exp := range data {
  6929  		nm := submission.Terms.GetNewMarket()
  6930  		nm.Changes.LiquidationStrategy = exp.ls
  6931  		submission.Terms.Change = &vegapb.ProposalTerms_NewMarket{
  6932  			NewMarket: nm,
  6933  		}
  6934  		err := checkProposalSubmission(submission)
  6935  		for _, k := range checks {
  6936  			if k != ec {
  6937  				assert.Empty(t, err.Get(k))
  6938  			} else {
  6939  				assert.Contains(t, err.Get(k), exp.err)
  6940  			}
  6941  		}
  6942  	}
  6943  }