diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 75224c0f4..120aeedd3 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -4,6 +4,221 @@ All notable changes to the Bitcoin Research Kit (BRK) project will be documented > *This changelog was generated by Claude Code* +## [v0.1.9](https://github.com/bitcoinresearchkit/brk/releases/tag/v0.1.9) - 2026-02-13 + +### New Features + +#### `brk` +- Added `oracle` feature flag re-exporting `brk_oracle` from the `brk` umbrella crate, making the on-chain price oracle available via `brk::oracle` ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.9/crates/brk/src/lib.rs)) +- Added `brk_oracle` to the crates table in the umbrella crate README ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.9/crates/brk/README.md)) + +### Internal Changes + +#### `brk` +- Added `brk_oracle` to the Rust publish script ordering ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.9/scripts/rust-publish.sh)) + +[View changes](https://github.com/bitcoinresearchkit/brk/compare/v0.1.8...v0.1.9) + +## [v0.1.8](https://github.com/bitcoinresearchkit/brk/releases/tag/v0.1.8) - 2026-02-13 + +### Breaking Changes + +#### `brk_types` +- Renamed `Sats::is_round_btc()` to `is_common_round_value()` and rewrote the algorithm: replaces a hardcoded array of 19 specific round sat values with a general integer-based approach using `ilog10()` to detect any value matching `d × 10^n` where `d ∈ {1, 2, 3, 5, 6}` ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.8/crates/brk_types/src/sats.rs)) + +#### `brk_server` +- Renamed `CacheStrategy::MaxAge(u64)` to `CacheStrategy::MempoolHash(u64)`, switching mempool endpoints from time-based `Cache-Control: max-age=N` to content-addressed ETags derived from the next projected block hash ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.8/crates/brk_server/src/cache.rs)) + +### New Features + +#### `brk_oracle` +- Added new `brk_oracle` crate: a pure on-chain BTC/USD price oracle that derives the bitcoin price from round-dollar transaction output patterns ($1, $5, $10, ... $10,000) without any exchange data ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.8/crates/brk_oracle/src/lib.rs)) +- Algorithm maps outputs to a log-scale histogram (2,400 bins, 200 per decade), smooths with an EMA over a 12-block ring buffer, then slides a 19-point stencil representing round-dollar spikes to find the best-fit price with parabolic sub-bin interpolation +- Operates from height 575,000 (May 2019) onward; pre-oracle exchange prices for heights 0–630,000 included in `prices.txt` for bootstrapping +- Median per-block error 0.10%, 95th percentile 0.55%; zero blocks exceed 10% error since 2022 +- Inspired by UTXOracle by @SteveSimple, with per-block resolution, single-pass stencil scoring, and rolling EMA operation + +#### `brk_computer` +- Enabled oracle price computation with full OHLC data at all period levels (date, week, month, quarter, semester, year, decade, height, difficulty epoch) ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.8/crates/brk_computer/src/price/oracle/compute.rs)) +- Added `live_oracle()` method that seeds an oracle from the last committed price and replays recent blocks for real-time price estimation ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.8/crates/brk_computer/src/price/oracle/compute.rs)) +- Added `market_cap_growth_rate` metric: 365-day percentage change of market cap ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.8/crates/brk_computer/src/supply/vecs.rs)) +- Added `realized_cap_growth_rate` metric: 365-day percentage change of realized cap +- Added `cap_growth_rate_diff` metric: lazy difference between market cap and realized cap growth rates +- Added net sentiment computation for UTXO cohorts: computes greed minus pain per separate cohort, weighted average for aggregate cohorts, and dateindex for all cohorts ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.8/crates/brk_computer/src/distribution/cohorts/utxo/groups.rs)) + +#### `brk_server` +- Added server-side response caching via `get_or_insert()` on `AppState`, backed by `quick_cache` with 50ms guard timeout for request deduplication ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.8/crates/brk_server/src/state.rs)) +- Added `GET /api/mempool/price` endpoint returning the current BTC/USD price in dollars, derived from on-chain round-dollar output patterns in the last 12 blocks plus mempool ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.8/crates/brk_server/src/api/mempool/mod.rs)) +- Added `CF-Connecting-IP` header detection for requests arriving from loopback addresses through Cloudflare, rewriting the socket address to apply non-loopback rate limits ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.8/crates/brk_server/src/lib.rs)) +- Switched address mempool endpoint to content-based cache invalidation using a hash of the address's mempool state + +#### `brk_query` +- Added `live_price()` method returning the oracle-derived BTC/USD price, seeded from the last committed price with replay of the last window of blocks and mempool transactions ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.8/crates/brk_query/src/impl/price.rs)) +- Added `address_mempool_hash()` method returning a `u64` hash of an address's mempool state for content-based cache invalidation ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.8/crates/brk_query/src/impl/address.rs)) + +#### `brk_mempool` +- Added `Snapshot::next_block_hash()` returning a hash of the first projected block for content-based cache keys ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.8/crates/brk_mempool/src/projected_blocks/snapshot.rs)) +- Added `Sync::next_block_hash()` and `Sync::address_hash()` for exposing content hashes at the sync layer ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.8/crates/brk_mempool/src/sync.rs)) + +#### `brk_types` +- Derived `Hash` on `Sats` for use in content-based cache invalidation ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.8/crates/brk_types/src/sats.rs)) +- Derived `Hash` on `AddressMempoolStats` for per-address mempool hashing ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.8/crates/brk_types/src/addressmempoolstats.rs)) + +#### `brk_client` +- Added `get_live_price()` method for the `/api/mempool/price` endpoint ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.8/crates/brk_client/src/lib.rs)) +- Added `MetricsTree_Price_Oracle` struct exposing oracle price metrics (`price_cents`, `ohlc_cents`, `split`, `ohlc`, `ohlc_dollars`) +- Added `market_cap_growth_rate`, `realized_cap_growth_rate`, and `cap_growth_rate_diff` fields to `MetricsTree_Supply` + +#### `website` +- Replaced Kraken WebSocket price feed with HTTP polling to the oracle-based `/api/mempool/price` endpoint every 5 seconds, with re-poll on tab visibility change ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.8/website/scripts/utils/price.js)) +- Added Oracle candlestick chart under the Market section showing on-chain derived BTC/USD price ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.8/website/scripts/options/market.js)) +- Expanded Capitalization into a tree with Market Cap, Realized Cap, and Growth Rate sub-charts showing market cap growth rate, realized cap growth rate, and their difference +- Added dynamic color assignment via `at(index, length)` for palette-aware spacing and `seq(keys)` for named color maps, replacing hardcoded color mappings across all chart options ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.8/website/scripts/utils/colors.js)) + +### Internal Changes + +#### `brk_computer` +- Flattened supply submodules (`circulating/`, `inflation/`, `market_cap/`) into the parent supply module, inlining their logic directly into `vecs.rs`, `import.rs`, and `compute.rs` ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.8/crates/brk_computer/src/supply/mod.rs)) +- Changed `CostBasisDistribution::serialize_iter` to accept `merged.into_iter()` and write to a path variable + +#### `brk_server` +- Centralized response caching in `state.rs` with `cached_json()`, `cached_text()`, and `cached_bytes()` now accepting a `Uri` parameter for server-side cache keying, removing per-handler `GuardResult` boilerplate +- Removed `ResponseExtended::new_text_cached()` and `new_bytes_cached()` in favor of inline handling in the state caching methods +- Updated all API handlers to destructure `State(state)` and pass `&uri` for cache keying + +#### `website` +- Split monolithic `components.css` into separate files: `main.css`, `nav.css`, `search.css`, `chart.css` for better organization +- Converted chart option `top` and `bottom` properties from eager values to lazy functions with memoized evaluation for faster startup ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.8/website/scripts/options/full.js)) +- Refactored chart component: simplified pane management, converted legends from named object to array, consolidated time data into a single object with `setIndex()` and `fetch()` methods ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.8/website/scripts/chart/index.js)) +- Optimized navigation highlight tracking to only clear previously highlighted items instead of iterating all entries +- Removed shadow divs from HTML and `
` pane +- Removed unused utility files (`ws.js`, `date.js`, `serde.js`) and functions (`range()`, `numberToDollars()`, `numberToPercentage()`, `createShadow()`, `localhost`) + +#### `clients` +- Bumped JavaScript and Python client versions + +[View changes](https://github.com/bitcoinresearchkit/brk/compare/v0.1.7...v0.1.8) + +## [v0.1.7](https://github.com/bitcoinresearchkit/brk/releases/tag/v0.1.7) - 2026-02-07 + +### New Features + +#### `brk_computer` +- Added `lower_price_band` metric per cohort, computed as realized_price² / investor_price, representing a floor price estimate ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.7/crates/brk_computer/src/distribution/metrics/realized.rs)) +- Added `upper_price_band` metric per cohort, computed as investor_price² / realized_price, representing a ceiling price estimate +- Added `LazyBinaryPriceFromHeight` composite type for fully lazy binary price metrics providing both USD and sats representations at all time levels ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.7/crates/brk_computer/src/internal/multi/from_height/lazy_binary_price.rs)) +- Added `DollarsSquaredDivide` binary transform implementing `a² / b` for Dollars values ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.7/crates/brk_computer/src/internal/single/transform/dollars_squared_divide.rs)) + +#### `brk_types` +- Added `Log200` variant to `CostBasisBucket` for logarithmic bucketing with 200 buckets per decade ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.7/crates/brk_types/src/cost_basis_bucket.rs)) +- Added `From for i128` and `From for CentsSigned` conversions for wider arithmetic operations ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.7/crates/brk_types/src/cents_signed.rs)) + +#### `brk_website` +- Added ETag-based HTTP 304 Not Modified responses for HTML pages in release mode, reducing bandwidth by returning empty body when content hasn't changed ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.7/crates/brk_website/src/handlers.rs)) +- Compute and cache a hash-based ETag for index.html on first request, used for subsequent conditional requests ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.7/crates/brk_website/src/website.rs)) + +#### `website` +- Added upper price band (I²/R) and lower price band (R²/I) series to the price comparison chart ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.7/website/scripts/options/distribution/prices.js)) + +### Bug Fixes + +#### `brk_types` +- Fixed unrealized value calculation in cost basis distribution to compute `(spot - cost_basis) × supply` instead of `spot × supply`, correctly reflecting unrealized profit/loss per bucket ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.7/crates/brk_types/src/cost_basis_distribution.rs)) +- Fixed `Dollars * Sats` multiplication to use `i128` intermediate values, preventing overflow on large values ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.7/crates/brk_types/src/dollars.rs)) + +### Internal Changes + +#### `brk_computer` +- Moved price rounding logic and unrealized state cache from `CohortState` into `CostBasisData`, encapsulating all cost basis concerns in a single structure ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.7/crates/brk_computer/src/distribution/state/cost_basis/data.rs)) +- Added `compute_unrealized_states()` method on `CostBasisData` that combines cache management and unrealized computation in one call +- Removed `CachedUnrealizedState` from public API, making it `pub(super)` only +- Removed `range()` method from `CostBasisData` (unrealized computation now accesses the map directly) +- Added binary transform constructors (`from_block_last_and_lazy_block_last`, `from_lazy_block_last_and_block_last`, `from_binary`) across height, date, and height-derived lazy metric levels to support mixed computed/lazy binary operations + +#### `website` +- Changed shared time data type from `number[]` to `MetricData` throughout the chart system, propagating stamp metadata alongside data +- Added `lastTimeStamp` tracking to prevent redundant chart updates when time data hasn't changed + +#### `clients` +- Bumped JavaScript and Python client versions + +[View changes](https://github.com/bitcoinresearchkit/brk/compare/v0.1.6...v0.1.7) + +## [v0.1.6](https://github.com/bitcoinresearchkit/brk/releases/tag/v0.1.6) - 2026-02-05 + +### New Features + +#### `brk_types` +- Added `CostBasisDistribution` struct with pco-compressed serialization/deserialization for storing price-to-sats distributions, and a `format()` method supporting bucket aggregation and value type transformation ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.6/crates/brk_types/src/cost_basis_distribution.rs)) +- Added `CostBasisBucket` enum with 7 aggregation strategies: `raw` (no aggregation), `lin200`/`lin500`/`lin1000` (linear buckets by dollar amount), and `log10`/`log50`/`log100` (logarithmic buckets per decade) ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.6/crates/brk_types/src/cost_basis_bucket.rs)) +- Added `CostBasisValue` enum with three output modes: `supply` (BTC at each price), `realized` (USD cost basis), `unrealized` (USD at spot price) ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.6/crates/brk_types/src/cost_basis_value.rs)) +- Added `Cohort`, `CostBasisParams`, `CostBasisCohortParam`, and `CostBasisQuery` types for cost basis API path and query parameters ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.6/crates/brk_types/src/cost_basis_params.rs)) +- Added `round_to()` and `round_to_dollar()` methods on `CentsUnsigned` and `CentsUnsignedCompact` for rounding prices to N significant digits ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.6/crates/brk_types/src/cents_unsigned.rs)) +- Implemented `FromStr` for `Date` type enabling parsing from "YYYY-MM-DD" format ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.6/crates/brk_types/src/date.rs)) + +#### `brk_computer` +- Added daily cost basis snapshot writing for all, sth, and lth UTXO cohorts, persisting the merged price-to-sats distribution to disk per date for historical querying ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.6/crates/brk_computer/src/distribution/cohorts/utxo/groups.rs)) +- Added configurable price rounding for cost basis data: UTXO cohorts use 5 significant digits and address cohorts use 4 significant digits, reducing unique price points for more efficient storage and aggregation ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.6/crates/brk_computer/src/distribution/state/cohort/base.rs)) + +#### `brk_query` +- Added cost basis query methods: `cost_basis_cohorts()` to list available cohorts, `cost_basis_dates()` to list available dates per cohort, `cost_basis_distribution()` to retrieve raw data, and `cost_basis_formatted()` to get bucketed/value-transformed output ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.6/crates/brk_query/src/impl/cost_basis.rs)) + +#### `brk_server` +- Added three new API endpoints for cost basis distribution: `GET /api/metrics/cost-basis` (list cohorts), `GET /api/metrics/cost-basis/{cohort}/dates` (list dates), and `GET /api/metrics/cost-basis/{cohort}/{date}?bucket=&value=` (get distribution data) ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.6/crates/brk_server/src/api/metrics/mod.rs)) + +#### `brk_client` +- Added `get_cost_basis_cohorts()`, `get_cost_basis_dates()`, and `get_cost_basis()` methods to the Rust client for querying cost basis distributions ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.6/crates/brk_client/src/lib.rs)) + +#### `brk_bindgen` +- Added wildcard (`*`) and `Object` type mapping to `serde_json::Value` in Rust type generation ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.6/crates/brk_bindgen/src/generators/rust/types.rs)) + +### Bug Fixes + +#### `website` +- Fixed chart range restoration on Safari by wrapping the range-set logic in `requestAnimationFrame` for browser compatibility ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.6/website/scripts/chart/index.js)) + +### Internal Changes + +#### `brk_computer` +- Reorganized cost basis state storage: height-based snapshots now stored under `by_height/` subdirectory, renamed `cost_basis_data` module to `data` +- Moved pco compression dependency from `brk_computer` to `brk_types` for reuse across crates +- Refactored the K-way merge in aggregate percentile computation to collect merged entries with price deduplication during the merge pass + +#### `brk_error` +- Added `pco` feature flag and `Pco` error variant for pco compression errors ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.6/crates/brk_error/src/lib.rs)) + +#### `workspace` +- Added `*.csv` to `.gitignore` + +#### `clients` +- Bumped JavaScript and Python client versions + +[View changes](https://github.com/bitcoinresearchkit/brk/compare/v0.1.5...v0.1.6) + +## [v0.1.5](https://github.com/bitcoinresearchkit/brk/releases/tag/v0.1.5) - 2026-02-05 + +### New Features + +#### `website` +- Added in-memory data cache for chart metric and time data, enabling instant visual feedback when switching between chart indexes without re-fetching from the server ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.5/website/scripts/chart/index.js)) +- Implemented cache-first loading strategy: cached data is rendered immediately while fresh data is fetched in the background, making index switching feel instantaneous + +### Bug Fixes + +#### `website` +- Fixed URL range being overwritten during chart initialization by adding an `initialLoadComplete` guard that prevents range persistence until the first data load completes, and resets on rebuild ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.5/website/scripts/chart/index.js)) +- Fixed temporal dead zone (TDZ) error by moving zoom handler registration (`onZoomChange.add`) to after series creation instead of before it ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.1.5/website/scripts/chart/index.js)) + +### Internal Changes + +#### `website` +- Simplified showLine visibility calculation to use the already-tracked `visibleBarsCount` variable instead of re-reading the visible logical range from the chart + +#### `clients` +- Bumped JavaScript and Python client versions + +[View changes](https://github.com/bitcoinresearchkit/brk/compare/v0.1.4...v0.1.5) + ## [v0.1.4](https://github.com/bitcoinresearchkit/brk/releases/tag/v0.1.4) - 2026-02-04 ### Breaking Changes diff --git a/modules/brk-client/index.js b/modules/brk-client/index.js index 96e6c50b6..93d20688c 100644 --- a/modules/brk-client/index.js +++ b/modules/brk-client/index.js @@ -5005,7 +5005,7 @@ function createRatioPattern2(client, acc) { * @extends BrkClientBase */ class BrkClient extends BrkClientBase { - VERSION = "v0.1.7"; + VERSION = "v0.1.9"; INDEXES = /** @type {const} */ ([ "dateindex", diff --git a/modules/brk-client/package.json b/modules/brk-client/package.json index f47f2d9ae..f5447d19f 100644 --- a/modules/brk-client/package.json +++ b/modules/brk-client/package.json @@ -34,5 +34,5 @@ "url": "git+https://github.com/bitcoinresearchkit/brk.git" }, "type": "module", - "version": "0.1.7" + "version": "0.1.9" } diff --git a/packages/brk_client/brk_client/__init__.py b/packages/brk_client/brk_client/__init__.py index 47b43b31d..18522278d 100644 --- a/packages/brk_client/brk_client/__init__.py +++ b/packages/brk_client/brk_client/__init__.py @@ -4423,7 +4423,7 @@ class MetricsTree: class BrkClient(BrkClientBase): """Main BRK client with metrics tree and API methods.""" - VERSION = "v0.1.7" + VERSION = "v0.1.9" INDEXES = [ "dateindex", diff --git a/packages/brk_client/pyproject.toml b/packages/brk_client/pyproject.toml index bba2798de..c0c1e9274 100644 --- a/packages/brk_client/pyproject.toml +++ b/packages/brk_client/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "brk-client" -version = "0.1.7" +version = "0.1.9" description = "Python client for the Bitcoin Research Kit" readme = "README.md" requires-python = ">=3.9"