global: fixes

This commit is contained in:
nym21
2026-04-01 21:11:20 +02:00
parent 098950fdde
commit 0558834eef
19 changed files with 253 additions and 172 deletions

View File

@@ -101,7 +101,7 @@ pub fn generate_api_methods(output: &mut String, endpoints: &[Endpoint]) {
.response_type
.as_deref()
.map(js_type_to_python)
.unwrap_or_else(|| "Any".to_string()),
.unwrap_or_else(|| "str".to_string()),
);
let return_type = if endpoint.supports_csv {
@@ -159,11 +159,19 @@ pub fn generate_api_methods(output: &mut String, endpoints: &[Endpoint]) {
// Build path
let path = build_path_template(&endpoint.path, &endpoint.path_params);
let fetch_method = if endpoint.returns_json() {
"get_json"
} else {
"get_text"
};
if endpoint.query_params.is_empty() {
if endpoint.path_params.is_empty() {
writeln!(output, " return self.get_json('{}')", path).unwrap();
writeln!(output, " return self.{}('{}')", fetch_method, path)
.unwrap();
} else {
writeln!(output, " return self.get_json(f'{}')", path).unwrap();
writeln!(output, " return self.{}(f'{}')", fetch_method, path)
.unwrap();
}
} else {
writeln!(output, " params = []").unwrap();
@@ -197,9 +205,9 @@ pub fn generate_api_methods(output: &mut String, endpoints: &[Endpoint]) {
if endpoint.supports_csv {
writeln!(output, " if format == 'csv':").unwrap();
writeln!(output, " return self.get_text(path)").unwrap();
writeln!(output, " return self.get_json(path)").unwrap();
writeln!(output, " return self.{}(path)", fetch_method).unwrap();
} else {
writeln!(output, " return self.get_json(path)").unwrap();
writeln!(output, " return self.{}(path)", fetch_method).unwrap();
}
}

View File

@@ -93,7 +93,7 @@ pub fn generate_api_methods(output: &mut String, endpoints: &[Endpoint]) {
.response_type
.as_deref()
.map(js_type_to_rust)
.unwrap_or_else(|| "serde_json::Value".to_string());
.unwrap_or_else(|| "String".to_string());
let return_type = if endpoint.supports_csv {
format!("FormatResponse<{}>", base_return_type)
@@ -132,12 +132,17 @@ pub fn generate_api_methods(output: &mut String, endpoints: &[Endpoint]) {
.unwrap();
let (path, index_arg) = build_path_template(endpoint);
let fetch_method = if endpoint.returns_json() {
"get_json"
} else {
"get_text"
};
if endpoint.query_params.is_empty() {
writeln!(
output,
" self.base.get_json(&format!(\"{}\"{}))",
path, index_arg
" self.base.{}(&format!(\"{}\"{}))",
fetch_method, path, index_arg
)
.unwrap();
} else {
@@ -186,12 +191,14 @@ pub fn generate_api_methods(output: &mut String, endpoints: &[Endpoint]) {
writeln!(output, " }} else {{").unwrap();
writeln!(
output,
" self.base.get_json(&path).map(FormatResponse::Json)"
" self.base.{}(&path).map(FormatResponse::Json)",
fetch_method
)
.unwrap();
writeln!(output, " }}").unwrap();
} else {
writeln!(output, " self.base.get_json(&path)").unwrap();
writeln!(output, " self.base.{}(&path)", fetch_method)
.unwrap();
}
}

View File

@@ -43,6 +43,11 @@ impl Endpoint {
self.method == "GET" && !self.deprecated
}
/// Returns true if this endpoint returns JSON (has a response_type extracted from application/json).
pub fn returns_json(&self) -> bool {
self.response_type.is_some()
}
/// Returns the operation ID or generates one from the path.
/// The returned string uses the raw case from the spec (typically camelCase).
pub fn operation_name(&self) -> String {

View File

@@ -8253,8 +8253,8 @@ impl BrkClient {
/// Compact OpenAPI specification optimized for LLM consumption. Removes redundant fields while preserving essential API information. Full spec available at `/openapi.json`.
///
/// Endpoint: `GET /api.json`
pub fn get_api(&self) -> Result<serde_json::Value> {
self.base.get_json(&format!("/api.json"))
pub fn get_api(&self) -> Result<String> {
self.base.get_text(&format!("/api.json"))
}
/// Address information
@@ -8327,8 +8327,8 @@ impl BrkClient {
/// *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-height)*
///
/// Endpoint: `GET /api/block-height/{height}`
pub fn get_block_by_height(&self, height: Height) -> Result<BlockHash> {
self.base.get_json(&format!("/api/block-height/{height}"))
pub fn get_block_by_height(&self, height: Height) -> Result<String> {
self.base.get_text(&format!("/api/block-height/{height}"))
}
/// Block information
@@ -8349,8 +8349,8 @@ impl BrkClient {
/// *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-header)*
///
/// Endpoint: `GET /api/block/{hash}/header`
pub fn get_block_header(&self, hash: BlockHash) -> Result<Hex> {
self.base.get_json(&format!("/api/block/{hash}/header"))
pub fn get_block_header(&self, hash: BlockHash) -> Result<String> {
self.base.get_text(&format!("/api/block/{hash}/header"))
}
/// Raw block
@@ -8382,8 +8382,8 @@ impl BrkClient {
/// *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-transaction-id)*
///
/// Endpoint: `GET /api/block/{hash}/txid/{index}`
pub fn get_block_txid(&self, hash: BlockHash, index: TxIndex) -> Result<Txid> {
self.base.get_json(&format!("/api/block/{hash}/txid/{index}"))
pub fn get_block_txid(&self, hash: BlockHash, index: TxIndex) -> Result<String> {
self.base.get_text(&format!("/api/block/{hash}/txid/{index}"))
}
/// Block transaction IDs
@@ -8397,6 +8397,17 @@ impl BrkClient {
self.base.get_json(&format!("/api/block/{hash}/txids"))
}
/// Block transactions
///
/// Retrieve transactions in a block by block hash. Returns up to 25 transactions starting from index 0.
///
/// *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-transactions)*
///
/// Endpoint: `GET /api/block/{hash}/txs`
pub fn get_block_txs(&self, hash: BlockHash) -> Result<Vec<Transaction>> {
self.base.get_json(&format!("/api/block/{hash}/txs"))
}
/// Block transactions (paginated)
///
/// Retrieve transactions in a block by block hash, starting from the specified index. Returns up to 25 transactions at a time.
@@ -8404,7 +8415,7 @@ impl BrkClient {
/// *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-transactions)*
///
/// Endpoint: `GET /api/block/{hash}/txs/{start_index}`
pub fn get_block_txs(&self, hash: BlockHash, start_index: TxIndex) -> Result<Vec<Transaction>> {
pub fn get_block_txs_from_index(&self, hash: BlockHash, start_index: TxIndex) -> Result<Vec<Transaction>> {
self.base.get_json(&format!("/api/block/{hash}/txs/{start_index}"))
}
@@ -8426,8 +8437,8 @@ impl BrkClient {
/// *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-tip-hash)*
///
/// Endpoint: `GET /api/blocks/tip/hash`
pub fn get_block_tip_hash(&self) -> Result<BlockHash> {
self.base.get_json(&format!("/api/blocks/tip/hash"))
pub fn get_block_tip_hash(&self) -> Result<String> {
self.base.get_text(&format!("/api/blocks/tip/hash"))
}
/// Block tip height
@@ -8437,8 +8448,8 @@ impl BrkClient {
/// *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-tip-height)*
///
/// Endpoint: `GET /api/blocks/tip/height`
pub fn get_block_tip_height(&self) -> Result<Height> {
self.base.get_json(&format!("/api/blocks/tip/height"))
pub fn get_block_tip_height(&self) -> Result<String> {
self.base.get_text(&format!("/api/blocks/tip/height"))
}
/// Blocks from height
@@ -8661,8 +8672,8 @@ impl BrkClient {
/// Returns the single most recent value for a series, unwrapped (not inside a SeriesData object).
///
/// Endpoint: `GET /api/series/{series}/{index}/latest`
pub fn get_series_latest(&self, series: SeriesName, index: Index) -> Result<serde_json::Value> {
self.base.get_json(&format!("/api/series/{series}/{}/latest", index.name()))
pub fn get_series_latest(&self, series: SeriesName, index: Index) -> Result<String> {
self.base.get_text(&format!("/api/series/{series}/{}/latest", index.name()))
}
/// Get series data length
@@ -8719,8 +8730,8 @@ impl BrkClient {
/// *[Mempool.space docs](https://mempool.space/docs/api/rest#get-transaction-hex)*
///
/// Endpoint: `GET /api/tx/{txid}/hex`
pub fn get_tx_hex(&self, txid: Txid) -> Result<Hex> {
self.base.get_json(&format!("/api/tx/{txid}/hex"))
pub fn get_tx_hex(&self, txid: Txid) -> Result<String> {
self.base.get_text(&format!("/api/tx/{txid}/hex"))
}
/// Transaction merkle proof
@@ -8742,7 +8753,7 @@ impl BrkClient {
///
/// Endpoint: `GET /api/tx/{txid}/merkleblock-proof`
pub fn get_tx_merkleblock_proof(&self, txid: Txid) -> Result<String> {
self.base.get_json(&format!("/api/tx/{txid}/merkleblock-proof"))
self.base.get_text(&format!("/api/tx/{txid}/merkleblock-proof"))
}
/// Output spend status
@@ -8899,8 +8910,8 @@ impl BrkClient {
/// *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-feerates)*
///
/// Endpoint: `GET /api/v1/mining/blocks/fee-rates/{time_period}`
pub fn get_block_fee_rates(&self, time_period: TimePeriod) -> Result<serde_json::Value> {
self.base.get_json(&format!("/api/v1/mining/blocks/fee-rates/{time_period}"))
pub fn get_block_fee_rates(&self, time_period: TimePeriod) -> Result<String> {
self.base.get_text(&format!("/api/v1/mining/blocks/fee-rates/{time_period}"))
}
/// Block fees
@@ -9137,8 +9148,8 @@ impl BrkClient {
/// Full OpenAPI 3.1 specification for this API.
///
/// Endpoint: `GET /openapi.json`
pub fn get_openapi(&self) -> Result<serde_json::Value> {
self.base.get_json(&format!("/openapi.json"))
pub fn get_openapi(&self) -> Result<String> {
self.base.get_text(&format!("/openapi.json"))
}
/// API version

View File

@@ -37,7 +37,7 @@ impl AddrRoutes for ApiRouter<AppState> {
.addrs_tag()
.summary("Address information")
.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::<AddrStats>()
.json_response::<AddrStats>()
.not_modified()
.bad_request()
.not_found()
@@ -59,7 +59,7 @@ impl AddrRoutes for ApiRouter<AppState> {
.addrs_tag()
.summary("Address transactions")
.description("Get transaction history for an address, sorted with newest first. Returns up to 50 mempool transactions plus the first 25 confirmed transactions. Use ?after_txid=<txid> for pagination.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-address-transactions)*")
.ok_response::<Vec<Transaction>>()
.json_response::<Vec<Transaction>>()
.not_modified()
.bad_request()
.not_found()
@@ -81,7 +81,7 @@ impl AddrRoutes for ApiRouter<AppState> {
.addrs_tag()
.summary("Address confirmed transactions")
.description("Get confirmed transactions 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<Transaction>>()
.json_response::<Vec<Transaction>>()
.not_modified()
.bad_request()
.not_found()
@@ -103,7 +103,7 @@ impl AddrRoutes for ApiRouter<AppState> {
.addrs_tag()
.summary("Address mempool transactions")
.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>>()
.json_response::<Vec<Txid>>()
.bad_request()
.not_found()
.server_error()
@@ -123,7 +123,7 @@ impl AddrRoutes for ApiRouter<AppState> {
.addrs_tag()
.summary("Address UTXOs")
.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>>()
.json_response::<Vec<Utxo>>()
.not_modified()
.bad_request()
.not_found()
@@ -144,7 +144,7 @@ impl AddrRoutes for ApiRouter<AppState> {
.addrs_tag()
.summary("Validate address")
.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::<AddrValidation>()
.json_response::<AddrValidation>()
.not_modified()
),
)

View File

@@ -5,8 +5,8 @@ use axum::{
};
use brk_query::BLOCK_TXS_PAGE_SIZE;
use brk_types::{
BlockHash, BlockHashParam, BlockHashStartIndex, BlockHashTxIndex, BlockInfo, BlockInfoV1,
BlockStatus, BlockTimestamp, Height, HeightParam, Hex, TimestampParam, Transaction, Txid,
BlockHashParam, BlockHashStartIndex, BlockHashTxIndex, BlockInfo, BlockInfoV1, BlockStatus,
BlockTimestamp, HeightParam, TimestampParam, Transaction, TxIndex, Txid,
};
use crate::{CacheStrategy, extended::TransformResponseExtended};
@@ -35,7 +35,7 @@ impl BlockRoutes for ApiRouter<AppState> {
.description(
"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>()
.json_response::<BlockInfo>()
.not_modified()
.bad_request()
.not_found()
@@ -57,7 +57,7 @@ impl BlockRoutes for ApiRouter<AppState> {
.blocks_tag()
.summary("Block (v1)")
.description("Returns block details with extras by hash.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-v1)*")
.ok_response::<BlockInfoV1>()
.json_response::<BlockInfoV1>()
.not_modified()
.not_found()
.server_error()
@@ -75,7 +75,7 @@ impl BlockRoutes for ApiRouter<AppState> {
.blocks_tag()
.summary("Block header")
.description("Returns the hex-encoded block header.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-header)*")
.ok_response::<Hex>()
.text_response()
.not_modified()
.not_found()
.server_error()
@@ -98,7 +98,7 @@ impl BlockRoutes for ApiRouter<AppState> {
.description(
"Retrieve the block hash at a given height. Returns the hash as plain text.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-height)*",
)
.ok_response::<BlockHash>()
.text_response()
.not_modified()
.bad_request()
.not_found()
@@ -120,7 +120,7 @@ impl BlockRoutes for ApiRouter<AppState> {
.blocks_tag()
.summary("Block by 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>()
.json_response::<BlockTimestamp>()
.not_modified()
.bad_request()
.not_found()
@@ -144,7 +144,7 @@ impl BlockRoutes for ApiRouter<AppState> {
.description(
"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>>()
.json_response::<Vec<u8>>()
.not_modified()
.bad_request()
.not_found()
@@ -168,7 +168,7 @@ impl BlockRoutes for ApiRouter<AppState> {
.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.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-status)*",
)
.ok_response::<BlockStatus>()
.json_response::<BlockStatus>()
.not_modified()
.bad_request()
.not_found()
@@ -187,7 +187,7 @@ impl BlockRoutes for ApiRouter<AppState> {
.blocks_tag()
.summary("Block tip height")
.description("Returns the height of the last block.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-tip-height)*")
.ok_response::<Height>()
.text_response()
.not_modified()
.server_error()
},
@@ -204,7 +204,7 @@ impl BlockRoutes for ApiRouter<AppState> {
.blocks_tag()
.summary("Block tip hash")
.description("Returns the hash of the last block.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-tip-hash)*")
.ok_response::<BlockHash>()
.text_response()
.not_modified()
.server_error()
},
@@ -226,7 +226,7 @@ impl BlockRoutes for ApiRouter<AppState> {
.description(
"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>()
.text_response()
.not_modified()
.bad_request()
.not_found()
@@ -250,7 +250,32 @@ impl BlockRoutes for ApiRouter<AppState> {
.description(
"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>>()
.json_response::<Vec<Txid>>()
.not_modified()
.bad_request()
.not_found()
.server_error()
},
),
)
.api_route(
"/api/block/{hash}/txs",
get_with(
async |uri: Uri,
headers: HeaderMap,
Path(path): Path<BlockHashParam>,
State(state): State<AppState>| {
state.cached_json(&headers, CacheStrategy::Static, &uri, move |q| q.block_txs(&path.hash, TxIndex::default())).await
},
|op| {
op.id("get_block_txs")
.blocks_tag()
.summary("Block transactions")
.description(&format!(
"Retrieve transactions in a block by block hash. Returns up to {} transactions starting from index 0.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-transactions)*",
BLOCK_TXS_PAGE_SIZE
))
.json_response::<Vec<Transaction>>()
.not_modified()
.bad_request()
.not_found()
@@ -268,14 +293,14 @@ impl BlockRoutes for ApiRouter<AppState> {
state.cached_json(&headers, CacheStrategy::Static, &uri, move |q| q.block_txs(&path.hash, path.start_index)).await
},
|op| {
op.id("get_block_txs")
op.id("get_block_txs_from_index")
.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.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-transactions)*",
BLOCK_TXS_PAGE_SIZE
))
.ok_response::<Vec<Transaction>>()
.json_response::<Vec<Transaction>>()
.not_modified()
.bad_request()
.not_found()
@@ -296,7 +321,7 @@ impl BlockRoutes for ApiRouter<AppState> {
.blocks_tag()
.summary("Recent blocks")
.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>>()
.json_response::<Vec<BlockInfo>>()
.not_modified()
.server_error()
},
@@ -318,7 +343,7 @@ impl BlockRoutes for ApiRouter<AppState> {
.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.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-blocks)*",
)
.ok_response::<Vec<BlockInfo>>()
.json_response::<Vec<BlockInfo>>()
.not_modified()
.bad_request()
.server_error()
@@ -338,7 +363,7 @@ impl BlockRoutes for ApiRouter<AppState> {
.blocks_tag()
.summary("Recent blocks with extras")
.description("Retrieve the last 10 blocks with extended data including pool identification and fee statistics.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-blocks-v1)*")
.ok_response::<Vec<BlockInfoV1>>()
.json_response::<Vec<BlockInfoV1>>()
.not_modified()
.server_error()
},
@@ -358,7 +383,7 @@ impl BlockRoutes for ApiRouter<AppState> {
.blocks_tag()
.summary("Blocks from height with extras")
.description("Retrieve up to 10 blocks with extended data going backwards from the given height.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-blocks-v1)*")
.ok_response::<Vec<BlockInfoV1>>()
.json_response::<Vec<BlockInfoV1>>()
.not_modified()
.bad_request()
.server_error()

View File

@@ -30,7 +30,7 @@ impl FeesRoutes for ApiRouter<AppState> {
.fees_tag()
.summary("Projected mempool blocks")
.description("Get projected blocks from the mempool for fee estimation.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-mempool-blocks-fees)*")
.ok_response::<Vec<MempoolBlock>>()
.json_response::<Vec<MempoolBlock>>()
.server_error()
},
),
@@ -50,7 +50,7 @@ impl FeesRoutes for ApiRouter<AppState> {
.fees_tag()
.summary("Recommended fees")
.description("Get recommended fee rates for different confirmation targets.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-recommended-fees)*")
.ok_response::<RecommendedFees>()
.json_response::<RecommendedFees>()
.server_error()
},
),
@@ -70,7 +70,7 @@ impl FeesRoutes for ApiRouter<AppState> {
.fees_tag()
.summary("Precise recommended fees")
.description("Get recommended fee rates with up to 3 decimal places.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-recommended-fees-precise)*")
.ok_response::<RecommendedFees>()
.json_response::<RecommendedFees>()
.server_error()
},
),

View File

@@ -32,7 +32,7 @@ impl GeneralRoutes for ApiRouter<AppState> {
.general_tag()
.summary("Difficulty adjustment")
.description("Get current difficulty adjustment progress and estimates.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-difficulty-adjustment)*")
.ok_response::<DifficultyAdjustment>()
.json_response::<DifficultyAdjustment>()
.not_modified()
.server_error()
},
@@ -56,7 +56,7 @@ impl GeneralRoutes for ApiRouter<AppState> {
.general_tag()
.summary("Current BTC price")
.description("Returns bitcoin latest price (on-chain derived, USD only).\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-price)*")
.ok_response::<Prices>()
.json_response::<Prices>()
.server_error()
},
),
@@ -79,7 +79,7 @@ impl GeneralRoutes for ApiRouter<AppState> {
.general_tag()
.summary("Historical price")
.description("Get historical BTC/USD price. Optionally specify a UNIX timestamp to get the price at that time.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-historical-price)*")
.ok_response::<HistoricalPrice>()
.json_response::<HistoricalPrice>()
.not_modified()
.server_error()
},

View File

@@ -28,7 +28,7 @@ impl MempoolRoutes for ApiRouter<AppState> {
.mempool_tag()
.summary("Mempool statistics")
.description("Get current mempool statistics including transaction count, total vsize, total fees, and fee histogram.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-mempool)*")
.ok_response::<MempoolInfo>()
.json_response::<MempoolInfo>()
.server_error()
},
),
@@ -46,7 +46,7 @@ impl MempoolRoutes for ApiRouter<AppState> {
.mempool_tag()
.summary("Mempool transaction IDs")
.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>>()
.json_response::<Vec<Txid>>()
.server_error()
},
),
@@ -64,7 +64,7 @@ impl MempoolRoutes for ApiRouter<AppState> {
.mempool_tag()
.summary("Recent mempool transactions")
.description("Get the last 10 transactions to enter the mempool.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-mempool-recent)*")
.ok_response::<Vec<MempoolRecentTx>>()
.json_response::<Vec<MempoolRecentTx>>()
.server_error()
},
),
@@ -86,7 +86,7 @@ impl MempoolRoutes for ApiRouter<AppState> {
on-chain round-dollar output patterns in the last 12 blocks \
plus mempool.",
)
.ok_response::<Dollars>()
.json_response::<Dollars>()
.server_error()
},
),

View File

@@ -57,7 +57,7 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
"**DEPRECATED** - Use `/api/series` instead.\n\n\
Sunset date: 2027-01-01."
)
.ok_response::<TreeNode>()
.json_response::<TreeNode>()
.not_modified(),
),
)
@@ -80,7 +80,7 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
"**DEPRECATED** - Use `/api/series/count` instead.\n\n\
Sunset date: 2027-01-01."
)
.ok_response::<DetailedSeriesCount>()
.json_response::<DetailedSeriesCount>()
.not_modified(),
),
)
@@ -103,7 +103,7 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
"**DEPRECATED** - Use `/api/series/indexes` instead.\n\n\
Sunset date: 2027-01-01."
)
.ok_response::<Vec<IndexInfo>>()
.json_response::<Vec<IndexInfo>>()
.not_modified(),
),
)
@@ -127,7 +127,7 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
"**DEPRECATED** - Use `/api/series/list` instead.\n\n\
Sunset date: 2027-01-01."
)
.ok_response::<PaginatedSeries>()
.json_response::<PaginatedSeries>()
.not_modified(),
),
)
@@ -151,7 +151,7 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
"**DEPRECATED** - Use `/api/series/search` instead.\n\n\
Sunset date: 2027-01-01."
)
.ok_response::<Vec<&str>>()
.json_response::<Vec<&str>>()
.not_modified()
.server_error(),
),
@@ -173,7 +173,7 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
"**DEPRECATED** - Use `/api/series/bulk` instead.\n\n\
Sunset date: 2027-01-01."
)
.ok_response::<Vec<SeriesData>>()
.json_response::<Vec<SeriesData>>()
.csv_response()
.not_modified(),
),
@@ -201,7 +201,7 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
"**DEPRECATED** - Use `/api/series/{series}` instead.\n\n\
Sunset date: 2027-01-01."
)
.ok_response::<SeriesInfo>()
.json_response::<SeriesInfo>()
.not_modified()
.not_found()
.server_error(),
@@ -231,7 +231,7 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
"**DEPRECATED** - Use `/api/series/{series}/{index}` instead.\n\n\
Sunset date: 2027-01-01."
)
.ok_response::<SeriesData>()
.json_response::<SeriesData>()
.csv_response()
.not_modified()
.not_found(),
@@ -261,7 +261,7 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
"**DEPRECATED** - Use `/api/series/{series}/{index}/data` instead.\n\n\
Sunset date: 2027-01-01."
)
.ok_response::<Vec<serde_json::Value>>()
.json_response::<Vec<serde_json::Value>>()
.csv_response()
.not_modified()
.not_found(),
@@ -289,7 +289,7 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
"**DEPRECATED** - Use `/api/series/{series}/{index}/latest` instead.\n\n\
Sunset date: 2027-01-01."
)
.ok_response::<serde_json::Value>()
.json_response::<serde_json::Value>()
.not_found(),
),
)
@@ -315,7 +315,7 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
"**DEPRECATED** - Use `/api/series/{series}/{index}/len` instead.\n\n\
Sunset date: 2027-01-01."
)
.ok_response::<usize>()
.json_response::<usize>()
.not_found(),
),
)
@@ -341,7 +341,7 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
"**DEPRECATED** - Use `/api/series/{series}/{index}/version` instead.\n\n\
Sunset date: 2027-01-01."
)
.ok_response::<brk_types::Version>()
.json_response::<brk_types::Version>()
.not_found(),
),
)
@@ -363,7 +363,7 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
"**DEPRECATED** - Use `/api/series/cost-basis` instead.\n\n\
Sunset date: 2027-01-01."
)
.ok_response::<Vec<String>>()
.json_response::<Vec<String>>()
.server_error()
},
),
@@ -390,7 +390,7 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
"**DEPRECATED** - Use `/api/series/cost-basis/{cohort}/dates` instead.\n\n\
Sunset date: 2027-01-01."
)
.ok_response::<Vec<Date>>()
.json_response::<Vec<Date>>()
.not_found()
.server_error()
},
@@ -424,7 +424,7 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
"**DEPRECATED** - Use `/api/series/cost-basis/{cohort}/{date}` instead.\n\n\
Sunset date: 2027-01-01."
)
.ok_response::<CostBasisFormatted>()
.json_response::<CostBasisFormatted>()
.not_found()
.server_error()
},
@@ -471,7 +471,7 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
Returns raw data without the SeriesData wrapper."
)
.deprecated()
.ok_response::<serde_json::Value>()
.json_response::<serde_json::Value>()
.not_modified(),
),
)
@@ -498,7 +498,7 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
Legacy endpoint for querying series. Returns raw data without the SeriesData wrapper."
)
.deprecated()
.ok_response::<serde_json::Value>()
.json_response::<serde_json::Value>()
.not_modified(),
),
)

