crates: snapshot

This commit is contained in:
nym21
2026-05-12 22:33:09 +02:00
parent 8fc2e71492
commit 5cc3fbfa6e
25 changed files with 450 additions and 362 deletions
+29 -10
View File
@@ -11,6 +11,14 @@ use crate::{
params::{AddrAfterTxidParam, AddrParam, Empty, ValidateAddrParam},
};
/// Esplora `/txs` and `/txs/chain` page sizes. Wire-protocol constants from
/// mempool.space/esplora, not deployment policy. `/txs` returns up to
/// `MEMPOOL_PAGE` mempool entries plus a chain page sized to reach
/// `TXS_TOTAL_TARGET` total, floored at `CHAIN_PAGE`.
const MEMPOOL_PAGE: usize = 50;
const CHAIN_PAGE: usize = 25;
const TXS_TOTAL_TARGET: usize = 50;
pub trait AddrRoutes {
fn add_addr_routes(self) -> Self;
}
@@ -26,7 +34,7 @@ impl AddrRoutes for ApiRouter<AppState> {
_: Empty,
State(state): State<AppState>
| {
let strategy = state.addr_strategy(Version::ONE, &path.addr, false);
let strategy = state.addr_strategy(Version::ONE, &path.addr, false, None);
state.respond_json(&headers, strategy, &uri, move |q| q.addr(path.addr)).await
}, |op| op
.id("get_address")
@@ -49,13 +57,24 @@ impl AddrRoutes for ApiRouter<AppState> {
_: Empty,
State(state): State<AppState>
| {
let strategy = state.addr_strategy(Version::ONE, &path.addr, false);
state.respond_json(&headers, strategy, &uri, move |q| q.addr_txs(path.addr, 50, 50)).await
let strategy = state.addr_strategy(Version::ONE, &path.addr, false, None);
state.respond_json(&headers, strategy, &uri, move |q| {
let mempool_txs = if q.mempool().is_some() {
q.addr_mempool_txs(&path.addr, MEMPOOL_PAGE)?
} else {
Vec::new()
};
let chain_limit = TXS_TOTAL_TARGET.saturating_sub(mempool_txs.len()).max(CHAIN_PAGE);
let chain_txs = q.addr_txs_chain(&path.addr, None, chain_limit)?;
let mut out = mempool_txs;
out.extend(chain_txs);
Ok(out)
}).await
}, |op| op
.id("get_address_txs")
.addrs_tag()
.summary("Address transactions")
.description("Get transaction history for an address, sorted with newest first. Returns up to 50 entries: mempool transactions first, then confirmed transactions filling the remainder. To paginate further confirmed transactions, use `/address/{address}/txs/chain/{last_seen_txid}`.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-address-transactions)*")
.description("Get transaction history for an address, newest first. Returns up to 50 mempool transactions plus a confirmed page sized to fill the response to 50 total (chain floor of 25, so 25-50 confirmed depending on mempool weight). To paginate further confirmed history, use `/address/{address}/txs/chain/{last_seen_txid}`.\n\n*[Mempool.space docs](https://mempool.space/docs/api/rest#get-address-transactions)*")
.json_response::<Vec<Transaction>>()
.not_modified()
.bad_request()
@@ -72,8 +91,8 @@ impl AddrRoutes for ApiRouter<AppState> {
_: Empty,
State(state): State<AppState>
| {
let strategy = state.addr_strategy(Version::ONE, &path.addr, true);
state.respond_json(&headers, strategy, &uri, move |q| q.addr_txs_chain(&path.addr, None, 25)).await
let strategy = state.addr_strategy(Version::ONE, &path.addr, true, None);
state.respond_json(&headers, strategy, &uri, move |q| q.addr_txs_chain(&path.addr, None, CHAIN_PAGE)).await
}, |op| op
.id("get_address_confirmed_txs")
.addrs_tag()
@@ -95,8 +114,8 @@ impl AddrRoutes for ApiRouter<AppState> {
_: Empty,
State(state): State<AppState>
| {
let strategy = state.addr_strategy(Version::ONE, &path.addr, true);
state.respond_json(&headers, strategy, &uri, move |q| q.addr_txs_chain(&path.addr, Some(path.after_txid), 25)).await
let strategy = state.addr_strategy(Version::ONE, &path.addr, true, Some(&path.after_txid));
state.respond_json(&headers, strategy, &uri, move |q| q.addr_txs_chain(&path.addr, Some(path.after_txid), CHAIN_PAGE)).await
}, |op| op
.id("get_address_confirmed_txs_after")
.addrs_tag()
@@ -119,7 +138,7 @@ impl AddrRoutes for ApiRouter<AppState> {
State(state): State<AppState>
| {
let hash = state.sync(|q| q.addr_mempool_hash(&path.addr)).unwrap_or(0);
state.respond_json(&headers, CacheStrategy::MempoolHash(hash), &uri, move |q| q.addr_mempool_txs(&path.addr, 50)).await
state.respond_json(&headers, CacheStrategy::MempoolHash(hash), &uri, move |q| q.addr_mempool_txs(&path.addr, MEMPOOL_PAGE)).await
}, |op| op
.id("get_address_mempool_txs")
.addrs_tag()
@@ -141,7 +160,7 @@ impl AddrRoutes for ApiRouter<AppState> {
_: Empty,
State(state): State<AppState>
| {
let strategy = state.addr_strategy(Version::ONE, &path.addr, false);
let strategy = state.addr_strategy(Version::ONE, &path.addr, false, None);
let max_utxos = state.max_utxos;
state.respond_json(&headers, strategy, &uri, move |q| q.addr_utxos(path.addr, max_utxos)).await
}, |op| op
+2 -1
View File
@@ -135,7 +135,8 @@ impl MiningRoutes for ApiRouter<AppState> {
"/api/v1/mining/pool/{slug}/blocks",
get_with(
async |uri: Uri, headers: HeaderMap, Path(path): Path<PoolSlugParam>, _: Empty, State(state): State<AppState>| {
state.respond_json(&headers, CacheStrategy::Tip, &uri, move |q| q.pool_blocks(path.slug, None, POOL_BLOCKS_LIMIT)).await
let strategy = state.pool_blocks_strategy(Version::ONE, path.slug);
state.respond_json(&headers, strategy, &uri, move |q| q.pool_blocks(path.slug, None, POOL_BLOCKS_LIMIT)).await
},
|op| {
op.id("get_pool_blocks")
+2 -8
View File
@@ -29,13 +29,7 @@ impl ServerRoutes for ApiRouter<AppState> {
let uptime = state.started_instant.elapsed();
let started_at = state.started_at.to_string();
let sync = state
.run(move |q| {
let tip_height = q
.client()
.get_last_height()
.unwrap_or(q.height());
q.sync_status(tip_height)
})
.run(move |q| q.sync_status(q.height()))
.await
.expect("health sync task panicked");
let mut response = axum::Json(Health {
@@ -57,7 +51,7 @@ impl ServerRoutes for ApiRouter<AppState> {
op.id("get_health")
.server_tag()
.summary("Health check")
.description("Returns the health status of the API server, including uptime information.")
.description("Liveness probe. Returns server identity, uptime, and indexed/computed heights from local state only (no bitcoind round-trip). For real chain-tip catch-up, see `/api/server/sync`.")
.json_response::<Health>()
},
),