mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-06-08 06:01:57 -07:00
heatmaps: part 13
This commit is contained in:
@@ -9865,40 +9865,40 @@ impl BrkClient {
|
||||
self.base.get_json(&format!("/api/oracle/price"))
|
||||
}
|
||||
|
||||
/// Live EMA histogram
|
||||
/// Live payment output histogram
|
||||
///
|
||||
/// Smoothed round-dollar payment histogram at the live tip: the committed EMA with the forming mempool block blended in. A flat array of log-scale bins.
|
||||
/// Live smoothed histogram of oracle-eligible payment outputs, binned by output value on the oracle log scale. It combines the committed oracle window with the forming mempool block. A flat array of log-scale bins.
|
||||
///
|
||||
/// Endpoint: `GET /api/oracle/histogram/ema/live`
|
||||
pub fn get_oracle_histogram_ema_live(&self) -> Result<Vec<i64>> {
|
||||
self.base.get_json(&format!("/api/oracle/histogram/ema/live"))
|
||||
/// Endpoint: `GET /api/oracle/histogram/payments/live`
|
||||
pub fn get_oracle_histogram_payments_live(&self) -> Result<Vec<i64>> {
|
||||
self.base.get_json(&format!("/api/oracle/histogram/payments/live"))
|
||||
}
|
||||
|
||||
/// EMA histogram at height or day
|
||||
/// Payment output histogram at height or day
|
||||
///
|
||||
/// Smoothed round-dollar payment histogram for a confirmed point: a block height (`840000`) gives that block's EMA, a calendar date (`YYYY-MM-DD`) gives the average of that day's per-block EMAs. A flat array of log-scale bins.
|
||||
/// Smoothed histogram of oracle-eligible payment outputs for a confirmed point. A block height (`840000`) gives that block's oracle payment histogram; a calendar date (`YYYY-MM-DD`) gives the average of that day's per-block payment histograms. A flat array of log-scale bins.
|
||||
///
|
||||
/// Endpoint: `GET /api/oracle/histogram/ema/{point}`
|
||||
pub fn get_oracle_histogram_ema(&self, point: &str) -> Result<Vec<i64>> {
|
||||
self.base.get_json(&format!("/api/oracle/histogram/ema/{point}"))
|
||||
/// Endpoint: `GET /api/oracle/histogram/payments/{point}`
|
||||
pub fn get_oracle_histogram_payments(&self, point: &str) -> Result<Vec<i64>> {
|
||||
self.base.get_json(&format!("/api/oracle/histogram/payments/{point}"))
|
||||
}
|
||||
|
||||
/// Live raw histogram
|
||||
/// Live output value histogram
|
||||
///
|
||||
/// Unfiltered output histogram for the forming mempool block: every live output binned by value, with none of the round-dollar payment filters applied. A flat array of log-scale bins, all zero when no mempool is configured.
|
||||
/// Live unfiltered output value histogram for the forming mempool block. Every live output is binned by value on the oracle log scale; no oracle payment filters are applied. A flat array of log-scale bins, all zero when no mempool is configured.
|
||||
///
|
||||
/// Endpoint: `GET /api/oracle/histogram/raw/live`
|
||||
pub fn get_oracle_histogram_raw_live(&self) -> Result<Vec<i64>> {
|
||||
self.base.get_json(&format!("/api/oracle/histogram/raw/live"))
|
||||
/// Endpoint: `GET /api/oracle/histogram/outputs/live`
|
||||
pub fn get_oracle_histogram_outputs_live(&self) -> Result<Vec<i64>> {
|
||||
self.base.get_json(&format!("/api/oracle/histogram/outputs/live"))
|
||||
}
|
||||
|
||||
/// Raw histogram at height or day
|
||||
/// Output value histogram at height or day
|
||||
///
|
||||
/// Unfiltered output histogram for a confirmed point: a block height (`840000`) gives that block's outputs, coinbase included, binned by value with no payment filtering; a calendar date (`YYYY-MM-DD`) sums every block that day. A flat array of log-scale bins.
|
||||
/// Unfiltered output value histogram for a confirmed point. A block height (`840000`) gives every output in that block, coinbase included, binned by value on the oracle log scale; a calendar date (`YYYY-MM-DD`) sums every block that day. A flat array of log-scale bins.
|
||||
///
|
||||
/// Endpoint: `GET /api/oracle/histogram/raw/{point}`
|
||||
pub fn get_oracle_histogram_raw(&self, point: &str) -> Result<Vec<i64>> {
|
||||
self.base.get_json(&format!("/api/oracle/histogram/raw/{point}"))
|
||||
/// Endpoint: `GET /api/oracle/histogram/outputs/{point}`
|
||||
pub fn get_oracle_histogram_outputs(&self, point: &str) -> Result<Vec<i64>> {
|
||||
self.base.get_json(&format!("/api/oracle/histogram/outputs/{point}"))
|
||||
}
|
||||
|
||||
/// Txid by index
|
||||
|
||||
@@ -3,8 +3,8 @@ use std::ops::Range;
|
||||
use brk_error::Result;
|
||||
use brk_indexer::{Indexer, Lengths};
|
||||
use brk_oracle::{
|
||||
Config, HistogramRaw, Oracle, START_HEIGHT_FAST, START_HEIGHT_SLOW, bin_to_cents, cents_to_bin,
|
||||
for_each_round_dollar_bin,
|
||||
bin_to_cents, cents_to_bin, for_each_round_dollar_bin, Config, HistogramRaw, Oracle,
|
||||
START_HEIGHT_FAST, START_HEIGHT_SLOW,
|
||||
};
|
||||
use brk_types::{Cents, OutputType, Sats, TxIndex, TxOutIndex};
|
||||
use tracing::info;
|
||||
@@ -115,13 +115,7 @@ impl Vecs {
|
||||
let seed_bin = cents_to_bin(prev_cents.inner() as f64);
|
||||
let warmup = config.window_size.min(committed - START_HEIGHT_SLOW);
|
||||
let mut oracle = Oracle::from_checkpoint(seed_bin, config, |o| {
|
||||
Self::feed_blocks_with(
|
||||
o,
|
||||
indexer,
|
||||
(committed - warmup)..committed,
|
||||
None,
|
||||
|_, _, _| {},
|
||||
);
|
||||
Self::feed_blocks_for_warmup(o, indexer, (committed - warmup)..committed, None);
|
||||
});
|
||||
|
||||
let num_new = total_heights - committed;
|
||||
@@ -136,7 +130,12 @@ impl Vecs {
|
||||
let mut ref_bins = Vec::with_capacity(num_new);
|
||||
if committed < START_HEIGHT_FAST {
|
||||
let slow_end = START_HEIGHT_FAST.min(total_heights);
|
||||
ref_bins.extend(Self::feed_blocks(&mut oracle, indexer, committed..slow_end, None));
|
||||
ref_bins.extend(Self::feed_blocks(
|
||||
&mut oracle,
|
||||
indexer,
|
||||
committed..slow_end,
|
||||
None,
|
||||
));
|
||||
if slow_end == START_HEIGHT_FAST {
|
||||
oracle.reconfigure(Config::default());
|
||||
}
|
||||
@@ -197,6 +196,16 @@ impl Vecs {
|
||||
ref_bins
|
||||
}
|
||||
|
||||
/// Feed blocks into an Oracle when callers only need the warmed EMA/window state.
|
||||
pub fn feed_blocks_for_warmup<IM: StorageMode>(
|
||||
oracle: &mut Oracle,
|
||||
indexer: &Indexer<IM>,
|
||||
range: Range<usize>,
|
||||
cap: Option<&Lengths>,
|
||||
) {
|
||||
Self::feed_blocks_with(oracle, indexer, range, cap, |_, _, _| {});
|
||||
}
|
||||
|
||||
/// Feed a range of blocks into an Oracle and call `on_block` after each
|
||||
/// processed block. This lets callers observe derived state such as EMA
|
||||
/// without duplicating the histogram extraction path.
|
||||
|
||||
@@ -66,7 +66,7 @@ impl Config {
|
||||
|
||||
/// Split a block range into sub-ranges with a single EMA configuration.
|
||||
pub fn segments_for_range(range: Range<usize>) -> impl Iterator<Item = Range<usize>> {
|
||||
let split = START_HEIGHT_FAST.clamp(range.start, range.end);
|
||||
let split = START_HEIGHT_FAST.max(range.start).min(range.end);
|
||||
[range.start..split, split..range.end]
|
||||
.into_iter()
|
||||
.filter(|range| !range.is_empty())
|
||||
|
||||
@@ -18,30 +18,32 @@ impl Query {
|
||||
Ok(self.live_oracle()?.price_dollars())
|
||||
}
|
||||
|
||||
/// Smoothed EMA histogram at the live tip, quantized for the wire.
|
||||
pub fn live_histogram_ema(&self) -> Result<HistogramEmaCompact> {
|
||||
/// Smoothed payment output histogram at the live tip, quantized for the wire.
|
||||
pub fn live_payment_histogram(&self) -> Result<HistogramEmaCompact> {
|
||||
Ok(self.live_oracle()?.ema().to_compact())
|
||||
}
|
||||
|
||||
/// Smoothed EMA histogram for a confirmed `height`, deterministically
|
||||
/// Smoothed payment output histogram for a confirmed `height`, deterministically
|
||||
/// reconstructed by replaying the window ending at `height`. EMA values are
|
||||
/// seed-independent, so the result is exact.
|
||||
pub fn confirmed_histogram_ema(&self, height: usize) -> Result<HistogramEmaCompact> {
|
||||
pub fn confirmed_payment_histogram(&self, height: usize) -> Result<HistogramEmaCompact> {
|
||||
let safe = self.check_histogram_height(height)?;
|
||||
Ok(self.ema_oracle_at(height, &safe)?.ema().to_compact())
|
||||
}
|
||||
|
||||
/// Smoothed EMA histogram for a calendar `day`: the bin-by-bin average of
|
||||
/// Smoothed payment output histogram for a calendar `day`: the bin-by-bin average of
|
||||
/// every confirmed block's per-block EMA. Each block's EMA is reconstructed
|
||||
/// independently (seed-independent, so exact); averaging keeps the result an
|
||||
/// intensive per-block rate rather than letting a busy day dominate.
|
||||
pub fn confirmed_histogram_ema_day(&self, day: Day1) -> Result<HistogramEmaCompact> {
|
||||
pub fn confirmed_payment_histogram_day(&self, day: Day1) -> Result<HistogramEmaCompact> {
|
||||
let safe = self.safe_lengths();
|
||||
let range = self.day_block_range(day, &safe)?;
|
||||
Ok(self.average_histogram_ema_range(range, &safe)?.to_compact())
|
||||
Ok(self
|
||||
.average_payment_histogram_range(range, &safe)?
|
||||
.to_compact())
|
||||
}
|
||||
|
||||
fn average_histogram_ema_range(
|
||||
fn average_payment_histogram_range(
|
||||
&self,
|
||||
range: Range<usize>,
|
||||
safe: &Lengths,
|
||||
@@ -72,7 +74,7 @@ impl Query {
|
||||
/// Unfiltered per-bin output counts at the live tip: every forming-block
|
||||
/// mempool output binned by value, with none of the round-dollar payment
|
||||
/// filters applied. Zeros when no mempool is configured.
|
||||
pub fn live_histogram_raw(&self) -> Result<HistogramRaw> {
|
||||
pub fn live_output_histogram(&self) -> Result<HistogramRaw> {
|
||||
Ok(match self.mempool() {
|
||||
Some(mempool) => mempool.live_raw_histogram(),
|
||||
None => HistogramRaw::zeros(),
|
||||
@@ -81,18 +83,18 @@ impl Query {
|
||||
|
||||
/// Unfiltered per-bin output counts for a confirmed `height`: every output
|
||||
/// in the block binned by value, with no payment filtering.
|
||||
pub fn confirmed_histogram_raw(&self, height: usize) -> Result<HistogramRaw> {
|
||||
pub fn confirmed_output_histogram(&self, height: usize) -> Result<HistogramRaw> {
|
||||
let safe = self.check_histogram_height(height)?;
|
||||
Ok(self.raw_histogram_for_blocks(height..height + 1, &safe))
|
||||
Ok(self.output_histogram_for_blocks(height..height + 1, &safe))
|
||||
}
|
||||
|
||||
/// Unfiltered per-bin output counts for a calendar `day`: every block's raw
|
||||
/// Unfiltered per-bin output counts for a calendar `day`: every block's output
|
||||
/// histogram summed bin-by-bin. Raw counts are additive, so the day total is
|
||||
/// just the sum across its confirmed blocks.
|
||||
pub fn confirmed_histogram_raw_day(&self, day: Day1) -> Result<HistogramRaw> {
|
||||
pub fn confirmed_output_histogram_day(&self, day: Day1) -> Result<HistogramRaw> {
|
||||
let safe = self.safe_lengths();
|
||||
let range = self.day_block_range(day, &safe)?;
|
||||
Ok(self.raw_histogram_for_blocks(range, &safe))
|
||||
Ok(self.output_histogram_for_blocks(range, &safe))
|
||||
}
|
||||
|
||||
/// The live tip oracle: the cached committed base, with the forming block's
|
||||
@@ -124,7 +126,14 @@ impl Query {
|
||||
return Ok(oracle);
|
||||
}
|
||||
|
||||
let last = self.computer().prices.spot.cents.height.len().saturating_sub(1);
|
||||
let last = self
|
||||
.computer()
|
||||
.prices
|
||||
.spot
|
||||
.cents
|
||||
.height
|
||||
.len()
|
||||
.saturating_sub(1);
|
||||
let seed_bin = self.seed_bin_at(last)?;
|
||||
let oracle = Arc::new(self.warm_oracle(seed_bin, height.to_usize(), &safe));
|
||||
|
||||
@@ -150,7 +159,7 @@ impl Query {
|
||||
let config = Config::for_height(end.saturating_sub(1));
|
||||
let start = end.saturating_sub(config.window_size);
|
||||
Oracle::from_checkpoint(seed_bin, config, |o| {
|
||||
PricesVecs::feed_blocks_with(o, self.indexer(), start..end, Some(safe), |_, _, _| {});
|
||||
PricesVecs::feed_blocks_for_warmup(o, self.indexer(), start..end, Some(safe));
|
||||
})
|
||||
}
|
||||
|
||||
@@ -222,7 +231,7 @@ impl Query {
|
||||
/// coinbase included, binned by value via `sats_to_bin` with no payment
|
||||
/// filtering. Raw counts are additive, so a day can be read as one output
|
||||
/// range instead of one block at a time.
|
||||
fn raw_histogram_for_blocks(&self, range: Range<usize>, safe: &Lengths) -> HistogramRaw {
|
||||
fn output_histogram_for_blocks(&self, range: Range<usize>, safe: &Lengths) -> HistogramRaw {
|
||||
let indexer = self.indexer();
|
||||
let total_outputs = safe.txout_index.to_usize();
|
||||
let collect_end = (range.end + 1).min(safe.height.to_usize());
|
||||
|
||||
@@ -43,23 +43,24 @@ impl OracleRoutes for ApiRouter<AppState> {
|
||||
),
|
||||
)
|
||||
.api_route(
|
||||
"/api/oracle/histogram/ema/live",
|
||||
"/api/oracle/histogram/payments/live",
|
||||
get_with(
|
||||
async |uri: Uri, headers: HeaderMap, _: Empty, State(state): State<AppState>| {
|
||||
state
|
||||
.respond_json(&headers, state.mempool_strategy(), &uri, |q| {
|
||||
q.live_histogram_ema()
|
||||
q.live_payment_histogram()
|
||||
})
|
||||
.await
|
||||
},
|
||||
|op| {
|
||||
op.id("get_oracle_histogram_ema_live")
|
||||
op.id("get_oracle_histogram_payments_live")
|
||||
.oracle_tag()
|
||||
.summary("Live EMA histogram")
|
||||
.summary("Live payment output histogram")
|
||||
.description(
|
||||
"Smoothed round-dollar payment histogram at the live tip: the \
|
||||
committed EMA with the forming mempool block blended in. \
|
||||
A flat array of log-scale bins.",
|
||||
"Live smoothed histogram of oracle-eligible payment outputs, binned \
|
||||
by output value on the oracle log scale. It combines the committed \
|
||||
oracle window with the forming mempool block. A flat array of \
|
||||
log-scale bins.",
|
||||
)
|
||||
.json_response::<HistogramEmaCompact>()
|
||||
.not_modified()
|
||||
@@ -68,7 +69,7 @@ impl OracleRoutes for ApiRouter<AppState> {
|
||||
),
|
||||
)
|
||||
.api_route(
|
||||
"/api/oracle/histogram/ema/{point}",
|
||||
"/api/oracle/histogram/payments/{point}",
|
||||
get_with(
|
||||
async |uri: Uri,
|
||||
headers: HeaderMap,
|
||||
@@ -81,7 +82,7 @@ impl OracleRoutes for ApiRouter<AppState> {
|
||||
let strategy = state.date_strategy(version, date);
|
||||
state
|
||||
.respond_json(&headers, strategy, &uri, move |q| {
|
||||
q.confirmed_histogram_ema_day(Day1::try_from(date)?)
|
||||
q.confirmed_payment_histogram_day(Day1::try_from(date)?)
|
||||
})
|
||||
.await
|
||||
}
|
||||
@@ -89,7 +90,7 @@ impl OracleRoutes for ApiRouter<AppState> {
|
||||
let strategy = state.height_strategy(version, height);
|
||||
state
|
||||
.respond_json(&headers, strategy, &uri, move |q| {
|
||||
q.confirmed_histogram_ema(usize::from(height))
|
||||
q.confirmed_payment_histogram(usize::from(height))
|
||||
})
|
||||
.await
|
||||
}
|
||||
@@ -97,14 +98,15 @@ impl OracleRoutes for ApiRouter<AppState> {
|
||||
}
|
||||
},
|
||||
|op| {
|
||||
op.id("get_oracle_histogram_ema")
|
||||
op.id("get_oracle_histogram_payments")
|
||||
.oracle_tag()
|
||||
.summary("EMA histogram at height or day")
|
||||
.summary("Payment output histogram at height or day")
|
||||
.description(
|
||||
"Smoothed round-dollar payment histogram for a confirmed point: a \
|
||||
block height (`840000`) gives that block's EMA, a calendar date \
|
||||
(`YYYY-MM-DD`) gives the average of that day's per-block EMAs. \
|
||||
A flat array of log-scale bins.",
|
||||
"Smoothed histogram of oracle-eligible payment outputs for a \
|
||||
confirmed point. A block height (`840000`) gives that block's oracle \
|
||||
payment histogram; a calendar date (`YYYY-MM-DD`) gives the average \
|
||||
of that day's per-block payment histograms. A flat array of log-scale \
|
||||
bins.",
|
||||
)
|
||||
.json_response::<HistogramEmaCompact>()
|
||||
.not_modified()
|
||||
@@ -115,24 +117,24 @@ impl OracleRoutes for ApiRouter<AppState> {
|
||||
),
|
||||
)
|
||||
.api_route(
|
||||
"/api/oracle/histogram/raw/live",
|
||||
"/api/oracle/histogram/outputs/live",
|
||||
get_with(
|
||||
async |uri: Uri, headers: HeaderMap, _: Empty, State(state): State<AppState>| {
|
||||
state
|
||||
.respond_json(&headers, state.mempool_strategy(), &uri, |q| {
|
||||
q.live_histogram_raw()
|
||||
q.live_output_histogram()
|
||||
})
|
||||
.await
|
||||
},
|
||||
|op| {
|
||||
op.id("get_oracle_histogram_raw_live")
|
||||
op.id("get_oracle_histogram_outputs_live")
|
||||
.oracle_tag()
|
||||
.summary("Live raw histogram")
|
||||
.summary("Live output value histogram")
|
||||
.description(
|
||||
"Unfiltered output histogram for the forming mempool block: every \
|
||||
live output binned by value, with none of the round-dollar payment \
|
||||
filters applied. A flat array of log-scale bins, all zero when no \
|
||||
mempool is configured.",
|
||||
"Live unfiltered output value histogram for the forming mempool \
|
||||
block. Every live output is binned by value on the oracle log scale; \
|
||||
no oracle payment filters are applied. A flat array of log-scale \
|
||||
bins, all zero when no mempool is configured.",
|
||||
)
|
||||
.json_response::<HistogramRaw>()
|
||||
.not_modified()
|
||||
@@ -141,7 +143,7 @@ impl OracleRoutes for ApiRouter<AppState> {
|
||||
),
|
||||
)
|
||||
.api_route(
|
||||
"/api/oracle/histogram/raw/{point}",
|
||||
"/api/oracle/histogram/outputs/{point}",
|
||||
get_with(
|
||||
async |uri: Uri,
|
||||
headers: HeaderMap,
|
||||
@@ -155,7 +157,7 @@ impl OracleRoutes for ApiRouter<AppState> {
|
||||
let strategy = state.date_strategy(version, date);
|
||||
state
|
||||
.respond_json(&headers, strategy, &uri, move |q| {
|
||||
q.confirmed_histogram_raw_day(Day1::try_from(date)?)
|
||||
q.confirmed_output_histogram_day(Day1::try_from(date)?)
|
||||
})
|
||||
.await
|
||||
}
|
||||
@@ -163,7 +165,7 @@ impl OracleRoutes for ApiRouter<AppState> {
|
||||
let strategy = state.height_strategy(version, height);
|
||||
state
|
||||
.respond_json(&headers, strategy, &uri, move |q| {
|
||||
q.confirmed_histogram_raw(usize::from(height))
|
||||
q.confirmed_output_histogram(usize::from(height))
|
||||
})
|
||||
.await
|
||||
}
|
||||
@@ -171,14 +173,15 @@ impl OracleRoutes for ApiRouter<AppState> {
|
||||
}
|
||||
},
|
||||
|op| {
|
||||
op.id("get_oracle_histogram_raw")
|
||||
op.id("get_oracle_histogram_outputs")
|
||||
.oracle_tag()
|
||||
.summary("Raw histogram at height or day")
|
||||
.summary("Output value histogram at height or day")
|
||||
.description(
|
||||
"Unfiltered output histogram for a confirmed point: a block height \
|
||||
(`840000`) gives that block's outputs, coinbase included, binned by \
|
||||
value with no payment filtering; a calendar date (`YYYY-MM-DD`) sums \
|
||||
every block that day. A flat array of log-scale bins.",
|
||||
"Unfiltered output value histogram for a confirmed point. A block \
|
||||
height (`840000`) gives every output in that block, coinbase \
|
||||
included, binned by value on the oracle log scale; a calendar date \
|
||||
(`YYYY-MM-DD`) sums every block that day. A flat array of log-scale \
|
||||
bins.",
|
||||
)
|
||||
.json_response::<HistogramRaw>()
|
||||
.not_modified()
|
||||
|
||||
+20
-20
@@ -11888,62 +11888,62 @@ class BrkClient extends BrkClientBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Live EMA histogram
|
||||
* Live payment output histogram
|
||||
*
|
||||
* Smoothed round-dollar payment histogram at the live tip: the committed EMA with the forming mempool block blended in. A flat array of log-scale bins.
|
||||
* Live smoothed histogram of oracle-eligible payment outputs, binned by output value on the oracle log scale. It combines the committed oracle window with the forming mempool block. A flat array of log-scale bins.
|
||||
*
|
||||
* Endpoint: `GET /api/oracle/histogram/ema/live`
|
||||
* Endpoint: `GET /api/oracle/histogram/payments/live`
|
||||
* @param {{ signal?: AbortSignal, onValue?: (value: number[]) => void }} [options]
|
||||
* @returns {Promise<number[]>}
|
||||
*/
|
||||
async getOracleHistogramEmaLive({ signal, onValue } = {}) {
|
||||
const path = `/api/oracle/histogram/ema/live`;
|
||||
async getOracleHistogramPaymentsLive({ signal, onValue } = {}) {
|
||||
const path = `/api/oracle/histogram/payments/live`;
|
||||
return this.getJson(path, { signal, onValue });
|
||||
}
|
||||
|
||||
/**
|
||||
* EMA histogram at height or day
|
||||
* Payment output histogram at height or day
|
||||
*
|
||||
* Smoothed round-dollar payment histogram for a confirmed point: a block height (`840000`) gives that block's EMA, a calendar date (`YYYY-MM-DD`) gives the average of that day's per-block EMAs. A flat array of log-scale bins.
|
||||
* Smoothed histogram of oracle-eligible payment outputs for a confirmed point. A block height (`840000`) gives that block's oracle payment histogram; a calendar date (`YYYY-MM-DD`) gives the average of that day's per-block payment histograms. A flat array of log-scale bins.
|
||||
*
|
||||
* Endpoint: `GET /api/oracle/histogram/ema/{point}`
|
||||
* Endpoint: `GET /api/oracle/histogram/payments/{point}`
|
||||
*
|
||||
* @param {string} point
|
||||
* @param {{ signal?: AbortSignal, onValue?: (value: number[]) => void }} [options]
|
||||
* @returns {Promise<number[]>}
|
||||
*/
|
||||
async getOracleHistogramEma(point, { signal, onValue } = {}) {
|
||||
const path = `/api/oracle/histogram/ema/${point}`;
|
||||
async getOracleHistogramPayments(point, { signal, onValue } = {}) {
|
||||
const path = `/api/oracle/histogram/payments/${point}`;
|
||||
return this.getJson(path, { signal, onValue });
|
||||
}
|
||||
|
||||
/**
|
||||
* Live raw histogram
|
||||
* Live output value histogram
|
||||
*
|
||||
* Unfiltered output histogram for the forming mempool block: every live output binned by value, with none of the round-dollar payment filters applied. A flat array of log-scale bins, all zero when no mempool is configured.
|
||||
* Live unfiltered output value histogram for the forming mempool block. Every live output is binned by value on the oracle log scale; no oracle payment filters are applied. A flat array of log-scale bins, all zero when no mempool is configured.
|
||||
*
|
||||
* Endpoint: `GET /api/oracle/histogram/raw/live`
|
||||
* Endpoint: `GET /api/oracle/histogram/outputs/live`
|
||||
* @param {{ signal?: AbortSignal, onValue?: (value: number[]) => void }} [options]
|
||||
* @returns {Promise<number[]>}
|
||||
*/
|
||||
async getOracleHistogramRawLive({ signal, onValue } = {}) {
|
||||
const path = `/api/oracle/histogram/raw/live`;
|
||||
async getOracleHistogramOutputsLive({ signal, onValue } = {}) {
|
||||
const path = `/api/oracle/histogram/outputs/live`;
|
||||
return this.getJson(path, { signal, onValue });
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw histogram at height or day
|
||||
* Output value histogram at height or day
|
||||
*
|
||||
* Unfiltered output histogram for a confirmed point: a block height (`840000`) gives that block's outputs, coinbase included, binned by value with no payment filtering; a calendar date (`YYYY-MM-DD`) sums every block that day. A flat array of log-scale bins.
|
||||
* Unfiltered output value histogram for a confirmed point. A block height (`840000`) gives every output in that block, coinbase included, binned by value on the oracle log scale; a calendar date (`YYYY-MM-DD`) sums every block that day. A flat array of log-scale bins.
|
||||
*
|
||||
* Endpoint: `GET /api/oracle/histogram/raw/{point}`
|
||||
* Endpoint: `GET /api/oracle/histogram/outputs/{point}`
|
||||
*
|
||||
* @param {string} point
|
||||
* @param {{ signal?: AbortSignal, onValue?: (value: number[]) => void }} [options]
|
||||
* @returns {Promise<number[]>}
|
||||
*/
|
||||
async getOracleHistogramRaw(point, { signal, onValue } = {}) {
|
||||
const path = `/api/oracle/histogram/raw/${point}`;
|
||||
async getOracleHistogramOutputs(point, { signal, onValue } = {}) {
|
||||
const path = `/api/oracle/histogram/outputs/${point}`;
|
||||
return this.getJson(path, { signal, onValue });
|
||||
}
|
||||
|
||||
|
||||
@@ -8674,37 +8674,37 @@ class BrkClient(BrkClientBase):
|
||||
Endpoint: `GET /api/oracle/price`"""
|
||||
return self.get_json('/api/oracle/price')
|
||||
|
||||
def get_oracle_histogram_ema_live(self) -> List[int]:
|
||||
"""Live EMA histogram.
|
||||
def get_oracle_histogram_payments_live(self) -> List[int]:
|
||||
"""Live payment output histogram.
|
||||
|
||||
Smoothed round-dollar payment histogram at the live tip: the committed EMA with the forming mempool block blended in. A flat array of log-scale bins.
|
||||
Live smoothed histogram of oracle-eligible payment outputs, binned by output value on the oracle log scale. It combines the committed oracle window with the forming mempool block. A flat array of log-scale bins.
|
||||
|
||||
Endpoint: `GET /api/oracle/histogram/ema/live`"""
|
||||
return self.get_json('/api/oracle/histogram/ema/live')
|
||||
Endpoint: `GET /api/oracle/histogram/payments/live`"""
|
||||
return self.get_json('/api/oracle/histogram/payments/live')
|
||||
|
||||
def get_oracle_histogram_ema(self, point: str) -> List[int]:
|
||||
"""EMA histogram at height or day.
|
||||
def get_oracle_histogram_payments(self, point: str) -> List[int]:
|
||||
"""Payment output histogram at height or day.
|
||||
|
||||
Smoothed round-dollar payment histogram for a confirmed point: a block height (`840000`) gives that block's EMA, a calendar date (`YYYY-MM-DD`) gives the average of that day's per-block EMAs. A flat array of log-scale bins.
|
||||
Smoothed histogram of oracle-eligible payment outputs for a confirmed point. A block height (`840000`) gives that block's oracle payment histogram; a calendar date (`YYYY-MM-DD`) gives the average of that day's per-block payment histograms. A flat array of log-scale bins.
|
||||
|
||||
Endpoint: `GET /api/oracle/histogram/ema/{point}`"""
|
||||
return self.get_json(f'/api/oracle/histogram/ema/{point}')
|
||||
Endpoint: `GET /api/oracle/histogram/payments/{point}`"""
|
||||
return self.get_json(f'/api/oracle/histogram/payments/{point}')
|
||||
|
||||
def get_oracle_histogram_raw_live(self) -> List[int]:
|
||||
"""Live raw histogram.
|
||||
def get_oracle_histogram_outputs_live(self) -> List[int]:
|
||||
"""Live output value histogram.
|
||||
|
||||
Unfiltered output histogram for the forming mempool block: every live output binned by value, with none of the round-dollar payment filters applied. A flat array of log-scale bins, all zero when no mempool is configured.
|
||||
Live unfiltered output value histogram for the forming mempool block. Every live output is binned by value on the oracle log scale; no oracle payment filters are applied. A flat array of log-scale bins, all zero when no mempool is configured.
|
||||
|
||||
Endpoint: `GET /api/oracle/histogram/raw/live`"""
|
||||
return self.get_json('/api/oracle/histogram/raw/live')
|
||||
Endpoint: `GET /api/oracle/histogram/outputs/live`"""
|
||||
return self.get_json('/api/oracle/histogram/outputs/live')
|
||||
|
||||
def get_oracle_histogram_raw(self, point: str) -> List[int]:
|
||||
"""Raw histogram at height or day.
|
||||
def get_oracle_histogram_outputs(self, point: str) -> List[int]:
|
||||
"""Output value histogram at height or day.
|
||||
|
||||
Unfiltered output histogram for a confirmed point: a block height (`840000`) gives that block's outputs, coinbase included, binned by value with no payment filtering; a calendar date (`YYYY-MM-DD`) sums every block that day. A flat array of log-scale bins.
|
||||
Unfiltered output value histogram for a confirmed point. A block height (`840000`) gives every output in that block, coinbase included, binned by value on the oracle log scale; a calendar date (`YYYY-MM-DD`) sums every block that day. A flat array of log-scale bins.
|
||||
|
||||
Endpoint: `GET /api/oracle/histogram/raw/{point}`"""
|
||||
return self.get_json(f'/api/oracle/histogram/raw/{point}')
|
||||
Endpoint: `GET /api/oracle/histogram/outputs/{point}`"""
|
||||
return self.get_json(f'/api/oracle/histogram/outputs/{point}')
|
||||
|
||||
def get_tx_by_index(self, index: TxIndex) -> Txid:
|
||||
"""Txid by index.
|
||||
|
||||
@@ -27,8 +27,8 @@ import { createCointimeSection } from "./cointime.js";
|
||||
import { createInvestingSection } from "./investing.js";
|
||||
import { demoHeatmapOption } from "../../src/heatmap/demo.js";
|
||||
import {
|
||||
oracleEmaHeatmapOption,
|
||||
oracleRawHeatmapOption,
|
||||
oracleOutputsHeatmapOption,
|
||||
oraclePaymentsHeatmapOption,
|
||||
} from "../../src/heatmap/oracle.js";
|
||||
|
||||
// Re-export types for external consumers
|
||||
@@ -306,8 +306,8 @@ export function createPartialOptions() {
|
||||
tree: [
|
||||
demoHeatmapOption,
|
||||
{
|
||||
name: "output values",
|
||||
tree: [oracleRawHeatmapOption, oracleEmaHeatmapOption],
|
||||
name: "oracle histograms",
|
||||
tree: [oracleOutputsHeatmapOption, oraclePaymentsHeatmapOption],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -486,7 +486,7 @@ function updateYControls(option) {
|
||||
const maxSelect = createSelect({
|
||||
id: "heatmap-y-max",
|
||||
label: "to",
|
||||
choices,
|
||||
choices: Array.from(choices).reverse(),
|
||||
initialValue: maxChoice,
|
||||
onChange(choice) {
|
||||
maxChoice = choice;
|
||||
|
||||
@@ -25,14 +25,17 @@ const AMOUNT_CHOICES = [
|
||||
{ label: "10k BTC", value: 4 },
|
||||
];
|
||||
|
||||
export const oracleRawHeatmapOption = createOracleHeatmapOption("raw", "raw");
|
||||
export const oracleEmaHeatmapOption = createOracleHeatmapOption(
|
||||
"ema",
|
||||
"smoothed",
|
||||
export const oracleOutputsHeatmapOption = createOracleHeatmapOption(
|
||||
"outputs",
|
||||
"outputs",
|
||||
);
|
||||
export const oraclePaymentsHeatmapOption = createOracleHeatmapOption(
|
||||
"payments",
|
||||
"payments",
|
||||
);
|
||||
|
||||
/**
|
||||
* @param {"raw" | "ema"} mode
|
||||
* @param {"outputs" | "payments"} mode
|
||||
* @param {string} name
|
||||
* @returns {PartialHeatmapOption}
|
||||
*/
|
||||
@@ -40,7 +43,8 @@ function createOracleHeatmapOption(mode, name) {
|
||||
return {
|
||||
kind: "heatmap",
|
||||
name,
|
||||
title: `${capitalize(name)} Output Value Distribution`,
|
||||
title:
|
||||
mode === "outputs" ? "Output Value Histogram" : "Payment Output Histogram",
|
||||
points: {
|
||||
fetch: (date, signal, onPoints) =>
|
||||
fetchOraclePoints(mode, date, signal, onPoints),
|
||||
@@ -64,7 +68,7 @@ function createOracleHeatmapOption(mode, name) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {"raw" | "ema"} mode
|
||||
* @param {"outputs" | "payments"} mode
|
||||
* @param {string} date
|
||||
* @param {AbortSignal} signal
|
||||
* @param {(points: HeatmapPoints) => void} [onPoints]
|
||||
@@ -82,7 +86,7 @@ async function fetchOraclePoints(mode, date, signal, onPoints) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {"raw" | "ema"} mode
|
||||
* @param {"outputs" | "payments"} mode
|
||||
* @param {string} date
|
||||
* @param {AbortSignal} signal
|
||||
* @param {(values: number[]) => void} [onValue]
|
||||
@@ -90,9 +94,9 @@ async function fetchOraclePoints(mode, date, signal, onPoints) {
|
||||
*/
|
||||
function fetchOracleValues(mode, date, signal, onValue) {
|
||||
return (
|
||||
mode === "raw"
|
||||
? brk.getOracleHistogramRaw(date, { signal, onValue })
|
||||
: brk.getOracleHistogramEma(date, { signal, onValue })
|
||||
mode === "outputs"
|
||||
? brk.getOracleHistogramOutputs(date, { signal, onValue })
|
||||
: brk.getOracleHistogramPayments(date, { signal, onValue })
|
||||
);
|
||||
}
|
||||
|
||||
@@ -138,8 +142,3 @@ function formatNumber(value) {
|
||||
function trimNumber(value) {
|
||||
return value.replace(/\.?0+$/, "");
|
||||
}
|
||||
|
||||
/** @param {string} value */
|
||||
function capitalize(value) {
|
||||
return value.charAt(0).toUpperCase() + value.slice(1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user