View File

@@ -38,7 +38,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.mining_tag()
.summary("List all mining pools")
.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>>()
.json_response::<Vec<PoolInfo>>()
.not_modified()
.server_error()
},
@@ -55,7 +55,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.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\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-mining-pools)*")
.ok_response::<PoolsSummary>()
.json_response::<PoolsSummary>()
.not_modified()
.server_error()
},
@@ -72,7 +72,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.mining_tag()
.summary("Mining pool details")
.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>()
.json_response::<PoolDetail>()
.not_modified()
.not_found()
.server_error()
@@ -90,7 +90,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.mining_tag()
.summary("All pools hashrate (all time)")
.description("Get hashrate data for all mining pools.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-mining-pool-hashrates)*")
.ok_response::<Vec<PoolHashrateEntry>>()
.json_response::<Vec<PoolHashrateEntry>>()
.not_modified()
.server_error()
},
@@ -107,7 +107,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.mining_tag()
.summary("All pools hashrate")
.description("Get hashrate data for all mining pools for a time period. Valid periods: 1m, 3m, 6m, 1y, 2y, 3y\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-mining-pool-hashrates)*")
.ok_response::<Vec<PoolHashrateEntry>>()
.json_response::<Vec<PoolHashrateEntry>>()
.not_modified()
.server_error()
},
@@ -124,7 +124,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.mining_tag()
.summary("Mining pool hashrate")
.description("Get hashrate history for a specific mining pool.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-mining-pool-hashrate)*")
.ok_response::<Vec<PoolHashrateEntry>>()
.json_response::<Vec<PoolHashrateEntry>>()
.not_modified()
.not_found()
.server_error()
@@ -142,7 +142,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.mining_tag()
.summary("Mining pool blocks")
.description("Get the 10 most recent blocks mined by a specific pool.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-mining-pool-blocks)*")
.ok_response::<Vec<BlockInfoV1>>()
.json_response::<Vec<BlockInfoV1>>()
.not_modified()
.not_found()
.server_error()
@@ -160,7 +160,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.mining_tag()
.summary("Mining pool blocks from height")
.description("Get 10 blocks mined by a specific pool before (and including) the given height.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-mining-pool-blocks)*")
.ok_response::<Vec<BlockInfoV1>>()
.json_response::<Vec<BlockInfoV1>>()
.not_modified()
.not_found()
.server_error()
@@ -178,7 +178,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.mining_tag()
.summary("Network hashrate (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>()
.json_response::<HashrateSummary>()
.not_modified()
.server_error()
},
@@ -195,7 +195,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.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\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-hashrate)*")
.ok_response::<HashrateSummary>()
.json_response::<HashrateSummary>()
.not_modified()
.server_error()
},
@@ -212,7 +212,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.mining_tag()
.summary("Difficulty adjustments (all time)")
.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>>()
.json_response::<Vec<DifficultyAdjustmentEntry>>()
.not_modified()
.server_error()
},
@@ -229,7 +229,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.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.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-difficulty-adjustments)*")
.ok_response::<Vec<DifficultyAdjustmentEntry>>()
.json_response::<Vec<DifficultyAdjustmentEntry>>()
.not_modified()
.server_error()
},
@@ -246,7 +246,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.mining_tag()
.summary("Mining reward statistics")
.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>()
.json_response::<RewardStats>()
.not_modified()
.server_error()
},
@@ -263,7 +263,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.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\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-fees)*")
.ok_response::<Vec<BlockFeesEntry>>()
.json_response::<Vec<BlockFeesEntry>>()
.not_modified()
.server_error()
},
@@ -280,7 +280,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.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\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-rewards)*")
.ok_response::<Vec<BlockRewardsEntry>>()
.json_response::<Vec<BlockRewardsEntry>>()
.not_modified()
.server_error()
},
@@ -312,7 +312,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.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\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-sizes-weights)*")
.ok_response::<BlockSizesWeights>()
.json_response::<BlockSizesWeights>()
.not_modified()
.server_error()
},

