code.vegaprotocol.io/vega@v0.79.0/datanode/sqlstore/fees_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 "code.vegaprotocol.io/vega/datanode/sqlstore" 25 "code.vegaprotocol.io/vega/datanode/sqlstore/helpers" 26 "code.vegaprotocol.io/vega/libs/ptr" 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 TestFeesStats_AddFeesStats(t *testing.T) { 35 t.Run("Should add the stats for the epoch if they do not exist", testAddFeesStatsEpochNotExists) 36 t.Run("Should return an error if the epoch already exists for the market/asset", testAddFeesStatsEpochExists) 37 } 38 39 type FeesStatsTestStores struct { 40 bs *sqlstore.Blocks 41 ms *sqlstore.Markets 42 ps *sqlstore.Parties 43 as *sqlstore.Assets 44 fs *sqlstore.FeesStats 45 } 46 47 func setupFeesStatsStores(t *testing.T) *FeesStatsTestStores { 48 t.Helper() 49 bs := sqlstore.NewBlocks(connectionSource) 50 ms := sqlstore.NewMarkets(connectionSource) 51 ps := sqlstore.NewParties(connectionSource) 52 as := sqlstore.NewAssets(connectionSource) 53 fs := sqlstore.NewFeesStats(connectionSource) 54 55 return &FeesStatsTestStores{ 56 bs: bs, 57 ms: ms, 58 ps: ps, 59 as: as, 60 fs: fs, 61 } 62 } 63 64 func testAddFeesStatsEpochNotExists(t *testing.T) { 65 stores := setupFeesStatsStores(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.FeesStats{ 72 MarketID: market.ID, 73 AssetID: asset.ID, 74 EpochSeq: 100, 75 TotalRewardsReceived: nil, 76 ReferrerRewardsGenerated: nil, 77 RefereesDiscountApplied: nil, 78 VolumeDiscountApplied: nil, 79 VegaTime: block.VegaTime, 80 } 81 82 err := stores.fs.AddFeesStats(ctx, &want) 83 require.NoError(t, err) 84 85 // Check that the stats were added 86 var got entities.FeesStats 87 err = pgxscan.Get(ctx, connectionSource, &got, 88 `SELECT * FROM fees_stats WHERE market_id = $1 AND asset_id = $2 AND epoch_seq = $3`, 89 market.ID, asset.ID, want.EpochSeq, 90 ) 91 require.NoError(t, err) 92 assert.Equal(t, want, got) 93 } 94 95 func testAddFeesStatsEpochExists(t *testing.T) { 96 stores := setupFeesStatsStores(t) 97 ctx := tempTransaction(t) 98 block := addTestBlock(t, ctx, stores.bs) 99 market := helpers.AddTestMarket(t, ctx, stores.ms, block) 100 asset := addTestAsset(t, ctx, stores.as, block) 101 102 want := entities.FeesStats{ 103 MarketID: market.ID, 104 AssetID: asset.ID, 105 EpochSeq: 100, 106 TotalRewardsReceived: nil, 107 ReferrerRewardsGenerated: nil, 108 RefereesDiscountApplied: nil, 109 VolumeDiscountApplied: nil, 110 VegaTime: block.VegaTime, 111 } 112 113 err := stores.fs.AddFeesStats(ctx, &want) 114 require.NoError(t, err) 115 116 // now try to insert again and make sure we get an error 117 err = stores.fs.AddFeesStats(ctx, &want) 118 require.Error(t, err) 119 assert.Contains(t, err.Error(), "duplicate key value violates unique constraint") 120 } 121 122 func TestFeesStats_GetFeesStats(t *testing.T) { 123 t.Run("Should return the stats for the market and epoch requested", testGetFeesStatsForMarketAndEpoch) 124 t.Run("Should return the stats for the asset and epoch requested", testGetFeesStatsForAssetAndEpoch) 125 t.Run("Should return the latest stats for the market requested", testGetFeesStatsForMarketLatest) 126 t.Run("Should return the latest stats for the asset requested", testGetFeesStatsForAssetLatest) 127 t.Run("Should return an error if an asset and market is provided", testGetFeesStatsNoAssetOrMarket) 128 t.Run("Should return the stats for the party and epoch requested", testGetFeesStatsForPartyAndEpoch) 129 t.Run("Should return the latest stats for the party", testGetFeesStatsForPartyLatest) 130 t.Run("Should return the stats for all asset given a party", testGetFeesStatsForParty) 131 } 132 133 func testGetFeesStatsForMarketAndEpoch(t *testing.T) { 134 stores := setupFeesStatsStores(t) 135 ctx := tempTransaction(t) 136 stats := setupFeesStats(t, ctx, stores.fs) 137 138 // get the stats for the first market and epoch 139 want := stats[0] 140 got, err := stores.fs.GetFeesStats(ctx, &want.MarketID, nil, &want.EpochSeq, nil, nil, nil) 141 require.NoError(t, err) 142 assert.Equal(t, want, *got) 143 144 // get the stats for the second market and epoch 145 want = stats[3] 146 got, err = stores.fs.GetFeesStats(ctx, &want.MarketID, nil, &want.EpochSeq, nil, nil, nil) 147 require.NoError(t, err) 148 assert.Equal(t, want, *got) 149 } 150 151 func testGetFeesStatsForAssetAndEpoch(t *testing.T) { 152 stores := setupFeesStatsStores(t) 153 ctx := tempTransaction(t) 154 stats := setupFeesStats(t, ctx, stores.fs) 155 156 // get the stats for the first market and epoch 157 want := stats[0] 158 got, err := stores.fs.GetFeesStats(ctx, nil, &want.AssetID, &want.EpochSeq, nil, nil, nil) 159 require.NoError(t, err) 160 assert.Equal(t, want, *got) 161 162 // get the stats for the second market and epoch 163 want = stats[6] 164 got, err = stores.fs.GetFeesStats(ctx, nil, &want.AssetID, &want.EpochSeq, nil, nil, nil) 165 require.NoError(t, err) 166 assert.Equal(t, want, *got) 167 } 168 169 func testGetFeesStatsForMarketLatest(t *testing.T) { 170 stores := setupFeesStatsStores(t) 171 ctx := tempTransaction(t) 172 stats := setupFeesStats(t, ctx, stores.fs) 173 174 // get the stats for the first market and epoch 175 want := stats[2] 176 got, err := stores.fs.GetFeesStats(ctx, &want.MarketID, nil, nil, nil, nil, nil) 177 require.NoError(t, err) 178 assert.Equal(t, want, *got) 179 180 // get the stats for the second market and epoch 181 want = stats[8] 182 got, err = stores.fs.GetFeesStats(ctx, &want.MarketID, nil, nil, nil, nil, nil) 183 require.NoError(t, err) 184 assert.Equal(t, want, *got) 185 } 186 187 func testGetFeesStatsForAssetLatest(t *testing.T) { 188 stores := setupFeesStatsStores(t) 189 ctx := tempTransaction(t) 190 stats := setupFeesStats(t, ctx, stores.fs) 191 192 // get the stats for the first market and epoch 193 want := stats[2] 194 got, err := stores.fs.GetFeesStats(ctx, nil, &want.AssetID, nil, nil, nil, nil) 195 require.NoError(t, err) 196 assert.Equal(t, want, *got) 197 198 // get the stats for the second market and epoch 199 want = stats[8] 200 got, err = stores.fs.GetFeesStats(ctx, nil, &want.AssetID, nil, nil, nil, nil) 201 require.NoError(t, err) 202 assert.Equal(t, want, *got) 203 } 204 205 func testGetFeesStatsNoAssetOrMarket(t *testing.T) { 206 stores := setupFeesStatsStores(t) 207 ctx := tempTransaction(t) 208 209 _, err := stores.fs.GetFeesStats(ctx, ptr.From(entities.MarketID("deadbeef01")), ptr.From(entities.AssetID("deadbeef02")), nil, nil, nil, nil) 210 require.Error(t, err) 211 } 212 213 func testGetFeesStatsForPartyAndEpoch(t *testing.T) { 214 stores := setupFeesStatsStores(t) 215 ctx := tempTransaction(t) 216 stats := setupFeesStats(t, ctx, stores.fs) 217 218 // get the stats for the first market and epoch 219 expected := stats[1] 220 want := entities.FeesStats{ 221 MarketID: entities.MarketID("deadbeef01"), 222 AssetID: entities.AssetID("deadbaad01"), 223 EpochSeq: 2, 224 TotalRewardsReceived: []*eventspb.PartyAmount{ 225 { 226 Party: "cafedaad01", 227 Amount: "1100000", 228 }, 229 }, 230 ReferrerRewardsGenerated: []*eventspb.ReferrerRewardsGenerated{ 231 { 232 Referrer: "cafedaad01", 233 GeneratedReward: []*eventspb.PartyAmount{ 234 { 235 Party: "cafed00d01", 236 Amount: "550000", 237 }, 238 { 239 Party: "cafed00d02", 240 Amount: "550000", 241 }, 242 }, 243 }, 244 }, 245 RefereesDiscountApplied: []*eventspb.PartyAmount{}, 246 VolumeDiscountApplied: []*eventspb.PartyAmount{}, 247 TotalMakerFeesReceived: []*eventspb.PartyAmount{}, 248 MakerFeesGenerated: []*eventspb.MakerFeesGenerated{}, 249 VegaTime: expected.VegaTime, 250 } 251 252 got, err := stores.fs.GetFeesStats(ctx, nil, &want.AssetID, ptr.From(want.EpochSeq), &want.ReferrerRewardsGenerated[0].Referrer, nil, nil) 253 require.NoError(t, err) 254 assert.Equal(t, want, *got) 255 } 256 257 func testGetFeesStatsForPartyLatest(t *testing.T) { 258 stores := setupFeesStatsStores(t) 259 ctx := tempTransaction(t) 260 stats := setupFeesStats(t, ctx, stores.fs) 261 262 // get the stats for the first market and epoch 263 expected := stats[2] 264 want := entities.FeesStats{ 265 MarketID: entities.MarketID("deadbeef01"), 266 AssetID: entities.AssetID("deadbaad01"), 267 EpochSeq: 3, 268 TotalRewardsReceived: []*eventspb.PartyAmount{ 269 { 270 Party: "cafedaad01", 271 Amount: "1200000", 272 }, 273 }, 274 ReferrerRewardsGenerated: []*eventspb.ReferrerRewardsGenerated{ 275 { 276 Referrer: "cafedaad01", 277 GeneratedReward: []*eventspb.PartyAmount{ 278 { 279 Party: "cafed00d01", 280 Amount: "600000", 281 }, 282 { 283 Party: "cafed00d02", 284 Amount: "600000", 285 }, 286 }, 287 }, 288 }, 289 RefereesDiscountApplied: []*eventspb.PartyAmount{}, 290 VolumeDiscountApplied: []*eventspb.PartyAmount{}, 291 TotalMakerFeesReceived: []*eventspb.PartyAmount{}, 292 MakerFeesGenerated: []*eventspb.MakerFeesGenerated{}, 293 VegaTime: expected.VegaTime, 294 } 295 got, err := stores.fs.GetFeesStats(ctx, nil, &want.AssetID, nil, &want.ReferrerRewardsGenerated[0].Referrer, nil, nil) 296 require.NoError(t, err) 297 assert.Equal(t, want, *got) 298 } 299 300 func testGetFeesStatsForParty(t *testing.T) { 301 stores := setupFeesStatsStores(t) 302 ctx := tempTransaction(t) 303 _ = setupFeesStats(t, ctx, stores.fs) 304 305 got, err := stores.fs.StatsForParty(ctx, "cafedaad01", ptr.From(entities.AssetID("deadbaad01")), ptr.From(uint64(1)), ptr.From(uint64(2))) 306 require.NoError(t, err) 307 assert.Equal(t, []entities.FeesStatsForParty{ 308 { 309 AssetID: entities.AssetID("deadbaad01"), 310 TotalRewardsReceived: "4200000", 311 RefereesDiscountApplied: "0", 312 VolumeDiscountApplied: "0", 313 TotalMakerFeesReceived: "0", 314 }, 315 }, got) 316 317 got, err = stores.fs.StatsForParty(ctx, "cafedaad01", ptr.From(entities.AssetID("deadbaad01")), ptr.From(uint64(2)), nil) 318 require.NoError(t, err) 319 assert.Equal(t, []entities.FeesStatsForParty{ 320 { 321 AssetID: entities.AssetID("deadbaad01"), 322 TotalRewardsReceived: "4600000", 323 RefereesDiscountApplied: "0", 324 VolumeDiscountApplied: "0", 325 TotalMakerFeesReceived: "0", 326 }, 327 }, got) 328 329 got, err = stores.fs.StatsForParty(ctx, "cafedaad01", ptr.From(entities.AssetID("deadbaad01")), nil, ptr.From(uint64(2))) 330 require.NoError(t, err) 331 assert.Equal(t, []entities.FeesStatsForParty{ 332 { 333 AssetID: entities.AssetID("deadbaad01"), 334 TotalRewardsReceived: "4200000", 335 RefereesDiscountApplied: "0", 336 VolumeDiscountApplied: "0", 337 TotalMakerFeesReceived: "0", 338 }, 339 }, got) 340 341 got, err = stores.fs.StatsForParty(ctx, "cafedaad01", ptr.From(entities.AssetID("deadbaad01")), nil, nil) 342 require.NoError(t, err) 343 assert.Equal(t, []entities.FeesStatsForParty{ 344 { 345 AssetID: entities.AssetID("deadbaad01"), 346 TotalRewardsReceived: "2400000", 347 RefereesDiscountApplied: "0", 348 VolumeDiscountApplied: "0", 349 TotalMakerFeesReceived: "0", 350 }, 351 }, got) 352 } 353 354 func setupFeesStats(t *testing.T, ctx context.Context, fs *sqlstore.FeesStats) []entities.FeesStats { 355 t.Helper() 356 vegaTime := time.Now().Add(-time.Minute).Round(time.Microsecond) // round to microsecond because Postgres doesn't store nanoseconds at the current time 357 stats := []entities.FeesStats{ 358 { 359 MarketID: entities.MarketID("deadbeef01"), 360 AssetID: entities.AssetID("deadbaad01"), 361 EpochSeq: 1, 362 TotalRewardsReceived: []*eventspb.PartyAmount{ 363 { 364 Party: "cafedaad01", 365 Amount: "1000000", 366 }, 367 }, 368 ReferrerRewardsGenerated: []*eventspb.ReferrerRewardsGenerated{ 369 { 370 Referrer: "cafedaad01", 371 GeneratedReward: []*eventspb.PartyAmount{ 372 { 373 Party: "cafed00d01", 374 Amount: "500000", 375 }, 376 { 377 Party: "cafed00d02", 378 Amount: "500000", 379 }, 380 }, 381 }, 382 }, 383 RefereesDiscountApplied: []*eventspb.PartyAmount{ 384 { 385 Party: "cafed00d01", 386 Amount: "100000", 387 }, 388 { 389 Party: "cafed00d02", 390 Amount: "100000", 391 }, 392 }, 393 VegaTime: vegaTime.Add(5 * time.Second), 394 }, 395 { 396 MarketID: entities.MarketID("deadbeef01"), 397 AssetID: entities.AssetID("deadbaad01"), 398 EpochSeq: 2, 399 TotalRewardsReceived: []*eventspb.PartyAmount{ 400 { 401 Party: "cafedaad01", 402 Amount: "1100000", 403 }, 404 }, 405 ReferrerRewardsGenerated: []*eventspb.ReferrerRewardsGenerated{ 406 { 407 Referrer: "cafedaad01", 408 GeneratedReward: []*eventspb.PartyAmount{ 409 { 410 Party: "cafed00d01", 411 Amount: "550000", 412 }, 413 { 414 Party: "cafed00d02", 415 Amount: "550000", 416 }, 417 }, 418 }, 419 }, 420 RefereesDiscountApplied: []*eventspb.PartyAmount{ 421 { 422 Party: "cafed00d01", 423 Amount: "110000", 424 }, 425 { 426 Party: "cafed00d02", 427 Amount: "110000", 428 }, 429 }, 430 VolumeDiscountApplied: []*eventspb.PartyAmount{}, 431 VegaTime: vegaTime.Add(10 * time.Second), 432 }, 433 { 434 MarketID: entities.MarketID("deadbeef01"), 435 AssetID: entities.AssetID("deadbaad01"), 436 EpochSeq: 3, 437 TotalRewardsReceived: []*eventspb.PartyAmount{ 438 { 439 Party: "cafedaad01", 440 Amount: "1200000", 441 }, 442 }, 443 ReferrerRewardsGenerated: []*eventspb.ReferrerRewardsGenerated{ 444 { 445 Referrer: "cafedaad01", 446 GeneratedReward: []*eventspb.PartyAmount{ 447 { 448 Party: "cafed00d01", 449 Amount: "600000", 450 }, 451 { 452 Party: "cafed00d02", 453 Amount: "600000", 454 }, 455 }, 456 }, 457 }, 458 RefereesDiscountApplied: []*eventspb.PartyAmount{ 459 { 460 Party: "cafed00d01", 461 Amount: "120000", 462 }, 463 { 464 Party: "cafed00d02", 465 Amount: "120000", 466 }, 467 }, 468 VolumeDiscountApplied: []*eventspb.PartyAmount{}, 469 VegaTime: vegaTime.Add(15 * time.Second), 470 }, 471 { 472 MarketID: entities.MarketID("deadbeef11"), 473 AssetID: entities.AssetID("deadbaad01"), 474 EpochSeq: 1, 475 TotalRewardsReceived: []*eventspb.PartyAmount{ 476 { 477 Party: "cafedaad01", 478 Amount: "1000000", 479 }, 480 }, 481 ReferrerRewardsGenerated: []*eventspb.ReferrerRewardsGenerated{ 482 { 483 Referrer: "cafedaad01", 484 GeneratedReward: []*eventspb.PartyAmount{ 485 { 486 Party: "cafed00d01", 487 Amount: "500000", 488 }, 489 { 490 Party: "cafed00d02", 491 Amount: "500000", 492 }, 493 }, 494 }, 495 }, 496 RefereesDiscountApplied: []*eventspb.PartyAmount{ 497 { 498 Party: "cafed00d01", 499 Amount: "100000", 500 }, 501 { 502 Party: "cafed00d02", 503 Amount: "100000", 504 }, 505 }, 506 VegaTime: vegaTime.Add(5 * time.Second), 507 }, 508 { 509 MarketID: entities.MarketID("deadbeef11"), 510 AssetID: entities.AssetID("deadbaad01"), 511 EpochSeq: 2, 512 TotalRewardsReceived: []*eventspb.PartyAmount{ 513 { 514 Party: "cafedaad01", 515 Amount: "1100000", 516 }, 517 }, 518 ReferrerRewardsGenerated: []*eventspb.ReferrerRewardsGenerated{ 519 { 520 Referrer: "cafedaad01", 521 GeneratedReward: []*eventspb.PartyAmount{ 522 { 523 Party: "cafed00d01", 524 Amount: "550000", 525 }, 526 { 527 Party: "cafed00d02", 528 Amount: "550000", 529 }, 530 }, 531 }, 532 }, 533 RefereesDiscountApplied: []*eventspb.PartyAmount{ 534 { 535 Party: "cafed00d01", 536 Amount: "110000", 537 }, 538 { 539 Party: "cafed00d02", 540 Amount: "110000", 541 }, 542 }, 543 VolumeDiscountApplied: []*eventspb.PartyAmount{}, 544 VegaTime: vegaTime.Add(10 * time.Second), 545 }, 546 { 547 MarketID: entities.MarketID("deadbeef11"), 548 AssetID: entities.AssetID("deadbaad01"), 549 EpochSeq: 3, 550 TotalRewardsReceived: []*eventspb.PartyAmount{ 551 { 552 Party: "cafedaad01", 553 Amount: "1200000", 554 }, 555 }, 556 ReferrerRewardsGenerated: []*eventspb.ReferrerRewardsGenerated{ 557 { 558 Referrer: "cafedaad01", 559 GeneratedReward: []*eventspb.PartyAmount{ 560 { 561 Party: "cafed00d01", 562 Amount: "600000", 563 }, 564 { 565 Party: "cafed00d02", 566 Amount: "600000", 567 }, 568 }, 569 }, 570 }, 571 RefereesDiscountApplied: []*eventspb.PartyAmount{ 572 { 573 Party: "cafed00d01", 574 Amount: "120000", 575 }, 576 { 577 Party: "cafed00d02", 578 Amount: "120000", 579 }, 580 }, 581 VolumeDiscountApplied: []*eventspb.PartyAmount{}, 582 VegaTime: vegaTime.Add(15 * time.Second), 583 }, 584 { 585 MarketID: entities.MarketID("deadbeef02"), 586 AssetID: entities.AssetID("deadbaad02"), 587 EpochSeq: 1, 588 TotalRewardsReceived: []*eventspb.PartyAmount{ 589 { 590 Party: "cafedaad02", 591 Amount: "2000000", 592 }, 593 }, 594 ReferrerRewardsGenerated: []*eventspb.ReferrerRewardsGenerated{ 595 { 596 Referrer: "cafedaad02", 597 GeneratedReward: []*eventspb.PartyAmount{ 598 { 599 Party: "cafed00d03", 600 Amount: "2000000", 601 }, 602 { 603 Party: "cafed00d04", 604 Amount: "2000000", 605 }, 606 }, 607 }, 608 }, 609 RefereesDiscountApplied: []*eventspb.PartyAmount{ 610 { 611 Party: "cafed00d03", 612 Amount: "200000", 613 }, 614 { 615 Party: "cafed00d04", 616 Amount: "200000", 617 }, 618 }, 619 VolumeDiscountApplied: []*eventspb.PartyAmount{}, 620 VegaTime: vegaTime.Add(5 * time.Second), 621 }, 622 { 623 MarketID: entities.MarketID("deadbeef02"), 624 AssetID: entities.AssetID("deadbaad02"), 625 EpochSeq: 2, 626 TotalRewardsReceived: []*eventspb.PartyAmount{ 627 { 628 Party: "cafedaad02", 629 Amount: "2100000", 630 }, 631 }, 632 ReferrerRewardsGenerated: []*eventspb.ReferrerRewardsGenerated{ 633 { 634 Referrer: "cafedaad01", 635 GeneratedReward: []*eventspb.PartyAmount{ 636 { 637 Party: "cafed00d03", 638 Amount: "1050000", 639 }, 640 { 641 Party: "cafed00d04", 642 Amount: "1050000", 643 }, 644 }, 645 }, 646 }, 647 RefereesDiscountApplied: []*eventspb.PartyAmount{ 648 { 649 Party: "cafed00d03", 650 Amount: "210000", 651 }, 652 { 653 Party: "cafed00d04", 654 Amount: "210000", 655 }, 656 }, 657 VolumeDiscountApplied: []*eventspb.PartyAmount{}, 658 VegaTime: vegaTime.Add(10 * time.Second), 659 }, 660 { 661 MarketID: entities.MarketID("deadbeef02"), 662 AssetID: entities.AssetID("deadbaad02"), 663 EpochSeq: 3, 664 TotalRewardsReceived: []*eventspb.PartyAmount{ 665 { 666 Party: "cafedaad02", 667 Amount: "2200000", 668 }, 669 }, 670 ReferrerRewardsGenerated: []*eventspb.ReferrerRewardsGenerated{ 671 { 672 Referrer: "cafedaad01", 673 GeneratedReward: []*eventspb.PartyAmount{ 674 { 675 Party: "cafed00d03", 676 Amount: "1100000", 677 }, 678 { 679 Party: "cafed00d04", 680 Amount: "1100000", 681 }, 682 }, 683 }, 684 }, 685 RefereesDiscountApplied: []*eventspb.PartyAmount{ 686 { 687 Party: "cafed00d03", 688 Amount: "220000", 689 }, 690 { 691 Party: "cafed00d04", 692 Amount: "220000", 693 }, 694 }, 695 VolumeDiscountApplied: []*eventspb.PartyAmount{}, 696 VegaTime: vegaTime.Add(15 * time.Second), 697 }, 698 } 699 700 for _, stat := range stats { 701 err := fs.AddFeesStats(ctx, &stat) 702 require.NoError(t, err) 703 } 704 705 return stats 706 }