mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-24 14:49:58 -07:00
global: snapshot
This commit is contained in:
@@ -87,7 +87,7 @@ export function createChart({ parent, brk, fitContent }) {
|
||||
const getTimeEndpoint = (idx) =>
|
||||
idx === "height"
|
||||
? brk.metrics.blocks.time.timestampMonotonic.by[idx]
|
||||
: brk.metrics.blocks.time.timestamp.by[idx];
|
||||
: /** @type {any} */ (brk.metrics.blocks.time.timestamp)[idx].by[idx];
|
||||
|
||||
const index = {
|
||||
/** @type {Set<(index: ChartableIndex) => void>} */
|
||||
@@ -137,7 +137,7 @@ export function createChart({ parent, brk, fitContent }) {
|
||||
if (cached) {
|
||||
this.data = cached;
|
||||
}
|
||||
endpoint.slice(-10000).fetch((result) => {
|
||||
endpoint.slice(-10000).fetch((/** @type {any} */ result) => {
|
||||
if (currentGen !== generation) return;
|
||||
cache.set(endpoint.path, result);
|
||||
this.data = result;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { colors } from "../utils/colors.js";
|
||||
import { brk } from "../client.js";
|
||||
import { Unit } from "../utils/units.js";
|
||||
import { dots, line, price } from "./series.js";
|
||||
import { dots, line, price, rollingWindowsTree } from "./series.js";
|
||||
import { satsBtcUsd, createPriceRatioCharts } from "./shared.js";
|
||||
|
||||
/**
|
||||
@@ -255,11 +255,11 @@ export function createCointimeSection() {
|
||||
name: "Compare",
|
||||
tree: [
|
||||
{
|
||||
name: "Sum",
|
||||
name: "Base",
|
||||
title: "Coinblocks",
|
||||
bottom: coinblocks.map(({ pattern, name, color }) =>
|
||||
line({
|
||||
metric: pattern.sum,
|
||||
metric: pattern.height,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.coinblocks,
|
||||
@@ -284,17 +284,18 @@ export function createCointimeSection() {
|
||||
name,
|
||||
tree: [
|
||||
{
|
||||
name: "Sum",
|
||||
name: "Base",
|
||||
title,
|
||||
bottom: [
|
||||
line({
|
||||
metric: pattern.sum,
|
||||
metric: pattern.height,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.coinblocks,
|
||||
}),
|
||||
],
|
||||
},
|
||||
rollingWindowsTree({ windows: pattern.sum, title, unit: Unit.coinblocks }),
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: `${title} (Total)`,
|
||||
@@ -320,14 +321,14 @@ export function createCointimeSection() {
|
||||
name: "Compare",
|
||||
tree: [
|
||||
{
|
||||
name: "Sum",
|
||||
name: "Base",
|
||||
title: "Cointime Value",
|
||||
bottom: [
|
||||
...cointimeValues.map(({ pattern, name, color }) =>
|
||||
line({ metric: pattern.sum, name, color, unit: Unit.usd }),
|
||||
line({ metric: pattern.height, name, color, unit: Unit.usd }),
|
||||
),
|
||||
line({
|
||||
metric: vocdd.pattern.sum,
|
||||
metric: vocdd.pattern.height,
|
||||
name: vocdd.name,
|
||||
color: vocdd.color,
|
||||
unit: Unit.usd,
|
||||
@@ -360,12 +361,13 @@ export function createCointimeSection() {
|
||||
name,
|
||||
tree: [
|
||||
{
|
||||
name: "Sum",
|
||||
name: "Base",
|
||||
title,
|
||||
bottom: [
|
||||
line({ metric: pattern.sum, name, color, unit: Unit.usd }),
|
||||
line({ metric: pattern.height, name, color, unit: Unit.usd }),
|
||||
],
|
||||
},
|
||||
rollingWindowsTree({ windows: pattern.sum, title, unit: Unit.usd }),
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: `${title} (Total)`,
|
||||
@@ -384,11 +386,11 @@ export function createCointimeSection() {
|
||||
name: vocdd.name,
|
||||
tree: [
|
||||
{
|
||||
name: "Sum",
|
||||
name: "Base",
|
||||
title: vocdd.title,
|
||||
bottom: [
|
||||
line({
|
||||
metric: vocdd.pattern.sum,
|
||||
metric: vocdd.pattern.height,
|
||||
name: vocdd.name,
|
||||
color: vocdd.color,
|
||||
unit: Unit.usd,
|
||||
@@ -401,6 +403,7 @@ export function createCointimeSection() {
|
||||
}),
|
||||
],
|
||||
},
|
||||
rollingWindowsTree({ windows: vocdd.pattern.sum, title: vocdd.title, unit: Unit.usd }),
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: `${vocdd.title} (Total)`,
|
||||
|
||||
@@ -174,13 +174,13 @@ function coinsDestroyedTree(list, all, title) {
|
||||
title: title("Coins Destroyed"),
|
||||
bottom: flatMapCohortsWithAll(list, all, ({ name, color, tree }) => [
|
||||
line({
|
||||
metric: tree.activity.coinblocksDestroyed.sum,
|
||||
metric: tree.activity.coinblocksDestroyed.sum._24h,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.coinblocks,
|
||||
}),
|
||||
line({
|
||||
metric: tree.activity.coindaysDestroyed.sum,
|
||||
metric: tree.activity.coindaysDestroyed.sum._24h,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.coindays,
|
||||
@@ -677,19 +677,19 @@ export function createActivitySection({
|
||||
defaultActive: false,
|
||||
}),
|
||||
line({
|
||||
metric: tree.activity.sent.sats.sum,
|
||||
metric: tree.activity.sent.base.sats,
|
||||
name: "sum",
|
||||
color,
|
||||
unit: Unit.sats,
|
||||
}),
|
||||
line({
|
||||
metric: tree.activity.sent.btc.sum,
|
||||
metric: tree.activity.sent.base.btc,
|
||||
name: "sum",
|
||||
color,
|
||||
unit: Unit.btc,
|
||||
}),
|
||||
line({
|
||||
metric: tree.activity.sent.usd.sum,
|
||||
metric: tree.activity.sent.base.usd,
|
||||
name: "sum",
|
||||
color,
|
||||
unit: Unit.usd,
|
||||
@@ -701,19 +701,19 @@ export function createActivitySection({
|
||||
title: title("Sent Volume (Total)"),
|
||||
bottom: [
|
||||
line({
|
||||
metric: tree.activity.sent.sats.cumulative,
|
||||
metric: tree.activity.sent.cumulative.sats,
|
||||
name: "all-time",
|
||||
color,
|
||||
unit: Unit.sats,
|
||||
}),
|
||||
line({
|
||||
metric: tree.activity.sent.btc.cumulative,
|
||||
metric: tree.activity.sent.cumulative.btc,
|
||||
name: "all-time",
|
||||
color,
|
||||
unit: Unit.btc,
|
||||
}),
|
||||
line({
|
||||
metric: tree.activity.sent.usd.cumulative,
|
||||
metric: tree.activity.sent.cumulative.usd,
|
||||
name: "all-time",
|
||||
color,
|
||||
unit: Unit.usd,
|
||||
@@ -816,13 +816,13 @@ export function createActivitySection({
|
||||
title: title("Coins Destroyed"),
|
||||
bottom: [
|
||||
line({
|
||||
metric: tree.activity.coinblocksDestroyed.sum,
|
||||
metric: tree.activity.coinblocksDestroyed.sum._24h,
|
||||
name: "Coinblocks",
|
||||
color,
|
||||
unit: Unit.coinblocks,
|
||||
}),
|
||||
line({
|
||||
metric: tree.activity.coindaysDestroyed.sum,
|
||||
metric: tree.activity.coindaysDestroyed.sum._24h,
|
||||
name: "Coindays",
|
||||
color,
|
||||
unit: Unit.coindays,
|
||||
@@ -1021,9 +1021,9 @@ export function createGroupedActivitySection({
|
||||
bottom: flatMapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
satsBtcUsd({
|
||||
pattern: {
|
||||
sats: tree.activity.sent.sats.sum,
|
||||
btc: tree.activity.sent.btc.sum,
|
||||
usd: tree.activity.sent.usd.sum,
|
||||
sats: tree.activity.sent.base.sats,
|
||||
btc: tree.activity.sent.base.btc,
|
||||
usd: tree.activity.sent.base.usd,
|
||||
},
|
||||
name,
|
||||
color,
|
||||
|
||||
@@ -74,7 +74,7 @@ export function createPricesSectionFull({ cohort, title }) {
|
||||
context: cohort.name,
|
||||
legend: "Realized",
|
||||
pricePattern: tree.realized.realizedPrice,
|
||||
ratio: tree.realized.realizedPriceExtra,
|
||||
ratio: { ...tree.realized.realizedPriceExtra, ...tree.realized.realizedPriceRatioExt },
|
||||
color,
|
||||
priceTitle: title("Realized Price"),
|
||||
titlePrefix: "Realized Price",
|
||||
@@ -86,7 +86,7 @@ export function createPricesSectionFull({ cohort, title }) {
|
||||
context: cohort.name,
|
||||
legend: "Investor",
|
||||
pricePattern: tree.realized.investorPrice,
|
||||
ratio: tree.realized.investorPriceExtra,
|
||||
ratio: { ...tree.realized.investorPriceExtra, ...tree.realized.investorPriceRatioExt },
|
||||
color,
|
||||
priceTitle: title("Investor Price"),
|
||||
titlePrefix: "Investor Price",
|
||||
|
||||
@@ -519,21 +519,21 @@ function realizedPnlSum(tree) {
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
dots({
|
||||
metric: r.realizedProfit.sum,
|
||||
metric: r.realizedProfit.height,
|
||||
name: "Profit",
|
||||
color: colors.profit,
|
||||
unit: Unit.usd,
|
||||
defaultActive: false,
|
||||
}),
|
||||
dots({
|
||||
metric: r.negRealizedLoss.sum,
|
||||
metric: r.negRealizedLoss,
|
||||
name: "Negative Loss",
|
||||
color: colors.loss,
|
||||
unit: Unit.usd,
|
||||
defaultActive: false,
|
||||
}),
|
||||
dots({
|
||||
metric: r.realizedLoss.sum,
|
||||
metric: r.realizedLoss.height,
|
||||
name: "Loss",
|
||||
color: colors.loss,
|
||||
unit: Unit.usd,
|
||||
@@ -547,13 +547,13 @@ function realizedPnlSum(tree) {
|
||||
defaultActive: false,
|
||||
}),
|
||||
baseline({
|
||||
metric: r.realizedProfitRelToRealizedCap.sum,
|
||||
metric: r.realizedProfitRelToRealizedCap,
|
||||
name: "Profit",
|
||||
color: colors.profit,
|
||||
unit: Unit.pctRcap,
|
||||
}),
|
||||
baseline({
|
||||
metric: r.realizedLossRelToRealizedCap.sum,
|
||||
metric: r.realizedLossRelToRealizedCap,
|
||||
name: "Loss",
|
||||
color: colors.loss,
|
||||
unit: Unit.pctRcap,
|
||||
@@ -575,13 +575,13 @@ function realizedNetPnlSum(tree) {
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
dotsBaseline({
|
||||
metric: r.netRealizedPnl.sum,
|
||||
metric: r.netRealizedPnl.height,
|
||||
name: "Net",
|
||||
unit: Unit.usd,
|
||||
defaultActive: false,
|
||||
}),
|
||||
baseline({
|
||||
metric: r.netRealizedPnlRelToRealizedCap.sum,
|
||||
metric: r.netRealizedPnlRelToRealizedCap,
|
||||
name: "Net",
|
||||
unit: Unit.pctRcap,
|
||||
}),
|
||||
@@ -609,20 +609,20 @@ function realizedPnlCumulative(tree) {
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
line({
|
||||
metric: r.negRealizedLoss.cumulative,
|
||||
metric: r.negRealizedLoss,
|
||||
name: "Negative Loss",
|
||||
color: colors.loss,
|
||||
unit: Unit.usd,
|
||||
defaultActive: false,
|
||||
}),
|
||||
baseline({
|
||||
metric: r.realizedProfitRelToRealizedCap.cumulative,
|
||||
metric: r.realizedProfitRelToRealizedCap,
|
||||
name: "Profit",
|
||||
color: colors.profit,
|
||||
unit: Unit.pctRcap,
|
||||
}),
|
||||
baseline({
|
||||
metric: r.realizedLossRelToRealizedCap.cumulative,
|
||||
metric: r.realizedLossRelToRealizedCap,
|
||||
name: "Loss",
|
||||
color: colors.loss,
|
||||
unit: Unit.pctRcap,
|
||||
@@ -644,7 +644,7 @@ function realizedNetPnlCumulative(tree) {
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
baseline({
|
||||
metric: r.netRealizedPnlRelToRealizedCap.cumulative,
|
||||
metric: r.netRealizedPnlRelToRealizedCap,
|
||||
name: "Net",
|
||||
unit: Unit.pctRcap,
|
||||
}),
|
||||
@@ -704,13 +704,13 @@ function sentInPnlTree(tree, title) {
|
||||
}),
|
||||
...satsBtcUsdFrom({
|
||||
source: r.sentInProfit,
|
||||
key: "sum",
|
||||
key: "base",
|
||||
name: "In Profit",
|
||||
color: colors.profit,
|
||||
}),
|
||||
...satsBtcUsdFrom({
|
||||
source: r.sentInLoss,
|
||||
key: "sum",
|
||||
key: "base",
|
||||
name: "In Loss",
|
||||
color: colors.loss,
|
||||
}),
|
||||
@@ -945,7 +945,7 @@ function realizedSubfolder(tree, title, rollingTree) {
|
||||
title: title("Realized Peak Regret"),
|
||||
bottom: [
|
||||
line({
|
||||
metric: r.peakRegret.sum,
|
||||
metric: r.peakRegret.height,
|
||||
name: "Peak Regret",
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
@@ -1839,7 +1839,7 @@ function groupedRealizedPnlSum(list, all, title) {
|
||||
title: title("Realized Profit"),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
line({
|
||||
metric: tree.realized.realizedProfit.sum,
|
||||
metric: tree.realized.realizedProfit.height,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.usd,
|
||||
@@ -1851,7 +1851,7 @@ function groupedRealizedPnlSum(list, all, title) {
|
||||
title: title("Realized Loss"),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
line({
|
||||
metric: tree.realized.negRealizedLoss.sum,
|
||||
metric: tree.realized.negRealizedLoss,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.usd,
|
||||
@@ -1936,7 +1936,7 @@ function groupedRealizedPnlCumulative(list, all, title) {
|
||||
title: title("Cumulative Realized Loss"),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
line({
|
||||
metric: tree.realized.negRealizedLoss.cumulative,
|
||||
metric: tree.realized.realizedLoss.cumulative,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.usd,
|
||||
@@ -1973,7 +1973,7 @@ function groupedSentInPnl(list, all, title) {
|
||||
...flatMapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
satsBtcUsdFrom({
|
||||
source: tree.realized.sentInProfit,
|
||||
key: "sum",
|
||||
key: "base",
|
||||
name,
|
||||
color,
|
||||
}),
|
||||
@@ -1995,7 +1995,7 @@ function groupedSentInPnl(list, all, title) {
|
||||
...flatMapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
satsBtcUsdFrom({
|
||||
source: tree.realized.sentInLoss,
|
||||
key: "sum",
|
||||
key: "base",
|
||||
name,
|
||||
color,
|
||||
}),
|
||||
@@ -2104,7 +2104,7 @@ function groupedRealizedSubfolder(list, all, title) {
|
||||
title: title("Net Realized P&L"),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
baseline({
|
||||
metric: tree.realized.netRealizedPnl.sum,
|
||||
metric: tree.realized.netRealizedPnl.height,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.usd,
|
||||
@@ -2166,7 +2166,7 @@ function groupedRealizedSubfolderWithExtras(list, all, title) {
|
||||
title: title("Net Realized P&L"),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
baseline({
|
||||
metric: tree.realized.netRealizedPnl.sum,
|
||||
metric: tree.realized.netRealizedPnl.height,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.usd,
|
||||
|
||||
@@ -76,7 +76,7 @@ export function createValuationSectionFull({ cohort, title }) {
|
||||
createRatioChart({
|
||||
title,
|
||||
pricePattern: tree.realized.realizedPrice,
|
||||
ratio: tree.realized.realizedPriceExtra,
|
||||
ratio: { ...tree.realized.realizedPriceExtra, ...tree.realized.realizedPriceRatioExt },
|
||||
color,
|
||||
name: "MVRV",
|
||||
}),
|
||||
|
||||
@@ -9,11 +9,11 @@ import {
|
||||
dots,
|
||||
dotted,
|
||||
distributionBtcSatsUsd,
|
||||
rollingWindowsTree,
|
||||
} from "./series.js";
|
||||
import {
|
||||
satsBtcUsd,
|
||||
satsBtcUsdFrom,
|
||||
satsBtcUsdFromFull,
|
||||
revenueBtcSatsUsd,
|
||||
} from "./shared.js";
|
||||
import { brk } from "../client.js";
|
||||
@@ -53,7 +53,7 @@ const ANTPOOL_AND_FRIENDS_IDS = /** @type {const} */ ([
|
||||
* @returns {PartialOptionsGroup}
|
||||
*/
|
||||
export function createMiningSection() {
|
||||
const { blocks, transactions, pools, mining } = brk.metrics;
|
||||
const { blocks, pools, mining } = brk.metrics;
|
||||
|
||||
// Pre-compute pool entries with resolved names
|
||||
const poolData = entries(pools.vecs).map(([id, pool]) => ({
|
||||
@@ -116,44 +116,17 @@ export function createMiningSection() {
|
||||
name: "Blocks Mined",
|
||||
tree: [
|
||||
{
|
||||
name: "Sum",
|
||||
name: "Base",
|
||||
title: `Blocks Mined: ${name}`,
|
||||
bottom: [
|
||||
line({
|
||||
metric: pool.blocksMined.sum,
|
||||
name: "sum",
|
||||
metric: pool.blocksMined.height,
|
||||
name: "base",
|
||||
unit: Unit.count,
|
||||
}),
|
||||
line({
|
||||
metric: pool.blocksMined24hSum,
|
||||
name: "24h",
|
||||
color: colors.time._24h,
|
||||
unit: Unit.count,
|
||||
defaultActive: false,
|
||||
}),
|
||||
line({
|
||||
metric: pool.blocksMined1wSum,
|
||||
name: "1w",
|
||||
color: colors.time._1w,
|
||||
unit: Unit.count,
|
||||
defaultActive: false,
|
||||
}),
|
||||
line({
|
||||
metric: pool.blocksMined1mSum,
|
||||
name: "1m",
|
||||
color: colors.time._1m,
|
||||
unit: Unit.count,
|
||||
defaultActive: false,
|
||||
}),
|
||||
line({
|
||||
metric: pool.blocksMined1ySum,
|
||||
name: "1y",
|
||||
color: colors.time._1y,
|
||||
unit: Unit.count,
|
||||
defaultActive: false,
|
||||
}),
|
||||
],
|
||||
},
|
||||
rollingWindowsTree({ windows: pool.blocksMined.sum, title: `Blocks Mined: ${name}`, unit: Unit.count }),
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: `Blocks Mined: ${name} (Total)`,
|
||||
@@ -177,7 +150,7 @@ export function createMiningSection() {
|
||||
coinbase: pool.coinbase,
|
||||
subsidy: pool.subsidy,
|
||||
fee: pool.fee,
|
||||
key: "sum",
|
||||
key: "base",
|
||||
}),
|
||||
},
|
||||
{
|
||||
@@ -372,8 +345,8 @@ export function createMiningSection() {
|
||||
bottom: revenueBtcSatsUsd({
|
||||
coinbase: mining.rewards.coinbase,
|
||||
subsidy: mining.rewards.subsidy,
|
||||
fee: transactions.fees.fee,
|
||||
key: "sum",
|
||||
fee: mining.rewards.fees,
|
||||
key: "base",
|
||||
}),
|
||||
},
|
||||
{
|
||||
@@ -382,7 +355,7 @@ export function createMiningSection() {
|
||||
bottom: revenueBtcSatsUsd({
|
||||
coinbase: mining.rewards.coinbase,
|
||||
subsidy: mining.rewards.subsidy,
|
||||
fee: transactions.fees.fee,
|
||||
fee: mining.rewards.fees,
|
||||
key: "cumulative",
|
||||
}),
|
||||
},
|
||||
@@ -394,24 +367,11 @@ export function createMiningSection() {
|
||||
{
|
||||
name: "Sum",
|
||||
title: "Coinbase Rewards",
|
||||
bottom: [
|
||||
...satsBtcUsdFromFull({
|
||||
source: mining.rewards.coinbase,
|
||||
key: "base",
|
||||
name: "sum",
|
||||
}),
|
||||
...satsBtcUsdFrom({
|
||||
source: mining.rewards.coinbase,
|
||||
key: "sum",
|
||||
name: "sum",
|
||||
}),
|
||||
...satsBtcUsd({
|
||||
pattern: mining.rewards.coinbase24hSum,
|
||||
name: "24h",
|
||||
color: colors.time._24h,
|
||||
defaultActive: false,
|
||||
}),
|
||||
],
|
||||
bottom: satsBtcUsdFrom({
|
||||
source: mining.rewards.coinbase,
|
||||
key: "base",
|
||||
name: "sum",
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "Rolling",
|
||||
@@ -421,22 +381,22 @@ export function createMiningSection() {
|
||||
title: "Coinbase Rolling Sum",
|
||||
bottom: [
|
||||
...satsBtcUsd({
|
||||
pattern: mining.rewards.coinbase24hSum,
|
||||
pattern: mining.rewards.coinbase._24h.sum,
|
||||
name: "24h",
|
||||
color: colors.time._24h,
|
||||
}),
|
||||
...satsBtcUsd({
|
||||
pattern: mining.rewards.coinbase7dSum,
|
||||
pattern: mining.rewards.coinbase._7d.sum,
|
||||
name: "7d",
|
||||
color: colors.time._1w,
|
||||
}),
|
||||
...satsBtcUsd({
|
||||
pattern: mining.rewards.coinbase30dSum,
|
||||
pattern: mining.rewards.coinbase._30d.sum,
|
||||
name: "30d",
|
||||
color: colors.time._1m,
|
||||
}),
|
||||
...satsBtcUsd({
|
||||
pattern: mining.rewards.coinbase1ySum,
|
||||
pattern: mining.rewards.coinbase._1y.sum,
|
||||
name: "1y",
|
||||
color: colors.time._1y,
|
||||
}),
|
||||
@@ -446,7 +406,7 @@ export function createMiningSection() {
|
||||
name: "24h",
|
||||
title: "Coinbase 24h Rolling Sum",
|
||||
bottom: satsBtcUsd({
|
||||
pattern: mining.rewards.coinbase24hSum,
|
||||
pattern: mining.rewards.coinbase._24h.sum,
|
||||
name: "24h",
|
||||
color: colors.time._24h,
|
||||
}),
|
||||
@@ -455,7 +415,7 @@ export function createMiningSection() {
|
||||
name: "7d",
|
||||
title: "Coinbase 7d Rolling Sum",
|
||||
bottom: satsBtcUsd({
|
||||
pattern: mining.rewards.coinbase7dSum,
|
||||
pattern: mining.rewards.coinbase._7d.sum,
|
||||
name: "7d",
|
||||
color: colors.time._1w,
|
||||
}),
|
||||
@@ -464,7 +424,7 @@ export function createMiningSection() {
|
||||
name: "30d",
|
||||
title: "Coinbase 30d Rolling Sum",
|
||||
bottom: satsBtcUsd({
|
||||
pattern: mining.rewards.coinbase30dSum,
|
||||
pattern: mining.rewards.coinbase._30d.sum,
|
||||
name: "30d",
|
||||
color: colors.time._1m,
|
||||
}),
|
||||
@@ -473,7 +433,7 @@ export function createMiningSection() {
|
||||
name: "1y",
|
||||
title: "Coinbase 1y Rolling Sum",
|
||||
bottom: satsBtcUsd({
|
||||
pattern: mining.rewards.coinbase1ySum,
|
||||
pattern: mining.rewards.coinbase._1y.sum,
|
||||
name: "1y",
|
||||
color: colors.time._1y,
|
||||
}),
|
||||
@@ -483,7 +443,7 @@ export function createMiningSection() {
|
||||
{
|
||||
name: "Distribution",
|
||||
title: "Coinbase Rewards per Block Distribution",
|
||||
bottom: distributionBtcSatsUsd(mining.rewards.coinbase),
|
||||
bottom: distributionBtcSatsUsd(mining.rewards.coinbase._24h),
|
||||
},
|
||||
{
|
||||
name: "Cumulative",
|
||||
@@ -503,14 +463,9 @@ export function createMiningSection() {
|
||||
name: "Sum",
|
||||
title: "Block Subsidy",
|
||||
bottom: [
|
||||
...satsBtcUsdFromFull({
|
||||
source: mining.rewards.subsidy,
|
||||
key: "base",
|
||||
name: "sum",
|
||||
}),
|
||||
...satsBtcUsdFrom({
|
||||
source: mining.rewards.subsidy,
|
||||
key: "sum",
|
||||
key: "base",
|
||||
name: "sum",
|
||||
}),
|
||||
line({
|
||||
@@ -522,10 +477,77 @@ export function createMiningSection() {
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Rolling",
|
||||
tree: [
|
||||
{
|
||||
name: "Compare",
|
||||
title: "Subsidy Rolling Sum",
|
||||
bottom: [
|
||||
...satsBtcUsd({
|
||||
pattern: mining.rewards.subsidy._24h.sum,
|
||||
name: "24h",
|
||||
color: colors.time._24h,
|
||||
}),
|
||||
...satsBtcUsd({
|
||||
pattern: mining.rewards.subsidy._7d.sum,
|
||||
name: "7d",
|
||||
color: colors.time._1w,
|
||||
}),
|
||||
...satsBtcUsd({
|
||||
pattern: mining.rewards.subsidy._30d.sum,
|
||||
name: "30d",
|
||||
color: colors.time._1m,
|
||||
}),
|
||||
...satsBtcUsd({
|
||||
pattern: mining.rewards.subsidy._1y.sum,
|
||||
name: "1y",
|
||||
color: colors.time._1y,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "24h",
|
||||
title: "Subsidy 24h Rolling Sum",
|
||||
bottom: satsBtcUsd({
|
||||
pattern: mining.rewards.subsidy._24h.sum,
|
||||
name: "24h",
|
||||
color: colors.time._24h,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "7d",
|
||||
title: "Subsidy 7d Rolling Sum",
|
||||
bottom: satsBtcUsd({
|
||||
pattern: mining.rewards.subsidy._7d.sum,
|
||||
name: "7d",
|
||||
color: colors.time._1w,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "30d",
|
||||
title: "Subsidy 30d Rolling Sum",
|
||||
bottom: satsBtcUsd({
|
||||
pattern: mining.rewards.subsidy._30d.sum,
|
||||
name: "30d",
|
||||
color: colors.time._1m,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "1y",
|
||||
title: "Subsidy 1y Rolling Sum",
|
||||
bottom: satsBtcUsd({
|
||||
pattern: mining.rewards.subsidy._1y.sum,
|
||||
name: "1y",
|
||||
color: colors.time._1y,
|
||||
}),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Distribution",
|
||||
title: "Block Subsidy Distribution",
|
||||
bottom: distributionBtcSatsUsd(mining.rewards.subsidy),
|
||||
bottom: distributionBtcSatsUsd(mining.rewards.subsidy._24h),
|
||||
},
|
||||
{
|
||||
name: "Cumulative",
|
||||
@@ -545,8 +567,8 @@ export function createMiningSection() {
|
||||
name: "Sum",
|
||||
title: "Transaction Fee Revenue per Block",
|
||||
bottom: satsBtcUsdFrom({
|
||||
source: transactions.fees.fee,
|
||||
key: "sum",
|
||||
source: mining.rewards.fees,
|
||||
key: "base",
|
||||
name: "sum",
|
||||
}),
|
||||
},
|
||||
@@ -558,22 +580,22 @@ export function createMiningSection() {
|
||||
title: "Fee Rolling Sum",
|
||||
bottom: [
|
||||
...satsBtcUsd({
|
||||
pattern: mining.rewards.fee24hSum,
|
||||
pattern: mining.rewards.fees._24h.sum,
|
||||
name: "24h",
|
||||
color: colors.time._24h,
|
||||
}),
|
||||
...satsBtcUsd({
|
||||
pattern: mining.rewards.fee7dSum,
|
||||
pattern: mining.rewards.fees._7d.sum,
|
||||
name: "7d",
|
||||
color: colors.time._1w,
|
||||
}),
|
||||
...satsBtcUsd({
|
||||
pattern: mining.rewards.fee30dSum,
|
||||
pattern: mining.rewards.fees._30d.sum,
|
||||
name: "30d",
|
||||
color: colors.time._1m,
|
||||
}),
|
||||
...satsBtcUsd({
|
||||
pattern: mining.rewards.fee1ySum,
|
||||
pattern: mining.rewards.fees._1y.sum,
|
||||
name: "1y",
|
||||
color: colors.time._1y,
|
||||
}),
|
||||
@@ -583,7 +605,7 @@ export function createMiningSection() {
|
||||
name: "24h",
|
||||
title: "Fee 24h Rolling Sum",
|
||||
bottom: satsBtcUsd({
|
||||
pattern: mining.rewards.fee24hSum,
|
||||
pattern: mining.rewards.fees._24h.sum,
|
||||
name: "24h",
|
||||
color: colors.time._24h,
|
||||
}),
|
||||
@@ -592,7 +614,7 @@ export function createMiningSection() {
|
||||
name: "7d",
|
||||
title: "Fee 7d Rolling Sum",
|
||||
bottom: satsBtcUsd({
|
||||
pattern: mining.rewards.fee7dSum,
|
||||
pattern: mining.rewards.fees._7d.sum,
|
||||
name: "7d",
|
||||
color: colors.time._1w,
|
||||
}),
|
||||
@@ -601,7 +623,7 @@ export function createMiningSection() {
|
||||
name: "30d",
|
||||
title: "Fee 30d Rolling Sum",
|
||||
bottom: satsBtcUsd({
|
||||
pattern: mining.rewards.fee30dSum,
|
||||
pattern: mining.rewards.fees._30d.sum,
|
||||
name: "30d",
|
||||
color: colors.time._1m,
|
||||
}),
|
||||
@@ -610,7 +632,7 @@ export function createMiningSection() {
|
||||
name: "1y",
|
||||
title: "Fee 1y Rolling Sum",
|
||||
bottom: satsBtcUsd({
|
||||
pattern: mining.rewards.fee1ySum,
|
||||
pattern: mining.rewards.fees._1y.sum,
|
||||
name: "1y",
|
||||
color: colors.time._1y,
|
||||
}),
|
||||
@@ -620,13 +642,13 @@ export function createMiningSection() {
|
||||
{
|
||||
name: "Distribution",
|
||||
title: "Transaction Fee Revenue per Block Distribution",
|
||||
bottom: distributionBtcSatsUsd(transactions.fees.fee),
|
||||
bottom: distributionBtcSatsUsd(mining.rewards.fees._24h),
|
||||
},
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: "Transaction Fee Revenue (Total)",
|
||||
bottom: satsBtcUsdFrom({
|
||||
source: transactions.fees.fee,
|
||||
source: mining.rewards.fees,
|
||||
key: "cumulative",
|
||||
name: "all-time",
|
||||
}),
|
||||
@@ -813,7 +835,7 @@ export function createMiningSection() {
|
||||
title: "Unclaimed Rewards",
|
||||
bottom: satsBtcUsdFrom({
|
||||
source: mining.rewards.unclaimedRewards,
|
||||
key: "sum",
|
||||
key: "base",
|
||||
name: "sum",
|
||||
}),
|
||||
},
|
||||
@@ -988,7 +1010,7 @@ export function createMiningSection() {
|
||||
bottom: majorPools.flatMap((p, i) =>
|
||||
satsBtcUsdFrom({
|
||||
source: p.pool.coinbase,
|
||||
key: "sum",
|
||||
key: "base",
|
||||
name: p.name,
|
||||
color: colors.at(i, majorPools.length),
|
||||
}),
|
||||
@@ -1030,7 +1052,7 @@ export function createMiningSection() {
|
||||
bottom: antpoolFriends.flatMap((p, i) =>
|
||||
satsBtcUsdFrom({
|
||||
source: p.pool.coinbase,
|
||||
key: "sum",
|
||||
key: "base",
|
||||
name: p.name,
|
||||
color: colors.at(i, antpoolFriends.length),
|
||||
}),
|
||||
|
||||
@@ -12,9 +12,12 @@ import {
|
||||
fromSupplyPattern,
|
||||
fromBaseStatsPattern,
|
||||
chartsFromFullPerBlock,
|
||||
chartsFromCount,
|
||||
chartsFromValueFull,
|
||||
fromStatsPattern,
|
||||
chartsFromSumPerBlock,
|
||||
statsAtWindow,
|
||||
rollingWindowsTree,
|
||||
} from "./series.js";
|
||||
import { satsBtcUsd, satsBtcUsdFrom } from "./shared.js";
|
||||
|
||||
@@ -204,17 +207,34 @@ export function createNetworkSection() {
|
||||
},
|
||||
{
|
||||
name: "New",
|
||||
tree: chartsFromFullPerBlock({
|
||||
pattern: distribution.newAddrCount[key],
|
||||
title: `${titlePrefix}New Address Count`,
|
||||
unit: Unit.count,
|
||||
}),
|
||||
tree: (() => {
|
||||
const p = distribution.newAddrCount[key];
|
||||
const t = `${titlePrefix}New Address Count`;
|
||||
return [
|
||||
{
|
||||
name: "Sum",
|
||||
title: t,
|
||||
bottom: [
|
||||
line({ metric: p.base, name: "base", unit: Unit.count }),
|
||||
],
|
||||
},
|
||||
rollingWindowsTree({ windows: p.rest.sum, title: t, unit: Unit.count }),
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: `${t} (Total)`,
|
||||
bottom: [
|
||||
line({ metric: p.rest.cumulative, name: "all-time", unit: Unit.count }),
|
||||
],
|
||||
},
|
||||
];
|
||||
})(),
|
||||
},
|
||||
{
|
||||
name: "Reactivated",
|
||||
title: `${titlePrefix}Reactivated Addresses per Block`,
|
||||
bottom: fromBaseStatsPattern({
|
||||
pattern: distribution.addressActivity[key].reactivated,
|
||||
window: "_24h",
|
||||
unit: Unit.count,
|
||||
}),
|
||||
},
|
||||
@@ -223,6 +243,7 @@ export function createNetworkSection() {
|
||||
title: `${titlePrefix}Address Growth Rate per Block`,
|
||||
bottom: fromBaseStatsPattern({
|
||||
pattern: distribution.growthRate[key],
|
||||
window: "_24h",
|
||||
unit: Unit.ratio,
|
||||
}),
|
||||
},
|
||||
@@ -235,6 +256,7 @@ export function createNetworkSection() {
|
||||
title: `${titlePrefix}${t.title}`,
|
||||
bottom: fromBaseStatsPattern({
|
||||
pattern: distribution.addressActivity[key][t.key],
|
||||
window: "_24h",
|
||||
unit: Unit.count,
|
||||
}),
|
||||
})),
|
||||
@@ -246,6 +268,7 @@ export function createNetworkSection() {
|
||||
title: `${titlePrefix}${b.title}`,
|
||||
bottom: fromBaseStatsPattern({
|
||||
pattern: distribution.addressActivity[key][b.key],
|
||||
window: "_24h",
|
||||
unit: Unit.count,
|
||||
}),
|
||||
})),
|
||||
@@ -287,7 +310,7 @@ export function createNetworkSection() {
|
||||
unit: Unit.count,
|
||||
}),
|
||||
line({
|
||||
metric: distribution.newAddrCount[t.key].sum,
|
||||
metric: distribution.newAddrCount[t.key].rest.sum._24h,
|
||||
name: t.name,
|
||||
color: t.color,
|
||||
unit: Unit.count,
|
||||
@@ -299,13 +322,14 @@ export function createNetworkSection() {
|
||||
title: `${groupName} Reactivated Addresses per Block`,
|
||||
bottom: types.flatMap((t) => [
|
||||
line({
|
||||
metric: distribution.addressActivity[t.key].reactivated.base,
|
||||
metric: distribution.addressActivity[t.key].reactivated.height,
|
||||
name: t.name,
|
||||
color: t.color,
|
||||
unit: Unit.count,
|
||||
}),
|
||||
line({
|
||||
metric: distribution.addressActivity[t.key].reactivated.average,
|
||||
metric:
|
||||
distribution.addressActivity[t.key].reactivated.average._24h,
|
||||
name: t.name,
|
||||
color: t.color,
|
||||
unit: Unit.count,
|
||||
@@ -317,13 +341,13 @@ export function createNetworkSection() {
|
||||
title: `${groupName} Address Growth Rate per Block`,
|
||||
bottom: types.flatMap((t) => [
|
||||
dots({
|
||||
metric: distribution.growthRate[t.key].base,
|
||||
metric: distribution.growthRate[t.key].height,
|
||||
name: t.name,
|
||||
color: t.color,
|
||||
unit: Unit.ratio,
|
||||
}),
|
||||
dots({
|
||||
metric: distribution.growthRate[t.key].average,
|
||||
metric: distribution.growthRate[t.key].average._24h,
|
||||
name: t.name,
|
||||
color: t.color,
|
||||
unit: Unit.ratio,
|
||||
@@ -337,13 +361,14 @@ export function createNetworkSection() {
|
||||
title: `${groupName} ${tr.compareTitle}`,
|
||||
bottom: types.flatMap((t) => [
|
||||
line({
|
||||
metric: distribution.addressActivity[t.key][tr.key].base,
|
||||
metric: distribution.addressActivity[t.key][tr.key].height,
|
||||
name: t.name,
|
||||
color: t.color,
|
||||
unit: Unit.count,
|
||||
}),
|
||||
line({
|
||||
metric: distribution.addressActivity[t.key][tr.key].average,
|
||||
metric:
|
||||
distribution.addressActivity[t.key][tr.key].average._24h,
|
||||
name: t.name,
|
||||
color: t.color,
|
||||
unit: Unit.count,
|
||||
@@ -358,13 +383,14 @@ export function createNetworkSection() {
|
||||
title: `${groupName} ${b.compareTitle}`,
|
||||
bottom: types.flatMap((t) => [
|
||||
line({
|
||||
metric: distribution.addressActivity[t.key][b.key].base,
|
||||
metric: distribution.addressActivity[t.key][b.key].height,
|
||||
name: t.name,
|
||||
color: t.color,
|
||||
unit: Unit.count,
|
||||
}),
|
||||
line({
|
||||
metric: distribution.addressActivity[t.key][b.key].average,
|
||||
metric:
|
||||
distribution.addressActivity[t.key][b.key].average._24h,
|
||||
name: t.name,
|
||||
color: t.color,
|
||||
unit: Unit.count,
|
||||
@@ -398,7 +424,7 @@ export function createNetworkSection() {
|
||||
title: `${groupName} Output Count`,
|
||||
bottom: types.map((t) =>
|
||||
line({
|
||||
metric: scripts.count[t.key].sum,
|
||||
metric: /** @type {CountPattern<number>} */ (scripts.count[t.key]).sum._24h,
|
||||
name: t.name,
|
||||
color: t.color,
|
||||
unit: Unit.count,
|
||||
@@ -410,7 +436,7 @@ export function createNetworkSection() {
|
||||
title: `${groupName} Output Count (Total)`,
|
||||
bottom: types.map((t) =>
|
||||
line({
|
||||
metric: scripts.count[t.key].cumulative,
|
||||
metric: /** @type {CountPattern<number>} */ (scripts.count[t.key]).cumulative,
|
||||
name: t.name,
|
||||
color: t.color,
|
||||
unit: Unit.count,
|
||||
@@ -454,7 +480,7 @@ export function createNetworkSection() {
|
||||
title: "Unspendable Supply",
|
||||
bottom: satsBtcUsdFrom({
|
||||
source: supply.burned.unspendable,
|
||||
key: "sum",
|
||||
key: "base",
|
||||
name: "sum",
|
||||
}),
|
||||
},
|
||||
@@ -495,7 +521,7 @@ export function createNetworkSection() {
|
||||
name: "Fee Rate",
|
||||
title: "Transaction Fee Rate",
|
||||
bottom: fromStatsPattern({
|
||||
pattern: transactions.fees.feeRate,
|
||||
pattern: transactions.fees.feeRate.block,
|
||||
unit: Unit.feeRate,
|
||||
}),
|
||||
},
|
||||
@@ -532,11 +558,11 @@ export function createNetworkSection() {
|
||||
title: "Transaction Size",
|
||||
bottom: [
|
||||
...fromStatsPattern({
|
||||
pattern: transactions.size.weight,
|
||||
pattern: transactions.size.weight.block,
|
||||
unit: Unit.wu,
|
||||
}),
|
||||
...fromStatsPattern({
|
||||
pattern: transactions.size.vsize,
|
||||
pattern: transactions.size.vsize.block,
|
||||
unit: Unit.vb,
|
||||
}),
|
||||
],
|
||||
@@ -545,12 +571,12 @@ export function createNetworkSection() {
|
||||
name: "Versions",
|
||||
tree: [
|
||||
{
|
||||
name: "Sum",
|
||||
name: "Base",
|
||||
title: "Transaction Versions",
|
||||
bottom: entries(transactions.versions).map(
|
||||
([v, data], i, arr) =>
|
||||
line({
|
||||
metric: data.sum,
|
||||
metric: data.height,
|
||||
name: v,
|
||||
color: colors.at(i, arr.length),
|
||||
unit: Unit.count,
|
||||
@@ -600,12 +626,12 @@ export function createNetworkSection() {
|
||||
name: "Count",
|
||||
tree: [
|
||||
{
|
||||
name: "Sum",
|
||||
name: "Base",
|
||||
title: "Block Count",
|
||||
bottom: [
|
||||
line({
|
||||
metric: blocks.count.blockCount.sum,
|
||||
name: "sum",
|
||||
metric: blocks.count.blockCount.height,
|
||||
name: "base",
|
||||
unit: Unit.count,
|
||||
}),
|
||||
line({
|
||||
@@ -617,36 +643,11 @@ export function createNetworkSection() {
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Rolling",
|
||||
title: "Block Count (Rolling)",
|
||||
bottom: [
|
||||
line({
|
||||
metric: blocks.count.blockCount24hSum,
|
||||
name: "24h",
|
||||
color: colors.time._24h,
|
||||
unit: Unit.count,
|
||||
}),
|
||||
line({
|
||||
metric: blocks.count.blockCount1wSum,
|
||||
name: "1w",
|
||||
color: colors.time._1w,
|
||||
unit: Unit.count,
|
||||
}),
|
||||
line({
|
||||
metric: blocks.count.blockCount1mSum,
|
||||
name: "1m",
|
||||
color: colors.time._1m,
|
||||
unit: Unit.count,
|
||||
}),
|
||||
line({
|
||||
metric: blocks.count.blockCount1ySum,
|
||||
name: "1y",
|
||||
color: colors.time._1y,
|
||||
unit: Unit.count,
|
||||
}),
|
||||
],
|
||||
},
|
||||
rollingWindowsTree({
|
||||
windows: blocks.count.blockCountSum,
|
||||
title: "Block Count",
|
||||
unit: Unit.count,
|
||||
}),
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: "Block Count (Total)",
|
||||
@@ -666,6 +667,7 @@ export function createNetworkSection() {
|
||||
bottom: [
|
||||
...fromBaseStatsPattern({
|
||||
pattern: blocks.interval,
|
||||
window: "_24h",
|
||||
unit: Unit.secs,
|
||||
}),
|
||||
priceLine({ unit: Unit.secs, name: "Target", number: 600 }),
|
||||
@@ -675,7 +677,7 @@ export function createNetworkSection() {
|
||||
name: "Size",
|
||||
tree: [
|
||||
{
|
||||
name: "Sum",
|
||||
name: "Base",
|
||||
title: "Block Size",
|
||||
bottom: [
|
||||
line({
|
||||
@@ -683,13 +685,9 @@ export function createNetworkSection() {
|
||||
name: "base",
|
||||
unit: Unit.bytes,
|
||||
}),
|
||||
line({
|
||||
metric: blocks.size.sum,
|
||||
name: "sum",
|
||||
unit: Unit.bytes,
|
||||
}),
|
||||
],
|
||||
},
|
||||
rollingWindowsTree({ windows: blocks.size.sum, title: "Block Size", unit: Unit.bytes }),
|
||||
{
|
||||
name: "Distribution",
|
||||
title: "Block Size Distribution",
|
||||
@@ -700,7 +698,7 @@ export function createNetworkSection() {
|
||||
unit: Unit.bytes,
|
||||
}),
|
||||
...fromStatsPattern({
|
||||
pattern: blocks.size,
|
||||
pattern: statsAtWindow(blocks.size, "_24h"),
|
||||
unit: Unit.bytes,
|
||||
}),
|
||||
],
|
||||
@@ -722,7 +720,7 @@ export function createNetworkSection() {
|
||||
name: "Weight",
|
||||
tree: [
|
||||
{
|
||||
name: "Sum",
|
||||
name: "Base",
|
||||
title: "Block Weight",
|
||||
bottom: [
|
||||
line({
|
||||
@@ -730,13 +728,9 @@ export function createNetworkSection() {
|
||||
name: "base",
|
||||
unit: Unit.wu,
|
||||
}),
|
||||
line({
|
||||
metric: blocks.weight.sum,
|
||||
name: "sum",
|
||||
unit: Unit.wu,
|
||||
}),
|
||||
],
|
||||
},
|
||||
rollingWindowsTree({ windows: blocks.weight.sum, title: "Block Weight", unit: Unit.wu }),
|
||||
{
|
||||
name: "Distribution",
|
||||
title: "Block Weight Distribution",
|
||||
@@ -747,7 +741,7 @@ export function createNetworkSection() {
|
||||
unit: Unit.wu,
|
||||
}),
|
||||
...fromStatsPattern({
|
||||
pattern: blocks.weight,
|
||||
pattern: statsAtWindow(blocks.weight, "_24h"),
|
||||
unit: Unit.wu,
|
||||
}),
|
||||
],
|
||||
@@ -769,32 +763,28 @@ export function createNetworkSection() {
|
||||
name: "vBytes",
|
||||
tree: [
|
||||
{
|
||||
name: "Sum",
|
||||
name: "Base",
|
||||
title: "Block vBytes",
|
||||
bottom: [
|
||||
line({
|
||||
metric: blocks.vbytes.base,
|
||||
metric: blocks.vbytes.height,
|
||||
name: "base",
|
||||
unit: Unit.vb,
|
||||
}),
|
||||
line({
|
||||
metric: blocks.vbytes.sum,
|
||||
name: "sum",
|
||||
unit: Unit.vb,
|
||||
}),
|
||||
],
|
||||
},
|
||||
rollingWindowsTree({ windows: blocks.vbytes.sum, title: "Block vBytes", unit: Unit.vb }),
|
||||
{
|
||||
name: "Distribution",
|
||||
title: "Block vBytes Distribution",
|
||||
bottom: [
|
||||
line({
|
||||
metric: blocks.vbytes.base,
|
||||
metric: blocks.vbytes.height,
|
||||
name: "base",
|
||||
unit: Unit.vb,
|
||||
}),
|
||||
...fromStatsPattern({
|
||||
pattern: blocks.vbytes,
|
||||
pattern: statsAtWindow(blocks.vbytes, "_24h"),
|
||||
unit: Unit.vb,
|
||||
}),
|
||||
],
|
||||
@@ -817,6 +807,7 @@ export function createNetworkSection() {
|
||||
title: "Block Fullness",
|
||||
bottom: fromBaseStatsPattern({
|
||||
pattern: blocks.fullness,
|
||||
window: "_24h",
|
||||
unit: Unit.percentage,
|
||||
}),
|
||||
},
|
||||
@@ -949,7 +940,7 @@ export function createNetworkSection() {
|
||||
defaultActive: t.defaultActive,
|
||||
}),
|
||||
line({
|
||||
metric: distribution.newAddrCount[t.key].sum,
|
||||
metric: distribution.newAddrCount[t.key].rest.sum._24h,
|
||||
name: t.name,
|
||||
color: t.color,
|
||||
unit: Unit.count,
|
||||
@@ -963,7 +954,7 @@ export function createNetworkSection() {
|
||||
bottom: addressTypes.flatMap((t) => [
|
||||
line({
|
||||
metric:
|
||||
distribution.addressActivity[t.key].reactivated.base,
|
||||
distribution.addressActivity[t.key].reactivated.height,
|
||||
name: t.name,
|
||||
color: t.color,
|
||||
unit: Unit.count,
|
||||
@@ -971,7 +962,7 @@ export function createNetworkSection() {
|
||||
}),
|
||||
line({
|
||||
metric:
|
||||
distribution.addressActivity[t.key].reactivated.average,
|
||||
distribution.addressActivity[t.key].reactivated.average._24h,
|
||||
name: t.name,
|
||||
color: t.color,
|
||||
unit: Unit.count,
|
||||
@@ -984,14 +975,14 @@ export function createNetworkSection() {
|
||||
title: "Address Growth Rate per Block by Type",
|
||||
bottom: addressTypes.flatMap((t) => [
|
||||
dots({
|
||||
metric: distribution.growthRate[t.key].base,
|
||||
metric: distribution.growthRate[t.key].height,
|
||||
name: t.name,
|
||||
color: t.color,
|
||||
unit: Unit.ratio,
|
||||
defaultActive: t.defaultActive,
|
||||
}),
|
||||
dots({
|
||||
metric: distribution.growthRate[t.key].average,
|
||||
metric: distribution.growthRate[t.key].average._24h,
|
||||
name: t.name,
|
||||
color: t.color,
|
||||
unit: Unit.ratio,
|
||||
@@ -1006,7 +997,7 @@ export function createNetworkSection() {
|
||||
title: tr.compareTitle,
|
||||
bottom: addressTypes.flatMap((t) => [
|
||||
line({
|
||||
metric: distribution.addressActivity[t.key][tr.key].base,
|
||||
metric: distribution.addressActivity[t.key][tr.key].height,
|
||||
name: t.name,
|
||||
color: t.color,
|
||||
unit: Unit.count,
|
||||
@@ -1014,7 +1005,7 @@ export function createNetworkSection() {
|
||||
}),
|
||||
line({
|
||||
metric:
|
||||
distribution.addressActivity[t.key][tr.key].average,
|
||||
distribution.addressActivity[t.key][tr.key].average._24h,
|
||||
name: t.name,
|
||||
color: t.color,
|
||||
unit: Unit.count,
|
||||
@@ -1030,7 +1021,7 @@ export function createNetworkSection() {
|
||||
title: b.compareTitle,
|
||||
bottom: addressTypes.flatMap((t) => [
|
||||
line({
|
||||
metric: distribution.addressActivity[t.key][b.key].base,
|
||||
metric: distribution.addressActivity[t.key][b.key].height,
|
||||
name: t.name,
|
||||
color: t.color,
|
||||
unit: Unit.count,
|
||||
@@ -1038,7 +1029,7 @@ export function createNetworkSection() {
|
||||
}),
|
||||
line({
|
||||
metric:
|
||||
distribution.addressActivity[t.key][b.key].average,
|
||||
distribution.addressActivity[t.key][b.key].average._24h,
|
||||
name: t.name,
|
||||
color: t.color,
|
||||
unit: Unit.count,
|
||||
@@ -1104,7 +1095,7 @@ export function createNetworkSection() {
|
||||
title: "Output Count by Script Type",
|
||||
bottom: scriptTypes.map((t) =>
|
||||
line({
|
||||
metric: scripts.count[t.key].sum,
|
||||
metric: /** @type {CountPattern<number>} */ (scripts.count[t.key]).sum._24h,
|
||||
name: t.name,
|
||||
color: t.color,
|
||||
unit: Unit.count,
|
||||
@@ -1133,8 +1124,8 @@ export function createNetworkSection() {
|
||||
createScriptCompare("Legacy", legacyScripts),
|
||||
...legacyScripts.map((t) => ({
|
||||
name: t.name,
|
||||
tree: chartsFromFullPerBlock({
|
||||
pattern: scripts.count[t.key],
|
||||
tree: chartsFromCount({
|
||||
pattern: /** @type {CountPattern<number>} */ (scripts.count[t.key]),
|
||||
title: `${t.name} Output Count`,
|
||||
unit: Unit.count,
|
||||
}),
|
||||
@@ -1147,8 +1138,8 @@ export function createNetworkSection() {
|
||||
createScriptCompare("Script Hash", scriptHashScripts),
|
||||
...scriptHashScripts.map((t) => ({
|
||||
name: t.name,
|
||||
tree: chartsFromFullPerBlock({
|
||||
pattern: scripts.count[t.key],
|
||||
tree: chartsFromCount({
|
||||
pattern: /** @type {CountPattern<number>} */ (scripts.count[t.key]),
|
||||
title: `${t.name} Output Count`,
|
||||
unit: Unit.count,
|
||||
}),
|
||||
@@ -1161,8 +1152,8 @@ export function createNetworkSection() {
|
||||
createScriptCompare("SegWit", segwitScripts),
|
||||
...segwitScripts.map((t) => ({
|
||||
name: t.name,
|
||||
tree: chartsFromFullPerBlock({
|
||||
pattern: scripts.count[t.key],
|
||||
tree: chartsFromCount({
|
||||
pattern: /** @type {CountPattern<number>} */ (scripts.count[t.key]),
|
||||
title: `${t.name} Output Count`,
|
||||
unit: Unit.count,
|
||||
}),
|
||||
@@ -1175,8 +1166,8 @@ export function createNetworkSection() {
|
||||
createScriptCompare("Taproot", taprootAddresses),
|
||||
...taprootAddresses.map((t) => ({
|
||||
name: t.name,
|
||||
tree: chartsFromFullPerBlock({
|
||||
pattern: scripts.count[t.key],
|
||||
tree: chartsFromCount({
|
||||
pattern: /** @type {CountPattern<number>} */ (scripts.count[t.key]),
|
||||
title: `${t.name} Output Count`,
|
||||
unit: Unit.count,
|
||||
}),
|
||||
@@ -1189,8 +1180,8 @@ export function createNetworkSection() {
|
||||
createScriptCompare("Other", otherScripts),
|
||||
...otherScripts.map((t) => ({
|
||||
name: t.name,
|
||||
tree: chartsFromFullPerBlock({
|
||||
pattern: scripts.count[t.key],
|
||||
tree: chartsFromCount({
|
||||
pattern: /** @type {CountPattern<number>} */ (scripts.count[t.key]),
|
||||
title: `${t.name} Output Count`,
|
||||
unit: Unit.count,
|
||||
}),
|
||||
@@ -1207,13 +1198,13 @@ export function createNetworkSection() {
|
||||
title: "Script Adoption",
|
||||
bottom: [
|
||||
line({
|
||||
metric: scripts.count.segwitAdoption.cumulative,
|
||||
metric: scripts.adoption.segwit,
|
||||
name: "SegWit",
|
||||
color: colors.segwit,
|
||||
unit: Unit.percentage,
|
||||
}),
|
||||
line({
|
||||
metric: scripts.count.taprootAdoption.cumulative,
|
||||
metric: scripts.adoption.taproot,
|
||||
name: "Taproot",
|
||||
color: taprootAddresses[1].color,
|
||||
unit: Unit.percentage,
|
||||
@@ -1225,19 +1216,8 @@ export function createNetworkSection() {
|
||||
title: "SegWit Adoption",
|
||||
bottom: [
|
||||
line({
|
||||
metric: scripts.count.segwitAdoption.base,
|
||||
name: "Base",
|
||||
unit: Unit.percentage,
|
||||
}),
|
||||
line({
|
||||
metric: scripts.count.segwitAdoption.sum,
|
||||
name: "Sum",
|
||||
unit: Unit.percentage,
|
||||
}),
|
||||
line({
|
||||
metric: scripts.count.segwitAdoption.cumulative,
|
||||
name: "All-Time",
|
||||
color: colors.time.all,
|
||||
metric: scripts.adoption.segwit,
|
||||
name: "Adoption",
|
||||
unit: Unit.percentage,
|
||||
}),
|
||||
],
|
||||
@@ -1247,19 +1227,8 @@ export function createNetworkSection() {
|
||||
title: "Taproot Adoption",
|
||||
bottom: [
|
||||
line({
|
||||
metric: scripts.count.taprootAdoption.base,
|
||||
name: "Base",
|
||||
unit: Unit.percentage,
|
||||
}),
|
||||
line({
|
||||
metric: scripts.count.taprootAdoption.sum,
|
||||
name: "Sum",
|
||||
unit: Unit.percentage,
|
||||
}),
|
||||
line({
|
||||
metric: scripts.count.taprootAdoption.cumulative,
|
||||
name: "All-Time",
|
||||
color: colors.time.all,
|
||||
metric: scripts.adoption.taproot,
|
||||
name: "Adoption",
|
||||
unit: Unit.percentage,
|
||||
}),
|
||||
],
|
||||
|
||||
@@ -47,7 +47,7 @@ export function price({
|
||||
|
||||
/**
|
||||
* Create percentile series (max/min/median/pct75/pct25/pct90/pct10) from any stats pattern
|
||||
* @param {StatsPattern<any> | BaseStatsPattern<any> | FullStatsPattern<any> | AnyStatsPattern} pattern
|
||||
* @param {DistributionStats} pattern
|
||||
* @param {Unit} unit
|
||||
* @param {string} title
|
||||
* @returns {AnyFetchedSeriesBlueprint[]}
|
||||
@@ -356,9 +356,10 @@ export function histogram({
|
||||
}
|
||||
|
||||
/**
|
||||
* Create series from a BaseStatsPattern (base + avg + percentiles, NO sum)
|
||||
* Create series from an AverageHeightMaxMedianMinP10P25P75P90Pattern (height + rolling stats)
|
||||
* @param {Object} args
|
||||
* @param {BaseStatsPattern<any>} args.pattern
|
||||
* @param {{ height: AnyMetricPattern } & Record<string, any>} args.pattern - Pattern with .height and rolling stats (p10/p25/p75/p90 as _1y24h30d7dPattern)
|
||||
* @param {string} args.window - Rolling window key (e.g., '_24h', '_7d', '_30d', '_1y')
|
||||
* @param {Unit} args.unit
|
||||
* @param {string} [args.title]
|
||||
* @param {Color} [args.baseColor]
|
||||
@@ -367,34 +368,37 @@ export function histogram({
|
||||
*/
|
||||
export function fromBaseStatsPattern({
|
||||
pattern,
|
||||
window,
|
||||
unit,
|
||||
title = "",
|
||||
baseColor,
|
||||
avgActive = true,
|
||||
}) {
|
||||
const { stat } = colors;
|
||||
const stats = statsAtWindow(pattern, window);
|
||||
return [
|
||||
dots({
|
||||
metric: pattern.base,
|
||||
metric: pattern.height,
|
||||
name: title || "base",
|
||||
color: baseColor,
|
||||
unit,
|
||||
}),
|
||||
dots({
|
||||
metric: pattern.average,
|
||||
metric: stats.average,
|
||||
name: `${title} avg`.trim(),
|
||||
color: stat.avg,
|
||||
unit,
|
||||
defaultActive: avgActive,
|
||||
}),
|
||||
...percentileSeries(pattern, unit, title),
|
||||
...percentileSeries(stats, unit, title),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create series from any pattern with avg + percentiles (works with StatsPattern, SumStatsPattern, etc.)
|
||||
* Create series from a flat stats pattern (average + pct percentiles as single metrics)
|
||||
* Use statsAtWindow() to extract from patterns with _1y24h30d7dPattern stats
|
||||
* @param {Object} args
|
||||
* @param {StatsPattern<any> | BaseStatsPattern<any> | FullStatsPattern<any> | AnyStatsPattern} args.pattern
|
||||
* @param {{ average: AnyMetricPattern, median: AnyMetricPattern, max: AnyMetricPattern, min: AnyMetricPattern, pct75: AnyMetricPattern, pct25: AnyMetricPattern, pct90: AnyMetricPattern, pct10: AnyMetricPattern }} args.pattern
|
||||
* @param {Unit} args.unit
|
||||
* @param {string} [args.title]
|
||||
* @returns {AnyFetchedSeriesBlueprint[]}
|
||||
@@ -412,14 +416,96 @@ export function fromStatsPattern({ pattern, unit, title = "" }) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create distribution series for btc/sats/usd from a value pattern with stats (average + percentiles)
|
||||
* @param {FullValuePattern | SumValuePattern} source
|
||||
* Extract stats at a specific rolling window from patterns with _1y24h30d7dPattern stats
|
||||
* @param {Record<string, any>} pattern - Pattern with pct10/pct25/pct75/pct90 and average/median/max/min as _1y24h30d7dPattern
|
||||
* @param {string} window
|
||||
*/
|
||||
export function statsAtWindow(pattern, window) {
|
||||
return {
|
||||
average: pattern.average[window],
|
||||
median: pattern.median[window],
|
||||
max: pattern.max[window],
|
||||
min: pattern.min[window],
|
||||
pct75: pattern.pct75[window],
|
||||
pct25: pattern.pct25[window],
|
||||
pct90: pattern.pct90[window],
|
||||
pct10: pattern.pct10[window],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Rolling folder tree from a _1y24h30d7dPattern (4 rolling windows)
|
||||
* @param {Object} args
|
||||
* @param {{ _24h: AnyMetricPattern, _7d: AnyMetricPattern, _30d: AnyMetricPattern, _1y: AnyMetricPattern }} args.windows
|
||||
* @param {string} args.title
|
||||
* @param {Unit} args.unit
|
||||
* @returns {PartialOptionsGroup}
|
||||
*/
|
||||
export function rollingWindowsTree({ windows, title, unit }) {
|
||||
return {
|
||||
name: "Rolling",
|
||||
tree: [
|
||||
{
|
||||
name: "Compare",
|
||||
title: `${title} Rolling`,
|
||||
bottom: [
|
||||
line({ metric: windows._24h, name: "24h", color: colors.time._24h, unit }),
|
||||
line({ metric: windows._7d, name: "7d", color: colors.time._1w, unit }),
|
||||
line({ metric: windows._30d, name: "30d", color: colors.time._1m, unit }),
|
||||
line({ metric: windows._1y, name: "1y", color: colors.time._1y, unit }),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "24h",
|
||||
title: `${title} 24h`,
|
||||
bottom: [line({ metric: windows._24h, name: "24h", color: colors.time._24h, unit })],
|
||||
},
|
||||
{
|
||||
name: "7d",
|
||||
title: `${title} 7d`,
|
||||
bottom: [line({ metric: windows._7d, name: "7d", color: colors.time._1w, unit })],
|
||||
},
|
||||
{
|
||||
name: "30d",
|
||||
title: `${title} 30d`,
|
||||
bottom: [line({ metric: windows._30d, name: "30d", color: colors.time._1m, unit })],
|
||||
},
|
||||
{
|
||||
name: "1y",
|
||||
title: `${title} 1y`,
|
||||
bottom: [line({ metric: windows._1y, name: "1y", color: colors.time._1y, unit })],
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Map a rolling window slot's stats to a specific unit, producing a stats-compatible pattern
|
||||
* @param {RollingWindowSlot} slot - Rolling window slot (e.g., pattern.rolling._24h)
|
||||
* @param {BtcSatsUsdKey} unitKey
|
||||
*/
|
||||
function rollingSlotForUnit(slot, unitKey) {
|
||||
return {
|
||||
average: slot.average[unitKey],
|
||||
median: slot.median[unitKey],
|
||||
max: slot.max[unitKey],
|
||||
min: slot.min[unitKey],
|
||||
pct75: slot.pct75[unitKey],
|
||||
pct25: slot.pct25[unitKey],
|
||||
pct90: slot.pct90[unitKey],
|
||||
pct10: slot.pct10[unitKey],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create distribution series for btc/sats/usd from a rolling window slot
|
||||
* @param {RollingWindowSlot} slot - Rolling window slot (e.g., pattern.rolling._24h)
|
||||
* @returns {AnyFetchedSeriesBlueprint[]}
|
||||
*/
|
||||
export const distributionBtcSatsUsd = (source) => [
|
||||
...fromStatsPattern({ pattern: source.btc, unit: Unit.btc }),
|
||||
...fromStatsPattern({ pattern: source.sats, unit: Unit.sats }),
|
||||
...fromStatsPattern({ pattern: source.usd, unit: Unit.usd }),
|
||||
export const distributionBtcSatsUsd = (slot) => [
|
||||
...fromStatsPattern({ pattern: rollingSlotForUnit(slot, "btc"), unit: Unit.btc }),
|
||||
...fromStatsPattern({ pattern: rollingSlotForUnit(slot, "sats"), unit: Unit.sats }),
|
||||
...fromStatsPattern({ pattern: rollingSlotForUnit(slot, "usd"), unit: Unit.usd }),
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -460,7 +546,7 @@ export function fromSupplyPattern({ pattern, title, color }) {
|
||||
|
||||
/**
|
||||
* Create distribution series (avg + percentiles)
|
||||
* @param {StatsPattern<any> | BaseStatsPattern<any> | FullStatsPattern<any> | AnyStatsPattern} pattern
|
||||
* @param {DistributionStats} pattern
|
||||
* @param {Unit} unit
|
||||
* @returns {AnyFetchedSeriesBlueprint[]}
|
||||
*/
|
||||
@@ -556,9 +642,10 @@ function btcSatsUsdSeries({ metrics, name, color, defaultActive }) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Split pattern with base + sum + distribution + cumulative into 3 charts
|
||||
* Split flat per-block pattern into charts (Sum/Rolling/Distribution/Cumulative)
|
||||
* Pattern has: .height, .cumulative, .sum (windowed), .average/.pct10/... (windowed, flat)
|
||||
* @param {Object} args
|
||||
* @param {FullStatsPattern<any>} args.pattern
|
||||
* @param {FullPerBlockPattern} args.pattern
|
||||
* @param {string} args.title
|
||||
* @param {Unit} args.unit
|
||||
* @param {string} [args.distributionSuffix]
|
||||
@@ -577,15 +664,13 @@ export function chartsFromFull({
|
||||
{
|
||||
name: "Sum",
|
||||
title,
|
||||
bottom: [
|
||||
{ metric: pattern.base, title: "sum", unit },
|
||||
{ metric: pattern.sum, title: "sum", unit },
|
||||
],
|
||||
bottom: [{ metric: pattern.height, title: "base", unit }],
|
||||
},
|
||||
rollingWindowsTree({ windows: pattern.sum, title, unit }),
|
||||
{
|
||||
name: "Distribution",
|
||||
title: distTitle,
|
||||
bottom: distributionSeries(pattern, unit),
|
||||
bottom: distributionSeries(statsAtWindow(pattern, "_24h"), unit),
|
||||
},
|
||||
{
|
||||
name: "Cumulative",
|
||||
@@ -596,9 +681,9 @@ export function chartsFromFull({
|
||||
}
|
||||
|
||||
/**
|
||||
* Split pattern into 3 charts with "per Block" in distribution title
|
||||
* Split pattern into 4 charts with "per Block" in distribution title
|
||||
* @param {Object} args
|
||||
* @param {FullStatsPattern<any>} args.pattern
|
||||
* @param {FullPerBlockPattern} args.pattern
|
||||
* @param {string} args.title
|
||||
* @param {Unit} args.unit
|
||||
* @returns {PartialOptionsTree}
|
||||
@@ -609,7 +694,7 @@ export const chartsFromFullPerBlock = (args) =>
|
||||
/**
|
||||
* Split pattern with sum + distribution + cumulative into 3 charts (no base)
|
||||
* @param {Object} args
|
||||
* @param {AnyStatsPattern} args.pattern
|
||||
* @param {FullStatsPattern} args.pattern
|
||||
* @param {string} args.title
|
||||
* @param {Unit} args.unit
|
||||
* @param {string} [args.distributionSuffix]
|
||||
@@ -647,7 +732,7 @@ export function chartsFromSum({
|
||||
/**
|
||||
* Split pattern into 3 charts with "per Block" in distribution title (no base)
|
||||
* @param {Object} args
|
||||
* @param {AnyStatsPattern} args.pattern
|
||||
* @param {FullStatsPattern} args.pattern
|
||||
* @param {string} args.title
|
||||
* @param {Unit} args.unit
|
||||
* @returns {PartialOptionsTree}
|
||||
@@ -656,7 +741,7 @@ export const chartsFromSumPerBlock = (args) =>
|
||||
chartsFromSum({ ...args, distributionSuffix: "per Block" });
|
||||
|
||||
/**
|
||||
* Split pattern with sum + cumulative into 2 charts
|
||||
* Split pattern with rolling sum windows + cumulative into charts
|
||||
* @param {Object} args
|
||||
* @param {CountPattern<any>} args.pattern
|
||||
* @param {string} args.title
|
||||
@@ -666,11 +751,7 @@ export const chartsFromSumPerBlock = (args) =>
|
||||
*/
|
||||
export function chartsFromCount({ pattern, title, unit, color }) {
|
||||
return [
|
||||
{
|
||||
name: "Sum",
|
||||
title,
|
||||
bottom: [{ metric: pattern.sum, title: "sum", color, unit }],
|
||||
},
|
||||
rollingWindowsTree({ windows: pattern.sum, title, unit }),
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: `${title} (Total)`,
|
||||
@@ -680,46 +761,7 @@ export function chartsFromCount({ pattern, title, unit, color }) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Split value pattern (btc/sats/usd with sum + cumulative) into 2 charts
|
||||
* @param {Object} args
|
||||
* @param {ValuePattern} args.pattern
|
||||
* @param {string} args.title
|
||||
* @param {Color} [args.color]
|
||||
* @returns {PartialOptionsTree}
|
||||
*/
|
||||
export function chartsFromValue({ pattern, title, color }) {
|
||||
return [
|
||||
{
|
||||
name: "Sum",
|
||||
title,
|
||||
bottom: btcSatsUsdSeries({
|
||||
metrics: {
|
||||
btc: pattern.btc.sum,
|
||||
sats: pattern.sats.sum,
|
||||
usd: pattern.usd.sum,
|
||||
},
|
||||
name: "sum",
|
||||
color,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: `${title} (Total)`,
|
||||
bottom: btcSatsUsdSeries({
|
||||
metrics: {
|
||||
btc: pattern.btc.cumulative,
|
||||
sats: pattern.sats.cumulative,
|
||||
usd: pattern.usd.cumulative,
|
||||
},
|
||||
name: "all-time",
|
||||
color,
|
||||
}),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Split btc/sats/usd pattern with full stats into 3 charts
|
||||
* Split BaseCumulativeRollingPattern into 3 charts (Sum/Distribution/Cumulative)
|
||||
* @param {Object} args
|
||||
* @param {CoinbasePattern} args.pattern
|
||||
* @param {string} args.title
|
||||
@@ -731,44 +773,23 @@ export function chartsFromValueFull({ pattern, title }) {
|
||||
name: "Sum",
|
||||
title,
|
||||
bottom: [
|
||||
...btcSatsUsdSeries({ metrics: pattern.base, name: "sum" }),
|
||||
...btcSatsUsdSeries({
|
||||
metrics: {
|
||||
btc: pattern.btc.base,
|
||||
sats: pattern.sats.base,
|
||||
usd: pattern.usd.base,
|
||||
},
|
||||
name: "sum",
|
||||
}),
|
||||
...btcSatsUsdSeries({
|
||||
metrics: {
|
||||
btc: pattern.btc.sum,
|
||||
sats: pattern.sats.sum,
|
||||
usd: pattern.usd.sum,
|
||||
},
|
||||
name: "sum",
|
||||
metrics: pattern._24h.sum,
|
||||
name: "24h sum",
|
||||
defaultActive: false,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Distribution",
|
||||
title: `${title} Distribution`,
|
||||
bottom: [
|
||||
...distributionSeries(pattern.btc, Unit.btc),
|
||||
...distributionSeries(pattern.sats, Unit.sats),
|
||||
...distributionSeries(pattern.usd, Unit.usd),
|
||||
],
|
||||
bottom: distributionBtcSatsUsd(pattern._24h),
|
||||
},
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: `${title} (Total)`,
|
||||
bottom: btcSatsUsdSeries({
|
||||
metrics: {
|
||||
btc: pattern.btc.cumulative,
|
||||
sats: pattern.sats.cumulative,
|
||||
usd: pattern.usd.cumulative,
|
||||
},
|
||||
name: "all-time",
|
||||
}),
|
||||
bottom: btcSatsUsdSeries({ metrics: pattern.cumulative, name: "all-time" }),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@@ -146,10 +146,10 @@ export function satsBtcUsdBaseline({ pattern, name, color, defaultActive }) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create sats/btc/usd series from any value pattern using sum or cumulative key
|
||||
* Create sats/btc/usd series from any value pattern using base or cumulative key
|
||||
* @param {Object} args
|
||||
* @param {AnyValuePatternType} args.source
|
||||
* @param {'sum' | 'cumulative'} args.key
|
||||
* @param {'base' | 'cumulative'} args.key
|
||||
* @param {string} args.name
|
||||
* @param {Color} [args.color]
|
||||
* @param {boolean} [args.defaultActive]
|
||||
@@ -157,11 +157,7 @@ export function satsBtcUsdBaseline({ pattern, name, color, defaultActive }) {
|
||||
*/
|
||||
export function satsBtcUsdFrom({ source, key, name, color, defaultActive }) {
|
||||
return satsBtcUsd({
|
||||
pattern: {
|
||||
btc: source.btc[key],
|
||||
sats: source.sats[key],
|
||||
usd: source.usd[key],
|
||||
},
|
||||
pattern: source[key],
|
||||
name,
|
||||
color,
|
||||
defaultActive,
|
||||
@@ -169,10 +165,10 @@ export function satsBtcUsdFrom({ source, key, name, color, defaultActive }) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create sats/btc/usd series from a full value pattern using base or average key
|
||||
* Create sats/btc/usd series from a full value pattern using base or cumulative key
|
||||
* @param {Object} args
|
||||
* @param {FullValuePattern} args.source
|
||||
* @param {'base' | 'average'} args.key
|
||||
* @param {'base' | 'cumulative'} args.key
|
||||
* @param {string} args.name
|
||||
* @param {Color} [args.color]
|
||||
* @param {boolean} [args.defaultActive]
|
||||
@@ -186,11 +182,7 @@ export function satsBtcUsdFromFull({
|
||||
defaultActive,
|
||||
}) {
|
||||
return satsBtcUsd({
|
||||
pattern: {
|
||||
btc: source.btc[key],
|
||||
sats: source.sats[key],
|
||||
usd: source.usd[key],
|
||||
},
|
||||
pattern: source[key],
|
||||
name,
|
||||
color,
|
||||
defaultActive,
|
||||
@@ -203,7 +195,7 @@ export function satsBtcUsdFromFull({
|
||||
* @param {AnyValuePatternType} args.coinbase
|
||||
* @param {AnyValuePatternType} args.subsidy
|
||||
* @param {AnyValuePatternType} args.fee
|
||||
* @param {'sum' | 'cumulative'} args.key
|
||||
* @param {'base' | 'cumulative'} args.key
|
||||
* @returns {FetchedLineSeriesBlueprint[]}
|
||||
*/
|
||||
export function revenueBtcSatsUsd({ coinbase, subsidy, fee, key }) {
|
||||
@@ -229,6 +221,47 @@ export function revenueBtcSatsUsd({ coinbase, subsidy, fee, key }) {
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create sats/btc/usd series from a rolling window (24h/7d/30d/1y sum)
|
||||
* @param {Object} args
|
||||
* @param {AnyValuePattern} args.pattern - A BtcSatsUsdPattern (e.g., source.rolling._24h.sum)
|
||||
* @param {string} args.name
|
||||
* @param {Color} [args.color]
|
||||
* @param {boolean} [args.defaultActive]
|
||||
* @returns {FetchedLineSeriesBlueprint[]}
|
||||
*/
|
||||
export function satsBtcUsdRolling({ pattern, name, color, defaultActive }) {
|
||||
return satsBtcUsd({ pattern, name, color, defaultActive });
|
||||
}
|
||||
|
||||
/**
|
||||
* Create coinbase/subsidy/fee rolling sum series from separate sources
|
||||
* @param {Object} args
|
||||
* @param {AnyValuePattern} args.coinbase - Rolling sum pattern (e.g., mining.rewards.coinbase.rolling._24h.sum)
|
||||
* @param {AnyValuePattern} args.subsidy
|
||||
* @param {AnyValuePattern} args.fee
|
||||
* @returns {FetchedLineSeriesBlueprint[]}
|
||||
*/
|
||||
export function revenueRollingBtcSatsUsd({ coinbase, subsidy, fee }) {
|
||||
return [
|
||||
...satsBtcUsd({
|
||||
pattern: coinbase,
|
||||
name: "Coinbase",
|
||||
color: colors.mining.coinbase,
|
||||
}),
|
||||
...satsBtcUsd({
|
||||
pattern: subsidy,
|
||||
name: "Subsidy",
|
||||
color: colors.mining.subsidy,
|
||||
}),
|
||||
...satsBtcUsd({
|
||||
pattern: fee,
|
||||
name: "Fees",
|
||||
color: colors.mining.fee,
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Build percentile USD mappings from a ratio pattern
|
||||
* @param {AnyRatioPattern} ratio
|
||||
|
||||
@@ -163,9 +163,8 @@
|
||||
* - AgeRangePattern (ageRange.*)
|
||||
* @typedef {LongTermPattern | AgeRangePattern} PatternWithPercentiles
|
||||
*
|
||||
* Patterns with RelToMarketCap in relative (RelativePattern):
|
||||
* - BasicUtxoPattern (minAge.*, geAmount.*, ltAmount.*)
|
||||
* @typedef {BasicUtxoPattern} PatternBasicWithMarketCap
|
||||
* Patterns with RelToMarketCap in relative (geAmount.*, ltAmount.*):
|
||||
* @typedef {UtxoAmountPattern | AddressAmountPattern} PatternBasicWithMarketCap
|
||||
*
|
||||
* Patterns without RelToMarketCap in relative (RelativePattern4):
|
||||
* - EpochPattern (epoch.*, amountRange.*, year.*, type.*)
|
||||
|
||||
@@ -45,7 +45,7 @@ export function init() {
|
||||
const usdPrice = {
|
||||
type: "Candlestick",
|
||||
title: "Price",
|
||||
metric: brk.metrics.prices.ohlc.usd,
|
||||
metric: brk.metrics.prices.ohlc.usd.day1,
|
||||
};
|
||||
result.set(Unit.usd, [usdPrice, ...(optionTop.get(Unit.usd) ?? [])]);
|
||||
|
||||
@@ -54,7 +54,7 @@ export function init() {
|
||||
const satsPrice = {
|
||||
type: "Candlestick",
|
||||
title: "Price",
|
||||
metric: brk.metrics.prices.ohlc.sats,
|
||||
metric: brk.metrics.prices.ohlc.sats.day1,
|
||||
colors: /** @type {const} */ ([colors.bi.p1[1], colors.bi.p1[0]]),
|
||||
};
|
||||
result.set(Unit.sats, [satsPrice, ...(optionTop.get(Unit.sats) ?? [])]);
|
||||
|
||||
@@ -33,40 +33,41 @@
|
||||
* @typedef {Brk.MetricsTree_Distribution_UtxoCohorts} UtxoCohortTree
|
||||
* @typedef {Brk.MetricsTree_Distribution_AddressCohorts} AddressCohortTree
|
||||
* @typedef {Brk.MetricsTree_Distribution_UtxoCohorts_All} AllUtxoPattern
|
||||
* @typedef {Brk.MetricsTree_Distribution_UtxoCohorts_Term_Short} ShortTermPattern
|
||||
* @typedef {Brk.MetricsTree_Distribution_UtxoCohorts_Term_Long} LongTermPattern
|
||||
* @typedef {Brk.MetricsTree_Distribution_UtxoCohorts_Sth} ShortTermPattern
|
||||
* @typedef {Brk.ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern} LongTermPattern
|
||||
* @typedef {Brk.MetricsTree_Distribution_UtxoCohorts_All_Relative} AllRelativePattern
|
||||
* @typedef {keyof Brk.BtcSatsUsdPattern} BtcSatsUsdKey
|
||||
* @typedef {Brk.BtcSatsUsdPattern} SupplyPattern
|
||||
* @typedef {Brk.MetricsTree_Blocks_Size} BlockSizePattern
|
||||
* @typedef {Brk.AverageCumulativeMaxMedianMinPct10Pct25Pct75Pct90SumPattern} BlockSizePattern
|
||||
* @typedef {keyof Brk.MetricsTree_Distribution_UtxoCohorts_Type} SpendableType
|
||||
* @typedef {keyof Brk.MetricsTree_Distribution_AnyAddressIndexes} AddressableType
|
||||
*
|
||||
* Brk pattern types (using new pattern names)
|
||||
* @typedef {Brk.ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern5} MaxAgePattern
|
||||
* @typedef {Brk.ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4} MaxAgePattern
|
||||
* @typedef {Brk.ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern} AgeRangePattern
|
||||
* @typedef {Brk.ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern3} UtxoAmountPattern
|
||||
* @typedef {Brk.ActivityAddrCostOutputsRealizedRelativeSupplyUnrealizedPattern} AddressAmountPattern
|
||||
* @typedef {Brk.ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4} BasicUtxoPattern
|
||||
* MinAgePattern: minAge cohorts have peakRegret in unrealized (Pattern6)
|
||||
* @typedef {Brk.ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern6} MinAgePattern
|
||||
* MinAgePattern: minAge cohorts have peakRegret in unrealized
|
||||
* @typedef {Brk.ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern5} MinAgePattern
|
||||
* @typedef {Brk.ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern3} EpochPattern
|
||||
* @typedef {Brk.ActivityCostOutputsRealizedSupplyUnrealizedPattern} EmptyPattern
|
||||
* @typedef {Brk.ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern3} EmptyPattern
|
||||
* @typedef {Brk._0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdSmaZscorePattern} Ratio1ySdPattern
|
||||
* @typedef {Brk.Dollars} Dollars
|
||||
* CoinbasePattern: patterns with btc/sats/usd each having base + sum + cumulative + stats
|
||||
* @typedef {Brk.BtcSatsUsdPattern3} CoinbasePattern
|
||||
* CoinbasePattern: base + cumulative + rolling windows (flattened)
|
||||
* @typedef {Brk._1y24h30d7dBaseCumulativePattern} CoinbasePattern
|
||||
* ActivePriceRatioPattern: ratio pattern with price (extended)
|
||||
* @typedef {Brk.PriceRatioPattern} ActivePriceRatioPattern
|
||||
* AnyRatioPattern: full ratio patterns (with or without price) - has ratio, percentiles, z-scores
|
||||
* @typedef {Brk.RatioPattern | Brk.PriceRatioPattern} AnyRatioPattern
|
||||
* ValuePattern: patterns with minimal stats (sum, cumulative only) for btc/sats/usd
|
||||
* @typedef {Brk.BtcSatsUsdPattern5 | Brk.BtcSatsUsdPattern2} ValuePattern
|
||||
* FullValuePattern: patterns with full stats (base, sum, cumulative, average, percentiles) for btc/sats/usd
|
||||
* @typedef {Brk.BtcSatsUsdPattern3} FullValuePattern
|
||||
* SumValuePattern: patterns with sum stats (sum, cumulative, average, percentiles - no base) for bitcoin/sats/dollars
|
||||
* @typedef {{btc: SumStatsPattern<any>, sats: SumStatsPattern<any>, usd: SumStatsPattern<any>}} SumValuePattern
|
||||
* ValuePattern: patterns with base + cumulative (no rolling)
|
||||
* @typedef {Brk.BaseCumulativeSumPattern | Brk.BaseCumulativePattern} ValuePattern
|
||||
* FullValuePattern: base + cumulative + rolling windows (flattened)
|
||||
* @typedef {Brk._1y24h30d7dBaseCumulativePattern} FullValuePattern
|
||||
* RollingWindowSlot: a single rolling window with stats (average, pct10, pct25, median, pct75, pct90, max, min, sum) per unit
|
||||
* @typedef {Brk.AverageMaxMedianMinPct10Pct25Pct75Pct90SumPattern2} RollingWindowSlot
|
||||
* AnyValuePatternType: union of all value pattern types
|
||||
* @typedef {ValuePattern | FullValuePattern} AnyValuePatternType
|
||||
* @typedef {Brk._1y24h30d7dBaseCumulativePattern | Brk.BaseCumulativeSumPattern | Brk.BaseCumulativePattern} AnyValuePatternType
|
||||
* @typedef {Brk.AnyMetricPattern} AnyMetricPattern
|
||||
* @typedef {Brk.SatsUsdPattern} ActivePricePattern
|
||||
* @typedef {Brk.AnyMetricEndpointBuilder} AnyMetricEndpoint
|
||||
@@ -78,11 +79,11 @@
|
||||
* - GlobalPeakRelativePattern: GlobalRelativePattern + unrealizedPeakRegretRelToMarketCap
|
||||
* - OwnRelativePattern: has RelToOwnMarketCap metrics (netUnrealizedPnlRelToOwnMarketCap, etc)
|
||||
* - FullRelativePattern: has BOTH RelToMarketCap AND RelToOwnMarketCap + unrealizedPeakRegretRelToMarketCap
|
||||
* @typedef {Brk.InvestedSupplyPattern} BasicRelativePattern
|
||||
* @typedef {Brk.InvestedNegNetNuplSupplyUnrealizedPattern} BasicRelativePattern
|
||||
* @typedef {Brk.InvestedNegNetNuplSupplyUnrealizedPattern} GlobalRelativePattern
|
||||
* @typedef {Brk.InvestedNegNetNuplSupplyUnrealizedPattern3} GlobalPeakRelativePattern
|
||||
* @typedef {Brk.InvestedNegNetSupplyUnrealizedPattern} OwnRelativePattern
|
||||
* @typedef {Brk.InvestedNegNetNuplSupplyUnrealizedPattern4} FullRelativePattern
|
||||
* @typedef {Brk.InvestedNegNetNuplSupplyUnrealizedPattern4} GlobalPeakRelativePattern
|
||||
* @typedef {Brk.InvestedNegNetNuplSupplyUnrealizedPattern2} OwnRelativePattern
|
||||
* @typedef {Brk.InvestedNegNetNuplSupplyUnrealizedPattern2} FullRelativePattern
|
||||
* @typedef {Brk.GreedInvestedInvestorNegNetPainSupplyTotalUnrealizedPattern} UnrealizedPattern
|
||||
* @typedef {Brk.GreedInvestedInvestorNegNetPainPeakSupplyTotalUnrealizedPattern} UnrealizedFullPattern
|
||||
*
|
||||
@@ -98,37 +99,43 @@
|
||||
* @typedef {Brk.MetricEndpointBuilder<T>} MetricEndpoint
|
||||
*/
|
||||
/**
|
||||
* Stats pattern: average, min, max, percentiles (NO base)
|
||||
* Stats pattern: average, min, max, percentiles (height-only indexes, NO base)
|
||||
* @template T
|
||||
* @typedef {Brk.AverageMaxMedianMinPct10Pct25Pct75Pct90TxindexPattern<T>} StatsPattern
|
||||
* @typedef {Brk.AverageMaxMedianMinPct10Pct25Pct75Pct90Pattern<T>} StatsPattern
|
||||
*/
|
||||
/**
|
||||
* Base stats pattern: base, average, min, max, percentiles (NO sum/cumulative)
|
||||
* Base stats pattern: height, average, min, max, percentiles (windowed, NO sum/cumulative)
|
||||
* @template T
|
||||
* @typedef {Brk.AverageBaseMaxMedianMinPct10Pct25Pct75Pct90Pattern<T>} BaseStatsPattern
|
||||
* @typedef {Brk.AverageHeightMaxMedianMinPct10Pct25Pct75Pct90Pattern<T>} BaseStatsPattern
|
||||
*/
|
||||
/**
|
||||
* Full stats pattern: base, average, sum, cumulative, min, max, percentiles
|
||||
* @template T
|
||||
* @typedef {Brk.AverageBaseCumulativeMaxMedianMinPct10Pct25Pct75Pct90SumPattern<T>} FullStatsPattern
|
||||
* Full stats pattern: cumulative, sum, average, min, max, percentiles + rolling
|
||||
* @typedef {Brk.AverageCumulativeMaxMedianMinPct10Pct25Pct75Pct90RollingSumPattern} FullStatsPattern
|
||||
*/
|
||||
/**
|
||||
* Sum stats pattern: average, sum, cumulative, percentiles (NO base)
|
||||
* @template T
|
||||
* @typedef {Brk.AverageCumulativeMaxMedianMinPct10Pct25Pct75Pct90SumPattern2<T>} SumStatsPattern
|
||||
* Sum stats pattern: cumulative, sum, average, min, max, percentiles + rolling (same as FullStatsPattern)
|
||||
* @typedef {Brk.AverageCumulativeMaxMedianMinPct10Pct25Pct75Pct90RollingSumPattern} SumStatsPattern
|
||||
*/
|
||||
/**
|
||||
* Full stats pattern for Bitcoin (non-generic variant with btc-specific indexes)
|
||||
* @typedef {Brk.AverageBaseCumulativeMaxMedianMinPct10Pct25Pct75Pct90SumPattern2} BtcFullStatsPattern
|
||||
* Full stats pattern for Bitcoin (non-generic variant) - same as FullStatsPattern
|
||||
* @typedef {Brk.AverageCumulativeMaxMedianMinPct10Pct25Pct75Pct90RollingSumPattern} BtcFullStatsPattern
|
||||
*/
|
||||
/**
|
||||
* Count pattern: sum and cumulative only
|
||||
* Count pattern: height, cumulative, and rolling sum windows
|
||||
* @template T
|
||||
* @typedef {Brk.CumulativeSumPattern<T>} CountPattern
|
||||
* @typedef {Brk.CumulativeHeightSumPattern<T>} CountPattern
|
||||
*/
|
||||
/**
|
||||
* Full per-block pattern: height, cumulative, sum, and distribution stats (all flat)
|
||||
* @typedef {Brk.AverageCumulativeHeightMaxMedianMinPct10Pct25Pct75Pct90SumPattern} FullPerBlockPattern
|
||||
*/
|
||||
/**
|
||||
* Any stats pattern union - patterns with sum/cumulative + percentiles
|
||||
* @typedef {SumStatsPattern<any> | FullStatsPattern<any> | BtcFullStatsPattern | BlockSizePattern} AnyStatsPattern
|
||||
* @typedef {FullStatsPattern | BtcFullStatsPattern} AnyStatsPattern
|
||||
*/
|
||||
/**
|
||||
* Distribution stats: 8 metric fields (average, min, max, median, pct10/25/75/90)
|
||||
* @typedef {{ average: AnyMetricPattern, min: AnyMetricPattern, max: AnyMetricPattern, median: AnyMetricPattern, pct10: AnyMetricPattern, pct25: AnyMetricPattern, pct75: AnyMetricPattern, pct90: AnyMetricPattern }} DistributionStats
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -144,7 +151,7 @@
|
||||
* @typedef {Brk.MetricsTree_Market_Dca} MarketDca
|
||||
* @typedef {Brk._10y2y3y4y5y6y8yPattern} PeriodCagrPattern
|
||||
* Full stats pattern union (both generic and non-generic variants)
|
||||
* @typedef {FullStatsPattern<any> | BtcFullStatsPattern} AnyFullStatsPattern
|
||||
* @typedef {FullStatsPattern | BtcFullStatsPattern} AnyFullStatsPattern
|
||||
*
|
||||
* DCA period keys - derived from pattern types
|
||||
* @typedef {keyof Brk._10y2y3y4y5y6y8yPattern} LongPeriodKey
|
||||
|
||||
Reference in New Issue
Block a user