View File

@@ -85,7 +85,7 @@ impl ApiRoutes for ApiRouter<AppState> {
Removes redundant fields while preserving essential API information. \
Full spec available at `/openapi.json`.",
)
.ok_response::<serde_json::Value>()
.json_response::<serde_json::Value>()
},
),
)

View File

@@ -59,7 +59,7 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
"Returns the complete hierarchical catalog of available series organized as a tree structure. \
Series are grouped by categories and subcategories."
)
.ok_response::<TreeNode>()
.json_response::<TreeNode>()
.not_modified(),
),
)
@@ -78,7 +78,7 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
.series_tag()
.summary("Series count")
.description("Returns the number of series available per index type.")
.ok_response::<Vec<SeriesCount>>()
.json_response::<Vec<SeriesCount>>()
.not_modified(),
),
)
@@ -99,7 +99,7 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
.description(
"Returns all available indexes with their accepted query aliases. Use any alias when querying series."
)
.ok_response::<Vec<IndexInfo>>()
.json_response::<Vec<IndexInfo>>()
.not_modified(),
),
)
@@ -119,7 +119,7 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
.series_tag()
.summary("Series list")
.description("Paginated flat list of all available series names. Use `page` query param for pagination.")
.ok_response::<PaginatedSeries>()
.json_response::<PaginatedSeries>()
.not_modified(),
),
)
@@ -139,7 +139,7 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
.series_tag()
.summary("Search series")
.description("Fuzzy search for series by name. Supports partial matches and typos.")
.ok_response::<Vec<&str>>()
.json_response::<Vec<&str>>()
.not_modified()
.server_error(),
),
@@ -164,7 +164,7 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
.description(
"Returns the supported indexes and value type for the specified series."
)
.ok_response::<SeriesInfo>()
.json_response::<SeriesInfo>()
.not_modified()
.not_found()
.server_error(),
@@ -198,7 +198,7 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
"Fetch data for a specific series at the given index. \
Use query parameters to filter by date range and format (json/csv)."
)
.ok_response::<SeriesData>()
.json_response::<SeriesData>()
.csv_response()
.not_modified()
.not_found(),
@@ -232,7 +232,7 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
"Returns just the data array without the SeriesData wrapper. \
Supports the same range and format parameters as the standard endpoint."
)
.ok_response::<Vec<serde_json::Value>>()
.json_response::<Vec<serde_json::Value>>()
.csv_response()
.not_modified()
.not_found(),
@@ -258,7 +258,7 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
.description(
"Returns the single most recent value for a series, unwrapped (not inside a SeriesData object)."
)
.ok_response::<serde_json::Value>()
.json_response::<serde_json::Value>()
.not_found(),
),
)
@@ -280,7 +280,7 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
.series_tag()
.summary("Get series data length")
.description("Returns the total number of data points for a series at the given index.")
.ok_response::<usize>()
.json_response::<usize>()
.not_found(),
),
)
@@ -302,7 +302,7 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
.series_tag()
.summary("Get series version")
.description("Returns the current version of a series. Changes when the series data is updated.")
.ok_response::<brk_types::Version>()
.json_response::<brk_types::Version>()
.not_found(),
),
)
@@ -320,7 +320,7 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
"Fetch multiple series in a single request. Supports filtering by index and date range. \
Returns an array of SeriesData objects. For a single series, use `get_series` instead."
)
.ok_response::<Vec<SeriesData>>()
.json_response::<Vec<SeriesData>>()
.csv_response()
.not_modified(),
),
@@ -339,7 +339,7 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
.series_tag()
.summary("Available cost basis cohorts")
.description("List available cohorts for cost basis distribution.")
.ok_response::<Vec<String>>()
.json_response::<Vec<String>>()
.server_error()
},
),
@@ -362,7 +362,7 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
.series_tag()
.summary("Available cost basis dates")
.description("List available dates for a cohort's cost basis distribution.")
.ok_response::<Vec<Date>>()
.json_response::<Vec<Date>>()
.not_found()
.server_error()
},
@@ -397,7 +397,7 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
- `bucket`: raw (default), lin200, lin500, lin1000, log10, log50, log100\n\
- `value`: supply (default, in BTC), realized (USD), unrealized (USD)",
)
.ok_response::<CostBasisFormatted>()
.json_response::<CostBasisFormatted>()
.not_found()
.server_error()
},

