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  }