code.vegaprotocol.io/vega@v0.79.0/core/fee/rebate_stats.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 fee 17 18 import ( 19 "sort" 20 21 "code.vegaprotocol.io/vega/libs/num" 22 eventspb "code.vegaprotocol.io/vega/protos/vega/events/v1" 23 24 "golang.org/x/exp/maps" 25 ) 26 27 type FeesStats struct { 28 // TotalMakerFeesReceived is the total of maker fees received by the maker side. 29 // maker -> amount 30 TotalMakerFeesReceived map[string]*num.Uint 31 // TradingFeesPaidAndReceived tracks all trading fees paid and received by party. 32 TradingFeesPaidAndReceived map[string]*num.Uint 33 // MakerFeesGenerated tracks maker fees paid by taker (aggressor) to the maker. 34 // taker -> maker -> amount 35 MakerFeesGenerated map[string]map[string]*num.Uint 36 // TotalRewardsReceived is the total of rewards received by the referrer. 37 // referrer -> amount 38 TotalRewardsReceived map[string]*num.Uint 39 ReferrerRewardsGenerated map[string]map[string]*num.Uint 40 RefereeDiscountApplied map[string]*num.Uint 41 VolumeDiscountApplied map[string]*num.Uint 42 } 43 44 func NewFeesStats() *FeesStats { 45 return &FeesStats{ 46 TotalMakerFeesReceived: map[string]*num.Uint{}, 47 MakerFeesGenerated: map[string]map[string]*num.Uint{}, 48 TradingFeesPaidAndReceived: map[string]*num.Uint{}, 49 TotalRewardsReceived: map[string]*num.Uint{}, 50 ReferrerRewardsGenerated: map[string]map[string]*num.Uint{}, 51 RefereeDiscountApplied: map[string]*num.Uint{}, 52 VolumeDiscountApplied: map[string]*num.Uint{}, 53 } 54 } 55 56 func NewFeesStatsFromProto(fsp *eventspb.FeesStats) *FeesStats { 57 fs := NewFeesStats() 58 59 for _, v := range fsp.RefereesDiscountApplied { 60 fs.RefereeDiscountApplied[v.Party] = num.MustUintFromString(v.Amount, 10) 61 } 62 63 for _, v := range fsp.VolumeDiscountApplied { 64 fs.VolumeDiscountApplied[v.Party] = num.MustUintFromString(v.Amount, 10) 65 } 66 67 for _, v := range fsp.TotalRewardsReceived { 68 fs.TotalRewardsReceived[v.Party] = num.MustUintFromString(v.Amount, 10) 69 } 70 71 for _, v := range fsp.ReferrerRewardsGenerated { 72 rg := map[string]*num.Uint{} 73 for _, pa := range v.GeneratedReward { 74 rg[pa.Party] = num.MustUintFromString(pa.Amount, 10) 75 } 76 77 fs.ReferrerRewardsGenerated[v.Referrer] = rg 78 } 79 80 for _, v := range fsp.TotalMakerFeesReceived { 81 fs.TotalMakerFeesReceived[v.Party] = num.MustUintFromString(v.Amount, 10) 82 } 83 84 for _, f := range fsp.MakerFeesGenerated { 85 rg := map[string]*num.Uint{} 86 for _, pa := range f.MakerFeesPaid { 87 rg[pa.Party] = num.MustUintFromString(pa.Amount, 10) 88 } 89 90 fs.MakerFeesGenerated[f.Taker] = rg 91 } 92 93 for _, f := range fsp.TotalFeesPaidAndReceived { 94 fs.TradingFeesPaidAndReceived[f.Party] = num.MustUintFromString(f.Amount, 10) 95 } 96 97 return fs 98 } 99 100 func (f *FeesStats) RegisterMakerFee(makerID, takerID string, amount *num.Uint) { 101 total, ok := f.TotalMakerFeesReceived[makerID] 102 if !ok { 103 total = num.NewUint(0) 104 f.TotalMakerFeesReceived[makerID] = total 105 } 106 107 total.Add(total, amount) 108 109 makerFeesGenerated, ok := f.MakerFeesGenerated[takerID] 110 if !ok { 111 makerFeesGenerated = map[string]*num.Uint{} 112 f.MakerFeesGenerated[takerID] = makerFeesGenerated 113 } 114 115 makerTally, ok := makerFeesGenerated[makerID] 116 if !ok { 117 makerTally = num.NewUint(0) 118 makerFeesGenerated[makerID] = makerTally 119 } 120 121 makerTally.Add(makerTally, amount) 122 } 123 124 // RegisterTradingFees registers fees paid or received by the party. 125 func (f *FeesStats) RegisterTradingFees(partyID string, amount *num.Uint) { 126 if _, ok := f.TradingFeesPaidAndReceived[partyID]; !ok { 127 f.TradingFeesPaidAndReceived[partyID] = num.UintZero() 128 } 129 130 f.TradingFeesPaidAndReceived[partyID].AddSum(amount) 131 } 132 133 func (f *FeesStats) RegisterReferrerReward( 134 referrer, referee string, 135 amount *num.Uint, 136 ) { 137 total, ok := f.TotalRewardsReceived[referrer] 138 if !ok { 139 total = num.NewUint(0) 140 f.TotalRewardsReceived[referrer] = total 141 } 142 143 total.Add(total, amount) 144 145 rewardsGenerated, ok := f.ReferrerRewardsGenerated[referrer] 146 if !ok { 147 rewardsGenerated = map[string]*num.Uint{} 148 f.ReferrerRewardsGenerated[referrer] = rewardsGenerated 149 } 150 151 refereeTally, ok := rewardsGenerated[referee] 152 if !ok { 153 refereeTally = num.NewUint(0) 154 rewardsGenerated[referee] = refereeTally 155 } 156 157 refereeTally.Add(refereeTally, amount) 158 } 159 160 func (f *FeesStats) RegisterRefereeDiscount(party string, amount *num.Uint) { 161 total, ok := f.RefereeDiscountApplied[party] 162 if !ok { 163 total = num.NewUint(0) 164 f.RefereeDiscountApplied[party] = total 165 } 166 167 total.Add(total, amount) 168 } 169 170 func (f *FeesStats) RegisterVolumeDiscount(party string, amount *num.Uint) { 171 total, ok := f.VolumeDiscountApplied[party] 172 if !ok { 173 total = num.NewUint(0) 174 f.VolumeDiscountApplied[party] = total 175 } 176 177 total.Add(total, amount) 178 } 179 180 // TotalTradingFeesPerParty returns per party sum of all paid and received trading fees. 181 func (f *FeesStats) TotalTradingFeesPerParty() map[string]*num.Uint { 182 return f.TradingFeesPaidAndReceived 183 } 184 185 func (f *FeesStats) ToProto(asset string, assetQuantum num.Decimal) *eventspb.FeesStats { 186 fs := &eventspb.FeesStats{ 187 Asset: asset, 188 TotalRewardsReceived: make([]*eventspb.PartyAmount, 0, len(f.TotalRewardsReceived)), 189 ReferrerRewardsGenerated: make([]*eventspb.ReferrerRewardsGenerated, 0, len(f.ReferrerRewardsGenerated)), 190 RefereesDiscountApplied: make([]*eventspb.PartyAmount, 0, len(f.RefereeDiscountApplied)), 191 VolumeDiscountApplied: make([]*eventspb.PartyAmount, 0, len(f.VolumeDiscountApplied)), 192 TotalMakerFeesReceived: make([]*eventspb.PartyAmount, 0, len(f.TotalMakerFeesReceived)), 193 MakerFeesGenerated: make([]*eventspb.MakerFeesGenerated, 0, len(f.MakerFeesGenerated)), 194 TotalFeesPaidAndReceived: make([]*eventspb.PartyAmount, 0, len(f.TradingFeesPaidAndReceived)), 195 } 196 197 totalRewardsReceivedParties := maps.Keys(f.TotalRewardsReceived) 198 sort.Strings(totalRewardsReceivedParties) 199 for _, party := range totalRewardsReceivedParties { 200 amount := f.TotalRewardsReceived[party] 201 fs.TotalRewardsReceived = append(fs.TotalRewardsReceived, &eventspb.PartyAmount{ 202 Party: party, 203 Amount: amount.String(), 204 QuantumAmount: amount.ToDecimal().Div(assetQuantum).Truncate(6).String(), 205 }) 206 } 207 208 refereesDiscountAppliedParties := maps.Keys(f.RefereeDiscountApplied) 209 sort.Strings(refereesDiscountAppliedParties) 210 for _, party := range refereesDiscountAppliedParties { 211 amount := f.RefereeDiscountApplied[party] 212 fs.RefereesDiscountApplied = append(fs.RefereesDiscountApplied, &eventspb.PartyAmount{ 213 Party: party, 214 Amount: amount.String(), 215 QuantumAmount: amount.ToDecimal().Div(assetQuantum).Truncate(6).String(), 216 }) 217 } 218 219 volumeDiscountAppliedParties := maps.Keys(f.VolumeDiscountApplied) 220 sort.Strings(volumeDiscountAppliedParties) 221 for _, party := range volumeDiscountAppliedParties { 222 amount := f.VolumeDiscountApplied[party] 223 fs.VolumeDiscountApplied = append(fs.VolumeDiscountApplied, &eventspb.PartyAmount{ 224 Party: party, 225 Amount: amount.String(), 226 QuantumAmount: amount.ToDecimal().Div(assetQuantum).Truncate(6).String(), 227 }) 228 } 229 230 referrerRewardsGeneratedParties := maps.Keys(f.ReferrerRewardsGenerated) 231 sort.Strings(referrerRewardsGeneratedParties) 232 for _, party := range referrerRewardsGeneratedParties { 233 partiesAmounts := f.ReferrerRewardsGenerated[party] 234 235 rewardsGenerated := &eventspb.ReferrerRewardsGenerated{ 236 Referrer: party, 237 GeneratedReward: make([]*eventspb.PartyAmount, 0, len(partiesAmounts)), 238 } 239 240 partiesAmountsParties := maps.Keys(partiesAmounts) 241 sort.Strings(partiesAmountsParties) 242 for _, party := range partiesAmountsParties { 243 amount := partiesAmounts[party] 244 rewardsGenerated.GeneratedReward = append( 245 rewardsGenerated.GeneratedReward, 246 &eventspb.PartyAmount{ 247 Party: party, 248 Amount: amount.String(), 249 QuantumAmount: amount.ToDecimal().Div(assetQuantum).Truncate(6).String(), 250 }, 251 ) 252 } 253 254 fs.ReferrerRewardsGenerated = append(fs.ReferrerRewardsGenerated, rewardsGenerated) 255 } 256 257 totalMakerFeesReceivedParties := maps.Keys(f.TotalMakerFeesReceived) 258 sort.Strings(totalMakerFeesReceivedParties) 259 for _, maker := range totalMakerFeesReceivedParties { 260 amount := f.TotalMakerFeesReceived[maker] 261 fs.TotalMakerFeesReceived = append(fs.TotalMakerFeesReceived, &eventspb.PartyAmount{ 262 Party: maker, 263 Amount: amount.String(), 264 QuantumAmount: amount.ToDecimal().Div(assetQuantum).Truncate(6).String(), 265 }) 266 } 267 268 makerFeesGeneratedParties := maps.Keys(f.MakerFeesGenerated) 269 sort.Strings(makerFeesGeneratedParties) 270 for _, taker := range makerFeesGeneratedParties { 271 makersAmounts := f.MakerFeesGenerated[taker] 272 273 rewardsGenerated := &eventspb.MakerFeesGenerated{ 274 Taker: taker, 275 MakerFeesPaid: make([]*eventspb.PartyAmount, 0, len(makersAmounts)), 276 } 277 278 makersAmountsParties := maps.Keys(makersAmounts) 279 sort.Strings(makersAmountsParties) 280 for _, maker := range makersAmountsParties { 281 amount := makersAmounts[maker] 282 rewardsGenerated.MakerFeesPaid = append( 283 rewardsGenerated.MakerFeesPaid, 284 &eventspb.PartyAmount{ 285 Party: maker, 286 Amount: amount.String(), 287 QuantumAmount: amount.ToDecimal().Div(assetQuantum).Truncate(6).String(), 288 }, 289 ) 290 } 291 292 fs.MakerFeesGenerated = append(fs.MakerFeesGenerated, rewardsGenerated) 293 } 294 295 tradingFeesGeneratedParties := maps.Keys(f.TradingFeesPaidAndReceived) 296 sort.Strings(tradingFeesGeneratedParties) 297 for _, party := range tradingFeesGeneratedParties { 298 amount := f.TradingFeesPaidAndReceived[party] 299 300 fs.TotalFeesPaidAndReceived = append(fs.TotalFeesPaidAndReceived, &eventspb.PartyAmount{ 301 Party: party, 302 Amount: amount.String(), 303 QuantumAmount: amount.ToDecimal().Div(assetQuantum).Truncate(6).String(), 304 }) 305 } 306 307 return fs 308 }