code.vegaprotocol.io/vega@v0.79.0/core/monitor/snapshot_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 monitor_test 17 18 import ( 19 "context" 20 "testing" 21 "time" 22 23 "code.vegaprotocol.io/vega/core/datasource" 24 "code.vegaprotocol.io/vega/core/monitor" 25 "code.vegaprotocol.io/vega/core/types" 26 "code.vegaprotocol.io/vega/libs/crypto" 27 "code.vegaprotocol.io/vega/libs/num" 28 "code.vegaprotocol.io/vega/libs/proto" 29 30 "github.com/stretchr/testify/assert" 31 "github.com/stretchr/testify/require" 32 ) 33 34 func getMarket(openingAuctionDuration *types.AuctionDuration) types.Market { 35 mkt := types.Market{ 36 Fees: &types.Fees{ 37 Factors: &types.FeeFactors{ 38 LiquidityFee: num.DecimalFromFloat(0.3), 39 InfrastructureFee: num.DecimalFromFloat(0.001), 40 MakerFee: num.DecimalFromFloat(0.004), 41 }, 42 }, 43 TradableInstrument: &types.TradableInstrument{ 44 Instrument: &types.Instrument{ 45 ID: "Crypto/ETHUSD/Futures/Dec19", 46 Code: "CRYPTO:ETHUSD/DEC19", 47 Name: "December 2019 ETH vs USD future", 48 Metadata: &types.InstrumentMetadata{ 49 Tags: []string{ 50 "asset_class:fx/crypto", 51 "product:futures", 52 }, 53 }, 54 Product: &types.InstrumentFuture{ 55 Future: &types.Future{ 56 SettlementAsset: "ETH", 57 QuoteName: "USD", 58 DataSourceSpecBinding: &datasource.SpecBindingForFuture{ 59 SettlementDataProperty: "prices.ETH.value", 60 TradingTerminationProperty: "trading.terminated", 61 }, 62 }, 63 }, 64 }, 65 MarginCalculator: &types.MarginCalculator{ 66 ScalingFactors: &types.ScalingFactors{ 67 SearchLevel: num.DecimalFromFloat(1.1), 68 InitialMargin: num.DecimalFromFloat(1.2), 69 CollateralRelease: num.DecimalFromFloat(1.4), 70 }, 71 }, 72 RiskModel: &types.TradableInstrumentSimpleRiskModel{ 73 SimpleRiskModel: &types.SimpleRiskModel{ 74 Params: &types.SimpleModelParams{ 75 FactorLong: num.DecimalFromFloat(0.15), 76 FactorShort: num.DecimalFromFloat(0.25), 77 MaxMoveUp: num.DecimalFromFloat(100.0), 78 MinMoveDown: num.DecimalFromFloat(100.0), 79 ProbabilityOfTrading: num.DecimalFromFloat(0.1), 80 }, 81 }, 82 }, 83 }, 84 OpeningAuction: openingAuctionDuration, 85 LiquidityMonitoringParameters: &types.LiquidityMonitoringParameters{ 86 TargetStakeParameters: &types.TargetStakeParameters{ 87 TimeWindow: 3600, // seconds = 1h 88 ScalingFactor: num.DecimalFromFloat(10), 89 }, 90 }, 91 } 92 return mkt 93 } 94 95 func createAuctionState() *monitor.AuctionState { 96 ad := &types.AuctionDuration{ 97 Duration: 100, 98 Volume: 100, 99 } 100 mktCfg := getMarket(ad) 101 return monitor.NewAuctionState(&mktCfg, time.Now()) 102 } 103 104 func getHash(t *testing.T, as *monitor.AuctionState) []byte { 105 t.Helper() 106 state := as.GetState() 107 pmproto := state.IntoProto() 108 bytes, err := proto.Marshal(pmproto) 109 require.NoError(t, err) 110 111 // Check our change flag has been reset 112 return crypto.Hash(bytes) 113 } 114 115 func TestEmpty(t *testing.T) { 116 as := createAuctionState() 117 118 // Get the hash and state for the empty object 119 hash1 := getHash(t, as) 120 state1 := as.GetState() 121 122 // Create a new object and restore into it 123 ad := &types.AuctionDuration{ 124 Duration: 100, 125 Volume: 100, 126 } 127 mktCfg := getMarket(ad) 128 as2 := monitor.NewAuctionStateFromSnapshot(&mktCfg, state1) 129 130 // Check the new hash matches the old hash 131 assert.Equal(t, hash1, getHash(t, as2)) 132 } 133 134 func TestRestoreTriggerType(t *testing.T) { 135 as := createAuctionState() 136 137 // Perform some updates to the object 138 as.StartPriceAuction(time.Now(), &types.AuctionDuration{ 139 Duration: 200, 140 Volume: 200, 141 }) 142 143 asNew := monitor.NewAuctionStateFromSnapshot(nil, as.GetState()) 144 require.Equal(t, as.IsPriceAuction(), asNew.IsPriceAuction()) 145 } 146 147 func TestChangedState(t *testing.T) { 148 as := createAuctionState() 149 150 // Get the hash for the empty object 151 original := getHash(t, as) 152 153 // Perform some updates to the object 154 as.StartPriceAuction(time.Now(), &types.AuctionDuration{ 155 Duration: 200, 156 Volume: 200, 157 }) 158 159 // Make sure we thinks things have changed 160 assert.True(t, as.Changed()) 161 162 auctionStart := getHash(t, as) 163 assert.NotEqual(t, original, auctionStart) 164 165 // extend the auction 166 as.ExtendAuction(types.AuctionDuration{Duration: 12, Volume: 12}) 167 assert.True(t, as.Changed()) 168 169 auctionExtended := getHash(t, as) 170 assert.NotEqual(t, auctionStart, auctionExtended) 171 172 // set Ready to leave 173 as.SetReadyToLeave() 174 assert.True(t, as.Changed()) 175 176 auctionReady := getHash(t, as) 177 assert.NotEqual(t, auctionStart, auctionReady) 178 179 // end it 180 as.Left(context.Background(), time.Now()) 181 assert.True(t, as.Changed()) 182 183 auctionEnded := getHash(t, as) 184 assert.NotEqual(t, auctionStart, auctionEnded) 185 } 186 187 // TestAuctionTypeChain checks that if an auction is ended, then started again it is logged as a change. 188 func TestAuctionEndsOpens(t *testing.T) { 189 as := createAuctionState() 190 now := time.Now() 191 // Perform some updates to the object 192 as.StartOpeningAuction(now, &types.AuctionDuration{ 193 Duration: 200, 194 Volume: 200, 195 }) 196 197 // Get the hash of a started auction 198 require.True(t, as.Changed()) 199 original := getHash(t, as) 200 201 // Close it down and then start exactly the same auction again 202 as.Left(context.Background(), now) 203 require.False(t, as.InAuction()) // definitely no auction 204 205 as.StartOpeningAuction(now, &types.AuctionDuration{ 206 Duration: 200, 207 Volume: 200, 208 }) 209 210 require.True(t, as.Changed()) 211 newAuction := getHash(t, as) 212 // change flagged even though hash is exactly the same (which is expected given all the state change that actually occurred) 213 assert.Equal(t, original, newAuction) 214 }