global: snapshot

This commit is contained in:
nym21
2026-01-12 11:39:44 +01:00
parent 8fe0af349d
commit 1b9e18f98b
33 changed files with 7603 additions and 7968 deletions

View File

@@ -32,9 +32,10 @@ impl AddressRoutes for ApiRouter<AppState> {
| {
state.cached_json(&headers, CacheStrategy::Height, move |q| q.address(path.address)).await
}, |op| op
.id("get_address")
.addresses_tag()
.summary("Address information")
.description("Retrieve comprehensive information about a Bitcoin address including balance, transaction history, UTXOs, and estimated investment metrics. Supports all standard Bitcoin address types (P2PKH, P2SH, P2WPKH, P2WSH, P2TR, etc.).")
.description("Retrieve address information including balance and transaction counts. Supports all standard Bitcoin address types (P2PKH, P2SH, P2WPKH, P2WSH, P2TR).\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-address)*")
.ok_response::<AddressStats>()
.not_modified()
.bad_request()
@@ -52,9 +53,10 @@ impl AddressRoutes for ApiRouter<AppState> {
| {
state.cached_json(&headers, CacheStrategy::Height, move |q| q.address_txids(path.address, params.after_txid, params.limit)).await
}, |op| op
.id("get_address_txs")
.addresses_tag()
.summary("Address transaction IDs")
.description("Get transaction IDs for an address, newest first. Use after_txid for pagination.")
.description("Get transaction IDs for an address, newest first. Use after_txid for pagination.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-address-transactions)*")
.ok_response::<Vec<Txid>>()
.not_modified()
.bad_request()
@@ -71,9 +73,10 @@ impl AddressRoutes for ApiRouter<AppState> {
| {
state.cached_json(&headers, CacheStrategy::Height, move |q| q.address_utxos(path.address)).await
}, |op| op
.id("get_address_utxos")
.addresses_tag()
.summary("Address UTXOs")
.description("Get unspent transaction outputs for an address.")
.description("Get unspent transaction outputs (UTXOs) for an address. Returns txid, vout, value, and confirmation status for each UTXO.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-address-utxo)*")
.ok_response::<Vec<Utxo>>()
.not_modified()
.bad_request()
@@ -91,9 +94,10 @@ impl AddressRoutes for ApiRouter<AppState> {
// Mempool txs for an address - use MaxAge since it's volatile
state.cached_json(&headers, CacheStrategy::MaxAge(5), move |q| q.address_mempool_txids(path.address)).await
}, |op| op
.id("get_address_mempool_txs")
.addresses_tag()
.summary("Address mempool transactions")
.description("Get unconfirmed transaction IDs for an address from the mempool (up to 50).")
.description("Get unconfirmed transaction IDs for an address from the mempool (up to 50).\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-address-transactions-mempool)*")
.ok_response::<Vec<Txid>>()
.bad_request()
.not_found()
@@ -110,9 +114,10 @@ impl AddressRoutes for ApiRouter<AppState> {
| {
state.cached_json(&headers, CacheStrategy::Height, move |q| q.address_txids(path.address, params.after_txid, 25)).await
}, |op| op
.id("get_address_confirmed_txs")
.addresses_tag()
.summary("Address confirmed transactions")
.description("Get confirmed transaction IDs for an address, 25 per page. Use ?after_txid=<txid> for pagination.")
.description("Get confirmed transaction IDs for an address, 25 per page. Use ?after_txid=<txid> for pagination.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-address-transactions-chain)*")
.ok_response::<Vec<Txid>>()
.not_modified()
.bad_request()
@@ -129,9 +134,10 @@ impl AddressRoutes for ApiRouter<AppState> {
| {
state.cached_json(&headers, CacheStrategy::Static, move |_q| Ok(AddressValidation::from_address(&path.address))).await
}, |op| op
.id("validate_address")
.addresses_tag()
.summary("Validate address")
.description("Validate a Bitcoin address and get information about its type and scriptPubKey.")
.description("Validate a Bitcoin address and get information about its type and scriptPubKey.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-address-validate)*")
.ok_response::<AddressValidation>()
.not_modified()
),

View File

@@ -28,9 +28,10 @@ impl BlockRoutes for ApiRouter<AppState> {
.await
},
|op| {
op.blocks_tag()
op.id("get_blocks")
.blocks_tag()
.summary("Recent blocks")
.description("Retrieve the last 10 blocks. Returns block metadata for each block.")
.description("Retrieve the last 10 blocks. Returns block metadata for each block.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-blocks)*")
.ok_response::<Vec<BlockInfo>>()
.not_modified()
.server_error()
@@ -46,10 +47,11 @@ impl BlockRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::Height, move |q| q.block(&path.hash)).await
},
|op| {
op.blocks_tag()
op.id("get_block")
.blocks_tag()
.summary("Block information")
.description(
"Retrieve block information by block hash. Returns block metadata including height, timestamp, difficulty, size, weight, and transaction count.",
"Retrieve block information by block hash. Returns block metadata including height, timestamp, difficulty, size, weight, and transaction count.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-block)*",
)
.ok_response::<BlockInfo>()
.not_modified()
@@ -68,10 +70,11 @@ impl BlockRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::Height, move |q| q.block_status(&path.hash)).await
},
|op| {
op.blocks_tag()
op.id("get_block_status")
.blocks_tag()
.summary("Block status")
.description(
"Retrieve the status of a block. Returns whether the block is in the best chain and, if so, its height and the hash of the next block.",
"Retrieve the status of a block. Returns whether the block is in the best chain and, if so, its height and the hash of the next block.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-status)*",
)
.ok_response::<BlockStatus>()
.not_modified()
@@ -90,10 +93,11 @@ impl BlockRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::Height, move |q| q.block_by_height(path.height)).await
},
|op| {
op.blocks_tag()
op.id("get_block_by_height")
.blocks_tag()
.summary("Block by height")
.description(
"Retrieve block information by block height. Returns block metadata including hash, timestamp, difficulty, size, weight, and transaction count.",
"Retrieve block information by block height. Returns block metadata including hash, timestamp, difficulty, size, weight, and transaction count.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-height)*",
)
.ok_response::<BlockInfo>()
.not_modified()
@@ -112,10 +116,11 @@ impl BlockRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::Height, move |q| q.blocks(Some(path.height))).await
},
|op| {
op.blocks_tag()
op.id("get_blocks_from_height")
.blocks_tag()
.summary("Blocks from height")
.description(
"Retrieve up to 10 blocks going backwards from the given height. For example, height=100 returns blocks 100, 99, 98, ..., 91. Height=0 returns only block 0.",
"Retrieve up to 10 blocks going backwards from the given height. For example, height=100 returns blocks 100, 99, 98, ..., 91. Height=0 returns only block 0.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-blocks)*",
)
.ok_response::<Vec<BlockInfo>>()
.not_modified()
@@ -133,10 +138,11 @@ impl BlockRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::Height, move |q| q.block_txids(&path.hash)).await
},
|op| {
op.blocks_tag()
op.id("get_block_txids")
.blocks_tag()
.summary("Block transaction IDs")
.description(
"Retrieve all transaction IDs in a block by block hash.",
"Retrieve all transaction IDs in a block. Returns an array of txids in block order.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-transaction-ids)*",
)
.ok_response::<Vec<Txid>>()
.not_modified()
@@ -155,10 +161,11 @@ impl BlockRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::Height, move |q| q.block_txs(&path.hash, path.start_index)).await
},
|op| {
op.blocks_tag()
op.id("get_block_txs")
.blocks_tag()
.summary("Block transactions (paginated)")
.description(&format!(
"Retrieve transactions in a block by block hash, starting from the specified index. Returns up to {} transactions at a time.",
"Retrieve transactions in a block by block hash, starting from the specified index. Returns up to {} transactions at a time.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-transactions)*",
BLOCK_TXS_PAGE_SIZE
))
.ok_response::<Vec<Transaction>>()
@@ -178,10 +185,11 @@ impl BlockRoutes for ApiRouter<AppState> {
state.cached_text(&headers, CacheStrategy::Height, move |q| q.block_txid_at_index(&path.hash, path.index).map(|t| t.to_string())).await
},
|op| {
op.blocks_tag()
op.id("get_block_txid")
.blocks_tag()
.summary("Transaction ID at index")
.description(
"Retrieve a single transaction ID at a specific index within a block. Returns plain text txid.",
"Retrieve a single transaction ID at a specific index within a block. Returns plain text txid.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-transaction-id)*",
)
.ok_response::<Txid>()
.not_modified()
@@ -200,9 +208,10 @@ impl BlockRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::Height, move |q| q.block_by_timestamp(path.timestamp)).await
},
|op| {
op.blocks_tag()
op.id("get_block_by_timestamp")
.blocks_tag()
.summary("Block by timestamp")
.description("Find the block closest to a given UNIX timestamp.")
.description("Find the block closest to a given UNIX timestamp.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-timestamp)*")
.ok_response::<BlockTimestamp>()
.not_modified()
.bad_request()
@@ -220,10 +229,11 @@ impl BlockRoutes for ApiRouter<AppState> {
state.cached_bytes(&headers, CacheStrategy::Height, move |q| q.block_raw(&path.hash)).await
},
|op| {
op.blocks_tag()
op.id("get_block_raw")
.blocks_tag()
.summary("Raw block")
.description(
"Returns the raw block data in binary format.",
"Returns the raw block data in binary format.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-raw)*",
)
.ok_response::<Vec<u8>>()
.not_modified()

View File

@@ -26,9 +26,10 @@ impl MempoolRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::MaxAge(5), |q| q.mempool_info()).await
},
|op| {
op.mempool_tag()
op.id("get_mempool")
.mempool_tag()
.summary("Mempool statistics")
.description("Get current mempool statistics including transaction count, total vsize, and total fees.")
.description("Get current mempool statistics including transaction count, total vsize, and total fees.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-mempool)*")
.ok_response::<MempoolInfo>()
.server_error()
},
@@ -41,9 +42,10 @@ impl MempoolRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::MaxAge(5), |q| q.mempool_txids()).await
},
|op| {
op.mempool_tag()
op.id("get_mempool_txids")
.mempool_tag()
.summary("Mempool transaction IDs")
.description("Get all transaction IDs currently in the mempool.")
.description("Get all transaction IDs currently in the mempool.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-mempool-transaction-ids)*")
.ok_response::<Vec<Txid>>()
.server_error()
},
@@ -56,9 +58,10 @@ impl MempoolRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::MaxAge(3), |q| q.recommended_fees()).await
},
|op| {
op.mempool_tag()
op.id("get_recommended_fees")
.mempool_tag()
.summary("Recommended fees")
.description("Get recommended fee rates for different confirmation targets based on current mempool state.")
.description("Get recommended fee rates for different confirmation targets based on current mempool state.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-recommended-fees)*")
.ok_response::<RecommendedFees>()
.server_error()
},
@@ -71,9 +74,10 @@ impl MempoolRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::MaxAge(5), |q| q.mempool_blocks()).await
},
|op| {
op.mempool_tag()
op.id("get_mempool_blocks")
.mempool_tag()
.summary("Projected mempool blocks")
.description("Get projected blocks from the mempool for fee estimation. Each block contains statistics about transactions that would be included if a block were mined now.")
.description("Get projected blocks from the mempool for fee estimation. Each block contains statistics about transactions that would be included if a block were mined now.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-mempool-blocks-fees)*")
.ok_response::<Vec<MempoolBlock>>()
.server_error()
},

