changelog + website: fixes

This commit is contained in:
nym21
2026-03-27 12:50:35 +01:00
parent 17570e12b8
commit 041652d85d
15 changed files with 130 additions and 218 deletions

View File

@@ -8195,7 +8195,7 @@ pub struct BrkClient {
impl BrkClient {
/// Client version.
pub const VERSION: &'static str = "v0.2.2";
pub const VERSION: &'static str = "v0.2.3";
/// Create a new client with the given base URL.
pub fn new(base_url: impl Into<String>) -> Self {

View File

@@ -4,6 +4,86 @@ All notable changes to the Bitcoin Research Kit (BRK) project will be documented
> *This changelog was generated by Claude Code*
## [v0.2.3](https://github.com/bitcoinresearchkit/brk/releases/tag/v0.2.3) - 2026-03-26
### New Features
#### `brk_computer`
- Added new `investing` module with complete Dollar-Cost Averaging (DCA) and lump-sum investment analysis — computes DCA stack (cumulative sats purchased at $100/day), cost basis, returns, and CAGR by rolling period (1w, 1m, 3m, 6m, 1y through 10y); lump-sum stack and returns by rolling period; and DCA stack, cost basis, and returns by year class (2015 through 2026). Extracted from `market::dca` into a standalone top-level module with parallel import and compute ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/crates/brk_computer/src/investing/mod.rs))
- Added `RealizedEnvelope` indicator that computes the tightest percentile bounds across 10 pricing models (realized price, investor price, STH/LTH variants, cointime vaultedness/activity/true market mean/cointime price), producing 8 envelope price bands (0.5th through 99.5th percentile), a zone index (-4 to +4) based on spot price position relative to envelope bands, and a composite score (-40 to +40) summing band crossings across all models ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/crates/brk_computer/src/indicators/realized_envelope.rs))
- Expanded `RatioPerBlockPercentiles` from 6 to 8 percentile bands, adding 0.5th and 99.5th percentiles alongside the existing 1st/2nd/5th/95th/98th/99th — `ExpandingPercentiles` Fenwick tree computation also widened from 6-quantile to 8-quantile output ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/crates/brk_computer/src/internal/per_block/ratio/percentiles.rs))
- Consolidated timestamp data into a new `indexes::timestamp::Timestamps` struct — moved `timestamp_monotonic`, `date`, and per-resolution timestamp lookups from `blocks::time::Vecs` into the indexes module, making timestamp data accessible without depending on the blocks module ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/crates/brk_computer/src/indexes/timestamp.rs))
#### `brk_indexer`
- Added `take_all_pending_ingests()` to batch all KV store puts/deletes into closures that can be executed on a background thread, enabling the indexer to hand off fjall store commits to `run_bg()` instead of blocking the main indexing loop ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/crates/brk_indexer/src/stores.rs))
- Extracted `stamped_write()` from `flush()` so vec stamping can happen on the main thread while compaction and store ingests run in the background ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/crates/brk_indexer/src/vecs/mod.rs))
#### `brk_store`
- Added `take_pending_ingest()` method that drains buffered puts/deletes and returns a `Send` closure for background ingestion into the fjall keyspace ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/crates/brk_store/src/lib.rs))
#### `website`
- Added range preset buttons (1w, 1m, 3m, 6m, 1y, 4y, 8y, YTD, all) to the chart that automatically select the appropriate sub-day resolution index (30min through 1w) and scroll the visible range to that time window ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/website/scripts/chart/index.js))
- Added value-dependent coloring support (`colorFn`) for histogram and baseline chart series, enabling per-bar colors based on data values ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/website/scripts/chart/index.js))
- Added "Realized Envelope" chart to market indicators showing 8-level percentile price bands as dashed lines, a color-coded zone index histogram, and a score baseline ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/website/scripts/options/market.js))
- Added `percentileBands()` and `priceBands()` shared helpers for displaying 8-level percentile bands with dedicated colors per level, reusable across ratio and price chart types ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/website/scripts/options/shared.js))
- Added subtle grid lines to charts using a new `offBorder` color variable ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/website/scripts/chart/index.js))
### Internal Changes
#### `brk_computer`
- Switched all module `compute()` methods to use `db.run_bg()` for background compaction instead of synchronous `db.compact()`, and added `db.sync_bg_tasks()` at compute entry to await prior background work — applies to blocks, cointime, distribution, indicators, inputs, investing, market, mining, outputs, pools, positions, prices, scripts, supply, and transactions ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/crates/brk_computer/src/blocks/compute.rs))
- Removed `market::dca` sub-module — DCA types (`ByDcaClass`, `ByDcaPeriod`, `ByDcaCagr`) and computation logic moved to the new top-level `investing` module; `market::returns` now imports `ByDcaPeriod` from `investing` ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/crates/brk_computer/src/market/mod.rs))
- Removed `blocks::time` sub-module — `timestamp_monotonic` compute logic and per-resolution timestamp imports relocated to `indexes::timestamp::Timestamps` ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/crates/brk_computer/src/blocks/mod.rs))
- Changed `lookback::compute()` to take `&indexes::Vecs` instead of `&time::Vecs`, sourcing monotonic timestamps from the indexes module ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/crates/brk_computer/src/blocks/lookback.rs))
- Changed `market::compute()` parameter order: now takes `(prices, indexes, blocks)` instead of `(indexes, prices, blocks)` ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/crates/brk_computer/src/market/compute.rs))
#### `brk_indexer`
- Moved indexer store ingest and fjall persist to background via `run_bg()`, running compaction, store commit, and fjall `SyncData` persist concurrently with the next indexing batch ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/crates/brk_indexer/src/lib.rs))
#### `brk_client`
- Added `Pct0Pct1Pct2Pct5Pct95Pct98Pct99Pattern` replacing `Pct1Pct2Pct5Pct95Pct98Pct99Pattern` to include the new 0.5th and 99.5th percentile bands ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/crates/brk_client/src/lib.rs))
- Added `SeriesTree_Investing` with full period/class sub-trees for DCA stack, cost basis, returns, CAGR, and lump-sum series ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/crates/brk_client/src/lib.rs))
- Added `SeriesTree_Indicators_RealizedEnvelope` with percentile price bands, index, and score series ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/crates/brk_client/src/lib.rs))
- Added `SeriesTree_Indexes_Timestamp` with monotonic and per-resolution timestamp series ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/crates/brk_client/src/lib.rs))
- Removed `date` and `timestamp_monotonic` from `SeriesTree_Blocks_Time`, simplified to only expose `timestamp` as a per-resolution pattern ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/crates/brk_client/src/lib.rs))
#### `brk_query`
- Updated all mining query endpoints (`day1_iter`, `difficulty`, `epochs`, `hashrate`) and series timestamp resolution to read from `indexes.timestamp` instead of `blocks.time.timestamp` ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/crates/brk_query/src/impl/series.rs))
#### `website`
- Refactored investing chart options to use the new `investing` tree path instead of `market.dca` ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/website/scripts/options/investing.js))
- Added dedicated percentile color palette (`_0_5` through `_99_5`) replacing the previous 6-color scheme with 8 distinct colors ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/website/scripts/utils/colors.js))
- Added `createRatioChart()` and `groupedWindowsCumulative()` shared chart builders for reuse across ratio-based chart options ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/website/scripts/options/shared.js))
#### `docker`
- Switched health check from `curl http://localhost:3110/health` to `pgrep -x brk`, replacing `curl` package dependency with `procps` and reducing start period from 60s to 10s ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/docker/docker-compose.yml))
#### `workspace`
- Bumped Rust toolchain from 1.94.0 to 1.94.1 ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/rust-toolchain.toml))
- Bumped `quickmatch-js` from 0.4.0 to 0.4.1 ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.3/modules/quickmatch-js/0.4.1/src/index.js))
[View changes](https://github.com/bitcoinresearchkit/brk/compare/v0.2.2...v0.2.3)
## [v0.2.2](https://github.com/bitcoinresearchkit/brk/releases/tag/v0.2.2) - 2026-03-23
### New Features
#### `website`
- Created a comprehensive LLM-readable API reference (`llms-full.txt`) documenting every endpoint with curl examples, response shapes, parameter descriptions, and series categories — enabling LLM agents to discover and use the BRK API via the [llms.txt standard](https://llmstxt.org/) ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.2/website/llms-full.txt))
- Rewrote `llms.txt` from a minimal overview into a structured quick-start guide with live links to key endpoints (search, series data, blocks, transactions, addresses, fees, live price) and links to the full reference, OpenAPI specs, and interactive docs ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.2/website/llms.txt))
- Added `llms-full.txt` to `robots.txt` as a sitemap entry so crawlers and LLM agents can discover it ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.2/website/robots.txt))
#### `brk_server`
- Added Open Graph and Twitter Card meta tags to the Scalar API documentation page, providing proper title, description, and image for social media link previews ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.2/crates/brk_server/src/api/scalar.html))
- Renamed the API docs page title from "BRK API" to "BRK API — Bitcoin Research Kit" with a richer meta description emphasizing the free, no-auth nature of the API ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.2/crates/brk_server/src/api/scalar.html))
### Internal Changes
#### `workspace`
- Re-enabled `cargo build --workspace --release` in the release script (was previously commented out) ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.2/scripts/quick-release.sh))
[View changes](https://github.com/bitcoinresearchkit/brk/compare/v0.2.1...v0.2.2)
## [v0.2.1](https://github.com/bitcoinresearchkit/brk/releases/tag/v0.2.1) - 2026-03-23
### Breaking Changes

View File

@@ -6381,7 +6381,7 @@ function createTransferPattern(client, acc) {
* @extends BrkClientBase
*/
class BrkClient extends BrkClientBase {
VERSION = "v0.2.2";
VERSION = "v0.2.3";
INDEXES = /** @type {const} */ ([
"minute10",

View File

@@ -40,5 +40,5 @@
"url": "git+https://github.com/bitcoinresearchkit/brk.git"
},
"type": "module",
"version": "0.2.2"
"version": "0.2.3"
}

View File

@@ -5679,7 +5679,7 @@ class SeriesTree:
class BrkClient(BrkClientBase):
"""Main BRK client with series tree and API methods."""
VERSION = "v0.2.2"
VERSION = "v0.2.3"
INDEXES = [
"minute10",

View File

@@ -1,6 +1,6 @@
[project]
name = "brk-client"
version = "0.2.2"
version = "0.2.3"
description = "Bitcoin on-chain analytics client — thousands of metrics, block explorer, and address index"
readme = "README.md"
requires-python = ">=3.9"

3
website/.gitignore vendored
View File

@@ -1,5 +1,4 @@
*/**/*.md
!scripts/**/_*.js
*_old.js
_*.js
dump-*
*dump*

View File

@@ -248,5 +248,4 @@
*
* Generic tree node type for walking
* @typedef {AnySeriesPattern | Record<string, unknown>} TreeNode
*
*/

View File

@@ -4,7 +4,6 @@ import {
HistogramSeries,
LineSeries,
BaselineSeries,
// } from "../modules/lightweight-charts/5.1.0/dist/lightweight-charts.standalone.development.mjs";
} from "../modules/lightweight-charts/5.1.0/dist/lightweight-charts.standalone.production.mjs";
import { createLegend, createSeriesLegend } from "./legend.js";
import { capture } from "./capture.js";
@@ -83,17 +82,18 @@ function getRangePresets() {
const m = now.getUTCMonth();
const d = now.getUTCDate();
/** @param {number} months @param {number} [days] */
const ago = (months, days = 0) => Math.floor(Date.UTC(y, m - months, d - days) / 1000);
const ago = (months, days = 0) =>
Math.floor(Date.UTC(y, m - months, d - days) / 1000);
/** @type {RangePreset[]} */
const presets = [
{ label: "1w", index: /** @type {IndexLabel} */ ("30mn"), from: ago(0, 7) },
{ label: "1m", index: /** @type {IndexLabel} */ ("1h"), from: ago(1) },
{ label: "3m", index: /** @type {IndexLabel} */ ("4h"), from: ago(3) },
{ label: "6m", index: /** @type {IndexLabel} */ ("12h"), from: ago(6) },
{ label: "1y", index: /** @type {IndexLabel} */ ("1d"), from: ago(12) },
{ label: "4y", index: /** @type {IndexLabel} */ ("3d"), from: ago(48) },
{ label: "8y", index: /** @type {IndexLabel} */ ("1w"), from: ago(96) },
{ label: "1m", index: /** @type {IndexLabel} */ ("1h"), from: ago(1) },
{ label: "3m", index: /** @type {IndexLabel} */ ("4h"), from: ago(3) },
{ label: "6m", index: /** @type {IndexLabel} */ ("12h"), from: ago(6) },
{ label: "1y", index: /** @type {IndexLabel} */ ("1d"), from: ago(12) },
{ label: "4y", index: /** @type {IndexLabel} */ ("3d"), from: ago(48) },
{ label: "8y", index: /** @type {IndexLabel} */ ("1w"), from: ago(96) },
];
const ytdFrom = Math.floor(Date.UTC(y, 0, 1) / 1000);
@@ -105,7 +105,11 @@ function getRangePresets() {
from: ytdFrom,
});
presets.push({ label: "all", index: /** @type {IndexLabel} */ ("1w"), from: -Infinity });
presets.push({
label: "all",
index: /** @type {IndexLabel} */ ("1w"),
from: -Infinity,
});
return presets;
}
@@ -445,7 +449,11 @@ export function createChart({ parent, brk, fitContent }) {
if (this.isAllHidden(paneIndex)) {
const collapsedHeight = paneIndex === 0 ? 32 : 64;
const chartHeight = ichart.chartElement().clientHeight;
pane.setStretchFactor(chartHeight > 0 ? collapsedHeight / (chartHeight - collapsedHeight) : 0);
pane.setStretchFactor(
chartHeight > 0
? collapsedHeight / (chartHeight - collapsedHeight)
: 0,
);
} else {
pane.setStretchFactor(1);
}

View File

@@ -62,6 +62,10 @@
padding: 0 var(--main-padding);
padding-top: 0.375rem;
@media (pointer: coarse) {
pointer-events: auto;
}
> * {
pointer-events: auto;
}
@@ -255,11 +259,11 @@
button {
color: var(--off-color);
padding: 0.375rem;
margin: -0.375rem 0.25rem;
padding: 0.375rem 0.5rem;
margin: -0.375rem 0;
&:first-of-type {
margin-left: -0.25rem;
margin-left: -0.5rem;
}
}
}

View File

@@ -55,11 +55,7 @@ aside {
flex: 1;
@media (max-width: 767px) {
padding-bottom: calc(var(--main-padding) + 1.5rem);
html[data-display="standalone"] & {
padding-bottom: calc(var(--main-padding) + 2rem);
}
padding-bottom: calc(var(--main-padding) + 0.5rem);
}
@media (min-width: 768px) {
@@ -95,16 +91,23 @@ button {
}
h1 {
font-size: var(--font-size-xl);
font-size: 2rem;
line-height: var(--line-height-xl);
font-weight: 300;
}
h3 {
font-size: var(--font-size-lg);
font-size: 1.5rem;
line-height: var(--line-height-lg);
}
h1,
h2,
h3 {
font-family: instrument;
letter-spacing: 0.05rem;
font-weight: 400;
}
html {
background-color: var(--background-color);
color: var(--color);
@@ -115,6 +118,8 @@ html {
input {
width: 100%;
padding: 0;
letter-spacing: inherit;
&::placeholder {
color: var(--off-color);
@@ -194,6 +199,7 @@ select {
flex-shrink: 0;
width: 100%;
text-transform: uppercase;
color: var(--color);
}
:is(input, select):focus-visible {

View File

@@ -29,7 +29,7 @@ main {
background-image: linear-gradient(
to bottom,
transparent,
var(--background-color) 90%,
var(--background-color) 85%,
var(--background-color)
);
}
@@ -96,12 +96,6 @@ main {
);
}
@media (max-width: 767px) {
html[data-display="standalone"] & {
margin-bottom: calc(var(--main-padding) + 0.5rem);
}
}
> fieldset {
display: flex;
gap: 1.25rem;

View File

@@ -52,7 +52,7 @@
h1 {
font-size: 2rem;
letter-spacing: 0.075rem;
letter-spacing: 0.05rem;
text-wrap: nowrap;
}
}

View File

@@ -49,184 +49,3 @@ h5,
h6 {
text-wrap: balance;
}
/**,
::after,
::before,
::backdrop,
::file-selector-button {
box-sizing: border-box;
margin: 0;
padding: 0;
border: 0 solid;
}
html,
:host {
line-height: 1.5;
-webkit-text-size-adjust: 100%;
tab-size: 4;
font-family:
"Lilex", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
"Liberation Mono", "Courier New", monospace;
-webkit-tap-highlight-color: transparent;
}
body {
line-height: inherit;
}
hr {
height: 0;
color: inherit;
border-top-width: 1px;
}
abbr:where([title]) {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-size: inherit;
font-weight: inherit;
}
a {
color: inherit;
}
b,
strong {
font-weight: bolder;
}
code,
kbd,
samp,
pre {
font-family:
var(--default-mono-font-family), ui-monospace, SFMono-Regular, Menlo,
Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
font-feature-settings: var(--default-mono-font-feature-settings, normal);
font-variation-settings: var(--default-mono-font-variation-settings, normal);
font-size: 1em;
}
small {
font-size: 80%;
}
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
table {
text-indent: 0;
border-color: inherit;
border-collapse: collapse;
}
button,
input,
optgroup,
select,
textarea,
::file-selector-button {
font: inherit;
font-feature-settings: inherit;
font-variation-settings: inherit;
letter-spacing: inherit;
color: inherit;
background: transparent;
text-transform: inherit;
}
button,
input:where([type="button"], [type="reset"], [type="submit"]),
::file-selector-button {
appearance: button;
}
:-moz-focusring {
outline: auto;
}
:-moz-ui-invalid {
box-shadow: none;
}
progress {
vertical-align: baseline;
}
::-webkit-inner-spin-button,
::-webkit-outer-spin-button {
height: auto;
}
::-webkit-search-decoration {
-webkit-appearance: none;
}
summary {
display: list-item;
}
ol,
ul,
menu {
list-style: none;
}
textarea {
resize: vertical;
}
::placeholder {
opacity: 1;
color: color-mix(in srgb, currentColor 50%, transparent);
}
:disabled {
cursor: default;
}
img,
svg,
video,
canvas,
audio,
iframe,
embed,
object {
display: block;
vertical-align: middle;
}
img,
video {
max-width: 100%;
height: auto;
}
[hidden] {
display: none !important;
}*/

View File

@@ -45,6 +45,9 @@
--line-height-xl: calc(1.75 / 1.25);
--main-padding: 2rem;
/*@media (max-width: 767px) {
--main-padding: 1.5rem;
}*/
--negative-main-padding: calc(-1 * var(--main-padding));
--font-weight-base: 400;
--default-main-width: 25rem;