code.vegaprotocol.io/vega@v0.79.0/core/integration/steps/the_referral_set_stats_should_be.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 steps 17 18 import ( 19 "errors" 20 "fmt" 21 "strings" 22 23 "code.vegaprotocol.io/vega/core/integration/stubs" 24 "code.vegaprotocol.io/vega/core/types" 25 "code.vegaprotocol.io/vega/libs/num" 26 27 "github.com/cucumber/godog" 28 "golang.org/x/exp/maps" 29 "golang.org/x/exp/slices" 30 ) 31 32 func TheReferralSetStatsShouldBe(broker *stubs.BrokerStub, code, epochStr, volumeStr string, table *godog.Table) error { 33 epoch, err := U64(epochStr) 34 if err != nil { 35 return fmt.Errorf("could not parse epoch: %w", err) 36 } 37 38 expectedVolume, overflown := num.UintFromString(volumeStr, 10) 39 if overflown { 40 return fmt.Errorf("could not parse the expected volume %q", volumeStr) 41 } 42 setID := types.ReferralSetID(code) 43 44 expectedRefereesStats, err := parseReferralStatsShouldBeTable(table) 45 if err != nil { 46 return fmt.Errorf("table is invalid: %w", err) 47 } 48 49 stats := broker.ReferralSetStats() 50 for _, stat := range stats { 51 if stat.AtEpoch == epoch && stat.SetID == setID { 52 if !stat.ReferralSetRunningVolume.EQ(expectedVolume) { 53 return fmt.Errorf("refferal set stats for set ID %q at epoch %q expect a running volume of %v, but got %v", code, epochStr, volumeStr, stat.ReferralSetRunningVolume) 54 } 55 56 return compareRefereesStats(expectedRefereesStats, stat.RefereesStats, stat.RewardFactors) 57 } 58 } 59 60 return fmt.Errorf("no stats found for set ID %q at epoch %q", code, epochStr) 61 } 62 63 type refereeStats struct { 64 DiscountFactor types.Factors 65 RewardFactor types.Factors 66 } 67 68 func parseReferralStatsShouldBeTable(table *godog.Table) (map[types.PartyID]*refereeStats, error) { 69 rows := StrictParseTable(table, []string{ 70 "party", 71 "discount infra factor", 72 "discount maker factor", 73 "discount liquidity factor", 74 "reward infra factor", 75 "reward maker factor", 76 "reward liquidity factor", 77 }, []string{}) 78 79 stats := map[types.PartyID]*refereeStats{} 80 for _, row := range rows { 81 specificRow := newReferralSetStatsShouldBeRow(row) 82 partyID := specificRow.Party() 83 _, alreadyRegistered := stats[partyID] 84 if alreadyRegistered { 85 return nil, fmt.Errorf("cannot have more than one expectation for party %q", partyID) 86 } 87 stats[partyID] = &refereeStats{ 88 DiscountFactor: types.Factors{ 89 Infra: specificRow.DiscountInfraFactor(), 90 Maker: specificRow.DiscountMakerFactor(), 91 Liquidity: specificRow.DiscountLiqFactor(), 92 }, 93 RewardFactor: types.Factors{ 94 Infra: specificRow.RewardInfraFactor(), 95 Maker: specificRow.RewardMakerFactor(), 96 Liquidity: specificRow.RewardLiqFactor(), 97 }, 98 } 99 } 100 101 return stats, nil 102 } 103 104 func compareRefereesStats( 105 expectedRefereesStats map[types.PartyID]*refereeStats, 106 foundRefereesStats map[types.PartyID]*types.RefereeStats, 107 foundRewardFactor types.Factors, 108 ) error { 109 foundRefereesIDs := maps.Keys(foundRefereesStats) 110 expectedRefereesIDs := maps.Keys(expectedRefereesStats) 111 112 slices.Sort(foundRefereesIDs) 113 slices.Sort(expectedRefereesIDs) 114 115 unexpectedParties := []string{} 116 partiesNotFound := []string{} 117 118 for _, expectedID := range expectedRefereesIDs { 119 if _, ok := foundRefereesStats[expectedID]; !ok { 120 partiesNotFound = append(partiesNotFound, string(expectedID)) 121 } 122 } 123 124 for _, foundID := range foundRefereesIDs { 125 if _, ok := expectedRefereesStats[foundID]; !ok { 126 unexpectedParties = append(unexpectedParties, string(foundID)) 127 } 128 } 129 130 var errStr string 131 if len(partiesNotFound) > 0 { 132 errStr = "parties not found: " + strings.Join(partiesNotFound, ", ") 133 } 134 if len(unexpectedParties) > 0 { 135 if errStr != "" { 136 errStr += ", and " 137 } 138 errStr += "unexpected parties: " + strings.Join(unexpectedParties, ", ") 139 } 140 if errStr != "" { 141 return errors.New(errStr) 142 } 143 144 for _, refereeID := range expectedRefereesIDs { 145 refereeIDStr := string(refereeID) 146 foundRefereeStats := foundRefereesStats[refereeID] 147 expectedRefereeStats := expectedRefereesStats[refereeID] 148 if !expectedRefereeStats.RewardFactor.Equal(foundRewardFactor) { 149 return fmt.Errorf("expecting reward factor of %v but got %v for party %q", expectedRefereeStats.RewardFactor.String(), foundRewardFactor.String(), refereeIDStr) 150 } 151 if !foundRefereeStats.DiscountFactors.Equal(expectedRefereeStats.DiscountFactor) { 152 return fmt.Errorf("expecting discount factor of %v but got %v for party %q", expectedRefereeStats.DiscountFactor.String(), foundRefereeStats.DiscountFactors.String(), refereeIDStr) 153 } 154 } 155 156 return nil 157 } 158 159 type referralSetStatsShouldBeRow struct { 160 row RowWrapper 161 } 162 163 func newReferralSetStatsShouldBeRow(r RowWrapper) referralSetStatsShouldBeRow { 164 row := referralSetStatsShouldBeRow{ 165 row: r, 166 } 167 return row 168 } 169 170 func (r referralSetStatsShouldBeRow) Party() types.PartyID { 171 return types.PartyID(r.row.MustStr("party")) 172 } 173 174 func (r referralSetStatsShouldBeRow) DiscountInfraFactor() num.Decimal { 175 return r.row.MustDecimal("discount infra factor") 176 } 177 178 func (r referralSetStatsShouldBeRow) DiscountMakerFactor() num.Decimal { 179 return r.row.MustDecimal("discount maker factor") 180 } 181 182 func (r referralSetStatsShouldBeRow) DiscountLiqFactor() num.Decimal { 183 return r.row.MustDecimal("discount liquidity factor") 184 } 185 186 func (r referralSetStatsShouldBeRow) RewardInfraFactor() num.Decimal { 187 return r.row.MustDecimal("reward infra factor") 188 } 189 190 func (r referralSetStatsShouldBeRow) RewardMakerFactor() num.Decimal { 191 return r.row.MustDecimal("reward maker factor") 192 } 193 194 func (r referralSetStatsShouldBeRow) RewardLiqFactor() num.Decimal { 195 return r.row.MustDecimal("reward liquidity factor") 196 }