View File

@@ -48,7 +48,7 @@ impl ServerRoutes for ApiRouter<AppState> {
.server_tag()
.summary("Health check")
.description("Returns the health status of the API server, including uptime information.")
.ok_response::<Health>()
.json_response::<Health>()
},
),
)
@@ -67,7 +67,7 @@ impl ServerRoutes for ApiRouter<AppState> {
.server_tag()
.summary("API version")
.description("Returns the current version of the API server")
.ok_response::<String>()
.json_response::<String>()
.not_modified()
},
),
@@ -91,7 +91,7 @@ impl ServerRoutes for ApiRouter<AppState> {
"Returns the sync status of the indexer, including indexed height, \
tip height, blocks behind, and last indexed timestamp.",
)
.ok_response::<SyncStatus>()
.json_response::<SyncStatus>()
.not_modified()
},
),
@@ -116,7 +116,7 @@ impl ServerRoutes for ApiRouter<AppState> {
.description(
"Returns the disk space used by BRK and Bitcoin data.",
)
.ok_response::<DiskUsage>()
.json_response::<DiskUsage>()
.not_modified()
},
),

View File

@@ -7,7 +7,7 @@ use axum::{
http::{HeaderMap, Uri},
};
use brk_types::{
CpfpInfo, Hex, MerkleProof, Transaction, TxOutspend, TxStatus, Txid, TxidParam, TxidVout,
CpfpInfo, MerkleProof, Transaction, TxOutspend, TxStatus, Txid, TxidParam, TxidVout,
TxidsParam,
};
@@ -33,7 +33,7 @@ impl TxRoutes for ApiRouter<AppState> {
.transactions_tag()
.summary("CPFP info")
.description("Returns ancestors and descendants for a CPFP transaction.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-children-pay-for-parent)*")
.ok_response::<CpfpInfo>()
.json_response::<CpfpInfo>()
.not_found()
.server_error(),
),
@@ -56,7 +56,7 @@ impl TxRoutes for ApiRouter<AppState> {
.description(
"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>()
.json_response::<Transaction>()
.not_modified()
.bad_request()
.not_found()
@@ -81,7 +81,7 @@ impl TxRoutes for ApiRouter<AppState> {
.description(
"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>()
.text_response()
.not_modified()
.bad_request()
.not_found()
@@ -99,7 +99,7 @@ impl TxRoutes for ApiRouter<AppState> {
.transactions_tag()
.summary("Transaction merkleblock proof")
.description("Get the merkleblock proof for a transaction (BIP37 format, hex encoded).\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-transaction-merkleblock-proof)*")
.ok_response::<String>()
.text_response()
.not_modified()
.bad_request()
.not_found()
@@ -117,7 +117,7 @@ impl TxRoutes for ApiRouter<AppState> {
.transactions_tag()
.summary("Transaction merkle proof")
.description("Get the merkle inclusion proof for a transaction.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-transaction-merkle-proof)*")
.ok_response::<MerkleProof>()
.json_response::<MerkleProof>()
.not_modified()
.bad_request()
.not_found()
@@ -143,7 +143,7 @@ impl TxRoutes for ApiRouter<AppState> {
.description(
"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>()
.json_response::<TxOutspend>()
.not_modified()
.bad_request()
.not_found()
@@ -168,7 +168,7 @@ impl TxRoutes for ApiRouter<AppState> {
.description(
"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>>()
.json_response::<Vec<TxOutspend>>()
.not_modified()
.bad_request()
.not_found()
@@ -186,7 +186,7 @@ impl TxRoutes for ApiRouter<AppState> {
.transactions_tag()
.summary("Transaction raw")
.description("Returns a transaction as binary data.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-transaction-raw)*")
.ok_response::<Vec<u8>>()
.json_response::<Vec<u8>>()
.not_modified()
.bad_request()
.not_found()
@@ -211,7 +211,7 @@ impl TxRoutes for ApiRouter<AppState> {
.description(
"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>()
.json_response::<TxStatus>()
.not_modified()
.bad_request()
.not_found()
@@ -230,7 +230,7 @@ impl TxRoutes for ApiRouter<AppState> {
.transactions_tag()
.summary("Transaction first-seen times")
.description("Returns timestamps when transactions were first seen in the mempool. Returns 0 for mined or unknown transactions.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-transaction-times)*")
.ok_response::<Vec<u64>>()
.json_response::<Vec<u64>>()
.server_error(),
),
)
@@ -248,7 +248,7 @@ impl TxRoutes for ApiRouter<AppState> {
.transactions_tag()
.summary("Broadcast transaction")
.description("Broadcast a raw transaction to the network. The transaction should be provided as hex in the request body. The txid will be returned on success.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#post-transaction)*")
.ok_response::<Txid>()
.json_response::<Txid>()
.bad_request()
.server_error()
},

View File

@@ -21,14 +21,16 @@ pub trait TransformResponseExtended<'t> {
fn deprecated(self) -> Self;
/// 200
fn ok_response<R>(self) -> Self
fn json_response<R>(self) -> Self
where
R: JsonSchema;
/// 200
fn ok_response_with<R, F>(self, f: F) -> Self
fn json_response_with<R, F>(self, f: F) -> Self
where
R: JsonSchema,
F: FnOnce(TransformResponse<'_, R>) -> TransformResponse<'_, R>;
/// 200 with text/plain content type
fn text_response(self) -> Self;
/// 200 with text/csv content type (adds CSV as alternative response format)
fn csv_response(self) -> Self;
/// 400
@@ -82,11 +84,11 @@ impl<'t> TransformResponseExtended<'t> for TransformOperation<'t> {
self.tag("Metrics")
}
fn ok_response<R>(self) -> Self
fn json_response<R>(self) -> Self
where
R: JsonSchema,
{
self.ok_response_with(|r: TransformResponse<'_, R>| r)
self.json_response_with(|r: TransformResponse<'_, R>| r)
}
fn deprecated(mut self) -> Self {
@@ -94,7 +96,7 @@ impl<'t> TransformResponseExtended<'t> for TransformOperation<'t> {
self
}
fn ok_response_with<R, F>(self, f: F) -> Self
fn json_response_with<R, F>(self, f: F) -> Self
where
R: JsonSchema,
F: FnOnce(TransformResponse<'_, R>) -> TransformResponse<'_, R>,
@@ -102,6 +104,10 @@ impl<'t> TransformResponseExtended<'t> for TransformOperation<'t> {
self.response_with::<200, Json<R>, _>(|res| f(res.description("Successful response")))
}
fn text_response(self) -> Self {
self.response_with::<200, String, _>(|res| res.description("Successful response"))
}
fn csv_response(mut self) -> Self {
// Add text/csv content type to existing 200 response
if let Some(responses) = &mut self.inner_mut().responses