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 .response_type
.as_deref() .as_deref()
.map(js_type_to_python) .map(js_type_to_python)
.unwrap_or_else(|| "Any".to_string()), .unwrap_or_else(|| "str".to_string()),
); );
let return_type = if endpoint.supports_csv { let return_type = if endpoint.supports_csv {
@@ -159,11 +159,19 @@ pub fn generate_api_methods(output: &mut String, endpoints: &[Endpoint]) {
// Build path // Build path
let path = build_path_template(&endpoint.path, &endpoint.path_params); 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.query_params.is_empty() {
if endpoint.path_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 { } else {
writeln!(output, " return self.get_json(f'{}')", path).unwrap(); writeln!(output, " return self.{}(f'{}')", fetch_method, path)
.unwrap();
} }
} else { } else {
writeln!(output, " params = []").unwrap(); writeln!(output, " params = []").unwrap();
@@ -197,9 +205,9 @@ pub fn generate_api_methods(output: &mut String, endpoints: &[Endpoint]) {
if endpoint.supports_csv { if endpoint.supports_csv {
writeln!(output, " if format == 'csv':").unwrap(); writeln!(output, " if format == 'csv':").unwrap();
writeln!(output, " return self.get_text(path)").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 { } 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 .response_type
.as_deref() .as_deref()
.map(js_type_to_rust) .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 { let return_type = if endpoint.supports_csv {
format!("FormatResponse<{}>", base_return_type) format!("FormatResponse<{}>", base_return_type)
@@ -132,12 +132,17 @@ pub fn generate_api_methods(output: &mut String, endpoints: &[Endpoint]) {
.unwrap(); .unwrap();
let (path, index_arg) = build_path_template(endpoint); 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() { if endpoint.query_params.is_empty() {
writeln!( writeln!(
output, output,
" self.base.get_json(&format!(\"{}\"{}))", " self.base.{}(&format!(\"{}\"{}))",
path, index_arg fetch_method, path, index_arg
) )
.unwrap(); .unwrap();
} else { } else {
@@ -186,12 +191,14 @@ pub fn generate_api_methods(output: &mut String, endpoints: &[Endpoint]) {
writeln!(output, " }} else {{").unwrap(); writeln!(output, " }} else {{").unwrap();
writeln!( writeln!(
output, output,
" self.base.get_json(&path).map(FormatResponse::Json)" " self.base.{}(&path).map(FormatResponse::Json)",
fetch_method
) )
.unwrap(); .unwrap();
writeln!(output, " }}").unwrap(); writeln!(output, " }}").unwrap();
} else { } 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 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. /// Returns the operation ID or generates one from the path.
/// The returned string uses the raw case from the spec (typically camelCase). /// The returned string uses the raw case from the spec (typically camelCase).
pub fn operation_name(&self) -> String { 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`. /// 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` /// Endpoint: `GET /api.json`
pub fn get_api(&self) -> Result<serde_json::Value> { pub fn get_api(&self) -> Result<String> {
self.base.get_json(&format!("/api.json")) self.base.get_text(&format!("/api.json"))
} }
/// Address information /// Address information
@@ -8327,8 +8327,8 @@ impl BrkClient {
/// *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-height)* /// *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-height)*
/// ///
/// Endpoint: `GET /api/block-height/{height}` /// Endpoint: `GET /api/block-height/{height}`
pub fn get_block_by_height(&self, height: Height) -> Result<BlockHash> { pub fn get_block_by_height(&self, height: Height) -> Result<String> {
self.base.get_json(&format!("/api/block-height/{height}")) self.base.get_text(&format!("/api/block-height/{height}"))
} }
/// Block information /// Block information
@@ -8349,8 +8349,8 @@ impl BrkClient {
/// *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-header)* /// *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-header)*
/// ///
/// Endpoint: `GET /api/block/{hash}/header` /// Endpoint: `GET /api/block/{hash}/header`
pub fn get_block_header(&self, hash: BlockHash) -> Result<Hex> { pub fn get_block_header(&self, hash: BlockHash) -> Result<String> {
self.base.get_json(&format!("/api/block/{hash}/header")) self.base.get_text(&format!("/api/block/{hash}/header"))
} }
/// Raw block /// Raw block
@@ -8382,8 +8382,8 @@ impl BrkClient {
/// *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-transaction-id)* /// *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-transaction-id)*
/// ///
/// Endpoint: `GET /api/block/{hash}/txid/{index}` /// Endpoint: `GET /api/block/{hash}/txid/{index}`
pub fn get_block_txid(&self, hash: BlockHash, index: TxIndex) -> Result<Txid> { pub fn get_block_txid(&self, hash: BlockHash, index: TxIndex) -> Result<String> {
self.base.get_json(&format!("/api/block/{hash}/txid/{index}")) self.base.get_text(&format!("/api/block/{hash}/txid/{index}"))
} }
/// Block transaction IDs /// Block transaction IDs
@@ -8397,6 +8397,17 @@ impl BrkClient {
self.base.get_json(&format!("/api/block/{hash}/txids")) 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) /// Block transactions (paginated)
/// ///
/// Retrieve transactions in a block by block hash, starting from the specified index. Returns up to 25 transactions at a time. /// 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)* /// *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-transactions)*
/// ///
/// Endpoint: `GET /api/block/{hash}/txs/{start_index}` /// 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}")) 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)* /// *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-tip-hash)*
/// ///
/// Endpoint: `GET /api/blocks/tip/hash` /// Endpoint: `GET /api/blocks/tip/hash`
pub fn get_block_tip_hash(&self) -> Result<BlockHash> { pub fn get_block_tip_hash(&self) -> Result<String> {
self.base.get_json(&format!("/api/blocks/tip/hash")) self.base.get_text(&format!("/api/blocks/tip/hash"))
} }
/// Block tip height /// Block tip height
@@ -8437,8 +8448,8 @@ impl BrkClient {
/// *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-tip-height)* /// *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-tip-height)*
/// ///
/// Endpoint: `GET /api/blocks/tip/height` /// Endpoint: `GET /api/blocks/tip/height`
pub fn get_block_tip_height(&self) -> Result<Height> { pub fn get_block_tip_height(&self) -> Result<String> {
self.base.get_json(&format!("/api/blocks/tip/height")) self.base.get_text(&format!("/api/blocks/tip/height"))
} }
/// Blocks from 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). /// Returns the single most recent value for a series, unwrapped (not inside a SeriesData object).
/// ///
/// Endpoint: `GET /api/series/{series}/{index}/latest` /// Endpoint: `GET /api/series/{series}/{index}/latest`
pub fn get_series_latest(&self, series: SeriesName, index: Index) -> Result<serde_json::Value> { pub fn get_series_latest(&self, series: SeriesName, index: Index) -> Result<String> {
self.base.get_json(&format!("/api/series/{series}/{}/latest", index.name())) self.base.get_text(&format!("/api/series/{series}/{}/latest", index.name()))
} }
/// Get series data length /// Get series data length
@@ -8719,8 +8730,8 @@ impl BrkClient {
/// *[Mempool.space docs](https://mempool.space/docs/api/rest#get-transaction-hex)* /// *[Mempool.space docs](https://mempool.space/docs/api/rest#get-transaction-hex)*
/// ///
/// Endpoint: `GET /api/tx/{txid}/hex` /// Endpoint: `GET /api/tx/{txid}/hex`
pub fn get_tx_hex(&self, txid: Txid) -> Result<Hex> { pub fn get_tx_hex(&self, txid: Txid) -> Result<String> {
self.base.get_json(&format!("/api/tx/{txid}/hex")) self.base.get_text(&format!("/api/tx/{txid}/hex"))
} }
/// Transaction merkle proof /// Transaction merkle proof
@@ -8742,7 +8753,7 @@ impl BrkClient {
/// ///
/// Endpoint: `GET /api/tx/{txid}/merkleblock-proof` /// Endpoint: `GET /api/tx/{txid}/merkleblock-proof`
pub fn get_tx_merkleblock_proof(&self, txid: Txid) -> Result<String> { 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 /// Output spend status
@@ -8899,8 +8910,8 @@ impl BrkClient {
/// *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-feerates)* /// *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-feerates)*
/// ///
/// Endpoint: `GET /api/v1/mining/blocks/fee-rates/{time_period}` /// Endpoint: `GET /api/v1/mining/blocks/fee-rates/{time_period}`
pub fn get_block_fee_rates(&self, time_period: TimePeriod) -> Result<serde_json::Value> { pub fn get_block_fee_rates(&self, time_period: TimePeriod) -> Result<String> {
self.base.get_json(&format!("/api/v1/mining/blocks/fee-rates/{time_period}")) self.base.get_text(&format!("/api/v1/mining/blocks/fee-rates/{time_period}"))
} }
/// Block fees /// Block fees
@@ -9137,8 +9148,8 @@ impl BrkClient {
/// Full OpenAPI 3.1 specification for this API. /// Full OpenAPI 3.1 specification for this API.
/// ///
/// Endpoint: `GET /openapi.json` /// Endpoint: `GET /openapi.json`
pub fn get_openapi(&self) -> Result<serde_json::Value> { pub fn get_openapi(&self) -> Result<String> {
self.base.get_json(&format!("/openapi.json")) self.base.get_text(&format!("/openapi.json"))
} }
/// API version /// API version

View File

@@ -37,7 +37,7 @@ impl AddrRoutes for ApiRouter<AppState> {
.addrs_tag() .addrs_tag()
.summary("Address information") .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)*") .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() .not_modified()
.bad_request() .bad_request()
.not_found() .not_found()
@@ -59,7 +59,7 @@ impl AddrRoutes for ApiRouter<AppState> {
.addrs_tag() .addrs_tag()
.summary("Address transactions") .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)*") .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() .not_modified()
.bad_request() .bad_request()
.not_found() .not_found()
@@ -81,7 +81,7 @@ impl AddrRoutes for ApiRouter<AppState> {
.addrs_tag() .addrs_tag()
.summary("Address confirmed transactions") .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)*") .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() .not_modified()
.bad_request() .bad_request()
.not_found() .not_found()
@@ -103,7 +103,7 @@ impl AddrRoutes for ApiRouter<AppState> {
.addrs_tag() .addrs_tag()
.summary("Address mempool transactions") .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)*") .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() .bad_request()
.not_found() .not_found()
.server_error() .server_error()
@@ -123,7 +123,7 @@ impl AddrRoutes for ApiRouter<AppState> {
.addrs_tag() .addrs_tag()
.summary("Address UTXOs") .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)*") .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() .not_modified()
.bad_request() .bad_request()
.not_found() .not_found()
@@ -144,7 +144,7 @@ impl AddrRoutes for ApiRouter<AppState> {
.addrs_tag() .addrs_tag()
.summary("Validate address") .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)*") .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() .not_modified()
), ),
) )

View File

@@ -5,8 +5,8 @@ use axum::{
}; };
use brk_query::BLOCK_TXS_PAGE_SIZE; use brk_query::BLOCK_TXS_PAGE_SIZE;
use brk_types::{ use brk_types::{
BlockHash, BlockHashParam, BlockHashStartIndex, BlockHashTxIndex, BlockInfo, BlockInfoV1, BlockHashParam, BlockHashStartIndex, BlockHashTxIndex, BlockInfo, BlockInfoV1, BlockStatus,
BlockStatus, BlockTimestamp, Height, HeightParam, Hex, TimestampParam, Transaction, Txid, BlockTimestamp, HeightParam, TimestampParam, Transaction, TxIndex, Txid,
}; };
use crate::{CacheStrategy, extended::TransformResponseExtended}; use crate::{CacheStrategy, extended::TransformResponseExtended};
@@ -35,7 +35,7 @@ impl BlockRoutes for ApiRouter<AppState> {
.description( .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)*", "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() .not_modified()
.bad_request() .bad_request()
.not_found() .not_found()
@@ -57,7 +57,7 @@ impl BlockRoutes for ApiRouter<AppState> {
.blocks_tag() .blocks_tag()
.summary("Block (v1)") .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)*") .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_modified()
.not_found() .not_found()
.server_error() .server_error()
@@ -75,7 +75,7 @@ impl BlockRoutes for ApiRouter<AppState> {
.blocks_tag() .blocks_tag()
.summary("Block header") .summary("Block header")
.description("Returns the hex-encoded block header.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-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_modified()
.not_found() .not_found()
.server_error() .server_error()
@@ -98,7 +98,7 @@ impl BlockRoutes for ApiRouter<AppState> {
.description( .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)*", "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() .not_modified()
.bad_request() .bad_request()
.not_found() .not_found()
@@ -120,7 +120,7 @@ impl BlockRoutes for ApiRouter<AppState> {
.blocks_tag() .blocks_tag()
.summary("Block by timestamp") .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)*") .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() .not_modified()
.bad_request() .bad_request()
.not_found() .not_found()
@@ -144,7 +144,7 @@ impl BlockRoutes for ApiRouter<AppState> {
.description( .description(
"Returns the raw block data in binary format.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-raw)*", "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() .not_modified()
.bad_request() .bad_request()
.not_found() .not_found()
@@ -168,7 +168,7 @@ impl BlockRoutes for ApiRouter<AppState> {
.description( .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)*", "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() .not_modified()
.bad_request() .bad_request()
.not_found() .not_found()
@@ -187,7 +187,7 @@ impl BlockRoutes for ApiRouter<AppState> {
.blocks_tag() .blocks_tag()
.summary("Block tip height") .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)*") .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() .not_modified()
.server_error() .server_error()
}, },
@@ -204,7 +204,7 @@ impl BlockRoutes for ApiRouter<AppState> {
.blocks_tag() .blocks_tag()
.summary("Block tip hash") .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)*") .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() .not_modified()
.server_error() .server_error()
}, },
@@ -226,7 +226,7 @@ impl BlockRoutes for ApiRouter<AppState> {
.description( .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)*", "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() .not_modified()
.bad_request() .bad_request()
.not_found() .not_found()
@@ -250,7 +250,32 @@ impl BlockRoutes for ApiRouter<AppState> {
.description( .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)*", "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() .not_modified()
.bad_request() .bad_request()
.not_found() .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 state.cached_json(&headers, CacheStrategy::Static, &uri, move |q| q.block_txs(&path.hash, path.start_index)).await
}, },
|op| { |op| {
op.id("get_block_txs") op.id("get_block_txs_from_index")
.blocks_tag() .blocks_tag()
.summary("Block transactions (paginated)") .summary("Block transactions (paginated)")
.description(&format!( .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)*", "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 BLOCK_TXS_PAGE_SIZE
)) ))
.ok_response::<Vec<Transaction>>() .json_response::<Vec<Transaction>>()
.not_modified() .not_modified()
.bad_request() .bad_request()
.not_found() .not_found()
@@ -296,7 +321,7 @@ impl BlockRoutes for ApiRouter<AppState> {
.blocks_tag() .blocks_tag()
.summary("Recent blocks") .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)*") .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() .not_modified()
.server_error() .server_error()
}, },
@@ -318,7 +343,7 @@ impl BlockRoutes for ApiRouter<AppState> {
.description( .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)*", "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() .not_modified()
.bad_request() .bad_request()
.server_error() .server_error()
@@ -338,7 +363,7 @@ impl BlockRoutes for ApiRouter<AppState> {
.blocks_tag() .blocks_tag()
.summary("Recent blocks with extras") .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)*") .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() .not_modified()
.server_error() .server_error()
}, },
@@ -358,7 +383,7 @@ impl BlockRoutes for ApiRouter<AppState> {
.blocks_tag() .blocks_tag()
.summary("Blocks from height with extras") .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)*") .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() .not_modified()
.bad_request() .bad_request()
.server_error() .server_error()

View File

@@ -30,7 +30,7 @@ impl FeesRoutes for ApiRouter<AppState> {
.fees_tag() .fees_tag()
.summary("Projected mempool blocks") .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)*") .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() .server_error()
}, },
), ),
@@ -50,7 +50,7 @@ impl FeesRoutes for ApiRouter<AppState> {
.fees_tag() .fees_tag()
.summary("Recommended fees") .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)*") .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() .server_error()
}, },
), ),
@@ -70,7 +70,7 @@ impl FeesRoutes for ApiRouter<AppState> {
.fees_tag() .fees_tag()
.summary("Precise recommended fees") .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)*") .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() .server_error()
}, },
), ),

View File

@@ -32,7 +32,7 @@ impl GeneralRoutes for ApiRouter<AppState> {
.general_tag() .general_tag()
.summary("Difficulty adjustment") .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)*") .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() .not_modified()
.server_error() .server_error()
}, },
@@ -56,7 +56,7 @@ impl GeneralRoutes for ApiRouter<AppState> {
.general_tag() .general_tag()
.summary("Current BTC price") .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)*") .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() .server_error()
}, },
), ),
@@ -79,7 +79,7 @@ impl GeneralRoutes for ApiRouter<AppState> {
.general_tag() .general_tag()
.summary("Historical price") .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)*") .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() .not_modified()
.server_error() .server_error()
}, },

