mirror of
https://github.com/muun/recovery.git
synced 2025-11-13 07:11:45 -05:00
Update project structure and build process
This commit is contained in:
79
libwallet/operation/fee_window.go
Normal file
79
libwallet/operation/fee_window.go
Normal file
@@ -0,0 +1,79 @@
|
||||
package operation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
const swapV2ConfTarget = 250 // Approx 2 days
|
||||
|
||||
type FeeWindow struct {
|
||||
TargetedFees map[uint]float64
|
||||
}
|
||||
|
||||
// SwapFeeRate gets the appropriate fee rate for a given swap (depends on confirmations needed).
|
||||
// Useful method for when swap doesn't have a fixed amount (e.g AmountLessInvoices + use all funds).
|
||||
func (f *FeeWindow) SwapFeeRate(confirmationsNeeded uint) (float64, error) {
|
||||
if confirmationsNeeded == 0 {
|
||||
return f.MinimumFeeRate(swapV2ConfTarget)
|
||||
}
|
||||
|
||||
return f.FastestFeeRate(), nil
|
||||
}
|
||||
|
||||
// MinimumFeeRate gets the minimum available fee rate that will hit a given confirmation target. We
|
||||
// make no guesses (no averages or interpolations), so we might overshoot the fee if data is too
|
||||
// sparse.
|
||||
// Note: the lower the confirmation target, the faster the tx will confirm, and greater the
|
||||
// fee(rate) will be.
|
||||
func (f *FeeWindow) MinimumFeeRate(confirmationTarget uint) (float64, error) {
|
||||
|
||||
if confirmationTarget <= 0 {
|
||||
return 0, fmt.Errorf("can't get feeRate. Expected positive confirmation target, got %v", confirmationTarget)
|
||||
}
|
||||
|
||||
// Walk the available targets backwards, finding the highest target below the given one:
|
||||
for closestTarget := confirmationTarget; closestTarget > 0; closestTarget-- {
|
||||
if feeRate, containsKey := f.TargetedFees[closestTarget]; containsKey {
|
||||
// Found! This is the lowest fee rate that hits the given target.
|
||||
return feeRate, nil
|
||||
}
|
||||
}
|
||||
|
||||
// No result? This is odd, but not illogical. It means *all* of our available targets
|
||||
// are above the requested one. Let's use the fastest:
|
||||
return f.FastestFeeRate(), nil
|
||||
}
|
||||
|
||||
// FastestFeeRate gets the fastest fee rate, in satoshis per weight unit.
|
||||
func (f *FeeWindow) FastestFeeRate() float64 {
|
||||
|
||||
var lowestTarget uint = math.MaxUint32
|
||||
for k := range f.TargetedFees {
|
||||
if k < lowestTarget {
|
||||
lowestTarget = k
|
||||
}
|
||||
}
|
||||
|
||||
return f.TargetedFees[lowestTarget]
|
||||
}
|
||||
|
||||
// NextHighestBlock finds the next highest confirmation/block target for a certain feeRate. Let me
|
||||
// explain, we have a map that associates a conf-target with a fee rate. Now we want to know
|
||||
// associate a conf-target with a given fee rate. We want the NEXT conf-target as we usually want
|
||||
// this data for predictions or estimations and this makes the predictions for the fee rate to
|
||||
// "fall on the correct side" (e.g when estimating max time to confirmation for a given fee rate).
|
||||
// Note: code is not our best work of art. The target < next comparison is to account for our
|
||||
// TargetedFees map not necessarily being sorted.
|
||||
func (f *FeeWindow) NextHighestBlock(feeRate float64) uint {
|
||||
next := uint(math.MaxUint32)
|
||||
for target, rate := range f.TargetedFees {
|
||||
if rate <= feeRate && target < next {
|
||||
next = target
|
||||
}
|
||||
}
|
||||
if next == math.MaxUint32 {
|
||||
return 0 // 0 is a not valid targetBlock, we use it to signal target not found
|
||||
}
|
||||
return next
|
||||
}
|
||||
Reference in New Issue
Block a user