2020-11-09 10:05:29 -03:00

114 lines
3.4 KiB
Go

package fees
import "github.com/btcsuite/btcutil"
const dustThreshold = 546
type BestRouteFees struct {
MaxCapacity btcutil.Amount
FeeProportionalMillionth uint64
FeeBase btcutil.Amount
}
type FundingOutputPolicies struct {
MaximumDebt btcutil.Amount
PotentialCollect btcutil.Amount
MaxAmountFor0Conf btcutil.Amount
}
type DebtType string
const (
DebtTypeNone DebtType = "NONE"
DebtTypeCollect = "COLLECT"
DebtTypeLend = "LEND"
)
type SwapFees struct {
RoutingFee btcutil.Amount
SweepFee btcutil.Amount
DebtType DebtType
DebtAmount btcutil.Amount
ConfirmationsNeeded uint32
}
func (p *FundingOutputPolicies) FundingConfirmations(paymentAmount, lightningFee btcutil.Amount) uint32 {
totalAmount := paymentAmount + lightningFee
if totalAmount <= p.MaxAmountFor0Conf {
return 0
}
return 1
}
func (p *FundingOutputPolicies) DebtType(paymentAmount, lightningFee btcutil.Amount) DebtType {
numConfirmations := p.FundingConfirmations(paymentAmount, lightningFee)
totalAmount := paymentAmount + lightningFee
if numConfirmations == 0 && totalAmount <= p.MaximumDebt {
return DebtTypeLend
}
if p.PotentialCollect > 0 {
return DebtTypeCollect
}
return DebtTypeNone
}
func (p *FundingOutputPolicies) DebtAmount(paymentAmount, lightningFee btcutil.Amount) btcutil.Amount {
switch p.DebtType(paymentAmount, lightningFee) {
case DebtTypeLend:
return paymentAmount + lightningFee
case DebtTypeCollect:
return p.PotentialCollect
case DebtTypeNone:
return 0
default:
return 0
}
}
func (p *FundingOutputPolicies) MinFundingAmount(paymentAmount, lightningFee btcutil.Amount) btcutil.Amount {
inputAmount := paymentAmount + lightningFee
if p.DebtType(paymentAmount, lightningFee) == DebtTypeCollect {
inputAmount += p.DebtAmount(paymentAmount, lightningFee)
}
return inputAmount
}
func (p *FundingOutputPolicies) FundingOutputAmount(paymentAmount, lightningFee btcutil.Amount) btcutil.Amount {
minAmount := p.MinFundingAmount(paymentAmount, lightningFee)
if minAmount < dustThreshold {
return dustThreshold
}
return minAmount
}
func (p *FundingOutputPolicies) FundingOutputPadding(paymentAmount, lightningFee btcutil.Amount) btcutil.Amount {
minAmount := p.MinFundingAmount(paymentAmount, lightningFee)
outputAmount := p.FundingOutputAmount(paymentAmount, lightningFee)
return outputAmount - minAmount
}
func ComputeSwapFees(amount btcutil.Amount, bestRouteFees []BestRouteFees, policies *FundingOutputPolicies) *SwapFees {
lightningFee := computeLightningFee(amount, bestRouteFees)
return &SwapFees{
RoutingFee: lightningFee,
SweepFee: policies.FundingOutputPadding(amount, lightningFee),
DebtType: policies.DebtType(amount, lightningFee),
DebtAmount: policies.DebtAmount(amount, lightningFee),
ConfirmationsNeeded: policies.FundingConfirmations(amount, lightningFee),
}
}
func computeLightningFee(amount btcutil.Amount, bestRouteFees []BestRouteFees) btcutil.Amount {
for _, fee := range bestRouteFees {
if amount <= fee.MaxCapacity {
return fee.ForAmount(amount)
}
}
lastRouteFee := bestRouteFees[len(bestRouteFees)-1]
return lastRouteFee.ForAmount(amount)
}
func (f *BestRouteFees) ForAmount(amount btcutil.Amount) btcutil.Amount {
return (btcutil.Amount(f.FeeProportionalMillionth)*amount)/1000000 + f.FeeBase
}