View File

@@ -28,7 +28,7 @@ impl MempoolRoutes for ApiRouter<AppState> {
.mempool_tag() .mempool_tag()
.summary("Mempool statistics") .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)*") .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() .server_error()
}, },
), ),
@@ -46,7 +46,7 @@ impl MempoolRoutes for ApiRouter<AppState> {
.mempool_tag() .mempool_tag()
.summary("Mempool transaction IDs") .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)*") .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() .server_error()
}, },
), ),
@@ -64,7 +64,7 @@ impl MempoolRoutes for ApiRouter<AppState> {
.mempool_tag() .mempool_tag()
.summary("Recent mempool transactions") .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)*") .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() .server_error()
}, },
), ),
@@ -86,7 +86,7 @@ impl MempoolRoutes for ApiRouter<AppState> {
on-chain round-dollar output patterns in the last 12 blocks \ on-chain round-dollar output patterns in the last 12 blocks \
plus mempool.", plus mempool.",
) )
.ok_response::<Dollars>() .json_response::<Dollars>()
.server_error() .server_error()
}, },
), ),

View File

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

View File

@@ -38,7 +38,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.mining_tag() .mining_tag()
.summary("List all mining pools") .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)*") .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() .not_modified()
.server_error() .server_error()
}, },
@@ -55,7 +55,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.mining_tag() .mining_tag()
.summary("Mining pool statistics") .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)*") .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() .not_modified()
.server_error() .server_error()
}, },
@@ -72,7 +72,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.mining_tag() .mining_tag()
.summary("Mining pool details") .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)*") .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_modified()
.not_found() .not_found()
.server_error() .server_error()
@@ -90,7 +90,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.mining_tag() .mining_tag()
.summary("All pools hashrate (all time)") .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)*") .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() .not_modified()
.server_error() .server_error()
}, },
@@ -107,7 +107,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.mining_tag() .mining_tag()
.summary("All pools hashrate") .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)*") .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() .not_modified()
.server_error() .server_error()
}, },
@@ -124,7 +124,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.mining_tag() .mining_tag()
.summary("Mining pool hashrate") .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)*") .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_modified()
.not_found() .not_found()
.server_error() .server_error()
@@ -142,7 +142,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.mining_tag() .mining_tag()
.summary("Mining pool blocks") .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)*") .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_modified()
.not_found() .not_found()
.server_error() .server_error()
@@ -160,7 +160,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.mining_tag() .mining_tag()
.summary("Mining pool blocks from height") .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)*") .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_modified()
.not_found() .not_found()
.server_error() .server_error()
@@ -178,7 +178,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.mining_tag() .mining_tag()
.summary("Network hashrate (all time)") .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)*") .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() .not_modified()
.server_error() .server_error()
}, },
@@ -195,7 +195,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.mining_tag() .mining_tag()
.summary("Network hashrate") .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)*") .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() .not_modified()
.server_error() .server_error()
}, },
@@ -212,7 +212,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.mining_tag() .mining_tag()
.summary("Difficulty adjustments (all time)") .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)*") .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() .not_modified()
.server_error() .server_error()
}, },
@@ -229,7 +229,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.mining_tag() .mining_tag()
.summary("Difficulty adjustments") .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)*") .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() .not_modified()
.server_error() .server_error()
}, },
@@ -246,7 +246,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.mining_tag() .mining_tag()
.summary("Mining reward statistics") .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)*") .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() .not_modified()
.server_error() .server_error()
}, },
@@ -263,7 +263,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.mining_tag() .mining_tag()
.summary("Block fees") .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)*") .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() .not_modified()
.server_error() .server_error()
}, },
@@ -280,7 +280,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.mining_tag() .mining_tag()
.summary("Block rewards") .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)*") .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() .not_modified()
.server_error() .server_error()
}, },
@@ -312,7 +312,7 @@ impl MiningRoutes for ApiRouter<AppState> {
.mining_tag() .mining_tag()
.summary("Block sizes and weights") .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)*") .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() .not_modified()
.server_error() .server_error()
}, },

