code.vegaprotocol.io/vega@v0.79.0/commands/proposal_submission_update_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 TestCheckProposalSubmissionForUpdateMarket(t *testing.T) {
    39  	t.Run("Submitting a market change without update market fails", testUpdateMarketChangeSubmissionWithoutUpdateMarketFails)
    40  	t.Run("Submitting a market change without changes fails", testUpdateMarketChangeSubmissionWithoutChangesFails)
    41  	t.Run("Submitting a market change without decimal places succeeds", testUpdateMarketChangeSubmissionWithoutDecimalPlacesSucceeds)
    42  	t.Run("Submitting a update market without price monitoring succeeds", testUpdateMarketChangeSubmissionWithoutPriceMonitoringSucceeds)
    43  	t.Run("Submitting a update market with price monitoring succeeds", testUpdateMarketChangeSubmissionWithPriceMonitoringSucceeds)
    44  	t.Run("Submitting a price monitoring change without triggers succeeds", testUpdateMarketPriceMonitoringChangeSubmissionWithoutTriggersSucceeds)
    45  	t.Run("Submitting a price monitoring change with triggers succeeds", testUpdateMarketPriceMonitoringChangeSubmissionWithTriggersSucceeds)
    46  	t.Run("Submitting a price monitoring change without trigger horizon fails", testUpdateMarketPriceMonitoringChangeSubmissionWithoutTriggerHorizonFails)
    47  	t.Run("Submitting a price monitoring change with trigger horizon succeeds", testUpdateMarketPriceMonitoringChangeSubmissionWithTriggerHorizonSucceeds)
    48  	t.Run("Submitting a price monitoring change with wrong trigger probability fails", testUpdateMarketPriceMonitoringChangeSubmissionWithWrongTriggerProbabilityFails)
    49  	t.Run("Submitting a price monitoring change with right trigger probability succeeds", testUpdateMarketPriceMonitoringChangeSubmissionWithRightTriggerProbabilitySucceeds)
    50  	t.Run("Submitting a price monitoring change without trigger auction extension fails", testUpdateMarketPriceMonitoringChangeSubmissionWithoutTriggerAuctionExtensionFails)
    51  	t.Run("Submitting a price monitoring change with trigger auction extension succeeds", testUpdateMarketPriceMonitoringChangeSubmissionWithTriggerAuctionExtensionSucceeds)
    52  	t.Run("Submitting a update market without liquidity monitoring fails", testUpdateMarketChangeSubmissionWithoutLiquidityMonitoringFails)
    53  	t.Run("Submitting a update market with liquidity monitoring succeeds", testUpdateMarketChangeSubmissionWithLiquidityMonitoringSucceeds)
    54  	t.Run("Submitting a liquidity monitoring change without target stake parameters fails", testUpdateMarketLiquidityMonitoringChangeSubmissionWithoutTargetStakeParametersFails)
    55  	t.Run("Submitting a liquidity monitoring change with target stake parameters succeeds", testUpdateMarketLiquidityMonitoringChangeSubmissionWithTargetStakeParametersSucceeds)
    56  	t.Run("Submitting a liquidity monitoring change with non-positive time window fails", testUpdateMarketLiquidityMonitoringChangeSubmissionWithNonPositiveTimeWindowFails)
    57  	t.Run("Submitting a liquidity monitoring change with positive time window succeeds", testUpdateMarketLiquidityMonitoringChangeSubmissionWithPositiveTimeWindowSucceeds)
    58  	t.Run("Submitting a liquidity monitoring change with non-positive scaling factor fails", testUpdateMarketLiquidityMonitoringChangeSubmissionWithNonPositiveScalingFactorFails)
    59  	t.Run("Submitting a liquidity monitoring change with positive scaling factor succeeds", testUpdateMarketLiquidityMonitoringChangeSubmissionWithPositiveScalingFactorSucceeds)
    60  	t.Run("Submitting a market change without instrument code fails", testUpdateMarketChangeSubmissionWithoutInstrumentCodeFails)
    61  	t.Run("Submitting a market change without instrument name fails", testUpdateMarketChangeSubmissionWithoutInstrumentNameFails)
    62  	t.Run("Submitting a market change with instrument code succeeds", testUpdateMarketChangeSubmissionWithInstrumentCodeSucceeds)
    63  	t.Run("Submitting a market change without product fails", testUpdateMarketChangeSubmissionWithoutProductFails)
    64  	t.Run("Submitting a market change with product succeeds", testUpdateMarketChangeSubmissionWithProductSucceeds)
    65  	t.Run("Submitting a future market change without future fails", testUpdateFutureMarketChangeSubmissionWithoutFutureFails)
    66  	t.Run("Submitting a future market change with future succeeds", testUpdateFutureMarketChangeSubmissionWithFutureSucceeds)
    67  	t.Run("Submitting a future market change without quote name fails", testUpdateFutureMarketChangeSubmissionWithoutQuoteNameFails)
    68  	t.Run("Submitting a future market change with quote name succeeds", testUpdateFutureMarketChangeSubmissionWithQuoteNameSucceeds)
    69  	t.Run("Submitting a future market change without oracle spec fails", testUpdateFutureMarketChangeSubmissionWithoutOracleSpecFails)
    70  	t.Run("Submitting a future market change without either of the required oracle spec fails", testUpdateFutureMarketChangeSubmissionMissingSingleOracleSpecFails)
    71  	t.Run("Submitting a future market change without a public key fails", testUpdateFutureMarketSettlementDataChangeSubmissionWithoutPubKeysFails)
    72  	t.Run("Submitting a future market change with empty oracle spec fails", testUpdateFutureMarketChangeSubmissionWithEmptyOracleSpecFails)
    73  	t.Run("Submitting a future market change with empty oracle spec type fails", testUpdateFutureMarketChangeSubmissionWithEmptyOracleSpecTypeFails)
    74  	t.Run("Submitting a future market change with empty internal oracle spec type fails", testUpdateFutureMarketChangeSubmissionWithEmptyInternalOracleSpecTypeFails)
    75  	t.Run("Submitting a future market change with wrong pub-keys fails", testUpdateFutureMarketChangeSubmissionWithWrongPubKeysFails)
    76  	t.Run("Submitting a future market change with pub-keys succeeds", testUpdateFutureMarketChangeSubmissionWithPubKeysSucceeds)
    77  	t.Run("Submitting a future market change without filters fails", testUpdateFutureMarketChangeSubmissionWithoutFiltersFails)
    78  	t.Run("Submitting a future market change with filters succeeds", testUpdateFutureMarketChangeSubmissionWithFiltersSucceeds)
    79  	t.Run("Submitting a future market change with filter without key fails", testUpdateFutureMarketChangeSubmissionWithFilterWithoutKeyFails)
    80  	t.Run("Submitting a future market change with filter with key succeeds", testUpdateFutureMarketChangeSubmissionWithFilterWithKeySucceeds)
    81  	t.Run("Submitting a future market change with filter without key name fails", testUpdateFutureMarketChangeSubmissionWithFilterWithoutKeyNameFails)
    82  	t.Run("Submitting a future market change with filter with key name succeeds", testUpdateFutureMarketChangeSubmissionWithFilterWithKeyNameSucceeds)
    83  	t.Run("Submitting a future market change with filter without key type fails", testUpdateFutureMarketChangeSubmissionWithFilterWithoutKeyTypeFails)
    84  	t.Run("Submitting a future market change with filter with key type succeeds", testUpdateFutureMarketChangeSubmissionWithFilterWithKeyTypeSucceeds)
    85  	t.Run("Submitting a future market change with filter without condition succeeds", testUpdateFutureMarketChangeSubmissionWithFilterWithoutConditionsSucceeds)
    86  	t.Run("Submitting a future market change with filter without condition operator fails", testUpdateFutureMarketChangeSubmissionWithFilterWithoutConditionOperatorFails)
    87  	t.Run("Submitting a future market change with filter with condition operator succeeds", testUpdateFutureMarketChangeSubmissionWithFilterWithConditionOperatorSucceeds)
    88  	t.Run("Submitting a future market change with filter without condition value fails", testUpdateFutureMarketChangeSubmissionWithFilterWithoutConditionValueFails)
    89  	t.Run("Submitting a future market change with filter with condition value succeeds", testUpdateFutureMarketChangeSubmissionWithFilterWithConditionValueSucceeds)
    90  	t.Run("Submitting a future market change without oracle spec bindings fails", testUpdateFutureMarketChangeSubmissionWithoutDataSourceSpecBindingFails)
    91  	t.Run("Submitting a future market change with oracle spec binding succeeds", testUpdateFutureMarketChangeSubmissionWithDataSourceSpecBindingSucceeds)
    92  	t.Run("Submitting a future market change without settlement data property fails", testUpdateFutureMarketChangeSubmissionWithoutSettlementDataPropertyFails)
    93  	t.Run("Submitting a future market change without trading termination property fails", testUpdateFutureMarketChangeSubmissionWithoutTradingTerminationPropertyFails)
    94  	t.Run("Submitting a future market change with a mismatch between binding property name and filter fails", testUpdateFutureMarketChangeSubmissionWithMismatchBetweenFilterAndBindingFails)
    95  	t.Run("Submitting a future market change with match between binding property name and filter succeeds", testUpdateFutureMarketChangeSubmissionWithNoMismatchBetweenFilterAndBindingSucceeds)
    96  	t.Run("Submitting a future market change with settlement data and trading termination properties succeeds", testUpdateFutureMarketChangeSubmissionWithSettlementDataPropertySucceeds)
    97  	t.Run("Submitting a simple risk parameters change without simple risk parameters fails", testUpdateSimpleRiskParametersChangeSubmissionWithoutSimpleRiskParametersFails)
    98  	t.Run("Submitting a simple risk parameters change with simple risk parameters succeeds", testUpdateSimpleRiskParametersChangeSubmissionWithSimpleRiskParametersSucceeds)
    99  	t.Run("Submitting a simple risk parameters change with min move down fails", testUpdateSimpleRiskParametersChangeSubmissionWithPositiveMinMoveDownFails)
   100  	t.Run("Submitting a simple risk parameters change with min move down succeeds", testUpdateSimpleRiskParametersChangeSubmissionWithNonPositiveMinMoveDownSucceeds)
   101  	t.Run("Submitting a simple risk parameters change with max move up fails", testUpdateSimpleRiskParametersChangeSubmissionWithNegativeMaxMoveUpFails)
   102  	t.Run("Submitting a simple risk parameters change with max move up succeeds", testUpdateSimpleRiskParametersChangeSubmissionWithNonNegativeMaxMoveUpSucceeds)
   103  	t.Run("Submitting a simple risk parameters change with wrong probability of trading fails", testUpdateSimpleRiskParametersChangeSubmissionWithWrongProbabilityOfTradingFails)
   104  	t.Run("Submitting a simple risk parameters change with right probability of trading succeeds", testUpdateSimpleRiskParametersChangeSubmissionWithRightProbabilityOfTradingSucceeds)
   105  	t.Run("Submitting a log normal risk parameters change without log normal risk parameters fails", testUpdateLogNormalRiskParametersChangeSubmissionWithoutLogNormalRiskParametersFails)
   106  	t.Run("Submitting a log normal risk parameters change with log normal risk parameters succeeds", testUpdateLogNormalRiskParametersChangeSubmissionWithLogNormalRiskParametersSucceeds)
   107  	t.Run("Submitting a log normal risk parameters change with params fails", testUpdateLogNormalRiskParametersChangeSubmissionWithoutParamsFails)
   108  	t.Run("Submitting a log normal risk parameters change with invalid risk aversion", testUpdateLogNormalRiskParametersChangeSubmissionInvalidRiskAversion)
   109  	t.Run("Submitting a log normal risk parameters change with invalid tau", testUpdateLogNormalRiskParametersChangeSubmissionInvalidTau)
   110  	t.Run("Submitting a log normal risk parameters change with invalid mu", testUpdateLogNormalRiskParametersChangeSubmissionInvalidMu)
   111  	t.Run("Submitting a log normal risk parameters change with invalid sigma", testUpdateLogNormalRiskParametersChangeSubmissionInvalidSigma)
   112  	t.Run("Submitting a log normal risk parameters change with invalid r", testUpdateLogNormalRiskParametersChangeSubmissionInvalidR)
   113  	t.Run("Submitting a update market with a too long reference fails", testUpdateMarketSubmissionWithTooLongReferenceFails)
   114  	t.Run("Submitting a market with market ID succeeds", testUpdateMarketWithMarketIDSucceeds)
   115  	t.Run("Submitting a market without market ID fails", testUpdateMarketWithoutMarketIDFails)
   116  	t.Run("Submitting a slippage fraction change with 'banana' value fails", tesUpdateMarketChangeSubmissionWithSlippageFactorBananaFails)
   117  	t.Run("Submitting a slippage fraction change with a negative value fails", testUpdateMarketChangeSubmissionWithSlippageFactorNegativeFails)
   118  	t.Run("Submitting a slippage fraction change with a too large value fails", testUpdateMarketChangeSubmissionWithSlippageFactorTooLargeFails)
   119  	t.Run("Submitting a slippage fraction change with an empty string succeeds", testUpdateNewMarketChangeSubmissionWithEmptySlippageFactorPasses)
   120  	t.Run("Submitting a market with external data for termination without signers fails", testUpdateMarketFutureMarketSubmissionWithExternalSourceForTradingTerminationNoSignersFails)
   121  	t.Run("Submitting a market with internal data source to terminate with `vegaprotocol.builtin` in key name no signers succeeds", testUpdateMarketFutureMarketSubmissionWithInternalTimestampForTradingTerminationNoSignersSucceeds)
   122  	t.Run("Submitting a market with internal data source to terminate with invalid operator and no signers fails", testUpdateMarketFutureMarketSubmissionWithInvalidOperatorInternalSourceForTradingTerminationNoSignersFails)
   123  	t.Run("Submitting a market with oracle to terminate with `vegaprotocol.builtin` in key name no signers fails", testUpdateMarketFutureMarketSubmissionWithExternalSourceForTradingTerminationBuiltInKeyNoSignersFails)
   124  	t.Run("Submitting a market with oracle to settle with `vegaprotocol.builtin` in key name no signers fails", testUpdateMarketFutureMarketSubmissionWithExternalSourceForTradingSettlementBuiltInKeyNoSignersFails)
   125  	t.Run("Submitting a market with trading settlement from external source with timestamp filter succeeds", testUpdateMarketFutureSubmissionWithExternalTradingSettlementTimestampKeySucceeds)
   126  	t.Run("Submitting a market with external data source for termination succeeds", testUpdateMarketWithExternalTradingTerminationBuiltInKeySucceeds)
   127  	t.Run("Submitting a market with external data source for termination without signers fails", testUpdateMarketWithExternalTradingTerminationNoSignerFails)
   128  	t.Run("Submitting a market with internal data source for settlement fails", testUpdateMarketWithInternalSettlementDataFails)
   129  	t.Run("Submitting a market with external data source for termination with signers and external settlement data without signers fails", testUpdateMarketWithExternalSettlementDataNoSignerFails)
   130  	t.Run("Submitting a market with external data sources for settlement and termination with no signers fail", testUpdateMarketWithExternalSettlementDataAndTerminationNoSignerFails)
   131  	t.Run("Submitting a market with external data sources for settlement and termination with empty signers fail", testUpdateMarketWithExternalSettlementDataAndTerminationEmptySignerFails)
   132  	t.Run("Submitting a market with external data sources for settlement and termination with empty pubKey signers fail", testUpdateMarketWithExternalSettlementDataAndTerminationEmptyPubKeySignerFails)
   133  	t.Run("Submitting a market with external data sources for settlement and termination with empty eth address signers fail", testUpdateMarketWithExternalSettlementDataAndTerminationEmptyEthAddressSignerFails)
   134  	t.Run("Submitting a market with termination time trigger fails", testUpdateMarketWithTerminationWithTimeTriggerFails)
   135  	t.Run("Submitting a market withsettlement with time trigger fails", testUpdateMarketWithSettlementWithTimeTriggerFails)
   136  	t.Run("Submitting a perps market product parameters", testUpdatePerpsMarketChangeSubmissionProductParameters)
   137  	t.Run("Submitting a perps market with funding rate modifiers", testUpdatePerpetualMarketWithFundingRateModifiers)
   138  	t.Run("Submitting a market update with invalid mark price configuration ", testUpdateMarketCompositePriceConfiguration)
   139  	t.Run("Submitting a market update with invalid intenal composite price configuration", testUpdatePerpsMarketChangeSubmissionWithInternalCompositePriceConfig)
   140  	t.Run("Submitting a market update with invalid tick size fails and valid tick size succeeds", testUpdateMarketTickSize)
   141  	t.Run("Submitting a spot market update with invalid liquifity fee settings", testUpdateLiquidityFeeSettingsSpot)
   142  	t.Run("Update Log Normal with overrides", testUpdateLogNormalRiskParametersChangeSubmissionWithOverrides)
   143  }
   144  
   145  func testUpdateMarketTickSize(t *testing.T) {
   146  	cases := getTickSizeCases()
   147  	for _, tsc := range cases {
   148  		err := checkProposalSubmission(&commandspb.ProposalSubmission{
   149  			Terms: &vegapb.ProposalTerms{
   150  				Change: &vegapb.ProposalTerms_UpdateMarket{
   151  					UpdateMarket: &vegapb.UpdateMarket{
   152  						Changes: &vegapb.UpdateMarketConfiguration{
   153  							TickSize: tsc.tickSize,
   154  						},
   155  					},
   156  				},
   157  			},
   158  		})
   159  		if tsc.err != nil {
   160  			assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.tick_size"), tsc.err)
   161  		} else {
   162  			assert.Empty(t, err.Get("proposal_submission.terms.change.update_market.changes.tick_size"))
   163  		}
   164  	}
   165  }
   166  
   167  func testUpdatePerpsMarketChangeSubmissionWithInternalCompositePriceConfig(t *testing.T) {
   168  	cases := getCompositePriceConfigurationCases()
   169  	for _, c := range cases {
   170  		err := checkProposalSubmission(&commandspb.ProposalSubmission{
   171  			Terms: &vegapb.ProposalTerms{
   172  				Change: &vegapb.ProposalTerms_UpdateMarket{
   173  					UpdateMarket: &vegapb.UpdateMarket{
   174  						Changes: &vegapb.UpdateMarketConfiguration{
   175  							Instrument: &vegapb.UpdateInstrumentConfiguration{
   176  								Product: &vegapb.UpdateInstrumentConfiguration_Perpetual{
   177  									Perpetual: &vegapb.UpdatePerpetualProduct{
   178  										InternalCompositePriceConfiguration: c.mpc,
   179  									},
   180  								},
   181  							},
   182  						},
   183  					},
   184  				},
   185  			},
   186  		})
   187  		if len(c.field) > 0 {
   188  			if c.err != nil {
   189  				assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.perps.internal_composite_price_configuration."+c.field), c.err)
   190  			} else {
   191  				assert.Empty(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.perps.internal_composite_price_configuration."+c.field))
   192  			}
   193  		} else {
   194  			assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.perps.internal_composite_price_configuration"), c.err)
   195  		}
   196  	}
   197  }
   198  
   199  func testUpdateMarketCompositePriceConfiguration(t *testing.T) {
   200  	cases := getCompositePriceConfigurationCases()
   201  	cases = append(cases, compositePriceConfigCase{
   202  		mpc:   nil,
   203  		field: "",
   204  		err:   commands.ErrIsRequired,
   205  	})
   206  
   207  	for _, c := range cases {
   208  		err := checkProposalSubmission(&commandspb.ProposalSubmission{
   209  			Terms: &vegapb.ProposalTerms{
   210  				Change: &vegapb.ProposalTerms_UpdateMarket{
   211  					UpdateMarket: &vegapb.UpdateMarket{
   212  						Changes: &vegapb.UpdateMarketConfiguration{
   213  							MarkPriceConfiguration: c.mpc,
   214  						},
   215  					},
   216  				},
   217  			},
   218  		})
   219  		if len(c.field) > 0 {
   220  			if c.err != nil {
   221  				assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.mark_price_configuration."+c.field), c.err, c.field)
   222  			} else {
   223  				assert.Empty(t, err.Get("proposal_submission.terms.change.update_market.changes.mark_price_configuration."+c.field))
   224  			}
   225  		} else {
   226  			assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.mark_price_configuration"), c.err)
   227  		}
   228  	}
   229  }
   230  
   231  func testUpdateMarketChangeSubmissionWithoutUpdateMarketFails(t *testing.T) {
   232  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   233  		Terms: &protoTypes.ProposalTerms{
   234  			Change: &protoTypes.ProposalTerms_UpdateMarket{},
   235  		},
   236  	})
   237  
   238  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market"), commands.ErrIsRequired)
   239  }
   240  
   241  func testUpdateMarketChangeSubmissionWithoutChangesFails(t *testing.T) {
   242  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   243  		Terms: &protoTypes.ProposalTerms{
   244  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   245  				UpdateMarket: &protoTypes.UpdateMarket{},
   246  			},
   247  		},
   248  	})
   249  
   250  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes"), commands.ErrIsRequired)
   251  }
   252  
   253  func testUpdateMarketChangeSubmissionWithoutDecimalPlacesSucceeds(t *testing.T) {
   254  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   255  		Terms: &protoTypes.ProposalTerms{
   256  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   257  				UpdateMarket: &protoTypes.UpdateMarket{
   258  					Changes: &protoTypes.UpdateMarketConfiguration{},
   259  				},
   260  			},
   261  		},
   262  	})
   263  
   264  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.decimal_places"), commands.ErrMustBePositiveOrZero)
   265  }
   266  
   267  func testUpdateMarketChangeSubmissionWithoutLiquidityMonitoringFails(t *testing.T) {
   268  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   269  		Terms: &protoTypes.ProposalTerms{
   270  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   271  				UpdateMarket: &protoTypes.UpdateMarket{
   272  					Changes: &protoTypes.UpdateMarketConfiguration{},
   273  				},
   274  			},
   275  		},
   276  	})
   277  
   278  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.liquidity_monitoring_parameters"), commands.ErrIsRequired)
   279  }
   280  
   281  func testUpdateMarketChangeSubmissionWithLiquidityMonitoringSucceeds(t *testing.T) {
   282  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   283  		Terms: &protoTypes.ProposalTerms{
   284  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   285  				UpdateMarket: &protoTypes.UpdateMarket{
   286  					Changes: &protoTypes.UpdateMarketConfiguration{
   287  						LiquidityMonitoringParameters: &protoTypes.LiquidityMonitoringParameters{},
   288  					},
   289  				},
   290  			},
   291  		},
   292  	})
   293  
   294  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.liquidity_monitoring_parameters"), commands.ErrIsRequired)
   295  }
   296  
   297  func testUpdateMarketLiquidityMonitoringChangeSubmissionWithoutTargetStakeParametersFails(t *testing.T) {
   298  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   299  		Terms: &protoTypes.ProposalTerms{
   300  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   301  				UpdateMarket: &protoTypes.UpdateMarket{
   302  					Changes: &protoTypes.UpdateMarketConfiguration{
   303  						LiquidityMonitoringParameters: &protoTypes.LiquidityMonitoringParameters{},
   304  					},
   305  				},
   306  			},
   307  		},
   308  	})
   309  
   310  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.liquidity_monitoring_parameters.target_stake_parameters"), commands.ErrIsRequired)
   311  }
   312  
   313  func testUpdateMarketLiquidityMonitoringChangeSubmissionWithTargetStakeParametersSucceeds(t *testing.T) {
   314  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   315  		Terms: &protoTypes.ProposalTerms{
   316  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   317  				UpdateMarket: &protoTypes.UpdateMarket{
   318  					Changes: &protoTypes.UpdateMarketConfiguration{
   319  						LiquidityMonitoringParameters: &protoTypes.LiquidityMonitoringParameters{
   320  							TargetStakeParameters: &protoTypes.TargetStakeParameters{},
   321  						},
   322  					},
   323  				},
   324  			},
   325  		},
   326  	})
   327  
   328  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.liquidity_monitoring_parameters.target_stake_parameters"), commands.ErrIsRequired)
   329  }
   330  
   331  func testUpdateMarketLiquidityMonitoringChangeSubmissionWithNonPositiveTimeWindowFails(t *testing.T) {
   332  	testCases := []struct {
   333  		msg   string
   334  		value int64
   335  	}{
   336  		{
   337  			msg:   "with ratio of 0",
   338  			value: 0,
   339  		}, {
   340  			msg:   "with ratio of -1",
   341  			value: test.RandomNegativeI64(),
   342  		},
   343  	}
   344  	for _, tc := range testCases {
   345  		t.Run(tc.msg, func(t *testing.T) {
   346  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
   347  				Terms: &protoTypes.ProposalTerms{
   348  					Change: &protoTypes.ProposalTerms_UpdateMarket{
   349  						UpdateMarket: &protoTypes.UpdateMarket{
   350  							Changes: &protoTypes.UpdateMarketConfiguration{
   351  								LiquidityMonitoringParameters: &protoTypes.LiquidityMonitoringParameters{
   352  									TargetStakeParameters: &protoTypes.TargetStakeParameters{
   353  										TimeWindow: tc.value,
   354  									},
   355  								},
   356  							},
   357  						},
   358  					},
   359  				},
   360  			})
   361  
   362  			assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.liquidity_monitoring_parameters.target_stake_parameters.time_window"), commands.ErrMustBePositive)
   363  		})
   364  	}
   365  }
   366  
   367  func testUpdateMarketLiquidityMonitoringChangeSubmissionWithPositiveTimeWindowSucceeds(t *testing.T) {
   368  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   369  		Terms: &protoTypes.ProposalTerms{
   370  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   371  				UpdateMarket: &protoTypes.UpdateMarket{
   372  					Changes: &protoTypes.UpdateMarketConfiguration{
   373  						LiquidityMonitoringParameters: &protoTypes.LiquidityMonitoringParameters{
   374  							TargetStakeParameters: &protoTypes.TargetStakeParameters{
   375  								TimeWindow: test.RandomPositiveI64(),
   376  							},
   377  						},
   378  					},
   379  				},
   380  			},
   381  		},
   382  	})
   383  
   384  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.liquidity_monitoring_parameters.target_stake_parameters.time_window"), commands.ErrMustBePositive)
   385  }
   386  
   387  func testUpdateMarketLiquidityMonitoringChangeSubmissionWithNonPositiveScalingFactorFails(t *testing.T) {
   388  	testCases := []struct {
   389  		msg   string
   390  		value float64
   391  	}{
   392  		{
   393  			msg:   "with ratio of 0",
   394  			value: 0,
   395  		}, {
   396  			msg:   "with ratio of -1.5",
   397  			value: -1.5,
   398  		},
   399  	}
   400  	for _, tc := range testCases {
   401  		t.Run(tc.msg, func(t *testing.T) {
   402  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
   403  				Terms: &protoTypes.ProposalTerms{
   404  					Change: &protoTypes.ProposalTerms_UpdateMarket{
   405  						UpdateMarket: &protoTypes.UpdateMarket{
   406  							Changes: &protoTypes.UpdateMarketConfiguration{
   407  								LiquidityMonitoringParameters: &protoTypes.LiquidityMonitoringParameters{
   408  									TargetStakeParameters: &protoTypes.TargetStakeParameters{
   409  										ScalingFactor: tc.value,
   410  									},
   411  								},
   412  							},
   413  						},
   414  					},
   415  				},
   416  			})
   417  
   418  			assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.liquidity_monitoring_parameters.target_stake_parameters.scaling_factor"), commands.ErrMustBePositive)
   419  		})
   420  	}
   421  }
   422  
   423  func testUpdateMarketLiquidityMonitoringChangeSubmissionWithPositiveScalingFactorSucceeds(t *testing.T) {
   424  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   425  		Terms: &protoTypes.ProposalTerms{
   426  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   427  				UpdateMarket: &protoTypes.UpdateMarket{
   428  					Changes: &protoTypes.UpdateMarketConfiguration{
   429  						LiquidityMonitoringParameters: &protoTypes.LiquidityMonitoringParameters{
   430  							TargetStakeParameters: &protoTypes.TargetStakeParameters{
   431  								ScalingFactor: 1.5,
   432  							},
   433  						},
   434  					},
   435  				},
   436  			},
   437  		},
   438  	})
   439  
   440  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.liquidity_monitoring_parameters.target_stake_parameters.scaling_factor"), commands.ErrMustBePositive)
   441  }
   442  
   443  func testUpdateMarketPriceMonitoringChangeSubmissionWithoutTriggersSucceeds(t *testing.T) {
   444  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   445  		Terms: &protoTypes.ProposalTerms{
   446  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   447  				UpdateMarket: &protoTypes.UpdateMarket{
   448  					Changes: &protoTypes.UpdateMarketConfiguration{
   449  						PriceMonitoringParameters: &protoTypes.PriceMonitoringParameters{
   450  							Triggers: []*protoTypes.PriceMonitoringTrigger{},
   451  						},
   452  					},
   453  				},
   454  			},
   455  		},
   456  	})
   457  
   458  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.price_monitoring_parameters.triggers"), commands.ErrIsRequired)
   459  }
   460  
   461  func testUpdateMarketPriceMonitoringChangeSubmissionWithTriggersSucceeds(t *testing.T) {
   462  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   463  		Terms: &protoTypes.ProposalTerms{
   464  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   465  				UpdateMarket: &protoTypes.UpdateMarket{
   466  					Changes: &protoTypes.UpdateMarketConfiguration{
   467  						PriceMonitoringParameters: &protoTypes.PriceMonitoringParameters{
   468  							Triggers: []*protoTypes.PriceMonitoringTrigger{
   469  								{},
   470  								{},
   471  							},
   472  						},
   473  					},
   474  				},
   475  			},
   476  		},
   477  	})
   478  
   479  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.price_monitoring_parameters.triggers"), commands.ErrIsRequired)
   480  }
   481  
   482  func testUpdateMarketPriceMonitoringChangeSubmissionWithoutTriggerHorizonFails(t *testing.T) {
   483  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   484  		Terms: &protoTypes.ProposalTerms{
   485  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   486  				UpdateMarket: &protoTypes.UpdateMarket{
   487  					Changes: &protoTypes.UpdateMarketConfiguration{
   488  						PriceMonitoringParameters: &protoTypes.PriceMonitoringParameters{
   489  							Triggers: []*protoTypes.PriceMonitoringTrigger{
   490  								{},
   491  								{},
   492  							},
   493  						},
   494  					},
   495  				},
   496  			},
   497  		},
   498  	})
   499  
   500  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.price_monitoring_parameters.triggers.0.horizon"), commands.ErrMustBePositive)
   501  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.price_monitoring_parameters.triggers.1.horizon"), commands.ErrMustBePositive)
   502  }
   503  
   504  func testUpdateMarketPriceMonitoringChangeSubmissionWithTriggerHorizonSucceeds(t *testing.T) {
   505  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   506  		Terms: &protoTypes.ProposalTerms{
   507  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   508  				UpdateMarket: &protoTypes.UpdateMarket{
   509  					Changes: &protoTypes.UpdateMarketConfiguration{
   510  						PriceMonitoringParameters: &protoTypes.PriceMonitoringParameters{
   511  							Triggers: []*protoTypes.PriceMonitoringTrigger{
   512  								{
   513  									Horizon: test.RandomPositiveI64(),
   514  								},
   515  								{
   516  									Horizon: test.RandomPositiveI64(),
   517  								},
   518  							},
   519  						},
   520  					},
   521  				},
   522  			},
   523  		},
   524  	})
   525  
   526  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.price_monitoring_parameters.triggers.0.horizon"), commands.ErrMustBePositive)
   527  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.price_monitoring_parameters.triggers.1.horizon"), commands.ErrMustBePositive)
   528  }
   529  
   530  func testUpdateMarketPriceMonitoringChangeSubmissionWithWrongTriggerProbabilityFails(t *testing.T) {
   531  	testCases := []struct {
   532  		msg   string
   533  		value float64
   534  	}{
   535  		{
   536  			msg:   "with probability of -1",
   537  			value: -1,
   538  		}, {
   539  			msg:   "with probability of 0",
   540  			value: 0,
   541  		}, {
   542  			msg:   "with probability of 1",
   543  			value: 1,
   544  		}, {
   545  			msg:   "with probability of 2",
   546  			value: 2,
   547  		},
   548  	}
   549  	for _, tc := range testCases {
   550  		t.Run(tc.msg, func(t *testing.T) {
   551  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
   552  				Terms: &protoTypes.ProposalTerms{
   553  					Change: &protoTypes.ProposalTerms_UpdateMarket{
   554  						UpdateMarket: &protoTypes.UpdateMarket{
   555  							Changes: &protoTypes.UpdateMarketConfiguration{
   556  								PriceMonitoringParameters: &protoTypes.PriceMonitoringParameters{
   557  									Triggers: []*protoTypes.PriceMonitoringTrigger{
   558  										{
   559  											Probability: fmt.Sprintf("%f", tc.value),
   560  										},
   561  										{
   562  											Probability: fmt.Sprintf("%f", tc.value),
   563  										},
   564  									},
   565  								},
   566  							},
   567  						},
   568  					},
   569  				},
   570  			})
   571  
   572  			assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.price_monitoring_parameters.triggers.0.probability"),
   573  				errors.New("should be between 0.9 (exclusive) and 1 (exclusive)"))
   574  			assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.price_monitoring_parameters.triggers.1.probability"),
   575  				errors.New("should be between 0.9 (exclusive) and 1 (exclusive)"))
   576  		})
   577  	}
   578  }
   579  
   580  func testUpdateMarketPriceMonitoringChangeSubmissionWithRightTriggerProbabilitySucceeds(t *testing.T) {
   581  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   582  		Terms: &protoTypes.ProposalTerms{
   583  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   584  				UpdateMarket: &protoTypes.UpdateMarket{
   585  					Changes: &protoTypes.UpdateMarketConfiguration{
   586  						PriceMonitoringParameters: &protoTypes.PriceMonitoringParameters{
   587  							Triggers: []*protoTypes.PriceMonitoringTrigger{
   588  								{
   589  									Probability: "0.01",
   590  								},
   591  								{
   592  									Probability: "0.9",
   593  								},
   594  							},
   595  						},
   596  					},
   597  				},
   598  			},
   599  		},
   600  	})
   601  
   602  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.price_monitoring_parameters.triggers.0.probability"),
   603  		errors.New("should be between 0 (exclusive) and 1 (exclusive)"))
   604  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.price_monitoring_parameters.triggers.1.probability"),
   605  		errors.New("should be between 0 (exclusive) and 1 (exclusive)"))
   606  }
   607  
   608  func testUpdateMarketPriceMonitoringChangeSubmissionWithoutTriggerAuctionExtensionFails(t *testing.T) {
   609  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   610  		Terms: &protoTypes.ProposalTerms{
   611  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   612  				UpdateMarket: &protoTypes.UpdateMarket{
   613  					Changes: &protoTypes.UpdateMarketConfiguration{
   614  						PriceMonitoringParameters: &protoTypes.PriceMonitoringParameters{
   615  							Triggers: []*protoTypes.PriceMonitoringTrigger{
   616  								{},
   617  								{},
   618  							},
   619  						},
   620  					},
   621  				},
   622  			},
   623  		},
   624  	})
   625  
   626  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.price_monitoring_parameters.triggers.0.auction_extension"), commands.ErrMustBePositive)
   627  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.price_monitoring_parameters.triggers.1.auction_extension"), commands.ErrMustBePositive)
   628  }
   629  
   630  func testUpdateMarketPriceMonitoringChangeSubmissionWithTriggerAuctionExtensionSucceeds(t *testing.T) {
   631  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   632  		Terms: &protoTypes.ProposalTerms{
   633  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   634  				UpdateMarket: &protoTypes.UpdateMarket{
   635  					Changes: &protoTypes.UpdateMarketConfiguration{
   636  						PriceMonitoringParameters: &protoTypes.PriceMonitoringParameters{
   637  							Triggers: []*protoTypes.PriceMonitoringTrigger{
   638  								{
   639  									AuctionExtension: test.RandomPositiveI64(),
   640  								},
   641  								{
   642  									AuctionExtension: test.RandomPositiveI64(),
   643  								},
   644  							},
   645  						},
   646  					},
   647  				},
   648  			},
   649  		},
   650  	})
   651  
   652  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.price_monitoring_parameters.triggers.0.auction_extension"), commands.ErrMustBePositive)
   653  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.price_monitoring_parameters.triggers.1.auction_extension"), commands.ErrMustBePositive)
   654  }
   655  
   656  func testUpdateMarketChangeSubmissionWithoutPriceMonitoringSucceeds(t *testing.T) {
   657  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   658  		Terms: &protoTypes.ProposalTerms{
   659  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   660  				UpdateMarket: &protoTypes.UpdateMarket{
   661  					Changes: &protoTypes.UpdateMarketConfiguration{},
   662  				},
   663  			},
   664  		},
   665  	})
   666  
   667  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.price_monitoring_parameters"), commands.ErrIsRequired)
   668  }
   669  
   670  func testUpdateMarketChangeSubmissionWithPriceMonitoringSucceeds(t *testing.T) {
   671  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   672  		Terms: &protoTypes.ProposalTerms{
   673  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   674  				UpdateMarket: &protoTypes.UpdateMarket{
   675  					Changes: &protoTypes.UpdateMarketConfiguration{
   676  						PriceMonitoringParameters: &protoTypes.PriceMonitoringParameters{},
   677  					},
   678  				},
   679  			},
   680  		},
   681  	})
   682  
   683  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.price_monitoring_parameters"), commands.ErrIsRequired)
   684  }
   685  
   686  func testUpdateMarketChangeSubmissionWithoutInstrumentNameFails(t *testing.T) {
   687  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   688  		Terms: &protoTypes.ProposalTerms{
   689  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   690  				UpdateMarket: &protoTypes.UpdateMarket{
   691  					Changes: &protoTypes.UpdateMarketConfiguration{
   692  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
   693  							Name: "",
   694  						},
   695  					},
   696  				},
   697  			},
   698  		},
   699  	})
   700  
   701  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.name"), commands.ErrIsRequired)
   702  }
   703  
   704  func testUpdateMarketChangeSubmissionWithoutInstrumentCodeFails(t *testing.T) {
   705  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   706  		Terms: &protoTypes.ProposalTerms{
   707  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   708  				UpdateMarket: &protoTypes.UpdateMarket{
   709  					Changes: &protoTypes.UpdateMarketConfiguration{
   710  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
   711  							Code: "",
   712  						},
   713  					},
   714  				},
   715  			},
   716  		},
   717  	})
   718  
   719  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.code"), commands.ErrIsRequired)
   720  }
   721  
   722  func testUpdateMarketChangeSubmissionWithInstrumentCodeSucceeds(t *testing.T) {
   723  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   724  		Terms: &protoTypes.ProposalTerms{
   725  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   726  				UpdateMarket: &protoTypes.UpdateMarket{
   727  					Changes: &protoTypes.UpdateMarketConfiguration{
   728  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
   729  							Code: "My code",
   730  						},
   731  					},
   732  				},
   733  			},
   734  		},
   735  	})
   736  
   737  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.code"), commands.ErrIsRequired)
   738  }
   739  
   740  func testUpdateMarketChangeSubmissionWithoutProductFails(t *testing.T) {
   741  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   742  		Terms: &protoTypes.ProposalTerms{
   743  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   744  				UpdateMarket: &protoTypes.UpdateMarket{
   745  					Changes: &protoTypes.UpdateMarketConfiguration{
   746  						Instrument: &protoTypes.UpdateInstrumentConfiguration{},
   747  					},
   748  				},
   749  			},
   750  		},
   751  	})
   752  
   753  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product"), commands.ErrIsRequired)
   754  }
   755  
   756  func testUpdateMarketChangeSubmissionWithProductSucceeds(t *testing.T) {
   757  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   758  		Terms: &protoTypes.ProposalTerms{
   759  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   760  				UpdateMarket: &protoTypes.UpdateMarket{
   761  					Changes: &protoTypes.UpdateMarketConfiguration{
   762  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
   763  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{},
   764  						},
   765  					},
   766  				},
   767  			},
   768  		},
   769  	})
   770  
   771  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product"), commands.ErrIsRequired)
   772  }
   773  
   774  func testUpdateFutureMarketChangeSubmissionWithoutFutureFails(t *testing.T) {
   775  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   776  		Terms: &protoTypes.ProposalTerms{
   777  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   778  				UpdateMarket: &protoTypes.UpdateMarket{
   779  					Changes: &protoTypes.UpdateMarketConfiguration{
   780  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
   781  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{},
   782  						},
   783  					},
   784  				},
   785  			},
   786  		},
   787  	})
   788  
   789  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future"), commands.ErrIsRequired)
   790  }
   791  
   792  func testUpdateFutureMarketChangeSubmissionWithFutureSucceeds(t *testing.T) {
   793  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   794  		Terms: &protoTypes.ProposalTerms{
   795  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   796  				UpdateMarket: &protoTypes.UpdateMarket{
   797  					Changes: &protoTypes.UpdateMarketConfiguration{
   798  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
   799  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
   800  								Future: &protoTypes.UpdateFutureProduct{},
   801  							},
   802  						},
   803  					},
   804  				},
   805  			},
   806  		},
   807  	})
   808  
   809  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future"), commands.ErrIsRequired)
   810  }
   811  
   812  func testUpdateFutureMarketChangeSubmissionWithoutQuoteNameFails(t *testing.T) {
   813  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   814  		Terms: &protoTypes.ProposalTerms{
   815  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   816  				UpdateMarket: &protoTypes.UpdateMarket{
   817  					Changes: &protoTypes.UpdateMarketConfiguration{
   818  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
   819  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
   820  								Future: &protoTypes.UpdateFutureProduct{
   821  									QuoteName: "",
   822  								},
   823  							},
   824  						},
   825  					},
   826  				},
   827  			},
   828  		},
   829  	})
   830  
   831  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.quote_name"), commands.ErrIsRequired)
   832  }
   833  
   834  func testUpdateFutureMarketChangeSubmissionWithQuoteNameSucceeds(t *testing.T) {
   835  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   836  		Terms: &protoTypes.ProposalTerms{
   837  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   838  				UpdateMarket: &protoTypes.UpdateMarket{
   839  					Changes: &protoTypes.UpdateMarketConfiguration{
   840  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
   841  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
   842  								Future: &protoTypes.UpdateFutureProduct{
   843  									QuoteName: "BTC",
   844  								},
   845  							},
   846  						},
   847  					},
   848  				},
   849  			},
   850  		},
   851  	})
   852  
   853  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.quote_name"), commands.ErrIsRequired)
   854  }
   855  
   856  func testUpdateFutureMarketChangeSubmissionWithoutOracleSpecFails(t *testing.T) {
   857  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   858  		Terms: &protoTypes.ProposalTerms{
   859  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   860  				UpdateMarket: &protoTypes.UpdateMarket{
   861  					Changes: &protoTypes.UpdateMarketConfiguration{
   862  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
   863  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
   864  								Future: &protoTypes.UpdateFutureProduct{},
   865  							},
   866  						},
   867  					},
   868  				},
   869  			},
   870  		},
   871  	})
   872  
   873  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data"), commands.ErrIsRequired)
   874  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_trading_termination"), commands.ErrIsRequired)
   875  }
   876  
   877  func testUpdateFutureMarketChangeSubmissionMissingSingleOracleSpecFails(t *testing.T) {
   878  	testUpdateFutureMarketChangeSubmissionWithoutEitherOracleSpecFails(t, "data_source_spec_for_settlement_data")
   879  	testUpdateFutureMarketChangeSubmissionWithoutEitherOracleSpecFails(t, "data_source_spec_for_trading_termination")
   880  }
   881  
   882  func testUpdateFutureMarketChangeSubmissionWithoutEitherOracleSpecFails(t *testing.T, oracleSpecName string) {
   883  	t.Helper()
   884  	future := &protoTypes.UpdateFutureProduct{}
   885  	if oracleSpecName == "data_source_spec_for_settlement_data" {
   886  		future.DataSourceSpecForTradingTermination = &vegapb.DataSourceDefinition{}
   887  	} else {
   888  		future.DataSourceSpecForSettlementData = &vegapb.DataSourceDefinition{}
   889  	}
   890  
   891  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   892  		Terms: &protoTypes.ProposalTerms{
   893  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   894  				UpdateMarket: &protoTypes.UpdateMarket{
   895  					Changes: &protoTypes.UpdateMarketConfiguration{
   896  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
   897  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
   898  								Future: &protoTypes.UpdateFutureProduct{},
   899  							},
   900  						},
   901  					},
   902  				},
   903  			},
   904  		},
   905  	})
   906  
   907  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future."+oracleSpecName), commands.ErrIsRequired)
   908  }
   909  
   910  func testUpdateFutureMarketChangeSubmissionWithEmptyOracleSpecFails(t *testing.T) {
   911  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   912  		Terms: &protoTypes.ProposalTerms{
   913  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   914  				UpdateMarket: &protoTypes.UpdateMarket{
   915  					Changes: &protoTypes.UpdateMarketConfiguration{
   916  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
   917  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
   918  								Future: &protoTypes.UpdateFutureProduct{
   919  									DataSourceSpecForSettlementData:     &vegapb.DataSourceDefinition{},
   920  									DataSourceSpecForTradingTermination: &vegapb.DataSourceDefinition{},
   921  								},
   922  							},
   923  						},
   924  					},
   925  				},
   926  			},
   927  		},
   928  	})
   929  
   930  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.source_type"), commands.ErrIsRequired)
   931  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_trading_termination.source_type"), commands.ErrIsRequired)
   932  }
   933  
   934  func testUpdateFutureMarketChangeSubmissionWithEmptyOracleSpecTypeFails(t *testing.T) {
   935  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   936  		Terms: &protoTypes.ProposalTerms{
   937  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   938  				UpdateMarket: &protoTypes.UpdateMarket{
   939  					Changes: &protoTypes.UpdateMarketConfiguration{
   940  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
   941  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
   942  								Future: &protoTypes.UpdateFutureProduct{
   943  									DataSourceSpecForSettlementData: &vegapb.DataSourceDefinition{
   944  										SourceType: &vegapb.DataSourceDefinition_External{
   945  											External: &vegapb.DataSourceDefinitionExternal{
   946  												SourceType: &vegapb.DataSourceDefinitionExternal_Oracle{
   947  													Oracle: nil,
   948  												},
   949  											},
   950  										},
   951  									},
   952  									DataSourceSpecForTradingTermination: &vegapb.DataSourceDefinition{
   953  										SourceType: &vegapb.DataSourceDefinition_External{
   954  											External: &vegapb.DataSourceDefinitionExternal{
   955  												SourceType: &vegapb.DataSourceDefinitionExternal_Oracle{
   956  													Oracle: nil,
   957  												},
   958  											},
   959  										},
   960  									},
   961  								},
   962  							},
   963  						},
   964  					},
   965  				},
   966  			},
   967  		},
   968  	})
   969  
   970  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle"), commands.ErrIsRequired)
   971  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_trading_termination.external.oracle"), commands.ErrIsRequired)
   972  }
   973  
   974  func testUpdateFutureMarketChangeSubmissionWithEmptyInternalOracleSpecTypeFails(t *testing.T) {
   975  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
   976  		Terms: &protoTypes.ProposalTerms{
   977  			Change: &protoTypes.ProposalTerms_UpdateMarket{
   978  				UpdateMarket: &protoTypes.UpdateMarket{
   979  					Changes: &protoTypes.UpdateMarketConfiguration{
   980  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
   981  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
   982  								Future: &protoTypes.UpdateFutureProduct{
   983  									DataSourceSpecForSettlementData: &vegapb.DataSourceDefinition{
   984  										SourceType: &vegapb.DataSourceDefinition_Internal{
   985  											Internal: &vegapb.DataSourceDefinitionInternal{
   986  												SourceType: &vegapb.DataSourceDefinitionInternal_Time{
   987  													Time: nil,
   988  												},
   989  											},
   990  										},
   991  									},
   992  									DataSourceSpecForTradingTermination: &vegapb.DataSourceDefinition{
   993  										SourceType: &vegapb.DataSourceDefinition_Internal{
   994  											Internal: &vegapb.DataSourceDefinitionInternal{
   995  												SourceType: &vegapb.DataSourceDefinitionInternal_Time{
   996  													Time: nil,
   997  												},
   998  											},
   999  										},
  1000  									},
  1001  								},
  1002  							},
  1003  						},
  1004  					},
  1005  				},
  1006  			},
  1007  		},
  1008  	})
  1009  
  1010  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data"), commands.ErrIsNotValid)
  1011  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_trading_termination.internal.time"), commands.ErrIsRequired)
  1012  }
  1013  
  1014  func testUpdateFutureMarketSettlementDataChangeSubmissionWithoutPubKeysFails(t *testing.T) {
  1015  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1016  		Terms: &protoTypes.ProposalTerms{
  1017  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  1018  				UpdateMarket: &protoTypes.UpdateMarket{
  1019  					Changes: &protoTypes.UpdateMarketConfiguration{
  1020  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  1021  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  1022  								Future: &protoTypes.UpdateFutureProduct{
  1023  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1024  										vegapb.DataSourceContentTypeOracle,
  1025  									).SetOracleConfig(
  1026  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1027  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1028  												Signers: []*datapb.Signer{},
  1029  												Filters: []*datapb.Filter{
  1030  													{
  1031  														Key: &datapb.PropertyKey{
  1032  															Name: "trading.terminated",
  1033  															Type: datapb.PropertyKey_TYPE_BOOLEAN,
  1034  														},
  1035  														Conditions: []*datapb.Condition{},
  1036  													},
  1037  												},
  1038  											},
  1039  										},
  1040  									),
  1041  								},
  1042  							},
  1043  						},
  1044  					},
  1045  				},
  1046  			},
  1047  		},
  1048  	})
  1049  
  1050  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers"), commands.ErrIsRequired)
  1051  }
  1052  
  1053  func testUpdateFutureMarketChangeSubmissionWithWrongPubKeysFails(t *testing.T) {
  1054  	pubKeys := []*datapb.Signer{
  1055  		{
  1056  			Signer: &datapb.Signer_PubKey{
  1057  				PubKey: &datapb.PubKey{
  1058  					Key: "0xDEADBEEF",
  1059  				},
  1060  			},
  1061  		},
  1062  		{
  1063  			Signer: &datapb.Signer_PubKey{
  1064  				PubKey: &datapb.PubKey{
  1065  					Key: "",
  1066  				},
  1067  			},
  1068  		},
  1069  	}
  1070  
  1071  	testCases := []struct {
  1072  		msg   string
  1073  		value []*datapb.Signer
  1074  	}{
  1075  		{
  1076  			msg:   "with empty signers",
  1077  			value: pubKeys,
  1078  		}, {
  1079  			msg:   "with blank signers",
  1080  			value: pubKeys,
  1081  		},
  1082  	}
  1083  
  1084  	for _, tc := range testCases {
  1085  		t.Run(tc.msg, func(t *testing.T) {
  1086  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1087  				Terms: &protoTypes.ProposalTerms{
  1088  					Change: &protoTypes.ProposalTerms_UpdateMarket{
  1089  						UpdateMarket: &protoTypes.UpdateMarket{
  1090  							Changes: &protoTypes.UpdateMarketConfiguration{
  1091  								Instrument: &protoTypes.UpdateInstrumentConfiguration{
  1092  									Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  1093  										Future: &protoTypes.UpdateFutureProduct{
  1094  											DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1095  												vegapb.DataSourceContentTypeOracle,
  1096  											).SetOracleConfig(
  1097  												&vegapb.DataSourceDefinitionExternal_Oracle{
  1098  													Oracle: &vegapb.DataSourceSpecConfiguration{
  1099  														Signers: tc.value,
  1100  													},
  1101  												},
  1102  											),
  1103  										},
  1104  									},
  1105  								},
  1106  							},
  1107  						},
  1108  					},
  1109  				},
  1110  			})
  1111  
  1112  			assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers.1"), commands.ErrIsNotValid)
  1113  		})
  1114  	}
  1115  }
  1116  
  1117  func testUpdateFutureMarketChangeSubmissionWithPubKeysSucceeds(t *testing.T) {
  1118  	pubKeys := []*datapb.Signer{
  1119  		{
  1120  			Signer: &datapb.Signer_PubKey{
  1121  				PubKey: &datapb.PubKey{
  1122  					Key: "0xDEADBEEF",
  1123  				},
  1124  			},
  1125  		},
  1126  		{
  1127  			Signer: &datapb.Signer_PubKey{
  1128  				PubKey: &datapb.PubKey{
  1129  					Key: "0xCAFEDUDE",
  1130  				},
  1131  			},
  1132  		},
  1133  	}
  1134  
  1135  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1136  		Terms: &protoTypes.ProposalTerms{
  1137  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  1138  				UpdateMarket: &protoTypes.UpdateMarket{
  1139  					Changes: &protoTypes.UpdateMarketConfiguration{
  1140  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  1141  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  1142  								Future: &protoTypes.UpdateFutureProduct{
  1143  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1144  										vegapb.DataSourceContentTypeOracle,
  1145  									).SetOracleConfig(
  1146  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1147  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1148  												Signers: pubKeys,
  1149  											},
  1150  										},
  1151  									),
  1152  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  1153  										vegapb.DataSourceContentTypeOracle,
  1154  									).SetOracleConfig(
  1155  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1156  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1157  												Signers: pubKeys,
  1158  											},
  1159  										},
  1160  									),
  1161  								},
  1162  							},
  1163  						},
  1164  					},
  1165  				},
  1166  			},
  1167  		},
  1168  	})
  1169  
  1170  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers"), commands.ErrIsRequired)
  1171  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers.0"), commands.ErrIsNotValid)
  1172  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers.1"), commands.ErrIsNotValid)
  1173  }
  1174  
  1175  func testUpdateFutureMarketChangeSubmissionWithoutFiltersFails(t *testing.T) {
  1176  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1177  		Terms: &protoTypes.ProposalTerms{
  1178  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  1179  				UpdateMarket: &protoTypes.UpdateMarket{
  1180  					Changes: &protoTypes.UpdateMarketConfiguration{
  1181  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  1182  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  1183  								Future: &protoTypes.UpdateFutureProduct{
  1184  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1185  										vegapb.DataSourceContentTypeOracle,
  1186  									).SetOracleConfig(
  1187  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1188  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1189  												Filters: []*datapb.Filter{},
  1190  											},
  1191  										},
  1192  									),
  1193  								},
  1194  							},
  1195  						},
  1196  					},
  1197  				},
  1198  			},
  1199  		},
  1200  	})
  1201  
  1202  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters"), commands.ErrIsRequired)
  1203  }
  1204  
  1205  func testUpdateFutureMarketChangeSubmissionWithFiltersSucceeds(t *testing.T) {
  1206  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1207  		Terms: &protoTypes.ProposalTerms{
  1208  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  1209  				UpdateMarket: &protoTypes.UpdateMarket{
  1210  					Changes: &protoTypes.UpdateMarketConfiguration{
  1211  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  1212  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  1213  								Future: &protoTypes.UpdateFutureProduct{
  1214  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1215  										vegapb.DataSourceContentTypeOracle,
  1216  									).SetOracleConfig(
  1217  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1218  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1219  												Filters: []*datapb.Filter{
  1220  													{},
  1221  												},
  1222  											},
  1223  										},
  1224  									),
  1225  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  1226  										vegapb.DataSourceContentTypeOracle,
  1227  									).SetOracleConfig(
  1228  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1229  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1230  												Filters: []*datapb.Filter{
  1231  													{},
  1232  												},
  1233  											},
  1234  										},
  1235  									),
  1236  								},
  1237  							},
  1238  						},
  1239  					},
  1240  				},
  1241  			},
  1242  		},
  1243  	})
  1244  
  1245  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters"), commands.ErrIsRequired)
  1246  }
  1247  
  1248  func testUpdateFutureMarketChangeSubmissionWithFilterWithoutKeyFails(t *testing.T) {
  1249  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1250  		Terms: &protoTypes.ProposalTerms{
  1251  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  1252  				UpdateMarket: &protoTypes.UpdateMarket{
  1253  					Changes: &protoTypes.UpdateMarketConfiguration{
  1254  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  1255  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  1256  								Future: &protoTypes.UpdateFutureProduct{
  1257  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1258  										vegapb.DataSourceContentTypeOracle,
  1259  									).SetOracleConfig(
  1260  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1261  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1262  												Filters: []*datapb.Filter{
  1263  													{}, {},
  1264  												},
  1265  											},
  1266  										},
  1267  									),
  1268  								},
  1269  							},
  1270  						},
  1271  					},
  1272  				},
  1273  			},
  1274  		},
  1275  	})
  1276  
  1277  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters.0.key"), commands.ErrIsNotValid)
  1278  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters.1.key"), commands.ErrIsNotValid)
  1279  }
  1280  
  1281  func testUpdateFutureMarketChangeSubmissionWithFilterWithKeySucceeds(t *testing.T) {
  1282  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1283  		Terms: &protoTypes.ProposalTerms{
  1284  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  1285  				UpdateMarket: &protoTypes.UpdateMarket{
  1286  					Changes: &protoTypes.UpdateMarketConfiguration{
  1287  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  1288  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  1289  								Future: &protoTypes.UpdateFutureProduct{
  1290  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1291  										vegapb.DataSourceContentTypeOracle,
  1292  									).SetOracleConfig(
  1293  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1294  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1295  												Filters: []*datapb.Filter{
  1296  													{
  1297  														Key: &datapb.PropertyKey{},
  1298  													}, {
  1299  														Key: &datapb.PropertyKey{},
  1300  													},
  1301  												},
  1302  											},
  1303  										},
  1304  									),
  1305  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  1306  										vegapb.DataSourceContentTypeOracle,
  1307  									).SetOracleConfig(
  1308  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1309  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1310  												Filters: []*datapb.Filter{
  1311  													{
  1312  														Key: &datapb.PropertyKey{},
  1313  													}, {
  1314  														Key: &datapb.PropertyKey{},
  1315  													},
  1316  												},
  1317  											},
  1318  										},
  1319  									),
  1320  								},
  1321  							},
  1322  						},
  1323  					},
  1324  				},
  1325  			},
  1326  		},
  1327  	})
  1328  
  1329  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters.0.key"), commands.ErrIsNotValid)
  1330  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters.1.key"), commands.ErrIsNotValid)
  1331  }
  1332  
  1333  func testUpdateFutureMarketChangeSubmissionWithFilterWithoutKeyNameFails(t *testing.T) {
  1334  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1335  		Terms: &protoTypes.ProposalTerms{
  1336  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  1337  				UpdateMarket: &protoTypes.UpdateMarket{
  1338  					Changes: &protoTypes.UpdateMarketConfiguration{
  1339  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  1340  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  1341  								Future: &protoTypes.UpdateFutureProduct{
  1342  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1343  										vegapb.DataSourceContentTypeOracle,
  1344  									).SetOracleConfig(
  1345  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1346  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1347  												Filters: []*datapb.Filter{
  1348  													{
  1349  														Key: &datapb.PropertyKey{
  1350  															Name: "",
  1351  														},
  1352  													}, {
  1353  														Key: &datapb.PropertyKey{
  1354  															Name: "",
  1355  														},
  1356  													},
  1357  												},
  1358  											},
  1359  										},
  1360  									),
  1361  								},
  1362  							},
  1363  						},
  1364  					},
  1365  				},
  1366  			},
  1367  		},
  1368  	})
  1369  
  1370  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters.0.key.name"), commands.ErrIsRequired)
  1371  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters.1.key.name"), commands.ErrIsRequired)
  1372  }
  1373  
  1374  func testUpdateFutureMarketChangeSubmissionWithFilterWithKeyNameSucceeds(t *testing.T) {
  1375  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1376  		Terms: &protoTypes.ProposalTerms{
  1377  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  1378  				UpdateMarket: &protoTypes.UpdateMarket{
  1379  					Changes: &protoTypes.UpdateMarketConfiguration{
  1380  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  1381  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  1382  								Future: &protoTypes.UpdateFutureProduct{
  1383  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1384  										vegapb.DataSourceContentTypeOracle,
  1385  									).SetOracleConfig(
  1386  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1387  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1388  												Filters: []*datapb.Filter{
  1389  													{
  1390  														Key: &datapb.PropertyKey{
  1391  															Name: "key1",
  1392  														},
  1393  													}, {
  1394  														Key: &datapb.PropertyKey{
  1395  															Name: "key2",
  1396  														},
  1397  													},
  1398  												},
  1399  											},
  1400  										},
  1401  									),
  1402  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  1403  										vegapb.DataSourceContentTypeOracle,
  1404  									).SetOracleConfig(
  1405  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1406  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1407  												Filters: []*datapb.Filter{
  1408  													{
  1409  														Key: &datapb.PropertyKey{
  1410  															Name: "key1",
  1411  														},
  1412  													}, {
  1413  														Key: &datapb.PropertyKey{
  1414  															Name: "key2",
  1415  														},
  1416  													},
  1417  												},
  1418  											},
  1419  										},
  1420  									),
  1421  								},
  1422  							},
  1423  						},
  1424  					},
  1425  				},
  1426  			},
  1427  		},
  1428  	})
  1429  
  1430  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters.0.key.name"), commands.ErrIsRequired)
  1431  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters.1.key.name"), commands.ErrIsRequired)
  1432  }
  1433  
  1434  func testUpdateFutureMarketChangeSubmissionWithFilterWithoutKeyTypeFails(t *testing.T) {
  1435  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1436  		Terms: &protoTypes.ProposalTerms{
  1437  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  1438  				UpdateMarket: &protoTypes.UpdateMarket{
  1439  					Changes: &protoTypes.UpdateMarketConfiguration{
  1440  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  1441  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  1442  								Future: &protoTypes.UpdateFutureProduct{
  1443  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1444  										vegapb.DataSourceContentTypeOracle,
  1445  									).SetOracleConfig(
  1446  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1447  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1448  												Filters: []*datapb.Filter{
  1449  													{
  1450  														Key: &datapb.PropertyKey{
  1451  															Type: datapb.PropertyKey_TYPE_UNSPECIFIED,
  1452  														},
  1453  													}, {
  1454  														Key: &datapb.PropertyKey{},
  1455  													},
  1456  												},
  1457  											},
  1458  										},
  1459  									),
  1460  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  1461  										vegapb.DataSourceContentTypeOracle,
  1462  									).SetOracleConfig(
  1463  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1464  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1465  												Filters: []*datapb.Filter{
  1466  													{
  1467  														Key: &datapb.PropertyKey{
  1468  															Type: datapb.PropertyKey_TYPE_UNSPECIFIED,
  1469  														},
  1470  													}, {
  1471  														Key: &datapb.PropertyKey{},
  1472  													},
  1473  												},
  1474  											},
  1475  										},
  1476  									),
  1477  								},
  1478  							},
  1479  						},
  1480  					},
  1481  				},
  1482  			},
  1483  		},
  1484  	})
  1485  
  1486  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters.0.key.type"), commands.ErrIsRequired)
  1487  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters.1.key.type"), commands.ErrIsRequired)
  1488  }
  1489  
  1490  func testUpdateFutureMarketChangeSubmissionWithFilterWithKeyTypeSucceeds(t *testing.T) {
  1491  	testCases := []struct {
  1492  		msg   string
  1493  		value datapb.PropertyKey_Type
  1494  	}{
  1495  		{
  1496  			msg:   "with EMPTY",
  1497  			value: datapb.PropertyKey_TYPE_EMPTY,
  1498  		}, {
  1499  			msg:   "with INTEGER",
  1500  			value: datapb.PropertyKey_TYPE_INTEGER,
  1501  		}, {
  1502  			msg:   "with STRING",
  1503  			value: datapb.PropertyKey_TYPE_STRING,
  1504  		}, {
  1505  			msg:   "with BOOLEAN",
  1506  			value: datapb.PropertyKey_TYPE_BOOLEAN,
  1507  		}, {
  1508  			msg:   "with DECIMAL",
  1509  			value: datapb.PropertyKey_TYPE_DECIMAL,
  1510  		}, {
  1511  			msg:   "with TIMESTAMP",
  1512  			value: datapb.PropertyKey_TYPE_TIMESTAMP,
  1513  		},
  1514  	}
  1515  	for _, tc := range testCases {
  1516  		t.Run(tc.msg, func(t *testing.T) {
  1517  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1518  				Terms: &protoTypes.ProposalTerms{
  1519  					Change: &protoTypes.ProposalTerms_UpdateMarket{
  1520  						UpdateMarket: &protoTypes.UpdateMarket{
  1521  							Changes: &protoTypes.UpdateMarketConfiguration{
  1522  								Instrument: &protoTypes.UpdateInstrumentConfiguration{
  1523  									Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  1524  										Future: &protoTypes.UpdateFutureProduct{
  1525  											DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1526  												vegapb.DataSourceContentTypeOracle,
  1527  											).SetOracleConfig(
  1528  												&vegapb.DataSourceDefinitionExternal_Oracle{
  1529  													Oracle: &vegapb.DataSourceSpecConfiguration{
  1530  														Filters: []*datapb.Filter{
  1531  															{
  1532  																Key: &datapb.PropertyKey{
  1533  																	Type: tc.value,
  1534  																},
  1535  															}, {
  1536  																Key: &datapb.PropertyKey{
  1537  																	Type: tc.value,
  1538  																},
  1539  															},
  1540  														},
  1541  													},
  1542  												},
  1543  											),
  1544  										},
  1545  									},
  1546  								},
  1547  							},
  1548  						},
  1549  					},
  1550  				},
  1551  			})
  1552  
  1553  			assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec.external.oracle.filters.0.key.type"), commands.ErrIsRequired)
  1554  			assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec.external.oracle.filters.1.key.type"), commands.ErrIsRequired)
  1555  		})
  1556  	}
  1557  }
  1558  
  1559  func testUpdateFutureMarketChangeSubmissionWithFilterWithoutConditionsSucceeds(t *testing.T) {
  1560  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1561  		Terms: &protoTypes.ProposalTerms{
  1562  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  1563  				UpdateMarket: &protoTypes.UpdateMarket{
  1564  					Changes: &protoTypes.UpdateMarketConfiguration{
  1565  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  1566  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  1567  								Future: &protoTypes.UpdateFutureProduct{
  1568  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1569  										vegapb.DataSourceContentTypeOracle,
  1570  									).SetOracleConfig(
  1571  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1572  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1573  												Filters: []*datapb.Filter{
  1574  													{
  1575  														Conditions: []*datapb.Condition{},
  1576  													},
  1577  												},
  1578  											},
  1579  										},
  1580  									),
  1581  								},
  1582  							},
  1583  						},
  1584  					},
  1585  				},
  1586  			},
  1587  		},
  1588  	})
  1589  
  1590  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec.external.oracle.filters.0.conditions"), commands.ErrIsRequired)
  1591  }
  1592  
  1593  func testUpdateFutureMarketChangeSubmissionWithFilterWithoutConditionOperatorFails(t *testing.T) {
  1594  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1595  		Terms: &protoTypes.ProposalTerms{
  1596  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  1597  				UpdateMarket: &protoTypes.UpdateMarket{
  1598  					Changes: &protoTypes.UpdateMarketConfiguration{
  1599  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  1600  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  1601  								Future: &protoTypes.UpdateFutureProduct{
  1602  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1603  										vegapb.DataSourceContentTypeOracle,
  1604  									).SetOracleConfig(
  1605  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1606  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1607  												Filters: []*datapb.Filter{
  1608  													{
  1609  														Conditions: []*datapb.Condition{
  1610  															{
  1611  																Operator: datapb.Condition_OPERATOR_UNSPECIFIED,
  1612  															},
  1613  															{},
  1614  														},
  1615  													},
  1616  												},
  1617  											},
  1618  										},
  1619  									),
  1620  								},
  1621  							},
  1622  						},
  1623  					},
  1624  				},
  1625  			},
  1626  		},
  1627  	})
  1628  
  1629  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters.0.conditions.0.operator"), commands.ErrIsRequired)
  1630  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters.0.conditions.1.operator"), commands.ErrIsRequired)
  1631  }
  1632  
  1633  func testUpdateFutureMarketChangeSubmissionWithFilterWithConditionOperatorSucceeds(t *testing.T) {
  1634  	testCases := []struct {
  1635  		msg   string
  1636  		value datapb.Condition_Operator
  1637  	}{
  1638  		{
  1639  			msg:   "with EQUALS",
  1640  			value: datapb.Condition_OPERATOR_EQUALS,
  1641  		}, {
  1642  			msg:   "with GREATER_THAN",
  1643  			value: datapb.Condition_OPERATOR_GREATER_THAN,
  1644  		}, {
  1645  			msg:   "with GREATER_THAN_OR_EQUAL",
  1646  			value: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  1647  		}, {
  1648  			msg:   "with LESS_THAN",
  1649  			value: datapb.Condition_OPERATOR_LESS_THAN,
  1650  		}, {
  1651  			msg:   "with LESS_THAN_OR_EQUAL",
  1652  			value: datapb.Condition_OPERATOR_LESS_THAN_OR_EQUAL,
  1653  		},
  1654  	}
  1655  	for _, tc := range testCases {
  1656  		t.Run(tc.msg, func(t *testing.T) {
  1657  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1658  				Terms: &protoTypes.ProposalTerms{
  1659  					Change: &protoTypes.ProposalTerms_UpdateMarket{
  1660  						UpdateMarket: &protoTypes.UpdateMarket{
  1661  							Changes: &protoTypes.UpdateMarketConfiguration{
  1662  								Instrument: &protoTypes.UpdateInstrumentConfiguration{
  1663  									Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  1664  										Future: &protoTypes.UpdateFutureProduct{
  1665  											DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1666  												vegapb.DataSourceContentTypeOracle,
  1667  											).SetOracleConfig(
  1668  												&vegapb.DataSourceDefinitionExternal_Oracle{
  1669  													Oracle: &vegapb.DataSourceSpecConfiguration{
  1670  														Filters: []*datapb.Filter{
  1671  															{
  1672  																Conditions: []*datapb.Condition{
  1673  																	{
  1674  																		Operator: tc.value,
  1675  																	},
  1676  																	{
  1677  																		Operator: tc.value,
  1678  																	},
  1679  																},
  1680  															},
  1681  														},
  1682  													},
  1683  												},
  1684  											),
  1685  										},
  1686  									},
  1687  								},
  1688  							},
  1689  						},
  1690  					},
  1691  				},
  1692  			})
  1693  
  1694  			assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec.external.oracle.filters.0.conditions.0.operator"), commands.ErrIsRequired)
  1695  			assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec.external.oracle.filters.1.conditions.0.operator"), commands.ErrIsRequired)
  1696  		})
  1697  	}
  1698  }
  1699  
  1700  func testUpdateFutureMarketChangeSubmissionWithFilterWithoutConditionValueFails(t *testing.T) {
  1701  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1702  		Terms: &protoTypes.ProposalTerms{
  1703  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  1704  				UpdateMarket: &protoTypes.UpdateMarket{
  1705  					Changes: &protoTypes.UpdateMarketConfiguration{
  1706  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  1707  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  1708  								Future: &protoTypes.UpdateFutureProduct{
  1709  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1710  										vegapb.DataSourceContentTypeOracle,
  1711  									).SetOracleConfig(
  1712  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1713  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1714  												Filters: []*datapb.Filter{
  1715  													{
  1716  														Conditions: []*datapb.Condition{
  1717  															{
  1718  																Value: "",
  1719  															},
  1720  															{
  1721  																Value: "",
  1722  															},
  1723  														},
  1724  													},
  1725  												},
  1726  											},
  1727  										},
  1728  									),
  1729  								},
  1730  							},
  1731  						},
  1732  					},
  1733  				},
  1734  			},
  1735  		},
  1736  	})
  1737  
  1738  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters.0.conditions.0.value"), commands.ErrIsRequired)
  1739  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.filters.0.conditions.1.value"), commands.ErrIsRequired)
  1740  }
  1741  
  1742  func testUpdateFutureMarketChangeSubmissionWithFilterWithConditionValueSucceeds(t *testing.T) {
  1743  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1744  		Terms: &protoTypes.ProposalTerms{
  1745  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  1746  				UpdateMarket: &protoTypes.UpdateMarket{
  1747  					Changes: &protoTypes.UpdateMarketConfiguration{
  1748  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  1749  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  1750  								Future: &protoTypes.UpdateFutureProduct{
  1751  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1752  										vegapb.DataSourceContentTypeOracle,
  1753  									).SetOracleConfig(
  1754  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1755  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1756  												Filters: []*datapb.Filter{
  1757  													{
  1758  														Conditions: []*datapb.Condition{
  1759  															{
  1760  																Value: "value 1",
  1761  															},
  1762  															{
  1763  																Value: "value 2",
  1764  															},
  1765  														},
  1766  													},
  1767  												},
  1768  											},
  1769  										},
  1770  									),
  1771  								},
  1772  							},
  1773  						},
  1774  					},
  1775  				},
  1776  			},
  1777  		},
  1778  	})
  1779  
  1780  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec.external.oracle.filters.0.conditions.0.value"), commands.ErrIsRequired)
  1781  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec.external.oracle.filters.0.conditions.1.value"), commands.ErrIsRequired)
  1782  }
  1783  
  1784  func testUpdateFutureMarketChangeSubmissionWithoutDataSourceSpecBindingFails(t *testing.T) {
  1785  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1786  		Terms: &protoTypes.ProposalTerms{
  1787  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  1788  				UpdateMarket: &protoTypes.UpdateMarket{
  1789  					Changes: &protoTypes.UpdateMarketConfiguration{
  1790  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  1791  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  1792  								Future: &protoTypes.UpdateFutureProduct{},
  1793  							},
  1794  						},
  1795  					},
  1796  				},
  1797  			},
  1798  		},
  1799  	})
  1800  
  1801  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_binding"), commands.ErrIsRequired)
  1802  }
  1803  
  1804  func testUpdateFutureMarketChangeSubmissionWithDataSourceSpecBindingSucceeds(t *testing.T) {
  1805  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1806  		Terms: &protoTypes.ProposalTerms{
  1807  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  1808  				UpdateMarket: &protoTypes.UpdateMarket{
  1809  					Changes: &protoTypes.UpdateMarketConfiguration{
  1810  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  1811  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  1812  								Future: &protoTypes.UpdateFutureProduct{
  1813  									DataSourceSpecBinding: &protoTypes.DataSourceSpecToFutureBinding{},
  1814  								},
  1815  							},
  1816  						},
  1817  					},
  1818  				},
  1819  			},
  1820  		},
  1821  	})
  1822  
  1823  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_binding"), commands.ErrIsRequired)
  1824  }
  1825  
  1826  func testUpdateFutureMarketChangeSubmissionMissingOracleBindingPropertyFails(t *testing.T, property string) {
  1827  	t.Helper()
  1828  	var binding *protoTypes.DataSourceSpecToFutureBinding
  1829  	if property == "settlement_data_property" {
  1830  		binding = &protoTypes.DataSourceSpecToFutureBinding{
  1831  			SettlementDataProperty: "",
  1832  		}
  1833  	} else {
  1834  		binding = &protoTypes.DataSourceSpecToFutureBinding{
  1835  			TradingTerminationProperty: "",
  1836  		}
  1837  	}
  1838  
  1839  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1840  		Terms: &protoTypes.ProposalTerms{
  1841  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  1842  				UpdateMarket: &protoTypes.UpdateMarket{
  1843  					Changes: &protoTypes.UpdateMarketConfiguration{
  1844  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  1845  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  1846  								Future: &protoTypes.UpdateFutureProduct{
  1847  									DataSourceSpecBinding: binding,
  1848  								},
  1849  							},
  1850  						},
  1851  					},
  1852  				},
  1853  			},
  1854  		},
  1855  	})
  1856  
  1857  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_binding."+property), commands.ErrIsRequired)
  1858  }
  1859  
  1860  func testUpdateFutureMarketChangeSubmissionWithoutTradingTerminationPropertyFails(t *testing.T) {
  1861  	testUpdateFutureMarketChangeSubmissionMissingOracleBindingPropertyFails(t, "trading_termination_property")
  1862  }
  1863  
  1864  func testUpdateFutureMarketChangeSubmissionWithoutSettlementDataPropertyFails(t *testing.T) {
  1865  	testUpdateFutureMarketChangeSubmissionMissingOracleBindingPropertyFails(t, "settlement_data_property")
  1866  }
  1867  
  1868  func testUpdateFutureMarketChangeSubmissionWithNoMismatchBetweenFilterAndBindingSucceeds(t *testing.T) {
  1869  	testUpdateFutureMarketChangeSubmissionWithNoMismatchBetweenFilterAndBindingForSpecSucceeds(t, &protoTypes.DataSourceSpecToFutureBinding{SettlementDataProperty: "key1"}, "settlement_data_property", "key1")
  1870  	testUpdateFutureMarketChangeSubmissionWithNoMismatchBetweenFilterAndBindingForSpecSucceeds(t, &protoTypes.DataSourceSpecToFutureBinding{TradingTerminationProperty: "key2"}, "settlement_data_property", "key2")
  1871  }
  1872  
  1873  func testUpdateFutureMarketChangeSubmissionWithNoMismatchBetweenFilterAndBindingForSpecSucceeds(t *testing.T, binding *protoTypes.DataSourceSpecToFutureBinding, bindingName string, bindingKey string) {
  1874  	t.Helper()
  1875  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1876  		Terms: &protoTypes.ProposalTerms{
  1877  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  1878  				UpdateMarket: &protoTypes.UpdateMarket{
  1879  					Changes: &protoTypes.UpdateMarketConfiguration{
  1880  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  1881  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  1882  								Future: &protoTypes.UpdateFutureProduct{
  1883  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  1884  										vegapb.DataSourceContentTypeOracle,
  1885  									).SetOracleConfig(
  1886  										&vegapb.DataSourceDefinitionExternal_Oracle{
  1887  											Oracle: &vegapb.DataSourceSpecConfiguration{
  1888  												Filters: []*datapb.Filter{
  1889  													{
  1890  														Key: &datapb.PropertyKey{
  1891  															Name: bindingKey,
  1892  														},
  1893  													}, {
  1894  														Key: &datapb.PropertyKey{},
  1895  													},
  1896  												},
  1897  											},
  1898  										},
  1899  									),
  1900  									DataSourceSpecBinding: binding,
  1901  								},
  1902  							},
  1903  						},
  1904  					},
  1905  				},
  1906  			},
  1907  		},
  1908  	})
  1909  
  1910  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_binding."+bindingName), commands.ErrIsMismatching)
  1911  }
  1912  
  1913  func testUpdateFutureMarketChangeSubmissionWithMismatchBetweenFilterAndBindingForSpecFails(t *testing.T, binding *protoTypes.DataSourceSpecToFutureBinding, bindingName string) {
  1914  	t.Helper()
  1915  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1916  		Terms: &protoTypes.ProposalTerms{
  1917  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  1918  				UpdateMarket: &protoTypes.UpdateMarket{
  1919  					Changes: &protoTypes.UpdateMarketConfiguration{
  1920  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  1921  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  1922  								Future: &protoTypes.UpdateFutureProduct{
  1923  									DataSourceSpecBinding: binding,
  1924  								},
  1925  							},
  1926  						},
  1927  					},
  1928  				},
  1929  			},
  1930  		},
  1931  	})
  1932  
  1933  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_binding."+bindingName), commands.ErrIsMismatching)
  1934  }
  1935  
  1936  func testUpdateFutureMarketChangeSubmissionWithMismatchBetweenFilterAndBindingFails(t *testing.T) {
  1937  	testUpdateFutureMarketChangeSubmissionWithMismatchBetweenFilterAndBindingForSpecFails(t, &protoTypes.DataSourceSpecToFutureBinding{SettlementDataProperty: "My property"}, "settlement_data_property")
  1938  	testUpdateFutureMarketChangeSubmissionWithMismatchBetweenFilterAndBindingForSpecFails(t, &protoTypes.DataSourceSpecToFutureBinding{TradingTerminationProperty: "My property"}, "trading_termination_property")
  1939  }
  1940  
  1941  func testUpdateFutureMarketChangeSubmissionWithSettlementDataPropertySucceeds(t *testing.T) {
  1942  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1943  		Terms: &protoTypes.ProposalTerms{
  1944  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  1945  				UpdateMarket: &protoTypes.UpdateMarket{
  1946  					Changes: &protoTypes.UpdateMarketConfiguration{
  1947  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  1948  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  1949  								Future: &protoTypes.UpdateFutureProduct{
  1950  									DataSourceSpecBinding: &protoTypes.DataSourceSpecToFutureBinding{
  1951  										SettlementDataProperty: "My property",
  1952  									},
  1953  								},
  1954  							},
  1955  						},
  1956  					},
  1957  				},
  1958  			},
  1959  		},
  1960  	})
  1961  
  1962  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_binding.settlement_data_property"), commands.ErrIsRequired)
  1963  }
  1964  
  1965  func testUpdateSimpleRiskParametersChangeSubmissionWithoutSimpleRiskParametersFails(t *testing.T) {
  1966  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1967  		Terms: &protoTypes.ProposalTerms{
  1968  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  1969  				UpdateMarket: &protoTypes.UpdateMarket{
  1970  					Changes: &protoTypes.UpdateMarketConfiguration{
  1971  						RiskParameters: &protoTypes.UpdateMarketConfiguration_Simple{},
  1972  					},
  1973  				},
  1974  			},
  1975  		},
  1976  	})
  1977  
  1978  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.risk_parameters.simple"), commands.ErrIsRequired)
  1979  }
  1980  
  1981  func testUpdateSimpleRiskParametersChangeSubmissionWithSimpleRiskParametersSucceeds(t *testing.T) {
  1982  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  1983  		Terms: &protoTypes.ProposalTerms{
  1984  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  1985  				UpdateMarket: &protoTypes.UpdateMarket{
  1986  					Changes: &protoTypes.UpdateMarketConfiguration{
  1987  						RiskParameters: &protoTypes.UpdateMarketConfiguration_Simple{
  1988  							Simple: &protoTypes.SimpleModelParams{},
  1989  						},
  1990  					},
  1991  				},
  1992  			},
  1993  		},
  1994  	})
  1995  
  1996  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.risk_parameters.simple"), commands.ErrIsRequired)
  1997  }
  1998  
  1999  func testUpdateSimpleRiskParametersChangeSubmissionWithPositiveMinMoveDownFails(t *testing.T) {
  2000  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2001  		Terms: &protoTypes.ProposalTerms{
  2002  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  2003  				UpdateMarket: &protoTypes.UpdateMarket{
  2004  					Changes: &protoTypes.UpdateMarketConfiguration{
  2005  						RiskParameters: &protoTypes.UpdateMarketConfiguration_Simple{
  2006  							Simple: &protoTypes.SimpleModelParams{
  2007  								MinMoveDown: 1,
  2008  							},
  2009  						},
  2010  					},
  2011  				},
  2012  			},
  2013  		},
  2014  	})
  2015  
  2016  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.risk_parameters.simple.min_move_down"), commands.ErrMustBeNegativeOrZero)
  2017  }
  2018  
  2019  func testUpdateSimpleRiskParametersChangeSubmissionWithNonPositiveMinMoveDownSucceeds(t *testing.T) {
  2020  	testCases := []struct {
  2021  		msg   string
  2022  		value float64
  2023  	}{
  2024  		{
  2025  			msg:   "with min move down of 0",
  2026  			value: 0,
  2027  		}, {
  2028  			msg:   "with min move down of -1",
  2029  			value: -1,
  2030  		},
  2031  	}
  2032  	for _, tc := range testCases {
  2033  		t.Run(tc.msg, func(t *testing.T) {
  2034  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2035  				Terms: &protoTypes.ProposalTerms{
  2036  					Change: &protoTypes.ProposalTerms_UpdateMarket{
  2037  						UpdateMarket: &protoTypes.UpdateMarket{
  2038  							Changes: &protoTypes.UpdateMarketConfiguration{
  2039  								RiskParameters: &protoTypes.UpdateMarketConfiguration_Simple{
  2040  									Simple: &protoTypes.SimpleModelParams{
  2041  										MinMoveDown: tc.value,
  2042  									},
  2043  								},
  2044  							},
  2045  						},
  2046  					},
  2047  				},
  2048  			})
  2049  
  2050  			assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.risk_parameters.simple.min_move_down"), commands.ErrMustBeNegativeOrZero)
  2051  		})
  2052  	}
  2053  }
  2054  
  2055  func testUpdateSimpleRiskParametersChangeSubmissionWithNegativeMaxMoveUpFails(t *testing.T) {
  2056  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2057  		Terms: &protoTypes.ProposalTerms{
  2058  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  2059  				UpdateMarket: &protoTypes.UpdateMarket{
  2060  					Changes: &protoTypes.UpdateMarketConfiguration{
  2061  						RiskParameters: &protoTypes.UpdateMarketConfiguration_Simple{
  2062  							Simple: &protoTypes.SimpleModelParams{
  2063  								MaxMoveUp: -1,
  2064  							},
  2065  						},
  2066  					},
  2067  				},
  2068  			},
  2069  		},
  2070  	})
  2071  
  2072  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.risk_parameters.simple.max_move_up"), commands.ErrMustBePositiveOrZero)
  2073  }
  2074  
  2075  func testUpdateSimpleRiskParametersChangeSubmissionWithNonNegativeMaxMoveUpSucceeds(t *testing.T) {
  2076  	testCases := []struct {
  2077  		msg   string
  2078  		value float64
  2079  	}{
  2080  		{
  2081  			msg:   "with max move up of 0",
  2082  			value: 0,
  2083  		}, {
  2084  			msg:   "with max move up of 1",
  2085  			value: 1,
  2086  		},
  2087  	}
  2088  	for _, tc := range testCases {
  2089  		t.Run(tc.msg, func(t *testing.T) {
  2090  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2091  				Terms: &protoTypes.ProposalTerms{
  2092  					Change: &protoTypes.ProposalTerms_UpdateMarket{
  2093  						UpdateMarket: &protoTypes.UpdateMarket{
  2094  							Changes: &protoTypes.UpdateMarketConfiguration{
  2095  								RiskParameters: &protoTypes.UpdateMarketConfiguration_Simple{
  2096  									Simple: &protoTypes.SimpleModelParams{
  2097  										MaxMoveUp: tc.value,
  2098  									},
  2099  								},
  2100  							},
  2101  						},
  2102  					},
  2103  				},
  2104  			})
  2105  
  2106  			assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.risk_parameters.simple.max_move_up"), commands.ErrMustBePositiveOrZero)
  2107  		})
  2108  	}
  2109  }
  2110  
  2111  func testUpdateSimpleRiskParametersChangeSubmissionWithWrongProbabilityOfTradingFails(t *testing.T) {
  2112  	testCases := []struct {
  2113  		msg   string
  2114  		value float64
  2115  	}{
  2116  		{
  2117  			msg:   "with probability of trading of -1",
  2118  			value: -1,
  2119  		}, {
  2120  			msg:   "with probability of trading of 2",
  2121  			value: 2,
  2122  		},
  2123  	}
  2124  	for _, tc := range testCases {
  2125  		t.Run(tc.msg, func(t *testing.T) {
  2126  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2127  				Terms: &protoTypes.ProposalTerms{
  2128  					Change: &protoTypes.ProposalTerms_UpdateMarket{
  2129  						UpdateMarket: &protoTypes.UpdateMarket{
  2130  							Changes: &protoTypes.UpdateMarketConfiguration{
  2131  								RiskParameters: &protoTypes.UpdateMarketConfiguration_Simple{
  2132  									Simple: &protoTypes.SimpleModelParams{
  2133  										ProbabilityOfTrading: tc.value,
  2134  									},
  2135  								},
  2136  							},
  2137  						},
  2138  					},
  2139  				},
  2140  			})
  2141  
  2142  			assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.risk_parameters.simple.probability_of_trading"),
  2143  				errors.New("should be between 0 (inclusive) and 1 (inclusive)"))
  2144  		})
  2145  	}
  2146  }
  2147  
  2148  func testUpdateSimpleRiskParametersChangeSubmissionWithRightProbabilityOfTradingSucceeds(t *testing.T) {
  2149  	testCases := []struct {
  2150  		msg   string
  2151  		value float64
  2152  	}{
  2153  		{
  2154  			msg:   "with probability of trading of 0",
  2155  			value: 0,
  2156  		}, {
  2157  			msg:   "with probability of trading of 1",
  2158  			value: 1,
  2159  		}, {
  2160  			msg:   "with probability of trading of 0.5",
  2161  			value: 0.5,
  2162  		},
  2163  	}
  2164  	for _, tc := range testCases {
  2165  		t.Run(tc.msg, func(t *testing.T) {
  2166  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2167  				Terms: &protoTypes.ProposalTerms{
  2168  					Change: &protoTypes.ProposalTerms_UpdateMarket{
  2169  						UpdateMarket: &protoTypes.UpdateMarket{
  2170  							Changes: &protoTypes.UpdateMarketConfiguration{
  2171  								RiskParameters: &protoTypes.UpdateMarketConfiguration_Simple{
  2172  									Simple: &protoTypes.SimpleModelParams{
  2173  										ProbabilityOfTrading: tc.value,
  2174  									},
  2175  								},
  2176  							},
  2177  						},
  2178  					},
  2179  				},
  2180  			})
  2181  
  2182  			assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.risk_parameters.simple.probability_of_trading"),
  2183  				errors.New("should be between 0 (inclusive) and 1 (inclusive)"))
  2184  		})
  2185  	}
  2186  }
  2187  
  2188  func testUpdateLogNormalRiskParametersChangeSubmissionWithOverrides(t *testing.T) {
  2189  	cases := []struct {
  2190  		desc     string
  2191  		get      string
  2192  		override *vegapb.RiskFactorOverride
  2193  		err      string
  2194  	}{
  2195  		{
  2196  			desc:     "no override is valid",
  2197  			get:      "proposal_submission.terms.change.update_market.changes.risk_parameters.log_normal.risk_factor_override",
  2198  			override: nil,
  2199  			err:      "",
  2200  		},
  2201  		{
  2202  			desc:     "non nil, but with empty short",
  2203  			get:      "proposal_submission.terms.change.update_market.changes.risk_parameters.log_normal.risk_factor_override.short",
  2204  			override: &vegapb.RiskFactorOverride{},
  2205  			err:      "is required",
  2206  		},
  2207  		{
  2208  			desc: "non nil, but with bad value short",
  2209  			get:  "proposal_submission.terms.change.update_market.changes.risk_parameters.log_normal.risk_factor_override.short",
  2210  			override: &vegapb.RiskFactorOverride{
  2211  				Short: "asd",
  2212  			},
  2213  			err: "is not a valid number",
  2214  		},
  2215  		{
  2216  			desc: "non nil, but with negative short",
  2217  			get:  "proposal_submission.terms.change.update_market.changes.risk_parameters.log_normal.risk_factor_override.short",
  2218  			override: &vegapb.RiskFactorOverride{
  2219  				Short: "-1",
  2220  			},
  2221  			err: "must be positive",
  2222  		},
  2223  		{
  2224  			desc: "non nil, but with 0 short",
  2225  			get:  "proposal_submission.terms.change.update_market.changes.risk_parameters.log_normal.risk_factor_override.short",
  2226  			override: &vegapb.RiskFactorOverride{
  2227  				Short: "0",
  2228  			},
  2229  			err: "must be positive",
  2230  		},
  2231  		{
  2232  			desc: "non nil, but with empty long",
  2233  			get:  "proposal_submission.terms.change.update_market.changes.risk_parameters.log_normal.risk_factor_override.long",
  2234  			override: &vegapb.RiskFactorOverride{
  2235  				Short: "0.1",
  2236  			},
  2237  			err: "is required",
  2238  		},
  2239  		{
  2240  			desc: "non nil, but with bad value long",
  2241  			get:  "proposal_submission.terms.change.update_market.changes.risk_parameters.log_normal.risk_factor_override.long",
  2242  			override: &vegapb.RiskFactorOverride{
  2243  				Short: "0.1",
  2244  				Long:  "asd",
  2245  			},
  2246  			err: "is not a valid number",
  2247  		},
  2248  		{
  2249  			desc: "non nil, but with negative long",
  2250  			get:  "proposal_submission.terms.change.update_market.changes.risk_parameters.log_normal.risk_factor_override.long",
  2251  			override: &vegapb.RiskFactorOverride{
  2252  				Short: "0.1",
  2253  				Long:  "-1",
  2254  			},
  2255  			err: "must be positive",
  2256  		},
  2257  		{
  2258  			desc: "non nil, but with 0 long",
  2259  			get:  "proposal_submission.terms.change.update_market.changes.risk_parameters.log_normal.risk_factor_override.long",
  2260  			override: &vegapb.RiskFactorOverride{
  2261  				Short: "0.1",
  2262  				Long:  "0",
  2263  			},
  2264  			err: "must be positive",
  2265  		},
  2266  		{
  2267  			desc: "both valid",
  2268  			get:  "proposal_submission.terms.change.update_market.changes.risk_parameters.log_normal.risk_factor_override",
  2269  			override: &vegapb.RiskFactorOverride{
  2270  				Short: "0.1",
  2271  				Long:  "0.1",
  2272  			},
  2273  			err: "",
  2274  		},
  2275  	}
  2276  
  2277  	for _, c := range cases {
  2278  		err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2279  			Terms: &vegapb.ProposalTerms{
  2280  				Change: &vegapb.ProposalTerms_UpdateMarket{
  2281  					UpdateMarket: &vegapb.UpdateMarket{
  2282  						Changes: &vegapb.UpdateMarketConfiguration{
  2283  							RiskParameters: &vegapb.UpdateMarketConfiguration_LogNormal{
  2284  								LogNormal: &vegapb.LogNormalRiskModel{
  2285  									RiskAversionParameter: 0.1,
  2286  									Tau:                   1,
  2287  									Params: &vegapb.LogNormalModelParams{
  2288  										Mu:    0,
  2289  										Sigma: 0.1,
  2290  										R:     0,
  2291  									},
  2292  									RiskFactorOverride: c.override,
  2293  								},
  2294  							},
  2295  						},
  2296  					},
  2297  				},
  2298  			},
  2299  		})
  2300  
  2301  		if len(c.err) <= 0 {
  2302  			// no error
  2303  			assert.Len(t, err.Get(c.get), 0, c.desc)
  2304  			continue
  2305  		}
  2306  
  2307  		assert.Contains(t, err.Get(c.get), errors.New(c.err), "test: %v, err: %v", c.desc, err)
  2308  	}
  2309  }
  2310  
  2311  func testUpdateLogNormalRiskParametersChangeSubmissionWithoutLogNormalRiskParametersFails(t *testing.T) {
  2312  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2313  		Terms: &protoTypes.ProposalTerms{
  2314  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  2315  				UpdateMarket: &protoTypes.UpdateMarket{
  2316  					Changes: &protoTypes.UpdateMarketConfiguration{
  2317  						RiskParameters: &protoTypes.UpdateMarketConfiguration_LogNormal{},
  2318  					},
  2319  				},
  2320  			},
  2321  		},
  2322  	})
  2323  
  2324  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.risk_parameters.log_normal"), commands.ErrIsRequired)
  2325  }
  2326  
  2327  func testUpdateLogNormalRiskParametersChangeSubmissionWithLogNormalRiskParametersSucceeds(t *testing.T) {
  2328  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2329  		Terms: &protoTypes.ProposalTerms{
  2330  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  2331  				UpdateMarket: &protoTypes.UpdateMarket{
  2332  					Changes: &protoTypes.UpdateMarketConfiguration{
  2333  						RiskParameters: &protoTypes.UpdateMarketConfiguration_LogNormal{
  2334  							LogNormal: &protoTypes.LogNormalRiskModel{
  2335  								RiskAversionParameter: 1,
  2336  								Tau:                   2,
  2337  								Params: &protoTypes.LogNormalModelParams{
  2338  									Mu:    0,
  2339  									Sigma: 0.1,
  2340  									R:     0,
  2341  								},
  2342  							},
  2343  						},
  2344  					},
  2345  				},
  2346  			},
  2347  		},
  2348  	})
  2349  
  2350  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.risk_parameters.log_normal"), commands.ErrIsRequired)
  2351  }
  2352  
  2353  func testUpdateLogNormalRiskParametersChangeSubmissionWithoutParamsFails(t *testing.T) {
  2354  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2355  		Terms: &protoTypes.ProposalTerms{
  2356  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  2357  				UpdateMarket: &protoTypes.UpdateMarket{
  2358  					Changes: &protoTypes.UpdateMarketConfiguration{
  2359  						RiskParameters: &protoTypes.UpdateMarketConfiguration_LogNormal{
  2360  							LogNormal: &protoTypes.LogNormalRiskModel{},
  2361  						},
  2362  					},
  2363  				},
  2364  			},
  2365  		},
  2366  	})
  2367  
  2368  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.risk_parameters.log_normal.params"), commands.ErrIsRequired)
  2369  }
  2370  
  2371  func testUpdateLogNormalRiskParametersChangeSubmissionInvalidRiskAversion(t *testing.T) {
  2372  	cZero := &commandspb.ProposalSubmission{
  2373  		Terms: &protoTypes.ProposalTerms{
  2374  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  2375  				UpdateMarket: &protoTypes.UpdateMarket{
  2376  					Changes: &protoTypes.UpdateMarketConfiguration{
  2377  						RiskParameters: &protoTypes.UpdateMarketConfiguration_LogNormal{
  2378  							LogNormal: &protoTypes.LogNormalRiskModel{
  2379  								RiskAversionParameter: 0,
  2380  								Tau:                   2,
  2381  								Params: &protoTypes.LogNormalModelParams{
  2382  									Mu:    0,
  2383  									Sigma: 0.1,
  2384  									R:     0,
  2385  								},
  2386  							},
  2387  						},
  2388  					},
  2389  				},
  2390  			},
  2391  		},
  2392  	}
  2393  	err := checkProposalSubmission(cZero)
  2394  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.risk_parameters.log_normal.risk_aversion_parameter"), commands.ErrMustBePositive)
  2395  
  2396  	cNeg := &commandspb.ProposalSubmission{
  2397  		Terms: &protoTypes.ProposalTerms{
  2398  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  2399  				UpdateMarket: &protoTypes.UpdateMarket{
  2400  					Changes: &protoTypes.UpdateMarketConfiguration{
  2401  						RiskParameters: &protoTypes.UpdateMarketConfiguration_LogNormal{
  2402  							LogNormal: &protoTypes.LogNormalRiskModel{
  2403  								RiskAversionParameter: -0.1,
  2404  								Tau:                   2,
  2405  								Params: &protoTypes.LogNormalModelParams{
  2406  									Mu:    0,
  2407  									Sigma: 0.1,
  2408  									R:     0,
  2409  								},
  2410  							},
  2411  						},
  2412  					},
  2413  				},
  2414  			},
  2415  		},
  2416  	}
  2417  	err = checkProposalSubmission(cNeg)
  2418  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.risk_parameters.log_normal.risk_aversion_parameter"), commands.ErrMustBePositive)
  2419  }
  2420  
  2421  func testUpdateLogNormalRiskParametersChangeSubmissionInvalidTau(t *testing.T) {
  2422  	cZero := &commandspb.ProposalSubmission{
  2423  		Terms: &protoTypes.ProposalTerms{
  2424  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  2425  				UpdateMarket: &protoTypes.UpdateMarket{
  2426  					Changes: &protoTypes.UpdateMarketConfiguration{
  2427  						RiskParameters: &protoTypes.UpdateMarketConfiguration_LogNormal{
  2428  							LogNormal: &protoTypes.LogNormalRiskModel{
  2429  								RiskAversionParameter: 0.1,
  2430  								Tau:                   0,
  2431  								Params: &protoTypes.LogNormalModelParams{
  2432  									Mu:    0,
  2433  									Sigma: 0.1,
  2434  									R:     0,
  2435  								},
  2436  							},
  2437  						},
  2438  					},
  2439  				},
  2440  			},
  2441  		},
  2442  	}
  2443  	err := checkProposalSubmission(cZero)
  2444  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.risk_parameters.log_normal.tau"), commands.ErrMustBePositive)
  2445  
  2446  	cNeg := &commandspb.ProposalSubmission{
  2447  		Terms: &protoTypes.ProposalTerms{
  2448  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  2449  				UpdateMarket: &protoTypes.UpdateMarket{
  2450  					Changes: &protoTypes.UpdateMarketConfiguration{
  2451  						RiskParameters: &protoTypes.UpdateMarketConfiguration_LogNormal{
  2452  							LogNormal: &protoTypes.LogNormalRiskModel{
  2453  								RiskAversionParameter: 0.1,
  2454  								Tau:                   -0.2,
  2455  								Params: &protoTypes.LogNormalModelParams{
  2456  									Mu:    0,
  2457  									Sigma: 0.1,
  2458  									R:     0,
  2459  								},
  2460  							},
  2461  						},
  2462  					},
  2463  				},
  2464  			},
  2465  		},
  2466  	}
  2467  	err = checkProposalSubmission(cNeg)
  2468  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.risk_parameters.log_normal.tau"), commands.ErrMustBePositive)
  2469  }
  2470  
  2471  func testUpdateLogNormalRiskParametersChangeSubmissionInvalidMu(t *testing.T) {
  2472  	cNaN := &commandspb.ProposalSubmission{
  2473  		Terms: &protoTypes.ProposalTerms{
  2474  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  2475  				UpdateMarket: &protoTypes.UpdateMarket{
  2476  					Changes: &protoTypes.UpdateMarketConfiguration{
  2477  						RiskParameters: &protoTypes.UpdateMarketConfiguration_LogNormal{
  2478  							LogNormal: &protoTypes.LogNormalRiskModel{
  2479  								RiskAversionParameter: 0.1,
  2480  								Tau:                   0.2,
  2481  								Params: &protoTypes.LogNormalModelParams{
  2482  									Mu:    math.NaN(),
  2483  									Sigma: 0.1,
  2484  									R:     0,
  2485  								},
  2486  							},
  2487  						},
  2488  					},
  2489  				},
  2490  			},
  2491  		},
  2492  	}
  2493  	err := checkProposalSubmission(cNaN)
  2494  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.risk_parameters.log_normal.params.mu"), commands.ErrIsNotValidNumber)
  2495  }
  2496  
  2497  func testUpdateLogNormalRiskParametersChangeSubmissionInvalidR(t *testing.T) {
  2498  	cNaN := &commandspb.ProposalSubmission{
  2499  		Terms: &protoTypes.ProposalTerms{
  2500  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  2501  				UpdateMarket: &protoTypes.UpdateMarket{
  2502  					Changes: &protoTypes.UpdateMarketConfiguration{
  2503  						RiskParameters: &protoTypes.UpdateMarketConfiguration_LogNormal{
  2504  							LogNormal: &protoTypes.LogNormalRiskModel{
  2505  								RiskAversionParameter: 0.1,
  2506  								Tau:                   0.2,
  2507  								Params: &protoTypes.LogNormalModelParams{
  2508  									Mu:    0.2,
  2509  									Sigma: 0.1,
  2510  									R:     math.NaN(),
  2511  								},
  2512  							},
  2513  						},
  2514  					},
  2515  				},
  2516  			},
  2517  		},
  2518  	}
  2519  	err := checkProposalSubmission(cNaN)
  2520  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.risk_parameters.log_normal.params.r"), commands.ErrIsNotValidNumber)
  2521  }
  2522  
  2523  func testUpdateLogNormalRiskParametersChangeSubmissionInvalidSigma(t *testing.T) {
  2524  	cNaN := &commandspb.ProposalSubmission{
  2525  		Terms: &protoTypes.ProposalTerms{
  2526  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  2527  				UpdateMarket: &protoTypes.UpdateMarket{
  2528  					Changes: &protoTypes.UpdateMarketConfiguration{
  2529  						RiskParameters: &protoTypes.UpdateMarketConfiguration_LogNormal{
  2530  							LogNormal: &protoTypes.LogNormalRiskModel{
  2531  								RiskAversionParameter: 0.1,
  2532  								Tau:                   0.2,
  2533  								Params: &protoTypes.LogNormalModelParams{
  2534  									Mu:    0.2,
  2535  									Sigma: math.NaN(),
  2536  									R:     0,
  2537  								},
  2538  							},
  2539  						},
  2540  					},
  2541  				},
  2542  			},
  2543  		},
  2544  	}
  2545  	err := checkProposalSubmission(cNaN)
  2546  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.risk_parameters.log_normal.params.sigma"), commands.ErrIsNotValidNumber)
  2547  
  2548  	cNeg := &commandspb.ProposalSubmission{
  2549  		Terms: &protoTypes.ProposalTerms{
  2550  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  2551  				UpdateMarket: &protoTypes.UpdateMarket{
  2552  					Changes: &protoTypes.UpdateMarketConfiguration{
  2553  						RiskParameters: &protoTypes.UpdateMarketConfiguration_LogNormal{
  2554  							LogNormal: &protoTypes.LogNormalRiskModel{
  2555  								RiskAversionParameter: 0.1,
  2556  								Tau:                   0.2,
  2557  								Params: &protoTypes.LogNormalModelParams{
  2558  									Mu:    0.2,
  2559  									Sigma: -0.1,
  2560  									R:     0,
  2561  								},
  2562  							},
  2563  						},
  2564  					},
  2565  				},
  2566  			},
  2567  		},
  2568  	}
  2569  	err = checkProposalSubmission(cNeg)
  2570  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.risk_parameters.log_normal.params.sigma"), commands.ErrMustBePositive)
  2571  
  2572  	c0 := &commandspb.ProposalSubmission{
  2573  		Terms: &protoTypes.ProposalTerms{
  2574  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  2575  				UpdateMarket: &protoTypes.UpdateMarket{
  2576  					Changes: &protoTypes.UpdateMarketConfiguration{
  2577  						RiskParameters: &protoTypes.UpdateMarketConfiguration_LogNormal{
  2578  							LogNormal: &protoTypes.LogNormalRiskModel{
  2579  								RiskAversionParameter: 0.1,
  2580  								Tau:                   0.2,
  2581  								Params: &protoTypes.LogNormalModelParams{
  2582  									Mu:    0.2,
  2583  									Sigma: 0,
  2584  									R:     0,
  2585  								},
  2586  							},
  2587  						},
  2588  					},
  2589  				},
  2590  			},
  2591  		},
  2592  	}
  2593  	err = checkProposalSubmission(c0)
  2594  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.risk_parameters.log_normal.params.sigma"), commands.ErrMustBePositive)
  2595  }
  2596  
  2597  func testUpdateMarketSubmissionWithTooLongReferenceFails(t *testing.T) {
  2598  	ref := make([]byte, 101)
  2599  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2600  		Reference: string(ref),
  2601  	})
  2602  	assert.Contains(t, err.Get("proposal_submission.reference"), commands.ErrReferenceTooLong)
  2603  }
  2604  
  2605  func testUpdateMarketFutureMarketSubmissionWithInternalTimestampForTradingTerminationNoSignersSucceeds(t *testing.T) {
  2606  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2607  		Terms: &protoTypes.ProposalTerms{
  2608  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  2609  				UpdateMarket: &protoTypes.UpdateMarket{
  2610  					Changes: &protoTypes.UpdateMarketConfiguration{
  2611  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  2612  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  2613  								Future: &protoTypes.UpdateFutureProduct{
  2614  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  2615  										vegapb.DataSourceContentTypeInternalTimeTermination,
  2616  									).SetOracleConfig(
  2617  										&vegapb.DataSourceDefinitionExternal_Oracle{
  2618  											Oracle: &vegapb.DataSourceSpecConfiguration{
  2619  												Signers: []*datapb.Signer{},
  2620  												Filters: []*datapb.Filter{
  2621  													{
  2622  														Conditions: []*datapb.Condition{
  2623  															{
  2624  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  2625  																Value:    fmt.Sprintf("%d", time.Now().Add(time.Hour*24*365).UnixNano()),
  2626  															},
  2627  														},
  2628  													},
  2629  												},
  2630  											},
  2631  										},
  2632  									),
  2633  								},
  2634  							},
  2635  						},
  2636  					},
  2637  				},
  2638  			},
  2639  		},
  2640  	})
  2641  
  2642  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_trading_termination.external.oracle.signers"), commands.ErrIsRequired)
  2643  }
  2644  
  2645  func testUpdateMarketFutureMarketSubmissionWithInvalidOperatorInternalSourceForTradingTerminationNoSignersFails(t *testing.T) {
  2646  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2647  		Terms: &protoTypes.ProposalTerms{
  2648  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  2649  				UpdateMarket: &protoTypes.UpdateMarket{
  2650  					Changes: &protoTypes.UpdateMarketConfiguration{
  2651  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  2652  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  2653  								Future: &protoTypes.UpdateFutureProduct{
  2654  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  2655  										vegapb.DataSourceContentTypeInternalTimeTermination,
  2656  									).SetOracleConfig(
  2657  										&vegapb.DataSourceDefinitionExternal_Oracle{
  2658  											Oracle: &vegapb.DataSourceSpecConfiguration{
  2659  												Signers: []*datapb.Signer{},
  2660  												Filters: []*datapb.Filter{
  2661  													{
  2662  														Conditions: []*datapb.Condition{
  2663  															{
  2664  																Operator: datapb.Condition_OPERATOR_UNSPECIFIED,
  2665  																Value:    "value 1",
  2666  															},
  2667  														},
  2668  													},
  2669  												},
  2670  											},
  2671  										},
  2672  									),
  2673  								},
  2674  							},
  2675  						},
  2676  					},
  2677  				},
  2678  			},
  2679  		},
  2680  	})
  2681  
  2682  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_trading_termination.internal.time.conditions"), commands.ErrIsRequired)
  2683  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_trading_termination.external.oracle.signers"), commands.ErrIsRequired)
  2684  
  2685  	err = checkProposalSubmission(&commandspb.ProposalSubmission{
  2686  		Terms: &protoTypes.ProposalTerms{
  2687  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  2688  				UpdateMarket: &protoTypes.UpdateMarket{
  2689  					Changes: &protoTypes.UpdateMarketConfiguration{
  2690  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  2691  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  2692  								Future: &protoTypes.UpdateFutureProduct{
  2693  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  2694  										vegapb.DataSourceContentTypeInternalTimeTermination,
  2695  									).SetTimeTriggerConditionConfig(
  2696  										[]*datapb.Condition{
  2697  											{
  2698  												Operator: datapb.Condition_OPERATOR_UNSPECIFIED,
  2699  												Value:    "value 1",
  2700  											},
  2701  										},
  2702  									),
  2703  								},
  2704  							},
  2705  						},
  2706  					},
  2707  				},
  2708  			},
  2709  		},
  2710  	})
  2711  
  2712  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_trading_termination.internal.time.conditions.0.operator"), commands.ErrIsRequired)
  2713  }
  2714  
  2715  func testUpdateMarketFutureMarketSubmissionWithExternalSourceForTradingTerminationNoSignersFails(t *testing.T) {
  2716  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2717  		Terms: &protoTypes.ProposalTerms{
  2718  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  2719  				UpdateMarket: &protoTypes.UpdateMarket{
  2720  					Changes: &protoTypes.UpdateMarketConfiguration{
  2721  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  2722  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  2723  								Future: &protoTypes.UpdateFutureProduct{
  2724  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  2725  										vegapb.DataSourceContentTypeOracle,
  2726  									).SetOracleConfig(
  2727  										&vegapb.DataSourceDefinitionExternal_Oracle{
  2728  											Oracle: &vegapb.DataSourceSpecConfiguration{
  2729  												Signers: []*datapb.Signer{},
  2730  												Filters: []*datapb.Filter{
  2731  													{
  2732  														Key: &datapb.PropertyKey{
  2733  															Name: "trading.terminated",
  2734  															Type: datapb.PropertyKey_TYPE_BOOLEAN,
  2735  														},
  2736  														Conditions: []*datapb.Condition{},
  2737  													},
  2738  												},
  2739  											},
  2740  										},
  2741  									),
  2742  								},
  2743  							},
  2744  						},
  2745  					},
  2746  				},
  2747  			},
  2748  		},
  2749  	})
  2750  
  2751  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_trading_termination.external.oracle.signers"), commands.ErrIsRequired)
  2752  }
  2753  
  2754  func testUpdateMarketFutureMarketSubmissionWithExternalSourceForTradingTerminationBuiltInKeyNoSignersFails(t *testing.T) {
  2755  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2756  		Terms: &protoTypes.ProposalTerms{
  2757  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  2758  				UpdateMarket: &protoTypes.UpdateMarket{
  2759  					Changes: &protoTypes.UpdateMarketConfiguration{
  2760  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  2761  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  2762  								Future: &protoTypes.UpdateFutureProduct{
  2763  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  2764  										vegapb.DataSourceContentTypeOracle,
  2765  									).SetOracleConfig(
  2766  										&vegapb.DataSourceDefinitionExternal_Oracle{
  2767  											Oracle: &vegapb.DataSourceSpecConfiguration{
  2768  												Signers: []*datapb.Signer{},
  2769  												Filters: []*datapb.Filter{
  2770  													{
  2771  														Key: &datapb.PropertyKey{
  2772  															Name: "vegaprotocol.builtin.timestamp",
  2773  															Type: datapb.PropertyKey_TYPE_TIMESTAMP,
  2774  														},
  2775  														Conditions: []*datapb.Condition{
  2776  															{
  2777  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  2778  																Value:    fmt.Sprintf("%d", time.Now().Add(time.Hour*24*365).UnixNano()),
  2779  															},
  2780  														},
  2781  													},
  2782  												},
  2783  											},
  2784  										},
  2785  									),
  2786  								},
  2787  							},
  2788  						},
  2789  					},
  2790  				},
  2791  			},
  2792  		},
  2793  	})
  2794  
  2795  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_trading_termination.external.oracle.signers"), commands.ErrIsRequired)
  2796  }
  2797  
  2798  func testUpdateMarketFutureMarketSubmissionWithExternalSourceForTradingSettlementBuiltInKeyNoSignersFails(t *testing.T) {
  2799  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2800  		Terms: &protoTypes.ProposalTerms{
  2801  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  2802  				UpdateMarket: &protoTypes.UpdateMarket{
  2803  					Changes: &protoTypes.UpdateMarketConfiguration{
  2804  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  2805  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  2806  								Future: &protoTypes.UpdateFutureProduct{
  2807  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  2808  										vegapb.DataSourceContentTypeOracle,
  2809  									).SetOracleConfig(
  2810  										&vegapb.DataSourceDefinitionExternal_Oracle{
  2811  											Oracle: &vegapb.DataSourceSpecConfiguration{
  2812  												Signers: []*datapb.Signer{},
  2813  												Filters: []*datapb.Filter{
  2814  													{
  2815  														Key: &datapb.PropertyKey{
  2816  															Name: "vegaprotocol.builtin.timestamp",
  2817  															Type: datapb.PropertyKey_TYPE_TIMESTAMP,
  2818  														},
  2819  														Conditions: []*datapb.Condition{
  2820  															{
  2821  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  2822  																Value:    fmt.Sprintf("%d", time.Now().Add(time.Hour*24*365).UnixNano()),
  2823  															},
  2824  														},
  2825  													},
  2826  												},
  2827  											},
  2828  										},
  2829  									),
  2830  								},
  2831  							},
  2832  						},
  2833  					},
  2834  				},
  2835  			},
  2836  		},
  2837  	})
  2838  
  2839  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data"), commands.ErrIsNotValid)
  2840  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers"), commands.ErrIsRequired)
  2841  }
  2842  
  2843  func testUpdateMarketFutureSubmissionWithExternalTradingSettlementTimestampKeySucceeds(t *testing.T) {
  2844  	pubKeys := []*dstypes.Signer{
  2845  		dstypes.CreateSignerFromString("0xDEADBEEF", dstypes.SignerTypePubKey),
  2846  		dstypes.CreateSignerFromString("", dstypes.SignerTypePubKey),
  2847  	}
  2848  
  2849  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2850  		Terms: &protoTypes.ProposalTerms{
  2851  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  2852  				UpdateMarket: &protoTypes.UpdateMarket{
  2853  					Changes: &protoTypes.UpdateMarketConfiguration{
  2854  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  2855  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  2856  								Future: &protoTypes.UpdateFutureProduct{
  2857  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  2858  										vegapb.DataSourceContentTypeOracle,
  2859  									).SetOracleConfig(
  2860  										&vegapb.DataSourceDefinitionExternal_Oracle{
  2861  											Oracle: &vegapb.DataSourceSpecConfiguration{
  2862  												Signers: dstypes.SignersIntoProto(pubKeys),
  2863  												Filters: []*datapb.Filter{
  2864  													{
  2865  														Key: &datapb.PropertyKey{
  2866  															Name: "price.BTC.value",
  2867  															Type: datapb.PropertyKey_TYPE_INTEGER,
  2868  														},
  2869  														Conditions: []*datapb.Condition{
  2870  															{
  2871  																Operator: datapb.Condition_OPERATOR_EQUALS,
  2872  																Value:    "15",
  2873  															},
  2874  														},
  2875  													},
  2876  													{
  2877  														Key: &datapb.PropertyKey{
  2878  															Name: "price.BTC.timestamp",
  2879  															Type: datapb.PropertyKey_TYPE_TIMESTAMP,
  2880  														},
  2881  														Conditions: []*datapb.Condition{
  2882  															{
  2883  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  2884  																Value:    fmt.Sprintf("%d", time.Now().Add(time.Hour*24*365).UnixNano()),
  2885  															},
  2886  														},
  2887  													},
  2888  												},
  2889  											},
  2890  										},
  2891  									),
  2892  								},
  2893  							},
  2894  						},
  2895  					},
  2896  				},
  2897  			},
  2898  		},
  2899  	})
  2900  
  2901  	assert.NotContains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.future.data_source_spec_for_settlement_data"), commands.ErrIsNotValid)
  2902  	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)
  2903  }
  2904  
  2905  func testUpdateMarketWithMarketIDSucceeds(t *testing.T) {
  2906  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2907  		Terms: &protoTypes.ProposalTerms{
  2908  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  2909  				UpdateMarket: &protoTypes.UpdateMarket{
  2910  					MarketId: "12345",
  2911  				},
  2912  			},
  2913  		},
  2914  	})
  2915  
  2916  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.market_id"), commands.ErrIsRequired)
  2917  }
  2918  
  2919  func testUpdateMarketWithoutMarketIDFails(t *testing.T) {
  2920  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2921  		Terms: &protoTypes.ProposalTerms{
  2922  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  2923  				UpdateMarket: &protoTypes.UpdateMarket{},
  2924  			},
  2925  		},
  2926  	})
  2927  
  2928  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.market_id"), commands.ErrIsRequired)
  2929  }
  2930  
  2931  func tesUpdateMarketChangeSubmissionWithSlippageFactorBananaFails(t *testing.T) {
  2932  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2933  		Terms: &protoTypes.ProposalTerms{
  2934  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  2935  				UpdateMarket: &protoTypes.UpdateMarket{
  2936  					Changes: &protoTypes.UpdateMarketConfiguration{
  2937  						LinearSlippageFactor: "banana",
  2938  					},
  2939  				},
  2940  			},
  2941  		},
  2942  	})
  2943  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.linear_slippage_factor"), commands.ErrIsNotValidNumber)
  2944  }
  2945  
  2946  func testUpdateMarketChangeSubmissionWithSlippageFactorNegativeFails(t *testing.T) {
  2947  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2948  		Terms: &protoTypes.ProposalTerms{
  2949  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  2950  				UpdateMarket: &protoTypes.UpdateMarket{
  2951  					Changes: &protoTypes.UpdateMarketConfiguration{
  2952  						LinearSlippageFactor: "-0.1",
  2953  					},
  2954  				},
  2955  			},
  2956  		},
  2957  	})
  2958  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.linear_slippage_factor"), commands.ErrMustBePositiveOrZero)
  2959  }
  2960  
  2961  func testUpdateMarketChangeSubmissionWithSlippageFactorTooLargeFails(t *testing.T) {
  2962  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2963  		Terms: &protoTypes.ProposalTerms{
  2964  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  2965  				UpdateMarket: &protoTypes.UpdateMarket{
  2966  					Changes: &protoTypes.UpdateMarketConfiguration{
  2967  						LinearSlippageFactor: "1000000.000001",
  2968  					},
  2969  				},
  2970  			},
  2971  		},
  2972  	})
  2973  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.linear_slippage_factor"), commands.ErrMustBeAtMost1M)
  2974  }
  2975  
  2976  func testUpdateNewMarketChangeSubmissionWithEmptySlippageFactorPasses(t *testing.T) {
  2977  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2978  		Terms: &protoTypes.ProposalTerms{
  2979  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  2980  				UpdateMarket: &protoTypes.UpdateMarket{
  2981  					Changes: &protoTypes.UpdateMarketConfiguration{},
  2982  				},
  2983  			},
  2984  		},
  2985  	})
  2986  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.linear_slippage_factor"), commands.ErrIsNotValidNumber)
  2987  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.quadratic_slippage_factor"), commands.ErrIsNotValidNumber)
  2988  }
  2989  
  2990  func testUpdateMarketWithExternalTradingTerminationBuiltInKeySucceeds(t *testing.T) {
  2991  	pubKey := []*dstypes.Signer{
  2992  		dstypes.CreateSignerFromString("bd069246503a57271375f1995c46e03db88c4e1a564077b33a9872f905650dc4", dstypes.SignerTypePubKey),
  2993  	}
  2994  
  2995  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  2996  		Terms: &protoTypes.ProposalTerms{
  2997  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  2998  				UpdateMarket: &protoTypes.UpdateMarket{
  2999  					Changes: &protoTypes.UpdateMarketConfiguration{
  3000  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  3001  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  3002  								Future: &protoTypes.UpdateFutureProduct{
  3003  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  3004  										vegapb.DataSourceContentTypeOracle,
  3005  									).SetOracleConfig(
  3006  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3007  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3008  												Signers: dstypes.SignersIntoProto(pubKey),
  3009  												Filters: []*datapb.Filter{
  3010  													{
  3011  														Key: &datapb.PropertyKey{
  3012  															Name: "prices.ETH.value",
  3013  															Type: datapb.PropertyKey_TYPE_INTEGER,
  3014  														},
  3015  														Conditions: []*datapb.Condition{
  3016  															{
  3017  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  3018  															},
  3019  														},
  3020  													},
  3021  												},
  3022  											},
  3023  										},
  3024  									),
  3025  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  3026  										vegapb.DataSourceContentTypeOracle,
  3027  									).SetOracleConfig(
  3028  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3029  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3030  												Signers: dstypes.SignersIntoProto(pubKey),
  3031  												Filters: []*datapb.Filter{
  3032  													{
  3033  														Key: &datapb.PropertyKey{
  3034  															Name: "vegaprotocol.builtin.timestamp",
  3035  															Type: datapb.PropertyKey_TYPE_TIMESTAMP,
  3036  														},
  3037  														Conditions: []*datapb.Condition{
  3038  															{
  3039  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  3040  																Value:    fmt.Sprintf("%d", time.Now().Add(time.Hour*24*365).UnixNano()),
  3041  															},
  3042  														},
  3043  													},
  3044  												},
  3045  											},
  3046  										},
  3047  									),
  3048  								},
  3049  							},
  3050  						},
  3051  					},
  3052  				},
  3053  			},
  3054  		},
  3055  	})
  3056  
  3057  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers"), commands.ErrIsRequired)
  3058  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_trading_termination.external.oracle.signers"), commands.ErrIsRequired)
  3059  }
  3060  
  3061  func testUpdateMarketWithExternalTradingTerminationNoSignerFails(t *testing.T) {
  3062  	pubKey := []*dstypes.Signer{
  3063  		dstypes.CreateSignerFromString("bd069246503a57271375f1995c46e03db88c4e1a564077b33a9872f905650dc4", dstypes.SignerTypePubKey),
  3064  	}
  3065  
  3066  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  3067  		Terms: &protoTypes.ProposalTerms{
  3068  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  3069  				UpdateMarket: &protoTypes.UpdateMarket{
  3070  					Changes: &protoTypes.UpdateMarketConfiguration{
  3071  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  3072  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  3073  								Future: &protoTypes.UpdateFutureProduct{
  3074  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  3075  										vegapb.DataSourceContentTypeOracle,
  3076  									).SetOracleConfig(
  3077  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3078  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3079  												Signers: dstypes.SignersIntoProto(pubKey),
  3080  												Filters: []*datapb.Filter{
  3081  													{
  3082  														Key: &datapb.PropertyKey{
  3083  															Name: "vegaprotocol.builtin.prices.ETH.value",
  3084  															Type: datapb.PropertyKey_TYPE_INTEGER,
  3085  														},
  3086  														Conditions: []*datapb.Condition{
  3087  															{
  3088  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  3089  															},
  3090  														},
  3091  													},
  3092  												},
  3093  											},
  3094  										},
  3095  									),
  3096  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  3097  										vegapb.DataSourceContentTypeOracle,
  3098  									).SetOracleConfig(
  3099  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3100  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3101  												Filters: []*datapb.Filter{
  3102  													{
  3103  														Key: &datapb.PropertyKey{
  3104  															Name: "trading.terminated",
  3105  															Type: datapb.PropertyKey_TYPE_BOOLEAN,
  3106  														},
  3107  														Conditions: []*datapb.Condition{},
  3108  													},
  3109  												},
  3110  											},
  3111  										},
  3112  									),
  3113  								},
  3114  							},
  3115  						},
  3116  					},
  3117  				},
  3118  			},
  3119  		},
  3120  	})
  3121  
  3122  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers"), commands.ErrIsRequired)
  3123  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_trading_termination.external.oracle.signers"), commands.ErrIsRequired)
  3124  }
  3125  
  3126  func testUpdateMarketWithInternalSettlementDataFails(t *testing.T) {
  3127  	pubKey := []*dstypes.Signer{
  3128  		dstypes.CreateSignerFromString("bd069246503a57271375f1995c46e03db88c4e1a564077b33a9872f905650dc4", dstypes.SignerTypePubKey),
  3129  	}
  3130  
  3131  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  3132  		Terms: &protoTypes.ProposalTerms{
  3133  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  3134  				UpdateMarket: &protoTypes.UpdateMarket{
  3135  					Changes: &protoTypes.UpdateMarketConfiguration{
  3136  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  3137  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  3138  								Future: &protoTypes.UpdateFutureProduct{
  3139  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  3140  										vegapb.DataSourceContentTypeInternalTimeTermination,
  3141  									).SetTimeTriggerConditionConfig(
  3142  										[]*datapb.Condition{
  3143  											{
  3144  												// It does not matter what conditions are set here
  3145  												Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  3146  											},
  3147  										},
  3148  									),
  3149  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  3150  										vegapb.DataSourceContentTypeOracle,
  3151  									).SetOracleConfig(
  3152  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3153  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3154  												Signers: dstypes.SignersIntoProto(pubKey),
  3155  												Filters: []*datapb.Filter{
  3156  													{
  3157  														Key: &datapb.PropertyKey{
  3158  															Name: "trading.terminated",
  3159  															Type: datapb.PropertyKey_TYPE_BOOLEAN,
  3160  														},
  3161  														Conditions: []*datapb.Condition{},
  3162  													},
  3163  												},
  3164  											},
  3165  										},
  3166  									),
  3167  								},
  3168  							},
  3169  						},
  3170  					},
  3171  				},
  3172  			},
  3173  		},
  3174  	})
  3175  
  3176  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data"), commands.ErrIsNotValid)
  3177  }
  3178  
  3179  func testUpdateMarketWithExternalSettlementDataNoSignerFails(t *testing.T) {
  3180  	pubKey := []*dstypes.Signer{
  3181  		dstypes.CreateSignerFromString("bd069246503a57271375f1995c46e03db88c4e1a564077b33a9872f905650dc4", dstypes.SignerTypePubKey),
  3182  	}
  3183  
  3184  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  3185  		Terms: &protoTypes.ProposalTerms{
  3186  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  3187  				UpdateMarket: &protoTypes.UpdateMarket{
  3188  					Changes: &protoTypes.UpdateMarketConfiguration{
  3189  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  3190  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  3191  								Future: &protoTypes.UpdateFutureProduct{
  3192  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  3193  										vegapb.DataSourceContentTypeOracle,
  3194  									).SetOracleConfig(
  3195  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3196  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3197  												Filters: []*datapb.Filter{
  3198  													{
  3199  														Key: &datapb.PropertyKey{
  3200  															Name: "vegaprotocol.builtin.prices.ETH.value",
  3201  															Type: datapb.PropertyKey_TYPE_INTEGER,
  3202  														},
  3203  														Conditions: []*datapb.Condition{
  3204  															{
  3205  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  3206  															},
  3207  														},
  3208  													},
  3209  												},
  3210  											},
  3211  										},
  3212  									),
  3213  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  3214  										vegapb.DataSourceContentTypeOracle,
  3215  									).SetOracleConfig(
  3216  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3217  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3218  												Signers: dstypes.SignersIntoProto(pubKey),
  3219  												Filters: []*datapb.Filter{
  3220  													{
  3221  														Key: &datapb.PropertyKey{
  3222  															Name: "trading.terminated",
  3223  															Type: datapb.PropertyKey_TYPE_BOOLEAN,
  3224  														},
  3225  														Conditions: []*datapb.Condition{},
  3226  													},
  3227  												},
  3228  											},
  3229  										},
  3230  									),
  3231  								},
  3232  							},
  3233  						},
  3234  					},
  3235  				},
  3236  			},
  3237  		},
  3238  	})
  3239  
  3240  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers"), commands.ErrIsRequired)
  3241  	assert.NotContains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_trading_termination.external.oracle.signers"), commands.ErrIsRequired)
  3242  }
  3243  
  3244  func testUpdateMarketWithExternalSettlementDataAndTerminationNoSignerFails(t *testing.T) {
  3245  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  3246  		Terms: &protoTypes.ProposalTerms{
  3247  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  3248  				UpdateMarket: &protoTypes.UpdateMarket{
  3249  					Changes: &protoTypes.UpdateMarketConfiguration{
  3250  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  3251  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  3252  								Future: &protoTypes.UpdateFutureProduct{
  3253  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  3254  										vegapb.DataSourceContentTypeOracle,
  3255  									).SetOracleConfig(
  3256  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3257  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3258  												Filters: []*datapb.Filter{
  3259  													{
  3260  														Key: &datapb.PropertyKey{
  3261  															Name: "vegaprotocol.builtin.prices.ETH.value",
  3262  															Type: datapb.PropertyKey_TYPE_INTEGER,
  3263  														},
  3264  														Conditions: []*datapb.Condition{
  3265  															{
  3266  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  3267  															},
  3268  														},
  3269  													},
  3270  												},
  3271  											},
  3272  										},
  3273  									),
  3274  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  3275  										vegapb.DataSourceContentTypeOracle,
  3276  									).SetOracleConfig(
  3277  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3278  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3279  												Filters: []*datapb.Filter{
  3280  													{
  3281  														Key: &datapb.PropertyKey{
  3282  															Name: "trading.terminated",
  3283  															Type: datapb.PropertyKey_TYPE_BOOLEAN,
  3284  														},
  3285  														Conditions: []*datapb.Condition{},
  3286  													},
  3287  												},
  3288  											},
  3289  										},
  3290  									),
  3291  								},
  3292  							},
  3293  						},
  3294  					},
  3295  				},
  3296  			},
  3297  		},
  3298  	})
  3299  
  3300  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers"), commands.ErrIsRequired)
  3301  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_trading_termination.external.oracle.signers"), commands.ErrIsRequired)
  3302  }
  3303  
  3304  func testUpdateMarketWithExternalSettlementDataAndTerminationEmptySignerFails(t *testing.T) {
  3305  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  3306  		Terms: &protoTypes.ProposalTerms{
  3307  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  3308  				UpdateMarket: &protoTypes.UpdateMarket{
  3309  					Changes: &protoTypes.UpdateMarketConfiguration{
  3310  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  3311  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  3312  								Future: &protoTypes.UpdateFutureProduct{
  3313  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  3314  										vegapb.DataSourceContentTypeOracle,
  3315  									).SetOracleConfig(
  3316  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3317  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3318  												Signers: []*datapb.Signer{},
  3319  												Filters: []*datapb.Filter{
  3320  													{
  3321  														Key: &datapb.PropertyKey{
  3322  															Name: "vegaprotocol.builtin.prices.ETH.value",
  3323  															Type: datapb.PropertyKey_TYPE_INTEGER,
  3324  														},
  3325  														Conditions: []*datapb.Condition{
  3326  															{
  3327  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  3328  															},
  3329  														},
  3330  													},
  3331  												},
  3332  											},
  3333  										},
  3334  									),
  3335  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  3336  										vegapb.DataSourceContentTypeOracle,
  3337  									).SetOracleConfig(
  3338  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3339  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3340  												Signers: []*datapb.Signer{},
  3341  												Filters: []*datapb.Filter{
  3342  													{
  3343  														Key: &datapb.PropertyKey{
  3344  															Name: "trading.terminated",
  3345  															Type: datapb.PropertyKey_TYPE_BOOLEAN,
  3346  														},
  3347  														Conditions: []*datapb.Condition{},
  3348  													},
  3349  												},
  3350  											},
  3351  										},
  3352  									),
  3353  								},
  3354  							},
  3355  						},
  3356  					},
  3357  				},
  3358  			},
  3359  		},
  3360  	})
  3361  
  3362  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers"), commands.ErrIsRequired)
  3363  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_trading_termination.external.oracle.signers"), commands.ErrIsRequired)
  3364  }
  3365  
  3366  func testUpdateMarketWithExternalSettlementDataAndTerminationEmptyPubKeySignerFails(t *testing.T) {
  3367  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  3368  		Terms: &protoTypes.ProposalTerms{
  3369  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  3370  				UpdateMarket: &protoTypes.UpdateMarket{
  3371  					Changes: &protoTypes.UpdateMarketConfiguration{
  3372  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  3373  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  3374  								Future: &protoTypes.UpdateFutureProduct{
  3375  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  3376  										vegapb.DataSourceContentTypeOracle,
  3377  									).SetOracleConfig(
  3378  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3379  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3380  												Signers: []*datapb.Signer{
  3381  													{
  3382  														Signer: &datapb.Signer_PubKey{
  3383  															PubKey: &datapb.PubKey{
  3384  																Key: "",
  3385  															},
  3386  														},
  3387  													},
  3388  												},
  3389  												Filters: []*datapb.Filter{
  3390  													{
  3391  														Key: &datapb.PropertyKey{
  3392  															Name: "vegaprotocol.builtin.prices.ETH.value",
  3393  															Type: datapb.PropertyKey_TYPE_INTEGER,
  3394  														},
  3395  														Conditions: []*datapb.Condition{
  3396  															{
  3397  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  3398  															},
  3399  														},
  3400  													},
  3401  												},
  3402  											},
  3403  										},
  3404  									),
  3405  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  3406  										vegapb.DataSourceContentTypeOracle,
  3407  									).SetOracleConfig(
  3408  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3409  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3410  												Signers: []*datapb.Signer{
  3411  													{
  3412  														Signer: &datapb.Signer_PubKey{
  3413  															PubKey: &datapb.PubKey{},
  3414  														},
  3415  													},
  3416  												},
  3417  												Filters: []*datapb.Filter{
  3418  													{
  3419  														Key: &datapb.PropertyKey{
  3420  															Name: "trading.terminated",
  3421  															Type: datapb.PropertyKey_TYPE_BOOLEAN,
  3422  														},
  3423  														Conditions: []*datapb.Condition{},
  3424  													},
  3425  												},
  3426  											},
  3427  										},
  3428  									),
  3429  								},
  3430  							},
  3431  						},
  3432  					},
  3433  				},
  3434  			},
  3435  		},
  3436  	})
  3437  
  3438  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers.0"), commands.ErrIsNotValid)
  3439  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_trading_termination.external.oracle.signers.0"), commands.ErrIsNotValid)
  3440  }
  3441  
  3442  func testUpdateMarketWithExternalSettlementDataAndTerminationEmptyEthAddressSignerFails(t *testing.T) {
  3443  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  3444  		Terms: &protoTypes.ProposalTerms{
  3445  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  3446  				UpdateMarket: &protoTypes.UpdateMarket{
  3447  					Changes: &protoTypes.UpdateMarketConfiguration{
  3448  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  3449  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  3450  								Future: &protoTypes.UpdateFutureProduct{
  3451  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  3452  										vegapb.DataSourceContentTypeOracle,
  3453  									).SetOracleConfig(
  3454  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3455  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3456  												Signers: []*datapb.Signer{
  3457  													{
  3458  														Signer: &datapb.Signer_EthAddress{
  3459  															EthAddress: &datapb.ETHAddress{
  3460  																Address: "",
  3461  															},
  3462  														},
  3463  													},
  3464  												},
  3465  												Filters: []*datapb.Filter{
  3466  													{
  3467  														Key: &datapb.PropertyKey{
  3468  															Name: "vegaprotocol.builtin.prices.ETH.value",
  3469  															Type: datapb.PropertyKey_TYPE_INTEGER,
  3470  														},
  3471  														Conditions: []*datapb.Condition{
  3472  															{
  3473  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  3474  															},
  3475  														},
  3476  													},
  3477  												},
  3478  											},
  3479  										},
  3480  									),
  3481  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  3482  										vegapb.DataSourceContentTypeOracle,
  3483  									).SetOracleConfig(
  3484  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3485  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3486  												Signers: []*datapb.Signer{
  3487  													{
  3488  														Signer: &datapb.Signer_EthAddress{
  3489  															EthAddress: &datapb.ETHAddress{
  3490  																Address: "",
  3491  															},
  3492  														},
  3493  													},
  3494  												},
  3495  												Filters: []*datapb.Filter{
  3496  													{
  3497  														Key: &datapb.PropertyKey{
  3498  															Name: "trading.terminated",
  3499  															Type: datapb.PropertyKey_TYPE_BOOLEAN,
  3500  														},
  3501  														Conditions: []*datapb.Condition{},
  3502  													},
  3503  												},
  3504  											},
  3505  										},
  3506  									),
  3507  								},
  3508  							},
  3509  						},
  3510  					},
  3511  				},
  3512  			},
  3513  		},
  3514  	})
  3515  
  3516  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.external.oracle.signers.0"), commands.ErrIsNotValid)
  3517  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_trading_termination.external.oracle.signers.0"), commands.ErrIsNotValid)
  3518  }
  3519  
  3520  func testUpdateMarketWithTerminationWithTimeTriggerFails(t *testing.T) {
  3521  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  3522  		Terms: &protoTypes.ProposalTerms{
  3523  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  3524  				UpdateMarket: &protoTypes.UpdateMarket{
  3525  					Changes: &protoTypes.UpdateMarketConfiguration{
  3526  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  3527  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  3528  								Future: &protoTypes.UpdateFutureProduct{
  3529  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  3530  										vegapb.DataSourceContentTypeOracle,
  3531  									).SetOracleConfig(
  3532  										&vegapb.DataSourceDefinitionExternal_Oracle{
  3533  											Oracle: &vegapb.DataSourceSpecConfiguration{
  3534  												Signers: []*datapb.Signer{
  3535  													{
  3536  														Signer: &datapb.Signer_EthAddress{
  3537  															EthAddress: &datapb.ETHAddress{
  3538  																Address: "",
  3539  															},
  3540  														},
  3541  													},
  3542  												},
  3543  												Filters: []*datapb.Filter{
  3544  													{
  3545  														Key: &datapb.PropertyKey{
  3546  															Name: "vegaprotocol.builtin.prices.ETH.value",
  3547  															Type: datapb.PropertyKey_TYPE_INTEGER,
  3548  														},
  3549  														Conditions: []*datapb.Condition{
  3550  															{
  3551  																Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  3552  															},
  3553  														},
  3554  													},
  3555  												},
  3556  											},
  3557  										},
  3558  									),
  3559  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  3560  										vegapb.DataSourceContentTypeInternalTimeTriggerTermination,
  3561  									).SetTimeTriggerConditionConfig(
  3562  										[]*datapb.Condition{
  3563  											{
  3564  												// It does not matter what conditions are set here
  3565  												Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  3566  											},
  3567  										},
  3568  									),
  3569  								},
  3570  							},
  3571  						},
  3572  					},
  3573  				},
  3574  			},
  3575  		},
  3576  	})
  3577  
  3578  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_trading_termination.internal.timetrigger"), commands.ErrIsNotValid)
  3579  }
  3580  
  3581  func testUpdateMarketWithSettlementWithTimeTriggerFails(t *testing.T) {
  3582  	err := checkProposalSubmission(&commandspb.ProposalSubmission{
  3583  		Terms: &protoTypes.ProposalTerms{
  3584  			Change: &protoTypes.ProposalTerms_UpdateMarket{
  3585  				UpdateMarket: &protoTypes.UpdateMarket{
  3586  					Changes: &protoTypes.UpdateMarketConfiguration{
  3587  						Instrument: &protoTypes.UpdateInstrumentConfiguration{
  3588  							Product: &protoTypes.UpdateInstrumentConfiguration_Future{
  3589  								Future: &protoTypes.UpdateFutureProduct{
  3590  									DataSourceSpecForSettlementData: vegapb.NewDataSourceDefinition(
  3591  										vegapb.DataSourceContentTypeInternalTimeTriggerTermination,
  3592  									).SetTimeTriggerConditionConfig(
  3593  										[]*datapb.Condition{
  3594  											{
  3595  												// It does not matter what conditions are set here
  3596  												Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  3597  											},
  3598  										},
  3599  									),
  3600  									DataSourceSpecForTradingTermination: vegapb.NewDataSourceDefinition(
  3601  										vegapb.DataSourceContentTypeInternalTimeTriggerTermination,
  3602  									).SetTimeTriggerConditionConfig(
  3603  										[]*datapb.Condition{
  3604  											{
  3605  												// It does not matter what conditions are set here
  3606  												Operator: datapb.Condition_OPERATOR_GREATER_THAN_OR_EQUAL,
  3607  											},
  3608  										},
  3609  									),
  3610  								},
  3611  							},
  3612  						},
  3613  					},
  3614  				},
  3615  			},
  3616  		},
  3617  	})
  3618  
  3619  	assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.future.data_source_spec_for_settlement_data.internal.timetrigger"), commands.ErrIsNotValid)
  3620  }
  3621  
  3622  func testUpdatePerpetualMarketWithFundingRateModifiers(t *testing.T) {
  3623  	cases := []struct {
  3624  		product vegapb.UpdatePerpetualProduct
  3625  		err     error
  3626  		path    string
  3627  		desc    string
  3628  	}{
  3629  		{
  3630  			product: vegapb.UpdatePerpetualProduct{
  3631  				FundingRateScalingFactor: ptr.From("hello"),
  3632  			},
  3633  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.funding_rate_scaling_factor",
  3634  			err:  commands.ErrIsNotValidNumber,
  3635  		},
  3636  		{
  3637  			product: vegapb.UpdatePerpetualProduct{
  3638  				FundingRateScalingFactor: ptr.From("-10"),
  3639  			},
  3640  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.funding_rate_scaling_factor",
  3641  			err:  commands.ErrMustBePositiveOrZero,
  3642  		},
  3643  		{
  3644  			product: vegapb.UpdatePerpetualProduct{
  3645  				FundingRateScalingFactor: ptr.From("0.1"),
  3646  			},
  3647  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.funding_rate_scaling_factor",
  3648  		},
  3649  		{
  3650  			product: vegapb.UpdatePerpetualProduct{
  3651  				FundingRateLowerBound: ptr.From("hello"),
  3652  			},
  3653  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.funding_rate_lower_bound",
  3654  			err:  commands.ErrIsNotValidNumber,
  3655  		},
  3656  		{
  3657  			product: vegapb.UpdatePerpetualProduct{
  3658  				FundingRateLowerBound: ptr.From("-100"),
  3659  			},
  3660  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.funding_rate_lower_bound",
  3661  		},
  3662  		{
  3663  			product: vegapb.UpdatePerpetualProduct{
  3664  				FundingRateUpperBound: ptr.From("hello"),
  3665  			},
  3666  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.funding_rate_upper_bound",
  3667  			err:  commands.ErrIsNotValidNumber,
  3668  		},
  3669  		{
  3670  			product: vegapb.UpdatePerpetualProduct{
  3671  				FundingRateUpperBound: ptr.From("100"),
  3672  			},
  3673  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.funding_rate_upper_bound",
  3674  		},
  3675  		{
  3676  			product: vegapb.UpdatePerpetualProduct{
  3677  				FundingRateUpperBound: ptr.From("100"),
  3678  				FundingRateLowerBound: ptr.From("200"),
  3679  			},
  3680  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.funding_rate_lower_bound",
  3681  			err:  commands.ErrIsNotValid,
  3682  		},
  3683  	}
  3684  
  3685  	for _, v := range cases {
  3686  		t.Run(v.desc, func(t *testing.T) {
  3687  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
  3688  				Terms: &vegapb.ProposalTerms{
  3689  					Change: &vegapb.ProposalTerms_UpdateMarket{
  3690  						UpdateMarket: &vegapb.UpdateMarket{
  3691  							Changes: &vegapb.UpdateMarketConfiguration{
  3692  								Instrument: &vegapb.UpdateInstrumentConfiguration{
  3693  									Product: &vegapb.UpdateInstrumentConfiguration_Perpetual{
  3694  										Perpetual: &v.product,
  3695  									},
  3696  								},
  3697  							},
  3698  						},
  3699  					},
  3700  				},
  3701  			})
  3702  			errs := err.Get(v.path)
  3703  			// no errors expected
  3704  			if v.err == nil {
  3705  				assert.Len(t, errs, 0, v.desc)
  3706  				return
  3707  			}
  3708  			assert.Contains(t, errs, v.err, v.desc)
  3709  		})
  3710  	}
  3711  }
  3712  
  3713  func testUpdatePerpsMarketChangeSubmissionProductParameters(t *testing.T) {
  3714  	cases := []struct {
  3715  		product vegapb.UpdatePerpetualProduct
  3716  		err     error
  3717  		path    string
  3718  		desc    string
  3719  	}{
  3720  		{
  3721  			product: vegapb.UpdatePerpetualProduct{
  3722  				MarginFundingFactor: "",
  3723  			},
  3724  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.margin_funding_factor",
  3725  			err:  commands.ErrIsRequired,
  3726  			desc: "margin_funding_factor is empty",
  3727  		},
  3728  		{
  3729  			product: vegapb.UpdatePerpetualProduct{
  3730  				MarginFundingFactor: "nope",
  3731  			},
  3732  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.margin_funding_factor",
  3733  			err:  commands.ErrIsNotValidNumber,
  3734  			desc: "margin_funding_factor is not a valid number",
  3735  		},
  3736  		{
  3737  			product: vegapb.UpdatePerpetualProduct{
  3738  				MarginFundingFactor: "-10",
  3739  			},
  3740  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.margin_funding_factor",
  3741  			err:  commands.ErrMustBeWithinRange01,
  3742  			desc: "margin_funding_factor is not within range (< 0)",
  3743  		},
  3744  		{
  3745  			product: vegapb.UpdatePerpetualProduct{
  3746  				MarginFundingFactor: "10",
  3747  			},
  3748  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.margin_funding_factor",
  3749  			err:  commands.ErrMustBeWithinRange01,
  3750  			desc: "margin_funding_factor is not within range (> 1)",
  3751  		},
  3752  		{
  3753  			product: vegapb.UpdatePerpetualProduct{
  3754  				MarginFundingFactor: "0.5",
  3755  			},
  3756  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.margin_funding_factor",
  3757  			desc: "margin_funding_factor is valid",
  3758  		},
  3759  		// interest_rate
  3760  		{
  3761  			product: vegapb.UpdatePerpetualProduct{
  3762  				InterestRate: "",
  3763  			},
  3764  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.interest_rate",
  3765  			err:  commands.ErrIsRequired,
  3766  			desc: "interest_rate is empty",
  3767  		},
  3768  		{
  3769  			product: vegapb.UpdatePerpetualProduct{
  3770  				InterestRate: "nope",
  3771  			},
  3772  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.interest_rate",
  3773  			err:  commands.ErrIsNotValidNumber,
  3774  			desc: "interest_rate is not a valid number",
  3775  		},
  3776  		{
  3777  			product: vegapb.UpdatePerpetualProduct{
  3778  				InterestRate: "-10",
  3779  			},
  3780  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.interest_rate",
  3781  			err:  commands.ErrMustBeWithinRange11,
  3782  			desc: "interest_rate is not within range (< -1)",
  3783  		},
  3784  		{
  3785  			product: vegapb.UpdatePerpetualProduct{
  3786  				InterestRate: "10",
  3787  			},
  3788  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.interest_rate",
  3789  			err:  commands.ErrMustBeWithinRange11,
  3790  			desc: "interest_rate is not within range (> 1)",
  3791  		},
  3792  		{
  3793  			product: vegapb.UpdatePerpetualProduct{
  3794  				InterestRate: "0.5",
  3795  			},
  3796  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.interest_rate",
  3797  			desc: "interest_rate is valid",
  3798  		},
  3799  		{
  3800  			product: vegapb.UpdatePerpetualProduct{
  3801  				InterestRate: "-0.5",
  3802  			},
  3803  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.interest_rate",
  3804  			desc: "interest_rate is valid",
  3805  		},
  3806  		// clamp_lower_bound
  3807  		{
  3808  			product: vegapb.UpdatePerpetualProduct{
  3809  				ClampLowerBound: "",
  3810  			},
  3811  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.clamp_lower_bound",
  3812  			err:  commands.ErrIsRequired,
  3813  			desc: "clamp_lower_bound is empty",
  3814  		},
  3815  		{
  3816  			product: vegapb.UpdatePerpetualProduct{
  3817  				ClampLowerBound: "nope",
  3818  			},
  3819  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.clamp_lower_bound",
  3820  			err:  commands.ErrIsNotValidNumber,
  3821  			desc: "clamp_lower_bound is not a valid number",
  3822  		},
  3823  		{
  3824  			product: vegapb.UpdatePerpetualProduct{
  3825  				ClampLowerBound: "-10",
  3826  			},
  3827  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.clamp_lower_bound",
  3828  			err:  commands.ErrMustBeWithinRange11,
  3829  			desc: "clamp_lower_bound is not within range (< -1)",
  3830  		},
  3831  		{
  3832  			product: vegapb.UpdatePerpetualProduct{
  3833  				ClampLowerBound: "10",
  3834  			},
  3835  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.clamp_lower_bound",
  3836  			err:  commands.ErrMustBeWithinRange11,
  3837  			desc: "clamp_lower_bound is not within range (> 1)",
  3838  		},
  3839  		{
  3840  			product: vegapb.UpdatePerpetualProduct{
  3841  				ClampLowerBound: "0.5",
  3842  			},
  3843  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.clamp_lower_bound",
  3844  			desc: "clamp_lower_bound is valid",
  3845  		},
  3846  		{
  3847  			product: vegapb.UpdatePerpetualProduct{
  3848  				ClampLowerBound: "-0.5",
  3849  			},
  3850  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.clamp_lower_bound",
  3851  			desc: "clamp_lower_bound is valid",
  3852  		},
  3853  		// clamp_upper_bound
  3854  		{
  3855  			product: vegapb.UpdatePerpetualProduct{
  3856  				ClampUpperBound: "",
  3857  			},
  3858  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.clamp_upper_bound",
  3859  			err:  commands.ErrIsRequired,
  3860  			desc: "clamp_upper_bound is empty",
  3861  		},
  3862  		{
  3863  			product: vegapb.UpdatePerpetualProduct{
  3864  				ClampUpperBound: "nope",
  3865  			},
  3866  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.clamp_upper_bound",
  3867  			err:  commands.ErrIsNotValidNumber,
  3868  			desc: "clamp_upper_bound is not a valid number",
  3869  		},
  3870  		{
  3871  			product: vegapb.UpdatePerpetualProduct{
  3872  				ClampUpperBound: "-10",
  3873  			},
  3874  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.clamp_upper_bound",
  3875  			err:  commands.ErrMustBeWithinRange11,
  3876  			desc: "clamp_upper_bound is not within range (< -1)",
  3877  		},
  3878  		{
  3879  			product: vegapb.UpdatePerpetualProduct{
  3880  				ClampUpperBound: "10",
  3881  			},
  3882  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.clamp_upper_bound",
  3883  			err:  commands.ErrMustBeWithinRange11,
  3884  			desc: "clamp_upper_bound is not within range (> 1)",
  3885  		},
  3886  		{
  3887  			product: vegapb.UpdatePerpetualProduct{
  3888  				ClampUpperBound: "0.5",
  3889  			},
  3890  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.clamp_upper_bound",
  3891  			desc: "clamp_upper_bound is valid",
  3892  		},
  3893  		{
  3894  			product: vegapb.UpdatePerpetualProduct{
  3895  				ClampUpperBound: "-0.5",
  3896  			},
  3897  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.clamp_upper_bound",
  3898  			desc: "clamp_upper_bound is valid",
  3899  		},
  3900  		// clamp lower and upper
  3901  		{
  3902  			product: vegapb.UpdatePerpetualProduct{
  3903  				ClampLowerBound: "0.5",
  3904  				ClampUpperBound: "0.5",
  3905  			},
  3906  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.clamp_upper_bound",
  3907  			desc: "clamp_upper_bound == clamp_lower_bound is valid",
  3908  		},
  3909  		{
  3910  			product: vegapb.UpdatePerpetualProduct{
  3911  				ClampLowerBound: "0.4",
  3912  				ClampUpperBound: "0.5",
  3913  			},
  3914  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.clamp_upper_bound",
  3915  			desc: "clamp_upper_bound > clamp_lower_bound is valid",
  3916  		},
  3917  		{
  3918  			product: vegapb.UpdatePerpetualProduct{
  3919  				ClampLowerBound: "0.5",
  3920  				ClampUpperBound: "0.4",
  3921  			},
  3922  			path: "proposal_submission.terms.change.update_market.changes.instrument.product.perps.clamp_upper_bound",
  3923  			err:  commands.ErrMustBeGTEClampLowerBound,
  3924  			desc: "clamp_upper_bound < clamp_lower_bound is invalid",
  3925  		},
  3926  	}
  3927  
  3928  	for _, v := range cases {
  3929  		t.Run(v.desc, func(t *testing.T) {
  3930  			err := checkProposalSubmission(&commandspb.ProposalSubmission{
  3931  				Terms: &vegapb.ProposalTerms{
  3932  					Change: &vegapb.ProposalTerms_UpdateMarket{
  3933  						UpdateMarket: &vegapb.UpdateMarket{
  3934  							Changes: &vegapb.UpdateMarketConfiguration{
  3935  								Instrument: &vegapb.UpdateInstrumentConfiguration{
  3936  									Product: &vegapb.UpdateInstrumentConfiguration_Perpetual{
  3937  										Perpetual: &v.product,
  3938  									},
  3939  								},
  3940  							},
  3941  						},
  3942  					},
  3943  				},
  3944  			})
  3945  
  3946  			errs := err.Get(v.path)
  3947  
  3948  			// no errors expected
  3949  			if v.err == nil {
  3950  				assert.Len(t, errs, 0, v.desc)
  3951  				return
  3952  			}
  3953  
  3954  			assert.Contains(t, errs, v.err, v.desc)
  3955  		})
  3956  	}
  3957  }
  3958  
  3959  func testUpdateLiquidityFeeSettingsSpot(t *testing.T) {
  3960  	cases := []struct {
  3961  		lfs   *vega.LiquidityFeeSettings
  3962  		field string
  3963  		err   error
  3964  	}{
  3965  		{
  3966  			lfs: &vega.LiquidityFeeSettings{
  3967  				Method:      vegapb.LiquidityFeeSettings_METHOD_MARGINAL_COST,
  3968  				FeeConstant: ptr.From("0.1"),
  3969  			},
  3970  			field: "method",
  3971  			err:   commands.ErrIsNotValid,
  3972  		},
  3973  		{
  3974  			lfs: &vega.LiquidityFeeSettings{
  3975  				Method:      vegapb.LiquidityFeeSettings_METHOD_WEIGHTED_AVERAGE,
  3976  				FeeConstant: ptr.From("0.1"),
  3977  			},
  3978  			field: "method",
  3979  			err:   commands.ErrIsNotValid,
  3980  		},
  3981  		{
  3982  			lfs: &vega.LiquidityFeeSettings{
  3983  				Method:      vegapb.LiquidityFeeSettings_METHOD_CONSTANT,
  3984  				FeeConstant: nil,
  3985  			},
  3986  			field: "fee_constant",
  3987  			err:   commands.ErrIsRequired,
  3988  		},
  3989  		{
  3990  			lfs: &vega.LiquidityFeeSettings{
  3991  				Method:      vegapb.LiquidityFeeSettings_METHOD_CONSTANT,
  3992  				FeeConstant: ptr.From("hello"),
  3993  			},
  3994  			field: "fee_constant",
  3995  			err:   commands.ErrIsNotValidNumber,
  3996  		},
  3997  		{
  3998  			lfs: &vega.LiquidityFeeSettings{
  3999  				Method:      vegapb.LiquidityFeeSettings_METHOD_CONSTANT,
  4000  				FeeConstant: ptr.From("-0.1"), // (0042-LIQF-072)
  4001  			},
  4002  			field: "fee_constant",
  4003  			err:   commands.ErrMustBePositiveOrZero,
  4004  		},
  4005  		{
  4006  			lfs: &vega.LiquidityFeeSettings{
  4007  				Method:      vegapb.LiquidityFeeSettings_METHOD_CONSTANT,
  4008  				FeeConstant: ptr.From("1.1"), // (0042-LIQF-072)
  4009  			},
  4010  			field: "fee_constant",
  4011  			err:   commands.ErrMustBeWithinRange01,
  4012  		},
  4013  		{
  4014  			lfs: &vega.LiquidityFeeSettings{
  4015  				Method: vegapb.LiquidityFeeSettings_METHOD_UNSPECIFIED,
  4016  			},
  4017  			field: "method",
  4018  			err:   commands.ErrIsRequired,
  4019  		},
  4020  		{
  4021  			lfs: &vega.LiquidityFeeSettings{
  4022  				Method: vegapb.LiquidityFeeSettings_Method(int32(100)),
  4023  			},
  4024  			field: "method",
  4025  			err:   commands.ErrIsNotValid,
  4026  		},
  4027  	}
  4028  
  4029  	for _, c := range cases {
  4030  		err := checkProposalSubmission(&commandspb.ProposalSubmission{
  4031  			Terms: &vegapb.ProposalTerms{
  4032  				Change: &vegapb.ProposalTerms_UpdateSpotMarket{
  4033  					UpdateSpotMarket: &vegapb.UpdateSpotMarket{
  4034  						Changes: &vegapb.UpdateSpotMarketConfiguration{
  4035  							Instrument:           &vegapb.UpdateSpotInstrumentConfiguration{},
  4036  							LiquidityFeeSettings: c.lfs,
  4037  						},
  4038  					},
  4039  				},
  4040  			},
  4041  		})
  4042  		assert.Contains(t, err.Get("proposal_submission.terms.change.update_spot_market.changes.liquidity_fee_settings."+c.field), c.err)
  4043  	}
  4044  }