mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-28 16:49:58 -07:00
mempool: init
This commit is contained in:
@@ -2,7 +2,8 @@ use aide::axum::{ApiRouter, routing::get_with};
|
||||
use axum::{
|
||||
extract::{Path, State},
|
||||
http::HeaderMap,
|
||||
response::Response,
|
||||
response::{Redirect, Response},
|
||||
routing::get,
|
||||
};
|
||||
use brk_structs::{AddressInfo, AddressPath};
|
||||
|
||||
@@ -13,14 +14,17 @@ use crate::{
|
||||
|
||||
use super::AppState;
|
||||
|
||||
pub trait AddressesRoutes {
|
||||
pub trait AddressRoutes {
|
||||
fn add_addresses_routes(self) -> Self;
|
||||
}
|
||||
|
||||
impl AddressesRoutes for ApiRouter<AppState> {
|
||||
impl AddressRoutes for ApiRouter<AppState> {
|
||||
fn add_addresses_routes(self) -> Self {
|
||||
self.api_route(
|
||||
"/api/chain/address/{address}",
|
||||
self
|
||||
.route("/api/address", get(Redirect::temporary("/api/addresses")))
|
||||
.route("/api/addresses", get(Redirect::temporary("/api#tag/addresses")))
|
||||
.api_route(
|
||||
"/api/address/{address}",
|
||||
get_with(async |
|
||||
headers: HeaderMap,
|
||||
Path(address): Path<AddressPath>,
|
||||
@@ -35,14 +39,14 @@ impl AddressesRoutes for ApiRouter<AppState> {
|
||||
Err((status, message)) => Response::new_json_with(status, &message, &etag)
|
||||
}
|
||||
}, |op| op
|
||||
.tag("Chain")
|
||||
.addresses_tag()
|
||||
.summary("Address information")
|
||||
.description("Retrieve comprehensive information about a Bitcoin address including balance, transaction history, UTXOs, and estimated investment metrics. Supports all standard Bitcoin address types (P2PKH, P2SH, P2WPKH, P2WSH, P2TR, etc.).")
|
||||
.with_ok_response::<AddressInfo, _>(|res| res)
|
||||
.with_not_modified()
|
||||
.with_bad_request()
|
||||
.with_not_found()
|
||||
.with_server_error()
|
||||
.ok_response::<AddressInfo>()
|
||||
.not_modified()
|
||||
.bad_request()
|
||||
.not_found()
|
||||
.server_error()
|
||||
),
|
||||
)
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
use aide::axum::ApiRouter;
|
||||
use axum::{response::Redirect, routing::get};
|
||||
|
||||
use crate::api::chain::{addresses::AddressesRoutes, transactions::TransactionsRoutes};
|
||||
|
||||
use super::AppState;
|
||||
|
||||
mod addresses;
|
||||
mod transactions;
|
||||
|
||||
pub trait ChainRoutes {
|
||||
fn add_chain_routes(self) -> Self;
|
||||
}
|
||||
|
||||
impl ChainRoutes for ApiRouter<AppState> {
|
||||
fn add_chain_routes(self) -> Self {
|
||||
self.route("/api/chain", get(Redirect::temporary("/api#tag/chain")))
|
||||
.add_addresses_routes()
|
||||
.add_transactions_routes()
|
||||
}
|
||||
}
|
||||
@@ -76,10 +76,7 @@ fn req_to_response_res(
|
||||
// .1
|
||||
// .etag(Stamp::from(interface.get_height()), to);
|
||||
|
||||
// if headers
|
||||
// .get_if_none_match()
|
||||
// .is_some_and(|prev_etag| etag == prev_etag)
|
||||
// {
|
||||
// if headers.has_etag(etag) {
|
||||
// return Ok(Response::new_not_modified());
|
||||
// }
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ pub trait ApiMetricsRoutes {
|
||||
impl ApiMetricsRoutes for ApiRouter<AppState> {
|
||||
fn add_metrics_routes(self) -> Self {
|
||||
self
|
||||
.route("/api/metric", get(Redirect::temporary("/api/metrics")))
|
||||
.route("/api/metrics", get(Redirect::temporary("/api#tag/metrics")))
|
||||
.api_route(
|
||||
"/api/metrics/count",
|
||||
@@ -39,11 +40,12 @@ impl ApiMetricsRoutes for ApiRouter<AppState> {
|
||||
}
|
||||
Response::new_json(state.metric_count(), etag)
|
||||
},
|
||||
|op| op.tag("Metrics")
|
||||
|op| op
|
||||
.metrics_tag()
|
||||
.summary("Metric count")
|
||||
.description("Current metric count")
|
||||
.with_ok_response::<Vec<MetricCount>, _>(|res| res)
|
||||
.with_not_modified(),
|
||||
.ok_response::<Vec<MetricCount>>()
|
||||
.not_modified(),
|
||||
),
|
||||
)
|
||||
.api_route(
|
||||
@@ -59,13 +61,14 @@ impl ApiMetricsRoutes for ApiRouter<AppState> {
|
||||
}
|
||||
Response::new_json(state.get_indexes(), etag)
|
||||
},
|
||||
|op| op.tag("Metrics")
|
||||
|op| op
|
||||
.metrics_tag()
|
||||
.summary("List available indexes")
|
||||
.description(
|
||||
"Returns all available indexes with their accepted query aliases. Use any alias when querying metrics."
|
||||
)
|
||||
.with_ok_response::<Vec<IndexInfo>, _>(|res| res)
|
||||
.with_not_modified(),
|
||||
.ok_response::<Vec<IndexInfo>>()
|
||||
.not_modified(),
|
||||
),
|
||||
)
|
||||
.api_route(
|
||||
@@ -82,11 +85,12 @@ impl ApiMetricsRoutes for ApiRouter<AppState> {
|
||||
}
|
||||
Response::new_json(state.get_metrics(pagination), etag)
|
||||
},
|
||||
|op| op.tag("Metrics")
|
||||
|op| op
|
||||
.metrics_tag()
|
||||
.summary("Metrics list")
|
||||
.description("Paginated list of available metrics")
|
||||
.with_ok_response::<PaginatedMetrics, _>(|res| res)
|
||||
.with_not_modified(),
|
||||
.ok_response::<PaginatedMetrics>()
|
||||
.not_modified(),
|
||||
),
|
||||
)
|
||||
.api_route(
|
||||
@@ -99,13 +103,14 @@ impl ApiMetricsRoutes for ApiRouter<AppState> {
|
||||
}
|
||||
Response::new_json(state.get_metrics_catalog(), etag)
|
||||
},
|
||||
|op| op.tag("Metrics")
|
||||
|op| op
|
||||
.metrics_tag()
|
||||
.summary("Metrics catalog")
|
||||
.description(
|
||||
"Returns the complete hierarchical catalog of available metrics organized as a tree structure. Metrics are grouped by categories and subcategories. Best viewed in an interactive JSON viewer (e.g., Firefox's built-in JSON viewer) for easy navigation of the nested structure."
|
||||
)
|
||||
.with_ok_response::<TreeNode, _>(|res| res)
|
||||
.with_not_modified(),
|
||||
.ok_response::<TreeNode>()
|
||||
.not_modified(),
|
||||
),
|
||||
)
|
||||
.api_route(
|
||||
@@ -122,15 +127,16 @@ impl ApiMetricsRoutes for ApiRouter<AppState> {
|
||||
}
|
||||
Response::new_json(state.match_metric(query), etag)
|
||||
},
|
||||
|op| op.tag("Metrics")
|
||||
|op| op
|
||||
.metrics_tag()
|
||||
.summary("Search metrics")
|
||||
.description("Fuzzy search for metrics by name. Supports partial matches and typos.")
|
||||
.with_ok_response::<Vec<String>, _>(|res| res)
|
||||
.with_not_modified(),
|
||||
.ok_response::<Vec<String>>()
|
||||
.not_modified(),
|
||||
),
|
||||
)
|
||||
.api_route(
|
||||
"/api/metrics/{metric}",
|
||||
"/api/metric/{metric}",
|
||||
get_with(
|
||||
async |
|
||||
headers: HeaderMap,
|
||||
@@ -154,36 +160,38 @@ impl ApiMetricsRoutes for ApiRouter<AppState> {
|
||||
};
|
||||
Response::new_json_with(StatusCode::NOT_FOUND, value, etag)
|
||||
},
|
||||
|op| op.tag("Metrics")
|
||||
|op| op
|
||||
.metrics_tag()
|
||||
.summary("Get supported indexes for a metric")
|
||||
.description(
|
||||
"Returns the list of indexes are supported by the specified metric. \
|
||||
For example, `realized_price` might be available on dateindex, weekindex, and monthindex."
|
||||
)
|
||||
.with_ok_response::<Vec<Index>, _>(|res| res)
|
||||
.with_not_modified()
|
||||
.with_not_found(),
|
||||
.ok_response::<Vec<Index>>()
|
||||
.not_modified()
|
||||
.not_found(),
|
||||
),
|
||||
)
|
||||
// WIP
|
||||
.route("/api/metrics/bulk", get(data::handler))
|
||||
// WIP
|
||||
.route(
|
||||
"/api/metrics/{metric}/{index}",
|
||||
"/api/metric/{metric}/{index}",
|
||||
get(
|
||||
async |uri: Uri,
|
||||
headers: HeaderMap,
|
||||
state: State<AppState>,
|
||||
Path((metric, index)): Path<(String, Index)>,
|
||||
Path((metric, index)): Path<(MetricPath, Index)>,
|
||||
Query(params_opt): Query<ParamsOpt>|
|
||||
-> Response {
|
||||
data::handler(
|
||||
uri,
|
||||
headers,
|
||||
Query(Params::from(((index, metric), params_opt))),
|
||||
state,
|
||||
)
|
||||
.await
|
||||
todo!();
|
||||
// data::handler(
|
||||
// uri,
|
||||
// headers,
|
||||
// Query(Params::from(((index, metric), params_opt))),
|
||||
// state,
|
||||
// )
|
||||
// .await
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
0
crates/brk_server/src/api/mining/mod.rs
Normal file
0
crates/brk_server/src/api/mining/mod.rs
Normal file
@@ -14,15 +14,16 @@ use brk_structs::Health;
|
||||
|
||||
use crate::{
|
||||
VERSION,
|
||||
api::{chain::ChainRoutes, metrics::ApiMetricsRoutes},
|
||||
api::{addresses::AddressRoutes, metrics::ApiMetricsRoutes, transactions::TxRoutes},
|
||||
extended::{HeaderMapExtended, ResponseExtended, TransformResponseExtended},
|
||||
};
|
||||
|
||||
use super::AppState;
|
||||
|
||||
mod chain;
|
||||
mod addresses;
|
||||
mod metrics;
|
||||
mod openapi;
|
||||
mod transactions;
|
||||
|
||||
pub use openapi::*;
|
||||
|
||||
@@ -32,7 +33,8 @@ pub trait ApiRoutes {
|
||||
|
||||
impl ApiRoutes for ApiRouter<AppState> {
|
||||
fn add_api_routes(self) -> Self {
|
||||
self.add_chain_routes()
|
||||
self.add_addresses_routes()
|
||||
.add_tx_routes()
|
||||
.add_metrics_routes()
|
||||
.route("/api/server", get(Redirect::temporary("/api#tag/server")))
|
||||
.api_route(
|
||||
@@ -40,10 +42,10 @@ impl ApiRoutes for ApiRouter<AppState> {
|
||||
get_with(
|
||||
async || -> Json<&'static str> { Json(VERSION) },
|
||||
|op| {
|
||||
op.tag("Server")
|
||||
op.server_tag()
|
||||
.summary("API version")
|
||||
.description("Returns the current version of the API server")
|
||||
.with_ok_response::<String, _>(|res| res)
|
||||
.ok_response::<String>()
|
||||
},
|
||||
),
|
||||
)
|
||||
@@ -58,10 +60,10 @@ impl ApiRoutes for ApiRouter<AppState> {
|
||||
})
|
||||
},
|
||||
|op| {
|
||||
op.tag("Server")
|
||||
op.server_tag()
|
||||
.summary("Health check")
|
||||
.description("Returns the health status of the API server")
|
||||
.with_ok_response::<Health, _>(|res| res)
|
||||
.ok_response::<Health>()
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
@@ -18,8 +18,7 @@ pub fn create_openapi() -> OpenApi {
|
||||
let info = Info {
|
||||
title: "Bitcoin Research Kit".to_string(),
|
||||
description: Some(
|
||||
"API for querying Bitcoin blockchain data including addresses, transactions, and chain statistics. This API provides low-level access to indexed blockchain data with advanced analytics capabilities.\n\n\
|
||||
⚠️ **Early Development**: This API is in very early stages of development. Breaking changes may occur without notice. For a more stable experience, [self-host](/install) or use the [hosting service](/service)."
|
||||
"API for querying Bitcoin blockchain data including addresses, transactions, and chain statistics. This API provides low-level access to indexed blockchain data with advanced analytics capabilities."
|
||||
.to_string(),
|
||||
),
|
||||
version: format!("v{VERSION}"),
|
||||
@@ -28,9 +27,17 @@ pub fn create_openapi() -> OpenApi {
|
||||
|
||||
let tags = vec![
|
||||
Tag {
|
||||
name: "Chain".to_string(),
|
||||
name: "Addresses".to_string(),
|
||||
description: Some(
|
||||
"Explore Bitcoin blockchain data: addresses, transactions, blocks, balances, and UTXOs."
|
||||
"Explore Bitcoin addresses."
|
||||
.to_string()
|
||||
),
|
||||
..Default::default()
|
||||
},
|
||||
Tag {
|
||||
name: "Blocks".to_string(),
|
||||
description: Some(
|
||||
"Explore Bitcoin blocks."
|
||||
.to_string()
|
||||
),
|
||||
..Default::default()
|
||||
@@ -44,6 +51,14 @@ pub fn create_openapi() -> OpenApi {
|
||||
),
|
||||
..Default::default()
|
||||
},
|
||||
Tag {
|
||||
name: "Mining".to_string(),
|
||||
description: Some(
|
||||
"Explore mining related endpoints."
|
||||
.to_string()
|
||||
),
|
||||
..Default::default()
|
||||
},
|
||||
Tag {
|
||||
name: "Server".to_string(),
|
||||
description: Some(
|
||||
@@ -51,7 +66,15 @@ pub fn create_openapi() -> OpenApi {
|
||||
.to_string()
|
||||
),
|
||||
..Default::default()
|
||||
},
|
||||
},
|
||||
Tag {
|
||||
name: "Transactions".to_string(),
|
||||
description: Some(
|
||||
"Explore Bitcoin transactions."
|
||||
.to_string()
|
||||
),
|
||||
..Default::default()
|
||||
},
|
||||
];
|
||||
|
||||
OpenApi {
|
||||
|
||||
@@ -2,7 +2,8 @@ use aide::axum::{ApiRouter, routing::get_with};
|
||||
use axum::{
|
||||
extract::{Path, State},
|
||||
http::HeaderMap,
|
||||
response::Response,
|
||||
response::{Redirect, Response},
|
||||
routing::get,
|
||||
};
|
||||
use brk_structs::{TransactionInfo, TxidPath};
|
||||
|
||||
@@ -13,14 +14,17 @@ use crate::{
|
||||
|
||||
use super::AppState;
|
||||
|
||||
pub trait TransactionsRoutes {
|
||||
fn add_transactions_routes(self) -> Self;
|
||||
pub trait TxRoutes {
|
||||
fn add_tx_routes(self) -> Self;
|
||||
}
|
||||
|
||||
impl TransactionsRoutes for ApiRouter<AppState> {
|
||||
fn add_transactions_routes(self) -> Self {
|
||||
self.api_route(
|
||||
"/api/chain/tx/{txid}",
|
||||
impl TxRoutes for ApiRouter<AppState> {
|
||||
fn add_tx_routes(self) -> Self {
|
||||
self
|
||||
.route("/api/tx", get(Redirect::temporary("/api/transactions")))
|
||||
.route("/api/transactions", get(Redirect::temporary("/api#tag/transactions")))
|
||||
.api_route(
|
||||
"/api/tx/{txid}",
|
||||
get_with(
|
||||
async |
|
||||
headers: HeaderMap,
|
||||
@@ -37,16 +41,16 @@ impl TransactionsRoutes for ApiRouter<AppState> {
|
||||
}
|
||||
},
|
||||
|op| op
|
||||
.tag("Chain")
|
||||
.transactions_tag()
|
||||
.summary("Transaction information")
|
||||
.description(
|
||||
"Retrieve complete transaction data by transaction ID (txid). Returns the full transaction details including inputs, outputs, and metadata. The transaction data is read directly from the blockchain data files.",
|
||||
)
|
||||
.with_ok_response::<TransactionInfo, _>(|res| res)
|
||||
.with_not_modified()
|
||||
.with_bad_request()
|
||||
.with_not_found()
|
||||
.with_server_error(),
|
||||
.ok_response::<TransactionInfo>()
|
||||
.not_modified()
|
||||
.bad_request()
|
||||
.not_found()
|
||||
.server_error(),
|
||||
),
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user