diff --git a/README.md b/README.md index 2c44c4d..de8e38e 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,8 @@ The transaction fee rate is calculated by taking the maximum value among three metrics from the Bitcoin blockchain: -- Average fee rate from the last two blocks -- Current mempool block's median fee rate -- Estimated "fastest" fee rate +- Average fee rate from the last two blocks `/api/v1/mining/blocks/fee-rates/24h` +- Current mempool block's median fee rate `/api/v1/fees/mempool-blocks` +- Recommended "fastest" fee rate by API `/api/v1/fees/recommended` Each metric is adjusted by an optional multiplier (defaults to 1.0) and the final result is rounded up to the nearest whole number. For regtest environments, a fixed fee rate of 2 is used. diff --git a/src/dlc-handlers/abstract-dlc-handler.ts b/src/dlc-handlers/abstract-dlc-handler.ts index 495355e..14e7766 100644 --- a/src/dlc-handlers/abstract-dlc-handler.ts +++ b/src/dlc-handlers/abstract-dlc-handler.ts @@ -1,6 +1,7 @@ import { Transaction } from '@scure/btc-signer'; import { P2Ret, P2TROut } from '@scure/btc-signer/payment'; import { Network } from 'bitcoinjs-lib'; +import { regtest } from 'bitcoinjs-lib/src/networks.js'; import { createNativeSegwitPayment, @@ -133,11 +134,16 @@ export abstract class AbstractDLCHandler { } } - private async getFeeRate(feeRateMultiplier?: number, customFeeRate?: bigint): Promise { - return ( - customFeeRate ?? - BigInt(await getFeeRate(this.bitcoinBlockchainFeeRecommendationAPI, feeRateMultiplier)) - ); + protected async getFeeRate(feeRateMultiplier?: number, customFeeRate?: bigint): Promise { + if (customFeeRate) { + return customFeeRate; + } + + if (this.bitcoinNetwork === regtest) { + return BigInt(2); + } + + return BigInt(await getFeeRate(this.bitcoinBlockchainFeeRecommendationAPI, feeRateMultiplier)); } async createFundingPSBT( diff --git a/src/dlc-handlers/ledger-dlc-handler.ts b/src/dlc-handlers/ledger-dlc-handler.ts index c99bb76..4c76ce4 100644 --- a/src/dlc-handlers/ledger-dlc-handler.ts +++ b/src/dlc-handlers/ledger-dlc-handler.ts @@ -10,7 +10,6 @@ import { deriveUnhardenedPublicKey, ecdsaPublicKeyToSchnorr, getBalance, - getFeeRate, getInputByPaymentTypeArray, getUnspendableKeyCommittedToUUID, } from '../functions/bitcoin/bitcoin-functions.js'; @@ -246,9 +245,7 @@ export class LedgerDLCHandler extends AbstractDLCHandler { attestorGroupPublicKey ); - const feeRate = - customFeeRate ?? - BigInt(await getFeeRate(this.bitcoinBlockchainFeeRecommendationAPI, feeRateMultiplier)); + const feeRate = await this.getFeeRate(feeRateMultiplier, customFeeRate); const addressBalance = await getBalance(fundingPayment, this.bitcoinBlockchainAPI); @@ -327,9 +324,7 @@ export class LedgerDLCHandler extends AbstractDLCHandler { attestorGroupPublicKey ); - const feeRate = - customFeeRate ?? - BigInt(await getFeeRate(this.bitcoinBlockchainFeeRecommendationAPI, feeRateMultiplier)); + const feeRate = await this.getFeeRate(feeRateMultiplier, customFeeRate); const withdrawTransaction = await createWithdrawTransaction( this.bitcoinBlockchainAPI, @@ -388,9 +383,7 @@ export class LedgerDLCHandler extends AbstractDLCHandler { const { fundingPayment, taprootDerivedPublicKey, fundingDerivedPublicKey, multisigPayment } = await this.createPayment(vault.uuid, attestorGroupPublicKey); - const feeRate = - customFeeRate ?? - BigInt(await getFeeRate(this.bitcoinBlockchainFeeRecommendationAPI, feeRateMultiplier)); + const feeRate = await this.getFeeRate(feeRateMultiplier, customFeeRate); const depositTransaction = await createDepositTransaction( this.bitcoinBlockchainAPI, diff --git a/src/functions/bitcoin/bitcoin-functions.ts b/src/functions/bitcoin/bitcoin-functions.ts index b2d8dc6..6453ff7 100644 --- a/src/functions/bitcoin/bitcoin-functions.ts +++ b/src/functions/bitcoin/bitcoin-functions.ts @@ -149,9 +149,9 @@ export function createTaprootMultisigPayment( * * @returns A promise that resolves to the last two blocks' median fee rates. */ -export async function getLastTwoBlocksFeeRate( +export async function getLastTwoBlocksFeeRateAverage( bitcoinBlockchainAPIFeeURL: string -): Promise { +): Promise { const dayFeeRateAPI = `${bitcoinBlockchainAPIFeeURL}/api/v1/mining/blocks/fee-rates/24h`; const response = await fetch(dayFeeRateAPI); @@ -162,7 +162,12 @@ export async function getLastTwoBlocksFeeRate( const historicalFeeRates: HistoricalFeeRate[] = await response.json(); - return historicalFeeRates.slice(historicalFeeRates.length - 2).map(rate => rate.avgFee_50); + return ( + historicalFeeRates + .slice(historicalFeeRates.length - 2) + .map(rate => rate.avgFee_50) + .reduce((a, b) => a + b) / 2 + ); } /** @@ -213,30 +218,19 @@ export async function getEstimatedFeeRate(bitcoinBlockchainAPIFeeURL: string): P */ export async function getFeeRate( bitcoinBlockchainAPIFeeURL: string, - feeRateMultiplier = 1, - isRegtest = false + feeRateMultiplier = 1 ): Promise { - if (isRegtest) return 2; - - const [lastTwoBlocksFeeRate, currentBlockFeeRate, estimatedFeeRate] = await Promise.all([ - getLastTwoBlocksFeeRate(bitcoinBlockchainAPIFeeURL), + const [lastTwoBlocksFeeRateAverage, currentBlockFeeRate, estimatedFeeRate] = await Promise.all([ + getLastTwoBlocksFeeRateAverage(bitcoinBlockchainAPIFeeURL), getCurrentMempoolBlockFeeRate(bitcoinBlockchainAPIFeeURL), getEstimatedFeeRate(bitcoinBlockchainAPIFeeURL), ]); - const currentBlockFeeRateMultiplied = currentBlockFeeRate * feeRateMultiplier; - - const lastTwoBlocksfeeRateAverageMultiplied = - (lastTwoBlocksFeeRate.reduce((a, b) => a + b) / lastTwoBlocksFeeRate.length) * - feeRateMultiplier; - - const estimatedFeeRateMultiplied = estimatedFeeRate * feeRateMultiplier; - return Math.ceil( Math.max( - lastTwoBlocksfeeRateAverageMultiplied, - currentBlockFeeRateMultiplied, - estimatedFeeRateMultiplied + lastTwoBlocksFeeRateAverage * feeRateMultiplier, + currentBlockFeeRate * feeRateMultiplier, + estimatedFeeRate * feeRateMultiplier ) ); }