6 "github.com/bytom/vapor/errors"
7 "github.com/bytom/vapor/protocol/bc"
11 // ErrInvalidAmountOfFee represent The fee charged is invalid
12 ErrInvalidAmountOfFee = errors.New("amount of fee is invalid")
16 // rate of fee in units of 10000
17 makerFeeRate int64 = 0
18 takerFeeRate int64 = 3
21 // AllocatedAssets represent reallocated assets after calculating fees
22 type AllocatedAssets struct {
23 Receives []*bc.AssetAmount
24 Fees []*bc.AssetAmount
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
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
39 // DefaultFeeStrategy represent the default fee charge strategy
40 type DefaultFeeStrategy struct{}
42 // NewDefaultFeeStrategy return a new instance of DefaultFeeStrategy
43 func NewDefaultFeeStrategy() *DefaultFeeStrategy {
44 return &DefaultFeeStrategy{}
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))
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}
57 return &AllocatedAssets{Receives: receives, Fees: fees}
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
72 func (d *DefaultFeeStrategy) calcFeeAmount(amount uint64, isMaker bool) uint64 {
73 feeRate := takerFeeRate
75 feeRate = makerFeeRate
77 return uint64(math.Ceil(float64(amount) * float64(feeRate) / 1E4))