From 326b70dabe773c384e6f09cbe64d906a74a3bb29 Mon Sep 17 00:00:00 2001 From: Tom Kirkpatrick Date: Sun, 18 Feb 2024 09:04:21 +0000 Subject: [PATCH] Provide current block height data --- src/custom.d.ts | 1 + src/util.ts | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/custom.d.ts b/src/custom.d.ts index 5e9cb80..9ac016f 100644 --- a/src/custom.d.ts +++ b/src/custom.d.ts @@ -16,6 +16,7 @@ type FeeByBlockTarget = { // Estimates represents the current block hash and fee by block target. type Estimates = { current_block_hash: string | null; // current block hash + current_block_height: number | null; // current block height fee_by_block_target: FeeByBlockTarget; // fee by block target (in sat/kb) }; diff --git a/src/util.ts b/src/util.ts index fb59a6a..43da17d 100644 --- a/src/util.ts +++ b/src/util.ts @@ -35,22 +35,37 @@ export const FEE_MINIMUM = config.get("settings.feeMinimum"); export const CACHE_STDTTL = config.get("cache.stdTTL"); export const CACHE_CHECKPERIOD = config.get("cache.checkperiod"); -// Constants +// Primary URLs export const MEMPOOL_TIP_HASH_URL = MEMPOOL_BASE_URL && `${MEMPOOL_BASE_URL}/api/blocks/tip/hash`; export const ESPLORA_TIP_HASH_URL = ESPLORA_BASE_URL && `${ESPLORA_BASE_URL}/api/blocks/tip/hash`; + +export const MEMPOOL_TIP_HEIGHT_URL = + MEMPOOL_BASE_URL && `${MEMPOOL_BASE_URL}/api/blocks/tip/height`; +export const ESPLORA_TIP_HEIGHT_URL = + ESPLORA_BASE_URL && `${ESPLORA_BASE_URL}/api/blocks/tip/height`; + export const MEMPOOL_FEES_URL = MEMPOOL_BASE_URL && `${MEMPOOL_BASE_URL}/api/v1/fees/recommended`; export const ESPLORA_FEE_ESTIMATES_URL = ESPLORA_BASE_URL && `${ESPLORA_BASE_URL}/api/fee-estimates`; +// Fallback URLs export const MEMPOOL_TIP_HASH_URL_FALLBACK = MEMPOOL_FALLBACK_BASE_URL && `${MEMPOOL_FALLBACK_BASE_URL}/api/blocks/tip/hash`; export const ESPLORA_TIP_HASH_URL_FALLBACK = ESPLORA_FALLBACK_BASE_URL && `${ESPLORA_FALLBACK_BASE_URL}/api/blocks/tip/hash`; + +export const MEMPOOL_TIP_HEIGHT_URL_FALLBACK = + MEMPOOL_FALLBACK_BASE_URL && + `${MEMPOOL_FALLBACK_BASE_URL}/api/blocks/tip/height`; +export const ESPLORA_TIP_HEIGHT_URL_FALLBACK = + ESPLORA_FALLBACK_BASE_URL && + `${ESPLORA_FALLBACK_BASE_URL}/api/blocks/tip/height`; + export const MEMPOOL_FEES_URL_FALLBACK = MEMPOOL_FALLBACK_BASE_URL && `${MEMPOOL_FALLBACK_BASE_URL}/api/v1/fees/recommended`; @@ -337,6 +352,33 @@ export async function fetchBlocksTipHash(): Promise { return res0 || res1 || null; } +/** + * Fetches the current block height. + */ +export async function fetchBlocksTipHeight(): Promise { + const tasks = [ + (MEMPOOL_TIP_HEIGHT_URL || MEMPOOL_TIP_HEIGHT_URL_FALLBACK) && + fetchAndHandle( + MEMPOOL_TIP_HEIGHT_URL, + "text", + MEMPOOL_TIP_HEIGHT_URL_FALLBACK, + ), + (ESPLORA_TIP_HEIGHT_URL || ESPLORA_TIP_HEIGHT_URL_FALLBACK) && + fetchAndHandle( + ESPLORA_TIP_HEIGHT_URL, + "text", + ESPLORA_TIP_HEIGHT_URL_FALLBACK, + ), + ].filter(Boolean); + const res = await Promise.allSettled(tasks); + + let res0 = getValueFromFulfilledPromise(res[0]); + let res1 = getValueFromFulfilledPromise(res[1]); + + const height = res0 || res1 || null; + return height ? Number(height) : null; +} + /** * Gets the current fee estimates from the cache or fetches them if they are not cached. */ @@ -353,12 +395,14 @@ export async function getEstimates(): Promise { await fetchEsploraData(), await fetchBitcoindData(), await fetchBlocksTipHash(), + await fetchBlocksTipHeight(), ]; - const [result1, result2, result3, result4] = await Promise.allSettled(tasks); + const [result1, result2, result3, result4, result5] = await Promise.allSettled(tasks); const mempoolFeeEstimates = getValueFromFulfilledPromise(result1); const esploraFeeEstimates = getValueFromFulfilledPromise(result2); const bitcoindFeeEstimates = getValueFromFulfilledPromise(result3); const blocksTipHash = getValueFromFulfilledPromise(result4); + const blocksTipHeight = getValueFromFulfilledPromise(result5); // Get the minimum fee. If the mempool fee estimates are not available, use a default value of FEE_MINIMUM sat/vbyte as a safety net. const feeMinimum = (mempoolFeeEstimates?.minimumFee ?? FEE_MINIMUM) * 1000; @@ -366,6 +410,7 @@ export async function getEstimates(): Promise { estimates = { current_block_hash: blocksTipHash, + current_block_height: blocksTipHeight, fee_by_block_target: calculateFees( mempoolFeeEstimates, esploraFeeEstimates,