OSDN Git Service

update fee rate
[bytom/vapor.git] / application / mov / match / fee_strategy.go
1 package match
2
3 import (
4         "math"
5
6         "github.com/bytom/vapor/errors"
7         "github.com/bytom/vapor/protocol/bc"
8 )
9
10 var (
11         // ErrInvalidAmountOfFee represent The fee charged is invalid
12         ErrInvalidAmountOfFee = errors.New("amount of fee is invalid")
13 )
14
15 const (
16         // rate of fee in units of 10000
17         makerFeeRate int64 = 0
18         takerFeeRate int64 = 3
19 )
20
21 // AllocatedAssets represent reallocated assets after calculating fees
22 type AllocatedAssets struct {
23         Receives []*bc.AssetAmount
24         Fees     []*bc.AssetAmount
25 }
26
27 // FeeStrategy used to indicate how to charge a matching fee
28 type FeeStrategy interface {
29         // Allocate will allocate the price differential in matching transaction to the participants and the fee
30         // @param receiveAmounts the amount of assets that the participants in the matching transaction can received when no fee is considered
31         // @param isMakers[i] represent whether i'th input is maker
32         // @return reallocated assets after calculating fees
33         Allocate(receiveAmounts []*bc.AssetAmount, isMakers []bool) *AllocatedAssets
34
35         // Validate verify that the fee charged for a matching transaction is correct
36         Validate(receiveAmounts []*bc.AssetAmount, feeAmounts map[bc.AssetID]uint64, isMakers []bool) error
37 }
38
39 // DefaultFeeStrategy represent the default fee charge strategy
40 type DefaultFeeStrategy struct{}
41
42 // NewDefaultFeeStrategy return a new instance of DefaultFeeStrategy
43 func NewDefaultFeeStrategy() *DefaultFeeStrategy {
44         return &DefaultFeeStrategy{}
45 }
46
47 // Allocate will allocate the price differential in matching transaction to the participants and the fee
48 func (d *DefaultFeeStrategy) Allocate(receiveAmounts []*bc.AssetAmount, isMakers []bool) *AllocatedAssets {
49         receives := make([]*bc.AssetAmount, len(receiveAmounts))
50         fees := make([]*bc.AssetAmount, len(receiveAmounts))
51
52         for i, receiveAmount := range receiveAmounts {
53                 fee := d.calcFeeAmount(receiveAmount.Amount, isMakers[i])
54                 receives[i] = &bc.AssetAmount{AssetId: receiveAmount.AssetId, Amount: receiveAmount.Amount - fee}
55                 fees[i] = &bc.AssetAmount{AssetId: receiveAmount.AssetId, Amount: fee}
56         }
57         return &AllocatedAssets{Receives: receives, Fees: fees}
58 }
59
60 // Validate verify that the fee charged for a matching transaction is correct
61 func (d *DefaultFeeStrategy) Validate(receiveAmounts []*bc.AssetAmount, feeAmounts map[bc.AssetID]uint64, isMakers []bool) error {
62         for i, receiveAmount := range receiveAmounts {
63                 realFeeAmount := feeAmounts[*receiveAmount.AssetId]
64                 feeAmount := d.calcFeeAmount(receiveAmount.Amount, isMakers[i])
65                 if realFeeAmount != feeAmount {
66                         return ErrInvalidAmountOfFee
67                 }
68         }
69         return nil
70 }
71
72 func (d *DefaultFeeStrategy) calcFeeAmount(amount uint64, isMaker bool) uint64 {
73         feeRate := takerFeeRate
74         if isMaker {
75                 feeRate = makerFeeRate
76         }
77         return uint64(math.Ceil(float64(amount) * float64(feeRate) / 1E4))
78 }