Merge pull request #5969 from mempool/mononaut/fix-fee-recommendations

fix fee recommendations
This commit is contained in:
wiz
2025-07-16 05:22:27 -10:00
committed by GitHub
3 changed files with 351 additions and 1 deletions

View File

@@ -0,0 +1,55 @@
import feeApi from '../../api/fee-api';
import { IBitcoinApi } from '../../api/bitcoin/bitcoin-api.interface';
const feeMempoolBlocks = require('./test-data/fee-mempool-blocks.json');
const subSatMempoolInfo: IBitcoinApi.MempoolInfo = {
mempoolminfee: 0.000001, // 0.1 sat/vbyte
loaded: true,
size: 100,
bytes: 10000,
usage: 10000,
total_fee: 10000,
maxmempool: 10000,
minrelaytxfee: 0.000001, // 0.1 sat/vbyte
};
const mempoolInfo: IBitcoinApi.MempoolInfo = {
mempoolminfee: 0.00001,
loaded: true,
size: 100,
bytes: 10000,
usage: 10000,
total_fee: 10000,
maxmempool: 10000,
minrelaytxfee: 0.00001,
};
describe('Fee API', () => {
test('should calculate recommended fees properly for sub-sat mempool', () => {
const fee = feeApi.calculateRecommendedFee(feeMempoolBlocks.subsat, subSatMempoolInfo);
expect(fee.fastestFee).toBe(2);
expect(fee.halfHourFee).toBe(1);
expect(fee.hourFee).toBe(1);
expect(fee.economyFee).toBe(1);
expect(fee.minimumFee).toBe(1);
});
test('should calculate recommended fees properly for full but low fee mempool', () => {
const fee = feeApi.calculateRecommendedFee(feeMempoolBlocks.lowfee, mempoolInfo);
expect(fee.fastestFee).toBe(2);
expect(fee.halfHourFee).toBe(2);
expect(fee.hourFee).toBe(2);
expect(fee.economyFee).toBe(2);
expect(fee.minimumFee).toBe(1);
});
test('should calculate recommended fees properly for empty mempool', () => {
const fee = feeApi.calculateRecommendedFee(feeMempoolBlocks.empty, mempoolInfo);
expect(fee.fastestFee).toBe(1);
expect(fee.halfHourFee).toBe(1);
expect(fee.hourFee).toBe(1);
expect(fee.economyFee).toBe(1);
expect(fee.minimumFee).toBe(1);
});
});

View File