View File

@@ -37,10 +37,12 @@ impl ApiMetricsRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::Static, |q| Ok(q.metrics_catalog().clone())).await
},
|op| op
.id("get_metrics_tree")
.metrics_tag()
.summary("Metrics catalog")
.description(
"Returns the complete hierarchical catalog of available metrics organized as a tree structure. Metrics are grouped by categories and subcategories. Best viewed in an interactive JSON viewer (e.g., Firefox's built-in JSON viewer) for easy navigation of the nested structure."
"Returns the complete hierarchical catalog of available metrics organized as a tree structure. \
Metrics are grouped by categories and subcategories."
)
.ok_response::<TreeNode>()
.not_modified(),
@@ -56,9 +58,10 @@ impl ApiMetricsRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::Static, |q| Ok(q.metric_count())).await
},
|op| op
.id("get_metrics_count")
.metrics_tag()
.summary("Metric count")
.description("Current metric count")
.description("Returns the number of metrics available per index type.")
.ok_response::<Vec<MetricCount>>()
.not_modified(),
),
@@ -73,6 +76,7 @@ impl ApiMetricsRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::Static, |q| Ok(q.indexes().to_vec())).await
},
|op| op
.id("get_indexes")
.metrics_tag()
.summary("List available indexes")
.description(
@@ -93,9 +97,10 @@ impl ApiMetricsRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::Static, move |q| Ok(q.metrics(pagination))).await
},
|op| op
.id("list_metrics")
.metrics_tag()
.summary("Metrics list")
.description("Paginated list of available metrics")
.description("Paginated flat list of all available metric names. Use `page` query param for pagination.")
.ok_response::<PaginatedMetrics>()
.not_modified(),
),
@@ -112,6 +117,7 @@ impl ApiMetricsRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::Static, move |q| Ok(q.match_metric(&path.metric, query.limit))).await
},
|op| op
.id("search_metrics")
.metrics_tag()
.summary("Search metrics")
.description("Fuzzy search for metrics by name. Supports partial matches and typos.")
@@ -136,10 +142,11 @@ impl ApiMetricsRoutes for ApiRouter<AppState> {
}).await
},
|op| op
.id("get_metric_info")
.metrics_tag()
.summary("Get supported indexes for a metric")
.description(
"Returns the list of indexes are supported by the specified metric. \
"Returns the list of indexes supported by the specified metric. \
For example, `realized_price` might be available on dateindex, weekindex, and monthindex."
)
.ok_response::<Vec<Index>>()
@@ -166,6 +173,7 @@ impl ApiMetricsRoutes for ApiRouter<AppState> {
.await
},
|op| op
.id("get_metric")
.metrics_tag()
.summary("Get metric data")
.description(
@@ -183,11 +191,12 @@ impl ApiMetricsRoutes for ApiRouter<AppState> {
get_with(
bulk::handler,
|op| op
.id("get_metrics")
.metrics_tag()
.summary("Bulk metric data")
.description(
"Fetch multiple metrics in a single request. Supports filtering by index and date range. \
Returns an array of MetricData objects."
Returns an array of MetricData objects. For a single metric, use `get_metric` instead."
)
.ok_response::<Vec<MetricData>>()
.csv_response()

View File

@@ -32,9 +32,10 @@ impl MiningRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::Height, |q| q.difficulty_adjustment()).await
},
|op| {
op.mining_tag()
op.id("get_difficulty_adjustment")
.mining_tag()
.summary("Difficulty adjustment")
.description("Get current difficulty adjustment information including progress through the current epoch, estimated retarget date, and difficulty change prediction.")
.description("Get current difficulty adjustment information including progress through the current epoch, estimated retarget date, and difficulty change prediction.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-difficulty-adjustment)*")
.ok_response::<DifficultyAdjustment>()
.not_modified()
.server_error()
@@ -49,9 +50,10 @@ impl MiningRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::Static, |q| Ok(q.all_pools())).await
},
|op| {
op.mining_tag()
op.id("get_pools")
.mining_tag()
.summary("List all mining pools")
.description("Get list of all known mining pools with their identifiers.")
.description("Get list of all known mining pools with their identifiers.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-mining-pools)*")
.ok_response::<Vec<PoolInfo>>()
.not_modified()
.server_error()
@@ -65,9 +67,10 @@ impl MiningRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::height_with(format!("{:?}", path.time_period)), move |q| q.mining_pools(path.time_period)).await
},
|op| {
op.mining_tag()
op.id("get_pool_stats")
.mining_tag()
.summary("Mining pool statistics")
.description("Get mining pool statistics for a time period. Valid periods: 24h, 3d, 1w, 1m, 3m, 6m, 1y, 2y, 3y")
.description("Get mining pool statistics for a time period. Valid periods: 24h, 3d, 1w, 1m, 3m, 6m, 1y, 2y, 3y\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-mining-pools)*")
.ok_response::<PoolsSummary>()
.not_modified()
.server_error()
@@ -81,9 +84,10 @@ impl MiningRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::height_with(path.slug), move |q| q.pool_detail(path.slug)).await
},
|op| {
op.mining_tag()
op.id("get_pool")
.mining_tag()
.summary("Mining pool details")
.description("Get detailed information about a specific mining pool including block counts and shares for different time periods.")
.description("Get detailed information about a specific mining pool including block counts and shares for different time periods.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-mining-pool)*")
.ok_response::<PoolDetail>()
.not_modified()
.not_found()
@@ -98,9 +102,10 @@ impl MiningRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::height_with("hashrate"), |q| q.hashrate(None)).await
},
|op| {
op.mining_tag()
op.id("get_hashrate")
.mining_tag()
.summary("Network hashrate (all time)")
.description("Get network hashrate and difficulty data for all time.")
.description("Get network hashrate and difficulty data for all time.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-hashrate)*")
.ok_response::<HashrateSummary>()
.not_modified()
.server_error()
@@ -114,9 +119,10 @@ impl MiningRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::height_with(format!("hashrate-{:?}", path.time_period)), move |q| q.hashrate(Some(path.time_period))).await
},
|op| {
op.mining_tag()
op.id("get_hashrate_by_period")
.mining_tag()
.summary("Network hashrate")
.description("Get network hashrate and difficulty data for a time period. Valid periods: 24h, 3d, 1w, 1m, 3m, 6m, 1y, 2y, 3y")
.description("Get network hashrate and difficulty data for a time period. Valid periods: 24h, 3d, 1w, 1m, 3m, 6m, 1y, 2y, 3y\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-hashrate)*")
.ok_response::<HashrateSummary>()
.not_modified()
.server_error()
@@ -130,9 +136,10 @@ impl MiningRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::height_with("diff-adj"), |q| q.difficulty_adjustments(None)).await
},
|op| {
op.mining_tag()
op.id("get_difficulty_adjustments")
.mining_tag()
.summary("Difficulty adjustments (all time)")
.description("Get historical difficulty adjustments. Returns array of [timestamp, height, difficulty, change_percent].")
.description("Get historical difficulty adjustments including timestamp, block height, difficulty value, and percentage change.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-difficulty-adjustments)*")
.ok_response::<Vec<DifficultyAdjustmentEntry>>()
.not_modified()
.server_error()
@@ -146,9 +153,10 @@ impl MiningRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::height_with(format!("diff-adj-{:?}", path.time_period)), move |q| q.difficulty_adjustments(Some(path.time_period))).await
},
|op| {
op.mining_tag()
op.id("get_difficulty_adjustments_by_period")
.mining_tag()
.summary("Difficulty adjustments")
.description("Get historical difficulty adjustments for a time period. Valid periods: 24h, 3d, 1w, 1m, 3m, 6m, 1y, 2y, 3y. Returns array of [timestamp, height, difficulty, change_percent].")
.description("Get historical difficulty adjustments for a time period. Valid periods: 24h, 3d, 1w, 1m, 3m, 6m, 1y, 2y, 3y.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-difficulty-adjustments)*")
.ok_response::<Vec<DifficultyAdjustmentEntry>>()
.not_modified()
.server_error()
@@ -162,9 +170,10 @@ impl MiningRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::height_with(format!("fees-{:?}", path.time_period)), move |q| q.block_fees(path.time_period)).await
},
|op| {
op.mining_tag()
op.id("get_block_fees")
.mining_tag()
.summary("Block fees")
.description("Get average block fees for a time period. Valid periods: 24h, 3d, 1w, 1m, 3m, 6m, 1y, 2y, 3y")
.description("Get average block fees for a time period. Valid periods: 24h, 3d, 1w, 1m, 3m, 6m, 1y, 2y, 3y\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-fees)*")
.ok_response::<Vec<BlockFeesEntry>>()
.not_modified()
.server_error()
@@ -178,32 +187,34 @@ impl MiningRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::height_with(format!("rewards-{:?}", path.time_period)), move |q| q.block_rewards(path.time_period)).await
},
|op| {
op.mining_tag()
op.id("get_block_rewards")
.mining_tag()
.summary("Block rewards")
.description("Get average block rewards (coinbase = subsidy + fees) for a time period. Valid periods: 24h, 3d, 1w, 1m, 3m, 6m, 1y, 2y, 3y")
.description("Get average block rewards (coinbase = subsidy + fees) for a time period. Valid periods: 24h, 3d, 1w, 1m, 3m, 6m, 1y, 2y, 3y\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-rewards)*")
.ok_response::<Vec<BlockRewardsEntry>>()
.not_modified()
.server_error()
},
),
)
// TODO: Disabled - dateindex doesn't have percentile fields (see block_fee_rates.rs)
// .api_route(
// "/api/v1/mining/blocks/fee-rates/{time_period}",
// get_with(
// async |headers: HeaderMap, Path(path): Path<TimePeriodParam>, State(state): State<AppState>| {
// state.cached_json(&headers, CacheStrategy::height_with(format!("feerates-{:?}", path.time_period)), move |q| q.block_fee_rates(path.time_period)).await
// },
// |op| {
// op.mining_tag()
// .summary("Block fee rates")
// .description("Get block fee rate percentiles (min, 10th, 25th, median, 75th, 90th, max) for a time period. Valid periods: 24h, 3d, 1w, 1m, 3m, 6m, 1y, 2y, 3y")
// .ok_response::<Vec<BlockFeeRatesEntry>>()
// .not_modified()
// .server_error()
// },
// ),
// )
.api_route(
"/api/v1/mining/blocks/fee-rates/{time_period}",
get_with(
async |Path(_path): Path<TimePeriodParam>| {
axum::Json(serde_json::json!({
"status": "wip",
"message": "This endpoint is work in progress. Percentile fields are not yet available."
}))
},
|op| {
op.id("get_block_fee_rates")
.mining_tag()
.summary("Block fee rates (WIP)")
.description("**Work in progress.** Get block fee rate percentiles (min, 10th, 25th, median, 75th, 90th, max) for a time period. Valid periods: 24h, 3d, 1w, 1m, 3m, 6m, 1y, 2y, 3y\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-feerates)*")
.ok_response::<serde_json::Value>()
},
),
)
.api_route(
"/api/v1/mining/blocks/sizes-weights/{time_period}",
get_with(
@@ -211,9 +222,10 @@ impl MiningRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::height_with(format!("sizes-{:?}", path.time_period)), move |q| q.block_sizes_weights(path.time_period)).await
},
|op| {
op.mining_tag()
op.id("get_block_sizes_weights")
.mining_tag()
.summary("Block sizes and weights")
.description("Get average block sizes and weights for a time period. Valid periods: 24h, 3d, 1w, 1m, 3m, 6m, 1y, 2y, 3y")
.description("Get average block sizes and weights for a time period. Valid periods: 24h, 3d, 1w, 1m, 3m, 6m, 1y, 2y, 3y\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-sizes-weights)*")
.ok_response::<BlockSizesWeights>()
.not_modified()
.server_error()
@@ -227,9 +239,10 @@ impl MiningRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::height_with(format!("reward-stats-{}", path.block_count)), move |q| q.reward_stats(path.block_count)).await
},
|op| {
op.mining_tag()
op.id("get_reward_stats")
.mining_tag()
.summary("Mining reward statistics")
.description("Get mining reward statistics for the last N blocks including total rewards, fees, and transaction count.")
.description("Get mining reward statistics for the last N blocks including total rewards, fees, and transaction count.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-reward-stats)*")
.ok_response::<RewardStats>()
.not_modified()
.server_error()

View File

@@ -58,7 +58,8 @@ impl ApiRoutes for ApiRouter<AppState> {
.await
},
|op| {
op.server_tag()
op.id("get_version")
.server_tag()
.summary("API version")
.description("Returns the current version of the API server")
.ok_response::<String>()
@@ -77,7 +78,8 @@ impl ApiRoutes for ApiRouter<AppState> {
})
},
|op| {
op.server_tag()
op.id("get_health")
.server_tag()
.summary("Health check")
.description("Returns the health status of the API server")
.ok_response::<Health>()

View File

@@ -1,4 +1,4 @@
use aide::openapi::{Info, OpenApi, Tag};
use aide::openapi::{Contact, Info, License, OpenApi, Tag};
//
// https://docs.rs/schemars/latest/schemars/derive.JsonSchema.html
@@ -18,10 +18,40 @@ pub fn create_openapi() -> OpenApi {
let info = Info {
title: "Bitcoin Research Kit".to_string(),
description: Some(
"API for querying Bitcoin blockchain data including addresses, transactions, and chain statistics. This API provides low-level access to indexed blockchain data with advanced analytics capabilities."
r#"API for querying Bitcoin blockchain data and on-chain metrics.
### Features
- **Metrics**: Thousands of time-series metrics across multiple indexes (date, block height, etc.)
- **[Mempool.space](https://mempool.space/docs/api/rest) compatible** (WIP): Most non-metrics endpoints follow the mempool.space API format
- **Multiple formats**: JSON and CSV output
### Client Libraries
- [JavaScript/TypeScript](https://www.npmjs.com/package/brk-client)
- [Python](https://pypi.org/project/brk-client/)
- [Rust](https://crates.io/crates/brk_client)
### Links
- [GitHub](https://github.com/bitcoinresearchkit/brk)
- [Bitview](https://bitview.space) - Web app built on this API"#
.to_string(),
),
version: format!("v{VERSION}"),
contact: Some(Contact {
name: Some("Bitcoin Research Kit".to_string()),
url: Some("https://github.com/bitcoinresearchkit/brk".to_string()),
email: Some("hello@bitcoinresearchkit.org".to_string()),
..Contact::default()
}),
license: Some(License {
name: "MIT".to_string(),
url: Some(
"https://github.com/bitcoinresearchkit/brk/blob/main/docs/LICENSE.md".to_string(),
),
..License::default()
}),
..Info::default()
};
@@ -29,8 +59,8 @@ pub fn create_openapi() -> OpenApi {
Tag {
name: "Metrics".to_string(),
description: Some(
"Access Bitcoin network metrics and time-series data. Query historical statistics \
across various indexes with JSON or CSV output."
"Access thousands of Bitcoin network metrics and time-series data. Query historical statistics \
across various indexes (date, week, month, block height) with JSON or CSV output."
.to_string(),
),
..Default::default()
@@ -39,7 +69,8 @@ pub fn create_openapi() -> OpenApi {
name: "Blocks".to_string(),
description: Some(
"Retrieve block data by hash or height. Access block headers, transaction lists, \
and raw block bytes."
and raw block bytes.\n\n\
*[Mempool.space](https://mempool.space/docs/api/rest) compatible (WIP).*"
.to_string(),
),
..Default::default()
@@ -48,7 +79,8 @@ pub fn create_openapi() -> OpenApi {
name: "Transactions".to_string(),
description: Some(
"Retrieve transaction data by txid. Access full transaction details, confirmation \
status, raw hex, and output spend information."
status, raw hex, and output spend information.\n\n\
*[Mempool.space](https://mempool.space/docs/api/rest) compatible (WIP).*"
.to_string(),
),
..Default::default()
@@ -57,7 +89,8 @@ pub fn create_openapi() -> OpenApi {
name: "Addresses".to_string(),
description: Some(
"Query Bitcoin address data including balances, transaction history, and UTXOs. \
Supports all address types: P2PKH, P2SH, P2WPKH, P2WSH, and P2TR."
Supports all address types: P2PKH, P2SH, P2WPKH, P2WSH, and P2TR.\n\n\
*[Mempool.space](https://mempool.space/docs/api/rest) compatible (WIP).*"
.to_string(),
),
..Default::default()
@@ -66,7 +99,8 @@ pub fn create_openapi() -> OpenApi {
name: "Mempool".to_string(),
description: Some(
"Monitor unconfirmed transactions and fee estimates. Get mempool statistics, \
transaction IDs, and recommended fee rates for different confirmation targets."
transaction IDs, and recommended fee rates for different confirmation targets.\n\n\
*[Mempool.space](https://mempool.space/docs/api/rest) compatible (WIP).*"
.to_string(),
),
..Default::default()
@@ -75,7 +109,8 @@ pub fn create_openapi() -> OpenApi {
name: "Mining".to_string(),
description: Some(
"Mining statistics including pool distribution, hashrate, difficulty adjustments, \
block rewards, and fee rates across configurable time periods."
block rewards, and fee rates across configurable time periods.\n\n\
*[Mempool.space](https://mempool.space/docs/api/rest) compatible (WIP).*"
.to_string(),
),
..Default::default()

View File

@@ -31,10 +31,11 @@ impl TxRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::Height, move |q| q.transaction(txid)).await
},
|op| op
.id("get_tx")
.transactions_tag()
.summary("Transaction information")
.description(
"Retrieve complete transaction data by transaction ID (txid). Returns the full transaction details including inputs, outputs, and metadata. The transaction data is read directly from the blockchain data files.",
"Retrieve complete transaction data by transaction ID (txid). Returns inputs, outputs, fee, size, and confirmation status.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-transaction)*",
)
.ok_response::<Transaction>()
.not_modified()
@@ -54,10 +55,11 @@ impl TxRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::Height, move |q| q.transaction_status(txid)).await
},
|op| op
.id("get_tx_status")
.transactions_tag()
.summary("Transaction status")
.description(
"Retrieve the confirmation status of a transaction. Returns whether the transaction is confirmed and, if so, the block height, hash, and timestamp.",
"Retrieve the confirmation status of a transaction. Returns whether the transaction is confirmed and, if so, the block height, hash, and timestamp.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-transaction-status)*",
)
.ok_response::<TxStatus>()
.not_modified()
@@ -77,10 +79,11 @@ impl TxRoutes for ApiRouter<AppState> {
state.cached_text(&headers, CacheStrategy::Height, move |q| q.transaction_hex(txid)).await
},
|op| op
.id("get_tx_hex")
.transactions_tag()
.summary("Transaction hex")
.description(
"Retrieve the raw transaction as a hex-encoded string. Returns the serialized transaction in hexadecimal format.",
"Retrieve the raw transaction as a hex-encoded string. Returns the serialized transaction in hexadecimal format.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-transaction-hex)*",
)
.ok_response::<Hex>()
.not_modified()
@@ -101,10 +104,11 @@ impl TxRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::Height, move |q| q.outspend(txid, path.vout)).await
},
|op| op
.id("get_tx_outspend")
.transactions_tag()
.summary("Output spend status")
.description(
"Get the spending status of a transaction output. Returns whether the output has been spent and, if so, the spending transaction details.",
"Get the spending status of a transaction output. Returns whether the output has been spent and, if so, the spending transaction details.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-transaction-outspend)*",
)
.ok_response::<TxOutspend>()
.not_modified()
@@ -124,10 +128,11 @@ impl TxRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::Height, move |q| q.outspends(txid)).await
},
|op| op
.id("get_tx_outspends")
.transactions_tag()
.summary("All output spend statuses")
.description(
"Get the spending status of all outputs in a transaction. Returns an array with the spend status for each output.",
"Get the spending status of all outputs in a transaction. Returns an array with the spend status for each output.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-transaction-outspends)*",
)
.ok_response::<Vec<TxOutspend>>()
.not_modified()