code.vegaprotocol.io/vega@v0.79.0/datanode/sqlstore/volume_discount_programs_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 sqlstore_test 17 18 import ( 19 "testing" 20 "time" 21 22 "code.vegaprotocol.io/vega/datanode/entities" 23 "code.vegaprotocol.io/vega/datanode/sqlstore" 24 "code.vegaprotocol.io/vega/libs/ptr" 25 "code.vegaprotocol.io/vega/protos/vega" 26 eventspb "code.vegaprotocol.io/vega/protos/vega/events/v1" 27 28 "github.com/georgysavva/scany/pgxscan" 29 "github.com/stretchr/testify/assert" 30 "github.com/stretchr/testify/require" 31 ) 32 33 func setupVolumeDiscountProgramTest(t *testing.T) (*sqlstore.Blocks, *sqlstore.VolumeDiscountPrograms) { 34 t.Helper() 35 36 bs := sqlstore.NewBlocks(connectionSource) 37 rs := sqlstore.NewVolumeDiscountPrograms(connectionSource) 38 39 return bs, rs 40 } 41 42 func TestVolumeDiscountPrograms_AddVolumeDiscountProgram(t *testing.T) { 43 bs, rs := setupVolumeDiscountProgramTest(t) 44 ctx := tempTransaction(t) 45 46 block := addTestBlock(t, ctx, bs) 47 block2 := addTestBlock(t, ctx, bs) 48 49 t.Run("AddVolumeDiscountProgram should create a new referral program record", func(t *testing.T) { 50 endTime := block.VegaTime.Add(time.Hour) 51 endTime2 := block2.VegaTime.Add(time.Hour) 52 53 programs := []*eventspb.VolumeDiscountProgramStarted{ 54 { 55 Program: &vega.VolumeDiscountProgram{ 56 Version: 1, 57 Id: GenerateID(), 58 BenefitTiers: []*vega.VolumeBenefitTier{ 59 { 60 MinimumRunningNotionalTakerVolume: "1000", 61 VolumeDiscountFactor: "0.01", 62 VolumeDiscountFactors: &vega.DiscountFactors{ 63 InfrastructureDiscountFactor: "0.004", 64 LiquidityDiscountFactor: "0.002", 65 MakerDiscountFactor: "0.004", 66 }, 67 TierNumber: ptr.From(uint64(1)), 68 }, 69 { 70 MinimumRunningNotionalTakerVolume: "10000", 71 VolumeDiscountFactor: "0.1", 72 VolumeDiscountFactors: &vega.DiscountFactors{ 73 InfrastructureDiscountFactor: "0.04", 74 LiquidityDiscountFactor: "0.02", 75 MakerDiscountFactor: "0.04", 76 }, 77 TierNumber: ptr.From(uint64(2)), 78 }, 79 }, 80 EndOfProgramTimestamp: endTime.Unix(), 81 WindowLength: 100, 82 }, 83 }, 84 { 85 Program: &vega.VolumeDiscountProgram{ 86 Version: 1, 87 Id: GenerateID(), 88 BenefitTiers: []*vega.VolumeBenefitTier{ 89 { 90 MinimumRunningNotionalTakerVolume: "2000", 91 VolumeDiscountFactor: "0.02", 92 VolumeDiscountFactors: &vega.DiscountFactors{ 93 InfrastructureDiscountFactor: "0.008", 94 LiquidityDiscountFactor: "0.002", 95 MakerDiscountFactor: "0.004", 96 }, 97 TierNumber: ptr.From(uint64(1)), 98 }, 99 { 100 MinimumRunningNotionalTakerVolume: "20000", 101 VolumeDiscountFactor: "0.2", 102 VolumeDiscountFactors: &vega.DiscountFactors{ 103 InfrastructureDiscountFactor: "0.08", 104 LiquidityDiscountFactor: "0.04", 105 MakerDiscountFactor: "0.08", 106 }, 107 TierNumber: ptr.From(uint64(2)), 108 }, 109 }, 110 EndOfProgramTimestamp: endTime2.Unix(), 111 WindowLength: 200, 112 }, 113 }, 114 } 115 116 want := entities.VolumeDiscountProgramFromProto(programs[0].Program, block.VegaTime, 0) 117 err := rs.AddVolumeDiscountProgram(ctx, want) 118 require.NoError(t, err) 119 120 var got []entities.VolumeDiscountProgram 121 require.NoError(t, pgxscan.Select(ctx, connectionSource, &got, "SELECT * FROM volume_discount_programs")) 122 require.Len(t, got, 1) 123 assert.Equal(t, *want, got[0]) 124 125 want2 := entities.VolumeDiscountProgramFromProto(programs[1].Program, block2.VegaTime, 0) 126 err = rs.AddVolumeDiscountProgram(ctx, want2) 127 require.NoError(t, err) 128 129 err = pgxscan.Select(ctx, connectionSource, &got, "SELECT * FROM volume_discount_programs") 130 require.NoError(t, err) 131 require.Len(t, got, 2) 132 wantAll := []entities.VolumeDiscountProgram{*want, *want2} 133 assert.Equal(t, wantAll, got) 134 }) 135 } 136 137 func getVolumeDiscountEvents(t *testing.T, endTime time.Time) (*eventspb.VolumeDiscountProgramStarted, 138 *eventspb.VolumeDiscountProgramUpdated, *eventspb.VolumeDiscountProgramEnded, 139 ) { 140 t.Helper() 141 142 started := eventspb.VolumeDiscountProgramStarted{ 143 Program: &vega.VolumeDiscountProgram{ 144 Version: 1, 145 Id: GenerateID(), 146 BenefitTiers: []*vega.VolumeBenefitTier{ 147 { 148 MinimumRunningNotionalTakerVolume: "1000", 149 VolumeDiscountFactor: "0.01", 150 VolumeDiscountFactors: &vega.DiscountFactors{ 151 InfrastructureDiscountFactor: "0.004", 152 LiquidityDiscountFactor: "0.002", 153 MakerDiscountFactor: "0.004", 154 }, 155 TierNumber: ptr.From(uint64(1)), 156 }, 157 { 158 MinimumRunningNotionalTakerVolume: "10000", 159 VolumeDiscountFactor: "0.1", 160 VolumeDiscountFactors: &vega.DiscountFactors{ 161 InfrastructureDiscountFactor: "0.04", 162 LiquidityDiscountFactor: "0.02", 163 MakerDiscountFactor: "0.04", 164 }, 165 TierNumber: ptr.From(uint64(2)), 166 }, 167 }, 168 EndOfProgramTimestamp: endTime.Unix(), 169 WindowLength: 100, 170 }, 171 StartedAt: endTime.Add(-1 * time.Hour).UnixNano(), 172 AtEpoch: 1, 173 } 174 175 updated := eventspb.VolumeDiscountProgramUpdated{ 176 Program: &vega.VolumeDiscountProgram{ 177 Version: 2, 178 Id: GenerateID(), 179 BenefitTiers: []*vega.VolumeBenefitTier{ 180 { 181 MinimumRunningNotionalTakerVolume: "2000", 182 VolumeDiscountFactor: "0.02", 183 VolumeDiscountFactors: &vega.DiscountFactors{ 184 InfrastructureDiscountFactor: "0.008", 185 LiquidityDiscountFactor: "0.004", 186 MakerDiscountFactor: "0.008", 187 }, 188 TierNumber: ptr.From(uint64(1)), 189 }, 190 { 191 MinimumRunningNotionalTakerVolume: "20000", 192 VolumeDiscountFactor: "0.2", 193 VolumeDiscountFactors: &vega.DiscountFactors{ 194 InfrastructureDiscountFactor: "0.08", 195 LiquidityDiscountFactor: "0.04", 196 MakerDiscountFactor: "0.08", 197 }, 198 TierNumber: ptr.From(uint64(2)), 199 }, 200 }, 201 EndOfProgramTimestamp: endTime.Unix(), 202 WindowLength: 200, 203 }, 204 UpdatedAt: endTime.Add(-30 * time.Minute).UnixNano(), 205 AtEpoch: 2, 206 } 207 208 ended := eventspb.VolumeDiscountProgramEnded{ 209 Version: 2, 210 Id: updated.Program.Id, 211 EndedAt: endTime.UnixNano(), 212 AtEpoch: 3, 213 } 214 215 return &started, &updated, &ended 216 } 217 218 func TestVolumeDiscountPrograms_UpdateVolumeDiscountProgram(t *testing.T) { 219 bs, rs := setupVolumeDiscountProgramTest(t) 220 ctx := tempTransaction(t) 221 222 block := addTestBlock(t, ctx, bs) 223 endTime := block.VegaTime.Add(time.Hour) 224 started, updated, _ := getVolumeDiscountEvents(t, endTime) 225 226 var want, wantUpdated *entities.VolumeDiscountProgram 227 t.Run("UpdateVolumeDiscountProgram should create a new referral program record with the updated data", func(t *testing.T) { 228 want = entities.VolumeDiscountProgramFromProto(started.Program, block.VegaTime, 0) 229 err := rs.AddVolumeDiscountProgram(ctx, want) 230 require.NoError(t, err) 231 232 var got []entities.VolumeDiscountProgram 233 err = pgxscan.Select(ctx, connectionSource, &got, "SELECT * FROM volume_discount_programs") 234 require.NoError(t, err) 235 236 require.Len(t, got, 1) 237 assert.Equal(t, *want, got[0]) 238 239 block = addTestBlock(t, ctx, bs) 240 wantUpdated = entities.VolumeDiscountProgramFromProto(updated.Program, block.VegaTime, 0) 241 err = rs.UpdateVolumeDiscountProgram(ctx, wantUpdated) 242 require.NoError(t, err) 243 244 err = pgxscan.Select(ctx, connectionSource, &got, "SELECT * FROM volume_discount_programs") 245 require.NoError(t, err) 246 247 require.Len(t, got, 2) 248 249 wantAll := []entities.VolumeDiscountProgram{*want, *wantUpdated} 250 assert.Equal(t, wantAll, got) 251 }) 252 253 t.Run("The current_referral view should list the updated referral program record", func(t *testing.T) { 254 var got []entities.VolumeDiscountProgram 255 err := pgxscan.Select(ctx, connectionSource, &got, "SELECT * FROM current_volume_discount_program") 256 require.NoError(t, err) 257 require.Len(t, got, 1) 258 assert.Equal(t, *wantUpdated, got[0]) 259 }) 260 } 261 262 func TestVolumeDiscountPrograms_EndVolumeDiscountProgram(t *testing.T) { 263 bs, rs := setupVolumeDiscountProgramTest(t) 264 ctx := tempTransaction(t) 265 266 t.Run("EndVolumeDiscountProgram should create a new referral program record with the data from the current referral program and set the ended_at timestamp", func(t *testing.T) { 267 block := addTestBlock(t, ctx, bs) 268 endTime := block.VegaTime.Add(time.Hour) 269 startedEvent, updatedEvent, endedEvent := getVolumeDiscountEvents(t, endTime) 270 271 started := entities.VolumeDiscountProgramFromProto(startedEvent.Program, block.VegaTime, 1) 272 err := rs.AddVolumeDiscountProgram(ctx, started) 273 require.NoError(t, err) 274 275 block = addTestBlock(t, ctx, bs) 276 updated := entities.VolumeDiscountProgramFromProto(updatedEvent.Program, block.VegaTime, 2) 277 err = rs.UpdateVolumeDiscountProgram(ctx, updated) 278 require.NoError(t, err) 279 280 block = addTestBlock(t, ctx, bs) 281 err = rs.EndVolumeDiscountProgram(ctx, endedEvent.Version, endTime, block.VegaTime, 3) 282 require.NoError(t, err) 283 284 ended := entities.VolumeDiscountProgramFromProto(updatedEvent.Program, block.VegaTime, 3) 285 ended.Version = endedEvent.Version 286 ended.EndedAt = &endTime 287 288 var got []entities.VolumeDiscountProgram 289 err = pgxscan.Select(ctx, connectionSource, &got, "SELECT * FROM volume_discount_programs order by vega_time") 290 require.NoError(t, err) 291 require.Len(t, got, 3) 292 wantAll := []entities.VolumeDiscountProgram{*started, *updated, *ended} 293 assert.Equal(t, wantAll, got) 294 295 err = pgxscan.Select(ctx, connectionSource, &got, "SELECT * FROM current_volume_discount_program") 296 require.NoError(t, err) 297 require.Len(t, got, 1) 298 assert.Equal(t, *ended, got[0]) 299 }) 300 } 301 302 func TestVolumeDiscountPrograms_GetCurrentVolumeDiscountProgram(t *testing.T) { 303 bs, rs := setupVolumeDiscountProgramTest(t) 304 ctx := tempTransaction(t) 305 306 t.Run("GetCurrentVolumeDiscountProgram should return the current referral program information", func(t *testing.T) { 307 block := addTestBlock(t, ctx, bs) 308 endTime := block.VegaTime.Add(time.Hour) 309 startedEvent, updatedEvent, endedEvent := getVolumeDiscountEvents(t, endTime) 310 311 started := entities.VolumeDiscountProgramFromProto(startedEvent.Program, block.VegaTime, 1) 312 err := rs.AddVolumeDiscountProgram(ctx, started) 313 require.NoError(t, err) 314 315 got, err := rs.GetCurrentVolumeDiscountProgram(ctx) 316 require.NoError(t, err) 317 assert.Equal(t, *started, got) 318 319 block = addTestBlock(t, ctx, bs) 320 updated := entities.VolumeDiscountProgramFromProto(updatedEvent.Program, block.VegaTime, 2) 321 err = rs.UpdateVolumeDiscountProgram(ctx, updated) 322 require.NoError(t, err) 323 324 got, err = rs.GetCurrentVolumeDiscountProgram(ctx) 325 require.NoError(t, err) 326 assert.Equal(t, *updated, got) 327 328 block = addTestBlock(t, ctx, bs) 329 err = rs.EndVolumeDiscountProgram(ctx, endedEvent.Version, endTime, block.VegaTime, 3) 330 require.NoError(t, err) 331 332 ended := entities.VolumeDiscountProgramFromProto(updatedEvent.Program, block.VegaTime, 3) 333 ended.Version = endedEvent.Version 334 ended.EndedAt = &endTime 335 336 got, err = rs.GetCurrentVolumeDiscountProgram(ctx) 337 require.NoError(t, err) 338 assert.Equal(t, *ended, got) 339 }) 340 }