@@ -0,0 +1,289 @@
{
"subsat": [
{
"blockSize": 1746106,
"blockVSize": 997953.25,
"nTx": 3750,
"totalFees": 1764766,
"medianFee": 1.0023586640951265,
"feeRange": [
0.6082474226804123,
0.6082474226804123,
0.6082474226804123,
0.6082474226804123,
1.2076788830715532,
3.166077738515901,
73.61111111111111
]
},
{
"blockSize": 1809871,
"blockVSize": 997963,
"nTx": 4861,
"totalFees": 588436,
"medianFee": 0.6082474226804123,
"feeRange": [
0.5156626506024097,
0.5649475055559813,
0.5670103092783505,
0.6082474226804123,
0.6082474226804123,
0.6082474226804123,
0.6082474226804123
]
},
{
"blockSize": 2917870,
"blockVSize": 997821.25,
"nTx": 1221,
"totalFees": 535389,
"medianFee": 0.5200034509958588,
"feeRange": [
0.35051546391752575,
0.5649475055559813,
0.5649475055559813,
0.5649475055559813,
0.5649475055559813,
0.5649475055559813,
0.5649475055559813
]
},
{
"blockSize": 3937966,
"blockVSize": 997875.25,
"nTx": 18,
"totalFees": 506205,
"medianFee": 0.5100003123470801,
"feeRange": [
0.35051546391752575,
0.35051546391752575,
0.35051546391752575,
0.5099980684971892,
0.5100003123470801,
0.5100020185186144,
0.5100025244589157
]
},
{
"blockSize": 3917639,
"blockVSize": 997810.25,
"nTx": 62,
"totalFees": 503529,
"medianFee": 0.5099975959779666,
"feeRange": [
0.35051546391752575,
0.35051546391752575,
0.35051546391752575,
0.35051546391752575,
0.35051546391752575,
0.5099971889756266,
0.5100002265056967
]
},
{
"blockSize": 3694897,
"blockVSize": 997893.25,
"nTx": 43,
"totalFees": 503307,
"medianFee": 0.5099952023028946,
"feeRange": [
0.35051546391752575,
0.35051546391752575,
0.35051546391752575,
0.35051546391752575,
0.3704911425797351,
0.5099952023028946,
0.5099967157103613
]
},
{
"blockSize": 2486759,
"blockVSize": 997857.5,
"nTx": 498,
"totalFees": 386911,
"medianFee": 0.36001120750903104,
"feeRange": [
0.35051546391752575,
0.35051546391752575,
0.35051546391752575,
0.35051546391752575,
0.35051546391752575,
0.35051546391752575,
0.5000054632270189
]
},
{
"blockSize": 6681226,
"blockVSize": 3385616.5,
"nTx": 10222,
"totalFees": 1197838,
"medianFee": 0.35051546391752575,
"feeRange": [
0.21576460085542437,
0.35051546391752575,
0.35051546391752575,
0.35051546391752575,
0.35051546391752575,
0.35051546391752575,
0.3599967979827291,
0.3600004002561639,
0.3600040026016911,
0.3600040026016911,
0.3600040026016911
]
}
],
"empty": [{
"blockSize": 10000,
"blockVSize": 10000,
"nTx": 2000,
"totalFees": 1197838,
"medianFee": 1,
"feeRange": [
1,
1,
1,
1,
1,
1,
1
]
}
],
"lowfee": [
{
"blockSize": 1746106,
"blockVSize": 997953.25,
"nTx": 3750,
"totalFees": 1764766,
"medianFee": 1.0023586640951265,
"feeRange": [
1.6082474226804123,
1.6082474226804123,
1.6082474226804123,
1.6082474226804123,
1.2076788830715532,
3.166077738515901,
73.61111111111111
]
},
{
"blockSize": 1809871,
"blockVSize": 997963,
"nTx": 4861,
"totalFees": 588436,
"medianFee": 1.6082474226804123,
"feeRange": [
1.5156626506024097,
1.5649475055559813,
1.5670103092783505,
1.6082474226804123,
1.6082474226804123,
1.6082474226804123,
1.6082474226804123
]
},
{
"blockSize": 2917870,
"blockVSize": 997821.25,
"nTx": 1221,
"totalFees": 535389,
"medianFee": 1.5200034509958588,
"feeRange": [
1.35051546391752575,
1.5649475055559813,
1.5649475055559813,
1.5649475055559813,
1.5649475055559813,
1.5649475055559813,
1.5649475055559813
]
},
{
"blockSize": 3937966,
"blockVSize": 997875.25,
"nTx": 18,
"totalFees": 506205,
"medianFee": 1.5100003123470801,
"feeRange": [
1.35051546391752575,
1.35051546391752575,
1.35051546391752575,
1.5099980684971892,
1.5100003123470801,
1.5100020185186144,
1.5100025244589157
]
},
{
"blockSize": 3917639,
"blockVSize": 997811.25,
"nTx": 62,
"totalFees": 503529,
"medianFee": 1.5099975959779666,
"feeRange": [
1.35051546391752575,
1.35051546391752575,
1.35051546391752575,
1.35051546391752575,
1.35051546391752575,
1.5099971889756266,
1.5100002265056967
]
},
{
"blockSize": 3694897,
"blockVSize": 997893.25,
"nTx": 43,
"totalFees": 503307,
"medianFee": 1.5099952023028946,
"feeRange": [
1.35051546391752575,
1.35051546391752575,
1.35051546391752575,
1.35051546391752575,
1.3704911425797351,
1.5099952023028946,
1.5099967157103613
]
},
{
"blockSize": 2486759,
"blockVSize": 997857.5,
"nTx": 498,
"totalFees": 386911,
"medianFee": 1.36001120750903104,
"feeRange": [
1.35051546391752575,
1.35051546391752575,
1.35051546391752575,
1.35051546391752575,
1.35051546391752575,
1.35051546391752575,
1.5000054632270189
]
},
{
"blockSize": 6681226,
"blockVSize": 3385616.5,
"nTx": 10222,
"totalFees": 1197838,
"medianFee": 1.35051546391752575,
"feeRange": [
1.21576460085542437,
1.35051546391752575,
1.35051546391752575,
1.35051546391752575,
1.35051546391752575,
1.35051546391752575,
1.3599967979827291,
1.3600004002561639,
1.3600040026016911,
1.3600040026016911,
1.3600040026016911
]
}
]
}

View File

@@ -1,4 +1,5 @@
import { MempoolBlock } from '../mempool.interfaces';
import { IBitcoinApi } from './bitcoin/bitcoin-api.interface';
import config from '../config';
import mempool from './mempool';
import projectedBlocks from './mempool-blocks';
@@ -22,6 +23,11 @@ class FeeApi {
public getRecommendedFee(): RecommendedFees {
const pBlocks = projectedBlocks.getMempoolBlocks();
const mPool = mempool.getMempoolInfo();
return this.calculateRecommendedFee(pBlocks, mPool);
}
public calculateRecommendedFee(pBlocks: MempoolBlock[], mPool: IBitcoinApi.MempoolInfo): RecommendedFees {
const minimumFee = this.roundUpToNearest(mPool.mempoolminfee * 100000, this.minimumIncrement);
const defaultMinFee = Math.max(minimumFee, this.defaultFee);
@@ -64,7 +70,7 @@ class FeeApi {
private optimizeMedianFee(pBlock: MempoolBlock, nextBlock: MempoolBlock | undefined, previousFee?: number): number {
const useFee = previousFee ? (pBlock.medianFee + previousFee) / 2 : pBlock.medianFee;
if (pBlock.blockVSize <= 500000) {
if (pBlock.blockVSize <= 500000 || pBlock.medianFee < 1) {
return this.defaultFee;
}
if (pBlock.blockVSize <= 950000 && !nextBlock) {