github.com/trezor/blockbook@v0.4.1-0.20240328132726-e9a08582ee2c/bchain/coins/btc/alternativefeeprovider.go (about)

     1  package btc
     2  
     3  import (
     4  	"fmt"
     5  	"math/big"
     6  	"sync"
     7  	"time"
     8  
     9  	"github.com/golang/glog"
    10  	"github.com/juju/errors"
    11  	"github.com/trezor/blockbook/bchain"
    12  )
    13  
    14  type alternativeFeeProviderFee struct {
    15  	blocks   int
    16  	feePerKB int
    17  }
    18  
    19  type alternativeFeeProvider struct {
    20  	fees     []alternativeFeeProviderFee
    21  	lastSync time.Time
    22  	chain    bchain.BlockChain
    23  	mux      sync.Mutex
    24  }
    25  
    26  type alternativeFeeProviderInterface interface {
    27  	compareToDefault()
    28  	estimateFee(blocks int) (big.Int, error)
    29  }
    30  
    31  func (p *alternativeFeeProvider) compareToDefault() {
    32  	output := ""
    33  	for _, fee := range p.fees {
    34  		conservative, err := p.chain.(*BitcoinRPC).blockchainEstimateSmartFee(fee.blocks, true)
    35  		if err != nil {
    36  			glog.Error(err)
    37  			return
    38  		}
    39  		economical, err := p.chain.(*BitcoinRPC).blockchainEstimateSmartFee(fee.blocks, false)
    40  		if err != nil {
    41  			glog.Error(err)
    42  			return
    43  		}
    44  		output += fmt.Sprintf("Blocks %d: alternative %d, conservative %s, economical %s\n", fee.blocks, fee.feePerKB, conservative.String(), economical.String())
    45  	}
    46  	glog.Info("alternativeFeeProviderCompareToDefault\n", output)
    47  }
    48  
    49  func (p *alternativeFeeProvider) estimateFee(blocks int) (big.Int, error) {
    50  	var r big.Int
    51  	p.mux.Lock()
    52  	defer p.mux.Unlock()
    53  	if len(p.fees) == 0 {
    54  		return r, errors.New("alternativeFeeProvider: no fees")
    55  	}
    56  	if p.lastSync.Before(time.Now().Add(time.Duration(-10) * time.Minute)) {
    57  		return r, errors.Errorf("alternativeFeeProvider: Missing recent value, last sync at %v", p.lastSync)
    58  	}
    59  	for i := range p.fees {
    60  		if p.fees[i].blocks >= blocks {
    61  			r = *big.NewInt(int64(p.fees[i].feePerKB))
    62  			return r, nil
    63  		}
    64  	}
    65  	// use the last value as fallback
    66  	r = *big.NewInt(int64(p.fees[len(p.fees)-1].feePerKB))
    67  	return r, nil
    68  }