View File

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

View File

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

View File

@@ -7,7 +7,7 @@ use axum::{
http::{HeaderMap, Uri}, http::{HeaderMap, Uri},
}; };
use brk_types::{ use brk_types::{
CpfpInfo, Hex, MerkleProof, Transaction, TxOutspend, TxStatus, Txid, TxidParam, TxidVout, CpfpInfo, MerkleProof, Transaction, TxOutspend, TxStatus, Txid, TxidParam, TxidVout,
TxidsParam, TxidsParam,
}; };
@@ -33,7 +33,7 @@ impl TxRoutes for ApiRouter<AppState> {
.transactions_tag() .transactions_tag()
.summary("CPFP info") .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)*") .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() .not_found()
.server_error(), .server_error(),
), ),
@@ -56,7 +56,7 @@ impl TxRoutes for ApiRouter<AppState> {
.description( .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)*", "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() .not_modified()
.bad_request() .bad_request()
.not_found() .not_found()
@@ -81,7 +81,7 @@ impl TxRoutes for ApiRouter<AppState> {
.description( .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)*", "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() .not_modified()
.bad_request() .bad_request()
.not_found() .not_found()
@@ -99,7 +99,7 @@ impl TxRoutes for ApiRouter<AppState> {
.transactions_tag() .transactions_tag()
.summary("Transaction merkleblock proof") .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)*") .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() .not_modified()
.bad_request() .bad_request()
.not_found() .not_found()
@@ -117,7 +117,7 @@ impl TxRoutes for ApiRouter<AppState> {
.transactions_tag() .transactions_tag()
.summary("Transaction merkle proof") .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)*") .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() .not_modified()
.bad_request() .bad_request()
.not_found() .not_found()
@@ -143,7 +143,7 @@ impl TxRoutes for ApiRouter<AppState> {
.description( .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)*", "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() .not_modified()
.bad_request() .bad_request()
.not_found() .not_found()
@@ -168,7 +168,7 @@ impl TxRoutes for ApiRouter<AppState> {
.description( .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)*", "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() .not_modified()
.bad_request() .bad_request()
.not_found() .not_found()
@@ -186,7 +186,7 @@ impl TxRoutes for ApiRouter<AppState> {
.transactions_tag() .transactions_tag()
.summary("Transaction raw") .summary("Transaction raw")
.description("Returns a transaction as binary data.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-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() .not_modified()
.bad_request() .bad_request()
.not_found() .not_found()
@@ -211,7 +211,7 @@ impl TxRoutes for ApiRouter<AppState> {
.description( .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)*", "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() .not_modified()
.bad_request() .bad_request()
.not_found() .not_found()
@@ -230,7 +230,7 @@ impl TxRoutes for ApiRouter<AppState> {
.transactions_tag() .transactions_tag()
.summary("Transaction first-seen times") .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)*") .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(), .server_error(),
), ),
) )
@@ -248,7 +248,7 @@ impl TxRoutes for ApiRouter<AppState> {
.transactions_tag() .transactions_tag()
.summary("Broadcast transaction") .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)*") .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() .bad_request()
.server_error() .server_error()
}, },

View File

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

View File

@@ -521,11 +521,6 @@
* @typedef {Object} HeightParam * @typedef {Object} HeightParam
* @property {Height} height * @property {Height} height
*/ */
/**
* Hex-encoded string
*
* @typedef {string} Hex
*/
/** /**
* Highest price value for a time period * Highest price value for a time period
* *
@@ -9521,7 +9516,7 @@ class BrkClient extends BrkClientBase {
* Endpoint: `GET /api/block-height/{height}` * Endpoint: `GET /api/block-height/{height}`
* *
* @param {Height} height * @param {Height} height
* @returns {Promise<BlockHash>} * @returns {Promise<*>}
*/ */
async getBlockByHeight(height) { async getBlockByHeight(height) {
return this.getJson(`/api/block-height/${height}`); return this.getJson(`/api/block-height/${height}`);
@@ -9553,7 +9548,7 @@ class BrkClient extends BrkClientBase {
* Endpoint: `GET /api/block/{hash}/header` * Endpoint: `GET /api/block/{hash}/header`
* *
* @param {BlockHash} hash * @param {BlockHash} hash
* @returns {Promise<Hex>} * @returns {Promise<*>}
*/ */
async getBlockHeader(hash) { async getBlockHeader(hash) {
return this.getJson(`/api/block/${hash}/header`); return this.getJson(`/api/block/${hash}/header`);
@@ -9602,7 +9597,7 @@ class BrkClient extends BrkClientBase {
* *
* @param {BlockHash} hash - Bitcoin block hash * @param {BlockHash} hash - Bitcoin block hash
* @param {TxIndex} index - Transaction index within the block (0-based) * @param {TxIndex} index - Transaction index within the block (0-based)
* @returns {Promise<Txid>} * @returns {Promise<*>}
*/ */
async getBlockTxid(hash, index) { async getBlockTxid(hash, index) {
return this.getJson(`/api/block/${hash}/txid/${index}`); return this.getJson(`/api/block/${hash}/txid/${index}`);
@@ -9624,6 +9619,22 @@ class BrkClient extends BrkClientBase {
return this.getJson(`/api/block/${hash}/txids`); return this.getJson(`/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`
*
* @param {BlockHash} hash
* @returns {Promise<Transaction[]>}
*/
async getBlockTxs(hash) {
return this.getJson(`/api/block/${hash}/txs`);
}
/** /**
* Block transactions (paginated) * Block transactions (paginated)
* *
@@ -9637,7 +9648,7 @@ class BrkClient extends BrkClientBase {
* @param {TxIndex} start_index - Starting transaction index within the block (0-based) * @param {TxIndex} start_index - Starting transaction index within the block (0-based)
* @returns {Promise<Transaction[]>} * @returns {Promise<Transaction[]>}
*/ */
async getBlockTxs(hash, start_index) { async getBlockTxsFromIndex(hash, start_index) {
return this.getJson(`/api/block/${hash}/txs/${start_index}`); return this.getJson(`/api/block/${hash}/txs/${start_index}`);
} }
@@ -9663,7 +9674,7 @@ class BrkClient extends BrkClientBase {
* *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-tip-hash)* * *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-tip-hash)*
* *
* Endpoint: `GET /api/blocks/tip/hash` * Endpoint: `GET /api/blocks/tip/hash`
* @returns {Promise<BlockHash>} * @returns {Promise<*>}
*/ */
async getBlockTipHash() { async getBlockTipHash() {
return this.getJson(`/api/blocks/tip/hash`); return this.getJson(`/api/blocks/tip/hash`);
@@ -9677,7 +9688,7 @@ class BrkClient extends BrkClientBase {
* *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-tip-height)* * *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-tip-height)*
* *
* Endpoint: `GET /api/blocks/tip/height` * Endpoint: `GET /api/blocks/tip/height`
* @returns {Promise<Height>} * @returns {Promise<*>}
*/ */
async getBlockTipHeight() { async getBlockTipHeight() {
return this.getJson(`/api/blocks/tip/height`); return this.getJson(`/api/blocks/tip/height`);
@@ -10079,7 +10090,7 @@ class BrkClient extends BrkClientBase {
* Endpoint: `GET /api/tx/{txid}/hex` * Endpoint: `GET /api/tx/{txid}/hex`
* *
* @param {Txid} txid * @param {Txid} txid
* @returns {Promise<Hex>} * @returns {Promise<*>}
*/ */
async getTxHex(txid) { async getTxHex(txid) {
return this.getJson(`/api/tx/${txid}/hex`); return this.getJson(`/api/tx/${txid}/hex`);
@@ -10111,7 +10122,7 @@ class BrkClient extends BrkClientBase {
* Endpoint: `GET /api/tx/{txid}/merkleblock-proof` * Endpoint: `GET /api/tx/{txid}/merkleblock-proof`
* *
* @param {Txid} txid * @param {Txid} txid
* @returns {Promise<string>} * @returns {Promise<*>}
*/ */
async getTxMerkleblockProof(txid) { async getTxMerkleblockProof(txid) {
return this.getJson(`/api/tx/${txid}/merkleblock-proof`); return this.getJson(`/api/tx/${txid}/merkleblock-proof`);

View File

@@ -112,8 +112,6 @@ Epoch = int
ExchangeRates = dict ExchangeRates = dict
FundedAddrIndex = TypeIndex FundedAddrIndex = TypeIndex
Halving = int Halving = int
# Hex-encoded string
Hex = str
# Highest price value for a time period # Highest price value for a time period
High = Dollars High = Dollars
Hour1 = int Hour1 = int
@@ -7067,7 +7065,7 @@ class BrkClient(BrkClientBase):
Compact OpenAPI specification optimized for LLM consumption. Removes redundant fields while preserving essential API information. Full spec available at `/openapi.json`. 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`""" Endpoint: `GET /api.json`"""
return self.get_json('/api.json') return self.get_text('/api.json')
def get_address(self, address: Addr) -> AddrStats: def get_address(self, address: Addr) -> AddrStats:
"""Address information. """Address information.
@@ -7127,7 +7125,7 @@ class BrkClient(BrkClientBase):
Endpoint: `GET /api/address/{address}/utxo`""" Endpoint: `GET /api/address/{address}/utxo`"""
return self.get_json(f'/api/address/{address}/utxo') return self.get_json(f'/api/address/{address}/utxo')
def get_block_by_height(self, height: Height) -> BlockHash: def get_block_by_height(self, height: Height) -> Any:
"""Block hash by height. """Block hash by height.
Retrieve the block hash at a given height. Returns the hash as plain text. Retrieve the block hash at a given height. Returns the hash as plain text.
@@ -7135,7 +7133,7 @@ class BrkClient(BrkClientBase):
*[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-height)* *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-height)*
Endpoint: `GET /api/block-height/{height}`""" Endpoint: `GET /api/block-height/{height}`"""
return self.get_json(f'/api/block-height/{height}') return self.get_text(f'/api/block-height/{height}')
def get_block(self, hash: BlockHash) -> BlockInfo: def get_block(self, hash: BlockHash) -> BlockInfo:
"""Block information. """Block information.
@@ -7147,7 +7145,7 @@ class BrkClient(BrkClientBase):
Endpoint: `GET /api/block/{hash}`""" Endpoint: `GET /api/block/{hash}`"""
return self.get_json(f'/api/block/{hash}') return self.get_json(f'/api/block/{hash}')
def get_block_header(self, hash: BlockHash) -> Hex: def get_block_header(self, hash: BlockHash) -> Any:
"""Block header. """Block header.
Returns the hex-encoded block header. Returns the hex-encoded block header.
@@ -7155,7 +7153,7 @@ class BrkClient(BrkClientBase):
*[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-header)* *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-header)*
Endpoint: `GET /api/block/{hash}/header`""" Endpoint: `GET /api/block/{hash}/header`"""
return self.get_json(f'/api/block/{hash}/header') return self.get_text(f'/api/block/{hash}/header')
def get_block_raw(self, hash: BlockHash) -> List[float]: def get_block_raw(self, hash: BlockHash) -> List[float]:
"""Raw block. """Raw block.
@@ -7177,7 +7175,7 @@ class BrkClient(BrkClientBase):
Endpoint: `GET /api/block/{hash}/status`""" Endpoint: `GET /api/block/{hash}/status`"""
return self.get_json(f'/api/block/{hash}/status') return self.get_json(f'/api/block/{hash}/status')
def get_block_txid(self, hash: BlockHash, index: TxIndex) -> Txid: def get_block_txid(self, hash: BlockHash, index: TxIndex) -> Any:
"""Transaction ID at index. """Transaction ID at index.
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.
@@ -7185,7 +7183,7 @@ class BrkClient(BrkClientBase):
*[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-transaction-id)* *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-transaction-id)*
Endpoint: `GET /api/block/{hash}/txid/{index}`""" Endpoint: `GET /api/block/{hash}/txid/{index}`"""
return self.get_json(f'/api/block/{hash}/txid/{index}') return self.get_text(f'/api/block/{hash}/txid/{index}')
def get_block_txids(self, hash: BlockHash) -> List[Txid]: def get_block_txids(self, hash: BlockHash) -> List[Txid]:
"""Block transaction IDs. """Block transaction IDs.
@@ -7197,7 +7195,17 @@ class BrkClient(BrkClientBase):
Endpoint: `GET /api/block/{hash}/txids`""" Endpoint: `GET /api/block/{hash}/txids`"""
return self.get_json(f'/api/block/{hash}/txids') return self.get_json(f'/api/block/{hash}/txids')
def get_block_txs(self, hash: BlockHash, start_index: TxIndex) -> List[Transaction]: def get_block_txs(self, hash: BlockHash) -> List[Transaction]:
"""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`"""
return self.get_json(f'/api/block/{hash}/txs')
def get_block_txs_from_index(self, hash: BlockHash, start_index: TxIndex) -> List[Transaction]:
"""Block transactions (paginated). """Block transactions (paginated).
Retrieve transactions in a block by block hash, starting from the specified index. Returns up to 25 transactions at a time. Retrieve transactions in a block by block hash, starting from the specified index. Returns up to 25 transactions at a time.
@@ -7217,7 +7225,7 @@ class BrkClient(BrkClientBase):
Endpoint: `GET /api/blocks`""" Endpoint: `GET /api/blocks`"""
return self.get_json('/api/blocks') return self.get_json('/api/blocks')
def get_block_tip_hash(self) -> BlockHash: def get_block_tip_hash(self) -> Any:
"""Block tip hash. """Block tip hash.
Returns the hash of the last block. Returns the hash of the last block.
@@ -7225,9 +7233,9 @@ class BrkClient(BrkClientBase):
*[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-tip-hash)* *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-tip-hash)*
Endpoint: `GET /api/blocks/tip/hash`""" Endpoint: `GET /api/blocks/tip/hash`"""
return self.get_json('/api/blocks/tip/hash') return self.get_text('/api/blocks/tip/hash')
def get_block_tip_height(self) -> Height: def get_block_tip_height(self) -> Any:
"""Block tip height. """Block tip height.
Returns the height of the last block. Returns the height of the last block.
@@ -7235,7 +7243,7 @@ class BrkClient(BrkClientBase):
*[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-tip-height)* *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-tip-height)*
Endpoint: `GET /api/blocks/tip/height`""" Endpoint: `GET /api/blocks/tip/height`"""
return self.get_json('/api/blocks/tip/height') return self.get_text('/api/blocks/tip/height')
def get_blocks_from_height(self, height: Height) -> List[BlockInfo]: def get_blocks_from_height(self, height: Height) -> List[BlockInfo]:
"""Blocks from height. """Blocks from height.
@@ -7435,7 +7443,7 @@ class BrkClient(BrkClientBase):
Returns the single most recent value for a series, unwrapped (not inside a SeriesData object). Returns the single most recent value for a series, unwrapped (not inside a SeriesData object).
Endpoint: `GET /api/series/{series}/{index}/latest`""" Endpoint: `GET /api/series/{series}/{index}/latest`"""
return self.get_json(f'/api/series/{series}/{index}/latest') return self.get_text(f'/api/series/{series}/{index}/latest')
def get_series_len(self, series: SeriesName, index: Index) -> float: def get_series_len(self, series: SeriesName, index: Index) -> float:
"""Get series data length. """Get series data length.
@@ -7479,7 +7487,7 @@ class BrkClient(BrkClientBase):
Endpoint: `GET /api/tx/{txid}`""" Endpoint: `GET /api/tx/{txid}`"""
return self.get_json(f'/api/tx/{txid}') return self.get_json(f'/api/tx/{txid}')
def get_tx_hex(self, txid: Txid) -> Hex: def get_tx_hex(self, txid: Txid) -> Any:
"""Transaction hex. """Transaction hex.
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.
@@ -7487,7 +7495,7 @@ class BrkClient(BrkClientBase):
*[Mempool.space docs](https://mempool.space/docs/api/rest#get-transaction-hex)* *[Mempool.space docs](https://mempool.space/docs/api/rest#get-transaction-hex)*
Endpoint: `GET /api/tx/{txid}/hex`""" Endpoint: `GET /api/tx/{txid}/hex`"""
return self.get_json(f'/api/tx/{txid}/hex') return self.get_text(f'/api/tx/{txid}/hex')
def get_tx_merkle_proof(self, txid: Txid) -> MerkleProof: def get_tx_merkle_proof(self, txid: Txid) -> MerkleProof:
"""Transaction merkle proof. """Transaction merkle proof.
@@ -7499,7 +7507,7 @@ class BrkClient(BrkClientBase):
Endpoint: `GET /api/tx/{txid}/merkle-proof`""" Endpoint: `GET /api/tx/{txid}/merkle-proof`"""
return self.get_json(f'/api/tx/{txid}/merkle-proof') return self.get_json(f'/api/tx/{txid}/merkle-proof')
def get_tx_merkleblock_proof(self, txid: Txid) -> str: def get_tx_merkleblock_proof(self, txid: Txid) -> Any:
"""Transaction merkleblock proof. """Transaction merkleblock proof.
Get the merkleblock proof for a transaction (BIP37 format, hex encoded). Get the merkleblock proof for a transaction (BIP37 format, hex encoded).
@@ -7507,7 +7515,7 @@ class BrkClient(BrkClientBase):
*[Mempool.space docs](https://mempool.space/docs/api/rest#get-transaction-merkleblock-proof)* *[Mempool.space docs](https://mempool.space/docs/api/rest#get-transaction-merkleblock-proof)*
Endpoint: `GET /api/tx/{txid}/merkleblock-proof`""" Endpoint: `GET /api/tx/{txid}/merkleblock-proof`"""
return self.get_json(f'/api/tx/{txid}/merkleblock-proof') return self.get_text(f'/api/tx/{txid}/merkleblock-proof')
def get_tx_outspend(self, txid: Txid, vout: Vout) -> TxOutspend: def get_tx_outspend(self, txid: Txid, vout: Vout) -> TxOutspend:
"""Output spend status. """Output spend status.
@@ -7651,7 +7659,7 @@ class BrkClient(BrkClientBase):
*[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-feerates)* *[Mempool.space docs](https://mempool.space/docs/api/rest#get-block-feerates)*
Endpoint: `GET /api/v1/mining/blocks/fee-rates/{time_period}`""" Endpoint: `GET /api/v1/mining/blocks/fee-rates/{time_period}`"""
return self.get_json(f'/api/v1/mining/blocks/fee-rates/{time_period}') return self.get_text(f'/api/v1/mining/blocks/fee-rates/{time_period}')
def get_block_fees(self, time_period: TimePeriod) -> List[BlockFeesEntry]: def get_block_fees(self, time_period: TimePeriod) -> List[BlockFeesEntry]:
"""Block fees. """Block fees.
@@ -7867,7 +7875,7 @@ class BrkClient(BrkClientBase):
Full OpenAPI 3.1 specification for this API. Full OpenAPI 3.1 specification for this API.
Endpoint: `GET /openapi.json`""" Endpoint: `GET /openapi.json`"""
return self.get_json('/openapi.json') return self.get_text('/openapi.json')
def get_version(self) -> str: def get_version(self) -> str:
"""API version. """API version.

View File

@@ -50,7 +50,7 @@ wheels = [
[[package]] [[package]]
name = "brk-client" name = "brk-client"
version = "0.2.2" version = "0.2.5"
source = { editable = "." } source = { editable = "." }
[package.dev-dependencies] [package.dev-dependencies]