diff --git a/crates/brk_client/src/lib.rs b/crates/brk_client/src/lib.rs index 22d2e8cb8..2925280f8 100644 --- a/crates/brk_client/src/lib.rs +++ b/crates/brk_client/src/lib.rs @@ -8198,7 +8198,7 @@ pub struct BrkClient { impl BrkClient { /// Client version. - pub const VERSION: &'static str = "v0.3.0-alpha.1"; + pub const VERSION: &'static str = "v0.3.0-alpha.2"; /// Create a new client with the given base URL. pub fn new(base_url: impl Into) -> Self { diff --git a/crates/brk_computer/src/cointime/reserve_risk/compute.rs b/crates/brk_computer/src/cointime/reserve_risk/compute.rs index 71281dc2f..140d89038 100644 --- a/crates/brk_computer/src/cointime/reserve_risk/compute.rs +++ b/crates/brk_computer/src/cointime/reserve_risk/compute.rs @@ -23,7 +23,7 @@ impl Vecs { self.hodl_bank.compute_cumulative_transformed_binary( starting_indexes.height, - &prices.spot.usd.height, + &prices.cached_spot_usd, &self.vocdd_median_1y, |price, median| StoredF64::from(f64::from(price) - f64::from(median)), exit, @@ -31,7 +31,7 @@ impl Vecs { self.value.height.compute_divide( starting_indexes.height, - &prices.spot.usd.height, + &prices.cached_spot_usd, &self.hodl_bank, exit, )?; diff --git a/crates/brk_computer/src/cointime/value/compute.rs b/crates/brk_computer/src/cointime/value/compute.rs index 14110e9e9..e3cc21318 100644 --- a/crates/brk_computer/src/cointime/value/compute.rs +++ b/crates/brk_computer/src/cointime/value/compute.rs @@ -24,7 +24,7 @@ impl Vecs { .compute(starting_indexes.height, exit, |vec| { vec.compute_multiply( starting_indexes.height, - &prices.spot.usd.height, + &prices.cached_spot_usd, &coinblocks_destroyed.block, exit, )?; @@ -34,7 +34,7 @@ impl Vecs { self.created.compute(starting_indexes.height, exit, |vec| { vec.compute_multiply( starting_indexes.height, - &prices.spot.usd.height, + &prices.cached_spot_usd, &activity.coinblocks_created.block, exit, )?; @@ -44,7 +44,7 @@ impl Vecs { self.stored.compute(starting_indexes.height, exit, |vec| { vec.compute_multiply( starting_indexes.height, - &prices.spot.usd.height, + &prices.cached_spot_usd, &activity.coinblocks_stored.block, exit, )?; @@ -57,7 +57,7 @@ impl Vecs { self.vocdd.compute(starting_indexes.height, exit, |vec| { vec.compute_transform3( starting_indexes.height, - &prices.spot.usd.height, + &prices.cached_spot_usd, &coindays_destroyed.block, circulating_supply, |(i, price, cdd, supply, _): (_, Dollars, StoredF64, Bitcoin, _)| { diff --git a/crates/brk_computer/src/distribution/metrics/cohort/all.rs b/crates/brk_computer/src/distribution/metrics/cohort/all.rs index 663a56dfd..c21e55ded 100644 --- a/crates/brk_computer/src/distribution/metrics/cohort/all.rs +++ b/crates/brk_computer/src/distribution/metrics/cohort/all.rs @@ -119,7 +119,7 @@ impl AllCohortMetrics { self.unrealized.compute( starting_indexes.height, - &prices.spot.cents.height, + &prices.cached_spot_cents, &self.realized.price.cents.height, exit, )?; @@ -139,7 +139,7 @@ impl AllCohortMetrics { self.cost_basis.compute_prices( starting_indexes, - &prices.spot.cents.height, + &prices.cached_spot_cents, &self.unrealized.invested_capital.in_profit.cents.height, &self.unrealized.invested_capital.in_loss.cents.height, &self.supply.in_profit.sats.height, @@ -150,7 +150,7 @@ impl AllCohortMetrics { )?; self.unrealized - .compute_sentiment(starting_indexes, &prices.spot.cents.height, exit)?; + .compute_sentiment(starting_indexes, &prices.cached_spot_cents, exit)?; self.relative.compute( starting_indexes.height, diff --git a/crates/brk_computer/src/distribution/metrics/cohort/basic.rs b/crates/brk_computer/src/distribution/metrics/cohort/basic.rs index c16245ba1..fcc7c4e5b 100644 --- a/crates/brk_computer/src/distribution/metrics/cohort/basic.rs +++ b/crates/brk_computer/src/distribution/metrics/cohort/basic.rs @@ -82,7 +82,7 @@ impl BasicCohortMetrics { self.unrealized.compute( starting_indexes.height, - &prices.spot.cents.height, + &prices.cached_spot_cents, &self.realized.price.cents.height, exit, )?; diff --git a/crates/brk_computer/src/distribution/metrics/cohort/core.rs b/crates/brk_computer/src/distribution/metrics/cohort/core.rs index de14a707a..233e39a58 100644 --- a/crates/brk_computer/src/distribution/metrics/cohort/core.rs +++ b/crates/brk_computer/src/distribution/metrics/cohort/core.rs @@ -140,7 +140,7 @@ impl CoreCohortMetrics { self.unrealized.compute( starting_indexes.height, - &prices.spot.cents.height, + &prices.cached_spot_cents, &self.realized.price.cents.height, exit, )?; diff --git a/crates/brk_computer/src/distribution/metrics/cohort/extended.rs b/crates/brk_computer/src/distribution/metrics/cohort/extended.rs index f4c857f56..2a20cf907 100644 --- a/crates/brk_computer/src/distribution/metrics/cohort/extended.rs +++ b/crates/brk_computer/src/distribution/metrics/cohort/extended.rs @@ -108,14 +108,14 @@ impl ExtendedCohortMetrics { self.unrealized.compute( starting_indexes.height, - &prices.spot.cents.height, + &prices.cached_spot_cents, &self.realized.price.cents.height, exit, )?; self.cost_basis.compute_prices( starting_indexes, - &prices.spot.cents.height, + &prices.cached_spot_cents, &self.unrealized.invested_capital.in_profit.cents.height, &self.unrealized.invested_capital.in_loss.cents.height, &self.supply.in_profit.sats.height, @@ -126,7 +126,7 @@ impl ExtendedCohortMetrics { )?; self.unrealized - .compute_sentiment(starting_indexes, &prices.spot.cents.height, exit)?; + .compute_sentiment(starting_indexes, &prices.cached_spot_cents, exit)?; self.relative.compute( starting_indexes.height, diff --git a/crates/brk_computer/src/distribution/metrics/cohort/minimal.rs b/crates/brk_computer/src/distribution/metrics/cohort/minimal.rs index 834aed0db..ad01be6e3 100644 --- a/crates/brk_computer/src/distribution/metrics/cohort/minimal.rs +++ b/crates/brk_computer/src/distribution/metrics/cohort/minimal.rs @@ -124,7 +124,7 @@ impl MinimalCohortMetrics { self.unrealized.compute( starting_indexes.height, - &prices.spot.cents.height, + &prices.cached_spot_cents, &self.realized.price.cents.height, exit, )?; diff --git a/crates/brk_computer/src/distribution/metrics/cohort/type.rs b/crates/brk_computer/src/distribution/metrics/cohort/type.rs index b0870b1bb..eeb15e2f3 100644 --- a/crates/brk_computer/src/distribution/metrics/cohort/type.rs +++ b/crates/brk_computer/src/distribution/metrics/cohort/type.rs @@ -86,7 +86,7 @@ impl TypeCohortMetrics { self.unrealized.compute( starting_indexes.height, - &prices.spot.cents.height, + &prices.cached_spot_cents, &self.realized.price.cents.height, exit, )?; diff --git a/crates/brk_computer/src/distribution/metrics/profitability.rs b/crates/brk_computer/src/distribution/metrics/profitability.rs index 7dd79392b..f289fa8f9 100644 --- a/crates/brk_computer/src/distribution/metrics/profitability.rs +++ b/crates/brk_computer/src/distribution/metrics/profitability.rs @@ -126,7 +126,7 @@ impl ProfitabilityBucket { self.unrealized_pnl.all.height.compute_transform3( max_from, - &prices.spot.cents.height, + &prices.cached_spot_cents, &self.realized_cap.all.height, &self.supply.all.sats.height, |(i, spot, cap, supply, ..)| { @@ -139,7 +139,7 @@ impl ProfitabilityBucket { )?; self.unrealized_pnl.sth.height.compute_transform3( max_from, - &prices.spot.cents.height, + &prices.cached_spot_cents, &self.realized_cap.sth.height, &self.supply.sth.sats.height, |(i, spot, cap, supply, ..)| { @@ -153,7 +153,7 @@ impl ProfitabilityBucket { self.nupl.bps.height.compute_transform3( max_from, - &prices.spot.cents.height, + &prices.cached_spot_cents, &self.realized_cap.all.height, &self.supply.all.sats.height, |(i, spot, cap_dollars, supply_sats, ..)| { diff --git a/crates/brk_computer/src/distribution/metrics/unrealized/full.rs b/crates/brk_computer/src/distribution/metrics/unrealized/full.rs index e5c276821..32a61af6e 100644 --- a/crates/brk_computer/src/distribution/metrics/unrealized/full.rs +++ b/crates/brk_computer/src/distribution/metrics/unrealized/full.rs @@ -122,7 +122,7 @@ impl UnrealizedFull { .compute_transform3( starting_indexes.height, supply_in_profit_sats, - &prices.spot.cents.height, + &prices.cached_spot_cents, &self.inner.basic.profit.cents.height, |(h, supply_sats, spot, profit, ..): (_, Sats, Cents, Cents, _)| { let market_value = supply_sats.as_u128() * spot.as_u128() / Sats::ONE_BTC_U128; @@ -142,7 +142,7 @@ impl UnrealizedFull { .compute_transform3( starting_indexes.height, supply_in_loss_sats, - &prices.spot.cents.height, + &prices.cached_spot_cents, &self.inner.basic.loss.cents.height, |(h, supply_sats, spot, loss, ..): (_, Sats, Cents, Cents, _)| { let market_value = supply_sats.as_u128() * spot.as_u128() / Sats::ONE_BTC_U128; diff --git a/crates/brk_computer/src/indicators/realized_envelope.rs b/crates/brk_computer/src/indicators/realized_envelope.rs index f496123f2..759529f36 100644 --- a/crates/brk_computer/src/indicators/realized_envelope.rs +++ b/crates/brk_computer/src/indicators/realized_envelope.rs @@ -1,7 +1,7 @@ use brk_error::Result; use brk_traversable::Traversable; use brk_types::{Cents, Height, Indexes, StoredI8, Version}; -use vecdb::{AnyVec, Database, EagerVec, Exit, PcoVec, ReadableVec, Rw, StorageMode, WritableVec}; +use vecdb::{AnyVec, Database, Exit, ReadableVec, Rw, StorageMode, WritableVec}; use crate::{ cointime, distribution, indexes, @@ -123,7 +123,7 @@ impl RealizedEnvelope { exit, )?; - let spot = &prices.spot.cents.height; + let spot = &prices.cached_spot_cents; // Zone: spot vs own envelope bands (-4 to +4) self.compute_index(spot, starting_indexes, exit)?; @@ -136,7 +136,7 @@ impl RealizedEnvelope { fn compute_index( &mut self, - spot: &EagerVec>, + spot: &impl ReadableVec, starting_indexes: &Indexes, exit: &Exit, ) -> Result<()> { @@ -214,7 +214,7 @@ impl RealizedEnvelope { fn compute_score( &mut self, models: &[&RatioPerBlockPercentiles; 10], - spot: &EagerVec>, + spot: &impl ReadableVec, starting_indexes: &Indexes, exit: &Exit, ) -> Result<()> { diff --git a/crates/brk_computer/src/internal/per_block/amount/base.rs b/crates/brk_computer/src/internal/per_block/amount/base.rs index 3b2067882..dd2ea32a6 100644 --- a/crates/brk_computer/src/internal/per_block/amount/base.rs +++ b/crates/brk_computer/src/internal/per_block/amount/base.rs @@ -59,7 +59,7 @@ impl AmountPerBlock { self.cents.compute_binary::( max_from, &self.sats.height, - &prices.spot.cents.height, + &prices.cached_spot_cents, exit, )?; Ok(()) diff --git a/crates/brk_computer/src/internal/per_block/amount/block.rs b/crates/brk_computer/src/internal/per_block/amount/block.rs index e7897bb1c..cf011f042 100644 --- a/crates/brk_computer/src/internal/per_block/amount/block.rs +++ b/crates/brk_computer/src/internal/per_block/amount/block.rs @@ -50,7 +50,7 @@ impl AmountBlock { self.cents.compute_binary::( max_from, &self.sats, - &prices.spot.cents.height, + &prices.cached_spot_cents, exit, )?; Ok(()) diff --git a/crates/brk_computer/src/internal/per_block/computed/distribution.rs b/crates/brk_computer/src/internal/per_block/computed/distribution.rs index aa075df69..bfa31cc45 100644 --- a/crates/brk_computer/src/internal/per_block/computed/distribution.rs +++ b/crates/brk_computer/src/internal/per_block/computed/distribution.rs @@ -98,6 +98,7 @@ impl PerBlockDistribution { let count_indexes_batch: Vec = count_indexes.collect_range_at(start, fi_len); + let zero = T::from(0_usize); let mut values: Vec = Vec::new(); first_indexes_batch @@ -114,8 +115,11 @@ impl PerBlockDistribution { &mut values, ); + if skip_count > 0 { + values.retain(|v| *v > zero); + } + if values.is_empty() { - let zero = T::from(0_usize); for vec in [ &mut *min, &mut *max, diff --git a/crates/brk_computer/src/internal/per_block/ratio/price_extended.rs b/crates/brk_computer/src/internal/per_block/ratio/price_extended.rs index 13fe4a799..c7c913c3d 100644 --- a/crates/brk_computer/src/internal/per_block/ratio/price_extended.rs +++ b/crates/brk_computer/src/internal/per_block/ratio/price_extended.rs @@ -71,7 +71,7 @@ impl PriceWithRatioPerBlock { F: FnMut(&mut EagerVec>) -> Result<()>, { compute_price(&mut self.cents.height)?; - self.compute_ratio(starting_indexes, &prices.spot.cents.height, exit) + self.compute_ratio(starting_indexes, &prices.cached_spot_cents, exit) } } @@ -104,7 +104,7 @@ impl PriceWithRatioExtendedPerBlock { starting_indexes: &Indexes, exit: &Exit, ) -> Result<()> { - let close_price = &prices.spot.cents.height; + let close_price = &prices.cached_spot_cents; self.base .compute_ratio(starting_indexes, close_price, exit)?; self.percentiles.compute( diff --git a/crates/brk_computer/src/investing/compute.rs b/crates/brk_computer/src/investing/compute.rs index c89456bd5..ec129c0a9 100644 --- a/crates/brk_computer/src/investing/compute.rs +++ b/crates/brk_computer/src/investing/compute.rs @@ -102,7 +102,7 @@ impl Vecs { { returns.compute_binary::( starting_indexes.height, - &prices.spot.cents.height, + &prices.cached_spot_cents, &average_price.cents.height, exit, )?; @@ -163,7 +163,7 @@ impl Vecs { { returns.compute_binary::( starting_indexes.height, - &prices.spot.cents.height, + &prices.cached_spot_cents, &lookback_price.cents.height, exit, )?; @@ -266,7 +266,7 @@ impl Vecs { { returns.compute_binary::( starting_indexes.height, - &prices.spot.cents.height, + &prices.cached_spot_cents, &average_price.cents.height, exit, )?; diff --git a/crates/brk_computer/src/market/ath/compute.rs b/crates/brk_computer/src/market/ath/compute.rs index 6b03d2152..32a3f12fd 100644 --- a/crates/brk_computer/src/market/ath/compute.rs +++ b/crates/brk_computer/src/market/ath/compute.rs @@ -15,7 +15,7 @@ impl Vecs { ) -> Result<()> { self.high.cents.height.compute_all_time_high( starting_indexes.height, - &prices.spot.cents.height, + &prices.cached_spot_cents, exit, )?; @@ -23,7 +23,7 @@ impl Vecs { self.days_since.height.compute_transform3( starting_indexes.height, &self.high.cents.height, - &prices.spot.cents.height, + &prices.cached_spot_cents, &indexes.timestamp.monotonic, |(i, ath, price, ts, slf)| { if ath_ts.is_none() { @@ -68,7 +68,7 @@ impl Vecs { self.drawdown.compute_drawdown( starting_indexes.height, - &prices.spot.cents.height, + &prices.cached_spot_cents, &self.high.cents.height, exit, )?; diff --git a/crates/brk_computer/src/market/lookback/compute.rs b/crates/brk_computer/src/market/lookback/compute.rs index 394aff667..c98e81dba 100644 --- a/crates/brk_computer/src/market/lookback/compute.rs +++ b/crates/brk_computer/src/market/lookback/compute.rs @@ -13,7 +13,7 @@ impl Vecs { starting_indexes: &Indexes, exit: &Exit, ) -> Result<()> { - let price = &prices.spot.cents.height; + let price = &prices.cached_spot_cents; for (price_past, days) in self.price_past.iter_mut_with_days() { let window_starts = blocks.lookback.start_vec(days as usize); diff --git a/crates/brk_computer/src/market/moving_average/compute.rs b/crates/brk_computer/src/market/moving_average/compute.rs index 69eeaa10d..b05c429ac 100644 --- a/crates/brk_computer/src/market/moving_average/compute.rs +++ b/crates/brk_computer/src/market/moving_average/compute.rs @@ -13,7 +13,7 @@ impl Vecs { starting_indexes: &Indexes, exit: &Exit, ) -> Result<()> { - let close = &prices.spot.cents.height; + let close = &prices.cached_spot_cents; for (sma, period) in [ (&mut self.sma._1w, 7), diff --git a/crates/brk_computer/src/market/range/compute.rs b/crates/brk_computer/src/market/range/compute.rs index fd9645246..54784c5ea 100644 --- a/crates/brk_computer/src/market/range/compute.rs +++ b/crates/brk_computer/src/market/range/compute.rs @@ -13,7 +13,7 @@ impl Vecs { starting_indexes: &Indexes, exit: &Exit, ) -> Result<()> { - let price = &prices.spot.cents.height; + let price = &prices.cached_spot_cents; for (min_vec, max_vec, starts) in [ ( diff --git a/crates/brk_computer/src/market/returns/compute.rs b/crates/brk_computer/src/market/returns/compute.rs index 4f46c022d..0cec1682d 100644 --- a/crates/brk_computer/src/market/returns/compute.rs +++ b/crates/brk_computer/src/market/returns/compute.rs @@ -24,7 +24,7 @@ impl Vecs { { returns.compute_binary::( starting_indexes.height, - &prices.spot.usd.height, + &prices.cached_spot_usd, &lookback_price.usd.height, exit, )?; diff --git a/crates/brk_computer/src/market/technical/macd.rs b/crates/brk_computer/src/market/technical/macd.rs index 8af7b3fd5..d008b3595 100644 --- a/crates/brk_computer/src/market/technical/macd.rs +++ b/crates/brk_computer/src/market/technical/macd.rs @@ -16,7 +16,7 @@ pub(super) fn compute( starting_indexes: &Indexes, exit: &Exit, ) -> Result<()> { - let close = &prices.spot.usd.height; + let close = &prices.cached_spot_usd; let ws_fast = blocks.lookback.start_vec(fast_days); let ws_slow = blocks.lookback.start_vec(slow_days); let ws_signal = blocks.lookback.start_vec(signal_days); diff --git a/crates/brk_computer/src/prices/mod.rs b/crates/brk_computer/src/prices/mod.rs index 1b72ca26d..ac5d9f36a 100644 --- a/crates/brk_computer/src/prices/mod.rs +++ b/crates/brk_computer/src/prices/mod.rs @@ -6,7 +6,8 @@ use std::path::Path; use brk_traversable::Traversable; use brk_types::Version; -use vecdb::{Database, ReadableCloneableVec, Rw, StorageMode}; +use brk_types::{Cents, Dollars, Height}; +use vecdb::{CachedVec, Database, LazyVecFrom1, ReadableCloneableVec, Rw, StorageMode}; use crate::{ indexes, @@ -27,6 +28,11 @@ pub struct Vecs { #[traversable(skip)] pub db: Database, + #[traversable(skip)] + pub cached_spot_cents: CachedVec, + #[traversable(skip)] + pub cached_spot_usd: LazyVecFrom1, + pub split: SplitByUnit, pub ohlc: OhlcByUnit, pub spot: PriceByUnit, @@ -169,6 +175,13 @@ impl Vecs { sats: ohlc_sats, }; + let cached_spot_cents = CachedVec::new(&price_cents.height); + let cached_spot_usd = LazyVecFrom1::transformed::( + "price", + version, + cached_spot_cents.read_only_boxed_clone(), + ); + let spot = PriceByUnit { usd: price_usd, cents: price_cents, @@ -177,6 +190,8 @@ impl Vecs { Ok(Self { db: db.clone(), + cached_spot_cents, + cached_spot_usd, split, ohlc, spot, diff --git a/crates/brk_computer/src/transactions/fees/import.rs b/crates/brk_computer/src/transactions/fees/import.rs index 3c2ab4b59..0996f4051 100644 --- a/crates/brk_computer/src/transactions/fees/import.rs +++ b/crates/brk_computer/src/transactions/fees/import.rs @@ -5,8 +5,8 @@ use vecdb::{Database, EagerVec, ImportableVec}; use super::Vecs; use crate::{indexes, internal::PerTxDistribution}; -/// Bump this when fee/feerate aggregation logic changes (e.g., skip coinbase). -const VERSION: Version = Version::new(2); +/// Bump this when fee/feerate aggregation logic changes (e.g., skip coinbase, skip zero-fee). +const VERSION: Version = Version::new(3); impl Vecs { pub(crate) fn forced_import( diff --git a/crates/brk_logger/src/lib.rs b/crates/brk_logger/src/lib.rs index e7558a9c1..dea11ca12 100644 --- a/crates/brk_logger/src/lib.rs +++ b/crates/brk_logger/src/lib.rs @@ -26,9 +26,8 @@ pub fn init(path: Option<&Path>) -> io::Result<()> { let level = std::env::var("LOG").unwrap_or_else(|_| DEFAULT_LEVEL.to_string()); let directives = std::env::var("RUST_LOG").unwrap_or_else(|_| { - // fjall=off,lsm_tree=off format!( - "{level},bitcoin=off,bitcoincore_rpc=off,corepc=off,tracing=off,aide=off,tower_http=off" + "{level},bitcoin=off,bitcoincore_rpc=off,corepc=off,tracing=off,aide=off,fjall=off,lsm_tree=off,tower_http=off" ) }); diff --git a/crates/brk_query/src/impl/block/info.rs b/crates/brk_query/src/impl/block/info.rs index b31db1873..b3eb52e8e 100644 --- a/crates/brk_query/src/impl/block/info.rs +++ b/crates/brk_query/src/impl/block/info.rs @@ -21,7 +21,7 @@ impl Query { } pub fn block_by_height(&self, height: Height) -> Result { - let max_height = self.max_height(); + let max_height = self.indexed_height(); if height > max_height { return Err(Error::OutOfRange("Block height out of range".into())); } @@ -31,7 +31,7 @@ impl Query { } pub fn block_by_height_v1(&self, height: Height) -> Result { - let max_height = self.max_height(); + let max_height = self.height(); if height > max_height { return Err(Error::OutOfRange("Block height out of range".into())); } @@ -47,7 +47,7 @@ impl Query { } pub fn block_hash_by_height(&self, height: Height) -> Result { - let max_height = self.max_height(); + let max_height = self.indexed_height(); if height > max_height { return Err(Error::OutOfRange("Block height out of range".into())); } @@ -219,6 +219,7 @@ impl Query { .block .sats .collect_range_at(begin, end); + let prices = computer.prices.cached_spot_usd.collect_range_at(begin, end); let output_volumes = computer .mining .rewards @@ -381,6 +382,7 @@ impl Query { utxo_set_size: *utxo_set_sizes[i], total_input_amt, virtual_size: vsize as f64, + price: prices[i], }; blocks.push(BlockInfoV1 { info, extras }); @@ -415,10 +417,6 @@ impl Query { .map_err(|_| Error::Internal("Failed to decode block header")) } - fn max_height(&self) -> Height { - Height::from(self.indexer().vecs.blocks.blockhash.len().saturating_sub(1)) - } - fn resolve_block_range(&self, start_height: Option, count: u32) -> (usize, usize) { let max_height = self.height(); let start = start_height.unwrap_or(max_height).min(max_height); diff --git a/crates/brk_query/src/impl/mining/block_window.rs b/crates/brk_query/src/impl/mining/block_window.rs index 97ee046e8..a61345d9c 100644 --- a/crates/brk_query/src/impl/mining/block_window.rs +++ b/crates/brk_query/src/impl/mining/block_window.rs @@ -77,9 +77,7 @@ impl BlockWindow { .collect_range_at(self.start, self.end); let all_prices: Vec = computer .prices - .spot - .cents - .height + .cached_spot_cents .collect_range_at(self.start, self.end); let read_start = self.start.saturating_sub(1).max(0); let all_cum = cumulative.collect_range_at(read_start, self.end); diff --git a/crates/brk_server/src/api/mempool_space/blocks.rs b/crates/brk_server/src/api/mempool_space/blocks.rs index 50f9c97b6..ee7660053 100644 --- a/crates/brk_server/src/api/mempool_space/blocks.rs +++ b/crates/brk_server/src/api/mempool_space/blocks.rs @@ -185,7 +185,7 @@ impl BlockRoutes for ApiRouter { "/api/blocks/tip/height", get_with( async |uri: Uri, headers: HeaderMap, State(state): State| { - state.cached_text(&headers, CacheStrategy::Tip, &uri, |q| Ok(q.height().to_string())).await + state.cached_text(&headers, CacheStrategy::Tip, &uri, |q| Ok(q.indexed_height().to_string())).await }, |op| { op.id("get_block_tip_height") diff --git a/crates/brk_types/src/block_extras.rs b/crates/brk_types/src/block_extras.rs index c87b5e987..cf50f42e7 100644 --- a/crates/brk_types/src/block_extras.rs +++ b/crates/brk_types/src/block_extras.rs @@ -1,7 +1,7 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use crate::{BlockPool, FeeRate, Sats, Weight}; +use crate::{BlockPool, Dollars, FeeRate, Sats, Weight}; /// Extended block data matching mempool.space /api/v1/blocks extras #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] @@ -106,4 +106,7 @@ pub struct BlockExtras { /// Virtual size in vbytes #[serde(rename = "virtualSize")] pub virtual_size: f64, + + /// USD price at block height + pub price: Dollars, } diff --git a/modules/brk-client/index.js b/modules/brk-client/index.js index 4c9af757d..a839dd480 100644 --- a/modules/brk-client/index.js +++ b/modules/brk-client/index.js @@ -139,6 +139,7 @@ * @property {number} utxoSetSize - Total UTXO set size at this height * @property {Sats} totalInputAmt - Total input amount in satoshis * @property {number} virtualSize - Virtual size in vbytes + * @property {Dollars} price - USD price at block height */ /** * A single block fees data point. @@ -6563,7 +6564,7 @@ function createTransferPattern(client, acc) { * @extends BrkClientBase */ class BrkClient extends BrkClientBase { - VERSION = "v0.3.0-alpha.1"; + VERSION = "v0.3.0-alpha.2"; INDEXES = /** @type {const} */ ([ "minute10", diff --git a/modules/brk-client/package.json b/modules/brk-client/package.json index 60a4ce529..0609001c0 100644 --- a/modules/brk-client/package.json +++ b/modules/brk-client/package.json @@ -40,5 +40,5 @@ "url": "git+https://github.com/bitcoinresearchkit/brk.git" }, "type": "module", - "version": "0.3.0-alpha.1" + "version": "0.3.0-alpha.2" } diff --git a/packages/brk_client/brk_client/__init__.py b/packages/brk_client/brk_client/__init__.py index 712c1ea1f..05f53a86e 100644 --- a/packages/brk_client/brk_client/__init__.py +++ b/packages/brk_client/brk_client/__init__.py @@ -50,12 +50,12 @@ BasisPointsSigned32 = int # Bitcoin amount as floating point (1 BTC = 100,000,000 satoshis) Bitcoin = float PoolSlug = Literal["unknown", "blockfills", "ultimuspool", "terrapool", "luxor", "onethash", "btccom", "bitfarms", "huobipool", "wayicn", "canoepool", "btctop", "bitcoincom", "pool175btc", "gbminers", "axbt", "asicminer", "bitminter", "bitcoinrussia", "btcserv", "simplecoinus", "btcguild", "eligius", "ozcoin", "eclipsemc", "maxbtc", "triplemining", "coinlab", "pool50btc", "ghashio", "stminingcorp", "bitparking", "mmpool", "polmine", "kncminer", "bitalo", "f2pool", "hhtt", "megabigpower", "mtred", "nmcbit", "yourbtcnet", "givemecoins", "braiinspool", "antpool", "multicoinco", "bcpoolio", "cointerra", "kanopool", "solock", "ckpool", "nicehash", "bitclub", "bitcoinaffiliatenetwork", "btcc", "bwpool", "exxbw", "bitsolo", "bitfury", "twentyoneinc", "digitalbtc", "eightbaochi", "mybtccoinpool", "tbdice", "hashpool", "nexious", "bravomining", "hotpool", "okexpool", "bcmonster", "onehash", "bixin", "tatmaspool", "viabtc", "connectbtc", "batpool", "waterhole", "dcexploration", "dcex", "btpool", "fiftyeightcoin", "bitcoinindia", "shawnp0wers", "phashio", "rigpool", "haozhuzhu", "sevenpool", "miningkings", "hashbx", "dpool", "rawpool", "haominer", "helix", "bitcoinukraine", "poolin", "secretsuperstar", "tigerpoolnet", "sigmapoolcom", "okpooltop", "hummerpool", "tangpool", "bytepool", "spiderpool", "novablock", "miningcity", "binancepool", "minerium", "lubiancom", "okkong", "aaopool", "emcdpool", "foundryusa", "sbicrypto", "arkpool", "purebtccom", "marapool", "kucoinpool", "entrustcharitypool", "okminer", "titan", "pegapool", "btcnuggets", "cloudhashing", "digitalxmintsy", "telco214", "btcpoolparty", "multipool", "transactioncoinmining", "btcdig", "trickysbtcpool", "btcmp", "eobot", "unomp", "patels", "gogreenlight", "bitcoinindiapool", "ekanembtc", "canoe", "tiger", "onem1x", "zulupool", "secpool", "ocean", "whitepool", "wiz", "wk057", "futurebitapollosolo", "carbonnegative", "portlandhodl", "phoenix", "neopool", "maxipool", "bitfufupool", "gdpool", "miningdutch", "publicpool", "miningsquared", "innopolistech", "btclab", "parasite", "redrockpool", "est3lar", "braiinssolo", "solopool"] +# US Dollar amount as floating point +Dollars = float # Fee rate in sats/vB FeeRate = float # Transaction or block weight in weight units (WU) Weight = int -# US Dollar amount as floating point -Dollars = float # Block height Height = int # UNIX timestamp in seconds @@ -354,6 +354,7 @@ class BlockExtras(TypedDict): utxoSetSize: Total UTXO set size at this height totalInputAmt: Total input amount in satoshis virtualSize: Virtual size in vbytes + price: USD price at block height """ totalFees: Sats medianFee: FeeRate @@ -381,6 +382,7 @@ class BlockExtras(TypedDict): utxoSetSize: int totalInputAmt: Sats virtualSize: float + price: Dollars class BlockFeesEntry(TypedDict): """ @@ -6001,7 +6003,7 @@ class SeriesTree: class BrkClient(BrkClientBase): """Main BRK client with series tree and API methods.""" - VERSION = "v0.3.0-alpha.1" + VERSION = "v0.3.0-alpha.2" INDEXES = [ "minute10", diff --git a/packages/brk_client/pyproject.toml b/packages/brk_client/pyproject.toml index 0cdc09dd5..2f75f7232 100644 --- a/packages/brk_client/pyproject.toml +++ b/packages/brk_client/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "brk-client" -version = "0.3.0-alpha.1" +version = "0.3.0-alpha.2" description = "Bitcoin on-chain analytics client — thousands of metrics, block explorer, and address index" readme = "README.md" requires-python = ">=3.9" diff --git a/website/scripts/panes/explorer.js b/website/scripts/panes/explorer.js index 1ba1539a1..099a1d0de 100644 --- a/website/scripts/panes/explorer.js +++ b/website/scripts/panes/explorer.js @@ -176,6 +176,7 @@ function renderDetails(block) { if (extras) { rows.push( + ["Price", `$${extras.price.toLocaleString()}`], ["Pool", extras.pool.name], ["Pool ID", extras.pool.id.toString()], ["Pool Slug", extras.pool.slug],