mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-07-11 19:18:14 -07:00
server: openapi fixes
This commit is contained in:
@@ -2,13 +2,11 @@ use aide::axum::{ApiRouter, routing::get_with};
|
||||
use axum::{
|
||||
extract::{Path, State},
|
||||
http::HeaderMap,
|
||||
response::Redirect,
|
||||
routing::get,
|
||||
};
|
||||
use brk_query::BLOCK_TXS_PAGE_SIZE;
|
||||
use brk_types::{
|
||||
BlockHashParam, BlockHashStartIndex, BlockHashTxIndex, BlockInfo, BlockStatus, BlockTimestamp,
|
||||
HeightParam, StartHeightParam, TimestampParam, Transaction, Txid,
|
||||
HeightParam, TimestampParam, Transaction, Txid,
|
||||
};
|
||||
|
||||
use crate::{CacheStrategy, extended::TransformResponseExtended};
|
||||
@@ -21,10 +19,23 @@ pub trait BlockRoutes {
|
||||
|
||||
impl BlockRoutes for ApiRouter<AppState> {
|
||||
fn add_block_routes(self) -> Self {
|
||||
self.route("/api/block", get(Redirect::temporary("/api/blocks")))
|
||||
.route(
|
||||
self.api_route(
|
||||
"/api/blocks",
|
||||
get(Redirect::temporary("/api#tag/blocks")),
|
||||
get_with(
|
||||
async |headers: HeaderMap, State(state): State<AppState>| {
|
||||
state
|
||||
.cached_json(&headers, CacheStrategy::Height, move |q| q.blocks(None))
|
||||
.await
|
||||
},
|
||||
|op| {
|
||||
op.blocks_tag()
|
||||
.summary("Recent blocks")
|
||||
.description("Retrieve the last 10 blocks. Returns block metadata for each block.")
|
||||
.ok_response::<Vec<BlockInfo>>()
|
||||
.not_modified()
|
||||
.server_error()
|
||||
},
|
||||
),
|
||||
)
|
||||
.api_route(
|
||||
"/api/block/{hash}",
|
||||
@@ -93,18 +104,18 @@ impl BlockRoutes for ApiRouter<AppState> {
|
||||
),
|
||||
)
|
||||
.api_route(
|
||||
"/api/blocks/{start_height}",
|
||||
"/api/blocks/{height}",
|
||||
get_with(
|
||||
async |headers: HeaderMap,
|
||||
Path(path): Path<StartHeightParam>,
|
||||
Path(path): Path<HeightParam>,
|
||||
State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, move |q| q.blocks(path.start_height)).await
|
||||
state.cached_json(&headers, CacheStrategy::Height, move |q| q.blocks(Some(path.height))).await
|
||||
},
|
||||
|op| {
|
||||
op.blocks_tag()
|
||||
.summary("Recent blocks")
|
||||
.summary("Blocks from height")
|
||||
.description(
|
||||
"Retrieve the last 10 blocks, optionally starting from a specific height. Returns block metadata for each block.",
|
||||
"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.",
|
||||
)
|
||||
.ok_response::<Vec<BlockInfo>>()
|
||||
.not_modified()
|
||||
|
||||
@@ -41,11 +41,11 @@ async fn req_to_response_res(
|
||||
) -> brk_error::Result<Response> {
|
||||
let format = params.format();
|
||||
let height = query.sync(|q| q.height());
|
||||
let to = params.to();
|
||||
|
||||
let cache_params = CacheParams::resolve(&CacheStrategy::height_with(format!("{to:?}")), || {
|
||||
height.into()
|
||||
});
|
||||
let cache_params =
|
||||
CacheParams::resolve(&CacheStrategy::height_with(params.etag_suffix()), || {
|
||||
height.into()
|
||||
});
|
||||
|
||||
if cache_params.matches_etag(&headers) {
|
||||
let mut response = (StatusCode::NOT_MODIFIED, "").into_response();
|
||||
|
||||
@@ -43,11 +43,11 @@ async fn req_to_response_res(
|
||||
) -> brk_error::Result<Response> {
|
||||
let format = params.format();
|
||||
let height = query.sync(|q| q.height());
|
||||
let to = params.to();
|
||||
|
||||
let cache_params = CacheParams::resolve(&CacheStrategy::height_with(format!("{to:?}")), || {
|
||||
height.into()
|
||||
});
|
||||
let cache_params =
|
||||
CacheParams::resolve(&CacheStrategy::height_with(params.etag_suffix()), || {
|
||||
height.into()
|
||||
});
|
||||
|
||||
if cache_params.matches_etag(&headers) {
|
||||
let mut response = (StatusCode::NOT_MODIFIED, "").into_response();
|
||||
|
||||
@@ -43,11 +43,11 @@ async fn req_to_response_res(
|
||||
) -> brk_error::Result<Response> {
|
||||
let format = params.format();
|
||||
let height = query.sync(|q| q.height());
|
||||
let to = params.to();
|
||||
|
||||
let cache_params = CacheParams::resolve(&CacheStrategy::height_with(format!("{to:?}")), || {
|
||||
height.into()
|
||||
});
|
||||
let cache_params =
|
||||
CacheParams::resolve(&CacheStrategy::height_with(params.etag_suffix()), || {
|
||||
height.into()
|
||||
});
|
||||
|
||||
if cache_params.matches_etag(&headers) {
|
||||
let mut response = (StatusCode::NOT_MODIFIED, "").into_response();
|
||||
|
||||
@@ -193,27 +193,9 @@ impl ApiMetricsRoutes for ApiRouter<AppState> {
|
||||
.not_modified(),
|
||||
),
|
||||
)
|
||||
// !!!
|
||||
// DEPRECATED: Do not use
|
||||
// !!!
|
||||
.route(
|
||||
"/api/vecs/query",
|
||||
get(
|
||||
async |uri: Uri,
|
||||
headers: HeaderMap,
|
||||
Query(params): Query<MetricSelectionLegacy>,
|
||||
state: State<AppState>|
|
||||
-> Response {
|
||||
legacy::handler(uri, headers, Query(params.into()), state).await
|
||||
},
|
||||
),
|
||||
)
|
||||
// !!!
|
||||
// DEPRECATED: Do not use
|
||||
// !!!
|
||||
.route(
|
||||
.api_route(
|
||||
"/api/vecs/{variant}",
|
||||
get(
|
||||
get_with(
|
||||
async |uri: Uri,
|
||||
headers: HeaderMap,
|
||||
Path(variant): Path<String>,
|
||||
@@ -236,6 +218,41 @@ impl ApiMetricsRoutes for ApiRouter<AppState> {
|
||||
));
|
||||
legacy::handler(uri, headers, Query(params), state).await
|
||||
},
|
||||
|op| op
|
||||
.metrics_tag()
|
||||
.summary("Legacy variant endpoint")
|
||||
.description(
|
||||
"**DEPRECATED** - Use `/api/metric/{metric}/{index}` instead.\n\n\
|
||||
Sunset date: 2027-01-01. May be removed earlier in case of abuse.\n\n\
|
||||
Legacy endpoint for querying metrics by variant path (e.g., `dateindex_to_price`). \
|
||||
Returns raw data without the MetricData wrapper."
|
||||
)
|
||||
.deprecated()
|
||||
.ok_response::<serde_json::Value>()
|
||||
.not_modified(),
|
||||
),
|
||||
)
|
||||
.api_route(
|
||||
"/api/vecs/query",
|
||||
get_with(
|
||||
async |uri: Uri,
|
||||
headers: HeaderMap,
|
||||
Query(params): Query<MetricSelectionLegacy>,
|
||||
state: State<AppState>|
|
||||
-> Response {
|
||||
legacy::handler(uri, headers, Query(params.into()), state).await
|
||||
},
|
||||
|op| op
|
||||
.metrics_tag()
|
||||
.summary("Legacy query endpoint")
|
||||
.description(
|
||||
"**DEPRECATED** - Use `/api/metric/{metric}/{index}` or `/api/metrics/bulk` instead.\n\n\
|
||||
Sunset date: 2027-01-01. May be removed earlier in case of abuse.\n\n\
|
||||
Legacy endpoint for querying metrics. Returns raw data without the MetricData wrapper."
|
||||
)
|
||||
.deprecated()
|
||||
.ok_response::<serde_json::Value>()
|
||||
.not_modified(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use axum::{
|
||||
routing::get,
|
||||
};
|
||||
use brk_types::{
|
||||
BlockCountParam, BlockFeeRatesEntry, BlockFeesEntry, BlockRewardsEntry, BlockSizesWeights,
|
||||
BlockCountParam, BlockFeesEntry, BlockRewardsEntry, BlockSizesWeights,
|
||||
DifficultyAdjustment, DifficultyAdjustmentEntry, HashrateSummary, PoolDetail, PoolInfo,
|
||||
PoolSlugParam, PoolsSummary, RewardStats, TimePeriodParam,
|
||||
};
|
||||
@@ -187,22 +187,23 @@ impl MiningRoutes for ApiRouter<AppState> {
|
||||
},
|
||||
),
|
||||
)
|
||||
.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()
|
||||
},
|
||||
),
|
||||
)
|
||||
// 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/sizes-weights/{time_period}",
|
||||
get_with(
|
||||
|
||||
Reference in New Issue
Block a user