code.vegaprotocol.io/vega@v0.79.0/datanode/sqlstore/paid_liquidity_fee_stats_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 "context" 20 "testing" 21 "time" 22 23 "code.vegaprotocol.io/vega/datanode/entities" 24 vgtesting "code.vegaprotocol.io/vega/datanode/libs/testing" 25 "code.vegaprotocol.io/vega/datanode/sqlstore" 26 "code.vegaprotocol.io/vega/datanode/sqlstore/helpers" 27 eventspb "code.vegaprotocol.io/vega/protos/vega/events/v1" 28 29 "github.com/georgysavva/scany/pgxscan" 30 "github.com/stretchr/testify/assert" 31 "github.com/stretchr/testify/require" 32 ) 33 34 func TestPaidLiquidityFeesStats_Add(t *testing.T) { 35 t.Run("Should add the stats for the epoch if they do not exist", testAddPaidLiquidityFeesStatsEpochIfNotExists) 36 t.Run("Should not return an error if the epoch already exists for the market/asset/vega_time", testAddPaidLiquidityFeesStatsEpochExists) 37 } 38 39 type paidLiquidityFeesStatsTestStores struct { 40 bs *sqlstore.Blocks 41 ms *sqlstore.Markets 42 ps *sqlstore.Parties 43 as *sqlstore.Assets 44 ls *sqlstore.PaidLiquidityFeesStats 45 } 46 47 func setupPaidLiquidityFeesStatsStores(t *testing.T) *paidLiquidityFeesStatsTestStores { 48 t.Helper() 49 bs := sqlstore.NewBlocks(connectionSource) 50 ms := sqlstore.NewMarkets(connectionSource) 51 ps := sqlstore.NewParties(connectionSource) 52 as := sqlstore.NewAssets(connectionSource) 53 ls := sqlstore.NewPaidLiquidityFeesStats(connectionSource) 54 55 return &paidLiquidityFeesStatsTestStores{ 56 bs: bs, 57 ms: ms, 58 ps: ps, 59 as: as, 60 ls: ls, 61 } 62 } 63 64 func testAddPaidLiquidityFeesStatsEpochIfNotExists(t *testing.T) { 65 stores := setupPaidLiquidityFeesStatsStores(t) 66 ctx := tempTransaction(t) 67 block := addTestBlock(t, ctx, stores.bs) 68 market := helpers.AddTestMarket(t, ctx, stores.ms, block) 69 asset := addTestAsset(t, ctx, stores.as, block) 70 71 want := entities.PaidLiquidityFeesStats{ 72 MarketID: market.ID, 73 AssetID: asset.ID, 74 EpochSeq: 100, 75 TotalFeesPaid: "100", 76 FeesPerParty: []*eventspb.PartyAmount{ 77 {Party: "party-1", Amount: "50"}, 78 {Party: "party-2", Amount: "50"}, 79 {Party: "party-3", Amount: "50"}, 80 }, 81 VegaTime: time.Now(), 82 } 83 84 err := stores.ls.Add(ctx, &want) 85 require.NoError(t, err) 86 87 // Check that the stats were added 88 var got entities.PaidLiquidityFeesStats 89 err = pgxscan.Get(ctx, connectionSource, &got, 90 `SELECT market_id, asset_id, epoch_seq, total_fees_paid, fees_paid_per_party as fees_per_party 91 FROM paid_liquidity_fees WHERE market_id = $1 AND asset_id = $2 AND epoch_seq = $3`, 92 market.ID, asset.ID, want.EpochSeq, 93 ) 94 require.NoError(t, err) 95 vgtesting.AssertProtoEqual(t, want.ToProto(), got.ToProto()) 96 } 97 98 func testAddPaidLiquidityFeesStatsEpochExists(t *testing.T) { 99 stores := setupPaidLiquidityFeesStatsStores(t) 100 ctx := tempTransaction(t) 101 block := addTestBlock(t, ctx, stores.bs) 102 market := helpers.AddTestMarket(t, ctx, stores.ms, block) 103 asset := addTestAsset(t, ctx, stores.as, block) 104 105 want := entities.PaidLiquidityFeesStats{ 106 MarketID: market.ID, 107 AssetID: asset.ID, 108 EpochSeq: 100, 109 TotalFeesPaid: "100", 110 FeesPerParty: []*eventspb.PartyAmount{ 111 {Party: "party-1", Amount: "50"}, 112 {Party: "party-2", Amount: "50"}, 113 {Party: "party-3", Amount: "50"}, 114 }, 115 VegaTime: time.Now(), 116 } 117 118 err := stores.ls.Add(ctx, &want) 119 require.NoError(t, err) 120 121 // now try to insert again and make sure we get an error 122 err = stores.ls.Add(ctx, &want) 123 require.NoError(t, err) 124 } 125 126 func TestPaidLiquidityFeesStats_List(t *testing.T) { 127 t.Run("Should return the stats for the market and epoch requested", testListPaidLiquidityFeesStatsForMarketAndEpoch) 128 t.Run("Should return the stats for the asset and epoch requested", testListPaidLiquidityFeesStatsForAssetAndEpoch) 129 t.Run("Should return the latest stats for the market requested", testListPaidLiquidityFeesStatsForMarketLatest) 130 t.Run("Should return the latest stats for the asset requested", testListPaidLiquidityFeesStatsForAssetLatest) 131 t.Run("Should return the stats for the party and epoch requested", testListPaidLiquidityFeesStatsForPartyAndEpoch) 132 t.Run("Should return the latest stats for the party", testListPaidLiquidityFeesStatsForPartyLatest) 133 } 134 135 func setupPaidLiquidityFeesStats(t *testing.T, ctx context.Context, ls *sqlstore.PaidLiquidityFeesStats) []entities.PaidLiquidityFeesStats { 136 t.Helper() 137 stats := []entities.PaidLiquidityFeesStats{ 138 { 139 MarketID: entities.MarketID("deadbeef01"), 140 AssetID: entities.AssetID("deadbaad01"), 141 EpochSeq: 1, 142 TotalFeesPaid: "1000000", 143 FeesPerParty: []*eventspb.PartyAmount{ 144 { 145 Party: "cafed00d01", 146 Amount: "500000", 147 }, 148 { 149 Party: "cafed00d02", 150 Amount: "500000", 151 }, 152 }, 153 }, 154 { 155 MarketID: entities.MarketID("deadbeef01"), 156 AssetID: entities.AssetID("deadbaad01"), 157 EpochSeq: 2, 158 TotalFeesPaid: "1200000", 159 FeesPerParty: []*eventspb.PartyAmount{ 160 { 161 Party: "cafed00d01", 162 Amount: "600000", 163 }, 164 { 165 Party: "cafed00d02", 166 Amount: "600000", 167 }, 168 }, 169 }, 170 { 171 MarketID: entities.MarketID("deadbeef01"), 172 AssetID: entities.AssetID("deadbaad01"), 173 EpochSeq: 3, 174 TotalFeesPaid: "1400000", 175 FeesPerParty: []*eventspb.PartyAmount{ 176 { 177 Party: "cafed00d01", 178 Amount: "700000", 179 }, 180 { 181 Party: "cafed00d02", 182 Amount: "700000", 183 }, 184 }, 185 }, 186 { 187 MarketID: entities.MarketID("deadbeef02"), 188 AssetID: entities.AssetID("deadbaad02"), 189 EpochSeq: 1, 190 TotalFeesPaid: "1200000", 191 FeesPerParty: []*eventspb.PartyAmount{ 192 { 193 Party: "cafed00d01", 194 Amount: "700000", 195 }, 196 { 197 Party: "cafed00d02", 198 Amount: "500000", 199 }, 200 }, 201 }, 202 { 203 MarketID: entities.MarketID("deadbeef02"), 204 AssetID: entities.AssetID("deadbaad02"), 205 EpochSeq: 2, 206 TotalFeesPaid: "1000000", 207 FeesPerParty: []*eventspb.PartyAmount{ 208 { 209 Party: "cafed00d01", 210 Amount: "500000", 211 }, 212 { 213 Party: "cafed00d02", 214 Amount: "500000", 215 }, 216 }, 217 }, 218 { 219 MarketID: entities.MarketID("deadbeef02"), 220 AssetID: entities.AssetID("deadbaad02"), 221 EpochSeq: 3, 222 TotalFeesPaid: "5000000", 223 FeesPerParty: []*eventspb.PartyAmount{ 224 { 225 Party: "cafed00d01", 226 Amount: "25000", 227 }, 228 { 229 Party: "cafed00d02", 230 Amount: "25000", 231 }, 232 }, 233 }, 234 } 235 236 for _, stat := range stats { 237 err := ls.Add(ctx, &stat) 238 require.NoError(t, err) 239 } 240 241 return stats 242 } 243 244 func testListPaidLiquidityFeesStatsForMarketAndEpoch(t *testing.T) { 245 stores := setupPaidLiquidityFeesStatsStores(t) 246 ctx := tempTransaction(t) 247 stats := setupPaidLiquidityFeesStats(t, ctx, stores.ls) 248 249 pagination := entities.DefaultCursorPagination(true) 250 251 // get the stats for the first market and epoch 252 want := stats[0:1] 253 got, _, err := stores.ls.List(ctx, &want[0].MarketID, nil, &want[0].EpochSeq, nil, pagination, nil, nil) 254 require.NoError(t, err) 255 256 assert.Len(t, got, len(want)) 257 vgtesting.AssertProtoEqual(t, want[0].ToProto(), got[0].ToProto()) 258 259 // get the stats for the second market and epoch 260 want = stats[3:4] 261 got, _, err = stores.ls.List(ctx, &want[0].MarketID, nil, &want[0].EpochSeq, nil, pagination, nil, nil) 262 require.NoError(t, err) 263 264 assert.Len(t, got, len(want)) 265 vgtesting.AssertProtoEqual(t, want[0].ToProto(), got[0].ToProto()) 266 } 267 268 func testListPaidLiquidityFeesStatsForAssetAndEpoch(t *testing.T) { 269 stores := setupPaidLiquidityFeesStatsStores(t) 270 ctx := tempTransaction(t) 271 stats := setupPaidLiquidityFeesStats(t, ctx, stores.ls) 272 273 pagination := entities.DefaultCursorPagination(true) 274 275 // get the stats for the first market and epoch 276 want := stats[1:2] 277 got, _, err := stores.ls.List(ctx, nil, &want[0].AssetID, &want[0].EpochSeq, nil, pagination, nil, nil) 278 require.NoError(t, err) 279 280 assert.Len(t, got, len(want)) 281 vgtesting.AssertProtoEqual(t, want[0].ToProto(), got[0].ToProto()) 282 283 // get the stats for the second market and epoch 284 want = stats[4:5] 285 got, _, err = stores.ls.List(ctx, nil, &want[0].AssetID, &want[0].EpochSeq, nil, pagination, nil, nil) 286 require.NoError(t, err) 287 288 assert.Len(t, got, len(want)) 289 vgtesting.AssertProtoEqual(t, want[0].ToProto(), got[0].ToProto()) 290 } 291 292 func testListPaidLiquidityFeesStatsForMarketLatest(t *testing.T) { 293 stores := setupPaidLiquidityFeesStatsStores(t) 294 ctx := tempTransaction(t) 295 stats := setupPaidLiquidityFeesStats(t, ctx, stores.ls) 296 297 pagination := entities.DefaultCursorPagination(true) 298 299 // get the stats for the first market and epoch 300 want := stats[2:3] 301 got, _, err := stores.ls.List(ctx, &want[0].MarketID, nil, nil, nil, pagination, nil, nil) 302 require.NoError(t, err) 303 304 assert.Len(t, got, len(want)) 305 vgtesting.AssertProtoEqual(t, want[0].ToProto(), got[0].ToProto()) 306 307 // get the stats for the second market and epoch 308 want = stats[5:6] 309 got, _, err = stores.ls.List(ctx, &want[0].MarketID, nil, nil, nil, pagination, nil, nil) 310 require.NoError(t, err) 311 312 assert.Len(t, got, len(want)) 313 vgtesting.AssertProtoEqual(t, want[0].ToProto(), got[0].ToProto()) 314 } 315 316 func testListPaidLiquidityFeesStatsForAssetLatest(t *testing.T) { 317 stores := setupPaidLiquidityFeesStatsStores(t) 318 ctx := tempTransaction(t) 319 stats := setupPaidLiquidityFeesStats(t, ctx, stores.ls) 320 321 pagination := entities.DefaultCursorPagination(true) 322 323 // get the stats for the first market and epoch 324 want := stats[2:3] 325 got, _, err := stores.ls.List(ctx, nil, &want[0].AssetID, nil, nil, pagination, nil, nil) 326 require.NoError(t, err) 327 328 assert.Len(t, got, len(want)) 329 vgtesting.AssertProtoEqual(t, want[0].ToProto(), got[0].ToProto()) 330 331 // get the stats for the second market and epoch 332 want = stats[5:6] 333 got, _, err = stores.ls.List(ctx, nil, &want[0].AssetID, nil, nil, pagination, nil, nil) 334 require.NoError(t, err) 335 336 assert.Len(t, got, len(want)) 337 vgtesting.AssertProtoEqual(t, want[0].ToProto(), got[0].ToProto()) 338 } 339 340 func testListPaidLiquidityFeesStatsForPartyAndEpoch(t *testing.T) { 341 stores := setupPaidLiquidityFeesStatsStores(t) 342 ctx := tempTransaction(t) 343 stats := setupPaidLiquidityFeesStats(t, ctx, stores.ls) 344 345 pagination := entities.DefaultCursorPagination(true) 346 347 // get the stats for the first market and epoch 348 want := append(stats[3:4], stats[0:1]...) 349 want[0].FeesPerParty = want[0].FeesPerParty[:1] 350 want[1].FeesPerParty = want[1].FeesPerParty[:1] 351 352 got, _, err := stores.ls.List(ctx, nil, nil, &want[0].EpochSeq, []string{want[0].FeesPerParty[0].Party}, pagination, nil, nil) 353 require.NoError(t, err) 354 355 assert.Len(t, got, len(want)) 356 vgtesting.AssertProtoEqual(t, want[0].ToProto(), got[0].ToProto()) 357 vgtesting.AssertProtoEqual(t, want[1].ToProto(), got[1].ToProto()) 358 } 359 360 func testListPaidLiquidityFeesStatsForPartyLatest(t *testing.T) { 361 stores := setupPaidLiquidityFeesStatsStores(t) 362 ctx := tempTransaction(t) 363 stats := setupPaidLiquidityFeesStats(t, ctx, stores.ls) 364 365 pagination := entities.DefaultCursorPagination(true) 366 367 // get the stats for the first market and epoch 368 want := append(stats[5:6], stats[2:3]...) 369 want[0].FeesPerParty = want[0].FeesPerParty[:1] 370 want[1].FeesPerParty = want[1].FeesPerParty[:1] 371 372 got, _, err := stores.ls.List(ctx, nil, nil, nil, []string{want[0].FeesPerParty[0].Party}, pagination, nil, nil) 373 require.NoError(t, err) 374 375 assert.Len(t, got, len(want)) 376 vgtesting.AssertProtoEqual(t, want[0].ToProto(), got[0].ToProto()) 377 vgtesting.AssertProtoEqual(t, want[1].ToProto(), got[1].ToProto()) 378 }