mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-07-14 12:38:13 -07:00
general: snapshot
This commit is contained in:
@@ -127,7 +127,7 @@ function createAddressPresetFolder<Scale extends ResourceScale>({
|
||||
scale: Scale;
|
||||
name: string;
|
||||
datasetKey: AddressCohortKey;
|
||||
color: string;
|
||||
color: Color;
|
||||
}): PartialPresetFolder {
|
||||
return {
|
||||
name,
|
||||
@@ -159,7 +159,7 @@ export function createLiquidityFolder<Scale extends ResourceScale>({
|
||||
scale: Scale;
|
||||
name: string;
|
||||
datasetKey: AddressCohortKey | "";
|
||||
color: string;
|
||||
color: Color;
|
||||
}): PartialPresetFolder {
|
||||
return {
|
||||
name: `Split By Liquidity`,
|
||||
@@ -189,7 +189,7 @@ export function createAddressCountPreset<Scale extends ResourceScale>({
|
||||
scale: Scale;
|
||||
name: string;
|
||||
datasetKey: AddressCohortKey;
|
||||
color: string;
|
||||
color: Color;
|
||||
}): PartialPreset {
|
||||
return {
|
||||
scale,
|
||||
|
||||
@@ -11,7 +11,11 @@ import { createHistogramSeries } from "../lightweightCharts/histogram";
|
||||
import { createSeriesLegend } from "../lightweightCharts/legend";
|
||||
import { createLineSeries } from "../lightweightCharts/line";
|
||||
import { setMinMaxMarkers } from "../lightweightCharts/markers";
|
||||
import { initTimeScale } from "../lightweightCharts/time";
|
||||
import {
|
||||
getInitialTimeRange,
|
||||
initTimeScale,
|
||||
setActiveIds,
|
||||
} from "../lightweightCharts/time";
|
||||
import { setWhitespace } from "../lightweightCharts/whitespace";
|
||||
import { colors } from "../utils/colors";
|
||||
import { debounce } from "../utils/debounce";
|
||||
@@ -27,7 +31,9 @@ export enum SeriesType {
|
||||
type SeriesConfig<Scale extends ResourceScale> =
|
||||
| {
|
||||
dataset: ResourceDataset<Scale>;
|
||||
color?: string;
|
||||
color?: Color;
|
||||
topColor?: Color;
|
||||
bottomColor?: Color;
|
||||
colors?: undefined;
|
||||
seriesType: SeriesType.Based;
|
||||
title: string;
|
||||
@@ -37,8 +43,8 @@ type SeriesConfig<Scale extends ResourceScale> =
|
||||
}
|
||||
| {
|
||||
dataset: ResourceDataset<Scale>;
|
||||
color?: string;
|
||||
colors?: string[];
|
||||
color?: Color;
|
||||
colors?: Color[];
|
||||
seriesType: SeriesType.Histogram;
|
||||
title: string;
|
||||
options?: DeepPartialHistogramOptions;
|
||||
@@ -57,7 +63,7 @@ type SeriesConfig<Scale extends ResourceScale> =
|
||||
}
|
||||
| {
|
||||
dataset: ResourceDataset<Scale>;
|
||||
color: string;
|
||||
color: Color;
|
||||
colors?: undefined;
|
||||
seriesType?: SeriesType.Line;
|
||||
title: string;
|
||||
@@ -78,7 +84,7 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
priceOptions,
|
||||
legendSetter,
|
||||
dark,
|
||||
activeRange,
|
||||
activeIds,
|
||||
}: {
|
||||
charts: RWS<IChartApi[]>;
|
||||
parentDiv: HTMLDivElement;
|
||||
@@ -90,8 +96,8 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
top?: SeriesConfig<Scale>[];
|
||||
bottom?: SeriesConfig<Scale>[];
|
||||
datasets: Datasets;
|
||||
dark: boolean;
|
||||
activeRange: RWS<number[]>;
|
||||
dark: Accessor<boolean>;
|
||||
activeIds: RWS<number[]>;
|
||||
}) {
|
||||
// ---
|
||||
// Reset states
|
||||
@@ -107,8 +113,6 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
return [];
|
||||
});
|
||||
|
||||
activeRange.set([]);
|
||||
|
||||
parentDiv.replaceChildren();
|
||||
|
||||
// ---
|
||||
@@ -124,11 +128,18 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
const activeDatasets: ResourceDataset<any, any>[] = [];
|
||||
|
||||
const lastActiveIndex = createMemo(() => {
|
||||
const last = activeRange().at(-1);
|
||||
const last = activeIds().at(-1);
|
||||
return last !== undefined ? chunkIdToIndex(scale, last) : undefined;
|
||||
});
|
||||
|
||||
const exactRange = createRWS(undefined as TimeRange | undefined);
|
||||
const exactRange = createRWS(getInitialTimeRange(scale));
|
||||
|
||||
setActiveIds({
|
||||
exactRange: exactRange(),
|
||||
activeIds: activeIds,
|
||||
});
|
||||
|
||||
const seriesNumber = 1 + (top || []).length + (bottom || []).length;
|
||||
|
||||
const charts = [top || [], bottom]
|
||||
.flatMap((list) => (list ? [list] : []))
|
||||
@@ -157,16 +168,74 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
|
||||
const whitespace = setWhitespace(chart, scale);
|
||||
|
||||
if (exactRange()) {
|
||||
chart.timeScale().setVisibleRange(exactRange());
|
||||
}
|
||||
|
||||
// const whitespace = new Array<ISeriesApi<"Line"> | undefined>(
|
||||
// scale === "date"
|
||||
// ? whitespaceDateDatasets.length
|
||||
// : whitespaceHeightDatasets.length,
|
||||
// ).fill(undefined);
|
||||
|
||||
// function createWhitespaceSeriesIfNeeded(index: number) {
|
||||
// console.log(index);
|
||||
// if (index >= 0 && index < whitespace.length && !whitespace[index]) {
|
||||
// const series = createLineSeries(chart);
|
||||
// whitespace[index] = series;
|
||||
|
||||
// if (scale === "date") {
|
||||
// series.setData(whitespaceDateDatasets[index]);
|
||||
// } else {
|
||||
// series.setData(whitespaceHeightDatasets[index]);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// createEffect(() => {
|
||||
// const ids = activeIds();
|
||||
// console.log(ids);
|
||||
|
||||
// const idsLength = ids.length;
|
||||
// for (let i = 0; i < idsLength; i++) {
|
||||
// const id = ids[i];
|
||||
|
||||
// const whitespaceIndex = chunkIdToIndex(
|
||||
// scale,
|
||||
// scale === "date"
|
||||
// ? id - whitespaceStartDateYear
|
||||
// : id - whitespaceHeightStart,
|
||||
// );
|
||||
|
||||
// if (i === 0) {
|
||||
// createWhitespaceSeriesIfNeeded(whitespaceIndex - 1);
|
||||
// }
|
||||
|
||||
// createWhitespaceSeriesIfNeeded(whitespaceIndex);
|
||||
|
||||
// if (i === idsLength - 1) {
|
||||
// createWhitespaceSeriesIfNeeded(whitespaceIndex + 1);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
|
||||
const chartLegend: SeriesLegend[] = [];
|
||||
|
||||
const debouncedSetMinMaxMarkers = debounce(() => {
|
||||
function _setMinMaxMarkers() {
|
||||
setMinMaxMarkers({
|
||||
scale,
|
||||
visibleRange: exactRange(),
|
||||
legendList: chartLegend,
|
||||
activeRange,
|
||||
activeIds: activeIds,
|
||||
});
|
||||
}, 50);
|
||||
}
|
||||
|
||||
const debouncedSetMinMaxMarkers = debounce(
|
||||
_setMinMaxMarkers,
|
||||
seriesNumber * 10,
|
||||
);
|
||||
|
||||
createEffect(on(exactRange, debouncedSetMinMaxMarkers));
|
||||
|
||||
if (index === 0) {
|
||||
const dataset =
|
||||
@@ -206,7 +275,7 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
}
|
||||
|
||||
return createSeriesGroup({
|
||||
activeRange,
|
||||
activeIds,
|
||||
seriesConfig,
|
||||
chart,
|
||||
chartLegend,
|
||||
@@ -214,6 +283,7 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
preset,
|
||||
disabled: () => priceSeriesType() !== seriesType,
|
||||
debouncedSetMinMaxMarkers,
|
||||
dark,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -233,13 +303,14 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
activeDatasets.push(seriesConfig.dataset);
|
||||
|
||||
createSeriesGroup({
|
||||
activeRange,
|
||||
activeIds: activeIds,
|
||||
seriesConfig,
|
||||
chartLegend,
|
||||
chart,
|
||||
preset,
|
||||
lastActiveIndex,
|
||||
debouncedSetMinMaxMarkers,
|
||||
dark,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -249,8 +320,6 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
createEffect(on(legend.visible, debouncedSetMinMaxMarkers));
|
||||
});
|
||||
|
||||
createEffect(on(exactRange, debouncedSetMinMaxMarkers));
|
||||
|
||||
return [
|
||||
{
|
||||
scale,
|
||||
@@ -271,7 +340,8 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
chart.div.style.border = "";
|
||||
visibleCharts.push(chart);
|
||||
} else {
|
||||
chart.div.style.height = "0px";
|
||||
chart.div.style.height = "100%";
|
||||
// chart.div.style.height = "0px";
|
||||
chart.div.style.border = "none";
|
||||
}
|
||||
});
|
||||
@@ -296,13 +366,13 @@ export function applySeriesList<Scale extends ResourceScale>({
|
||||
initTimeScale({
|
||||
scale,
|
||||
charts,
|
||||
activeRange,
|
||||
activeIds: activeIds,
|
||||
exactRange,
|
||||
});
|
||||
|
||||
const activeDatasetsLength = activeDatasets.length;
|
||||
createEffect(() => {
|
||||
const range = activeRange();
|
||||
const range = activeIds();
|
||||
|
||||
untrack(() => {
|
||||
for (let i = 0; i < range.length; i++) {
|
||||
@@ -382,7 +452,7 @@ function updateVisiblePriceSeriesType(
|
||||
}
|
||||
|
||||
function createSeriesGroup<Scale extends ResourceScale>({
|
||||
activeRange,
|
||||
activeIds,
|
||||
seriesConfig,
|
||||
preset,
|
||||
chartLegend,
|
||||
@@ -390,8 +460,9 @@ function createSeriesGroup<Scale extends ResourceScale>({
|
||||
disabled,
|
||||
lastActiveIndex,
|
||||
debouncedSetMinMaxMarkers,
|
||||
dark,
|
||||
}: {
|
||||
activeRange: Accessor<number[]>;
|
||||
activeIds: Accessor<number[]>;
|
||||
seriesConfig: SeriesConfig<Scale>;
|
||||
preset: Preset;
|
||||
chart: IChartApi;
|
||||
@@ -399,6 +470,7 @@ function createSeriesGroup<Scale extends ResourceScale>({
|
||||
lastActiveIndex: Accessor<number | undefined>;
|
||||
disabled?: Accessor<boolean>;
|
||||
debouncedSetMinMaxMarkers: VoidFunction;
|
||||
dark: Accessor<boolean>;
|
||||
}) {
|
||||
const {
|
||||
dataset,
|
||||
@@ -417,15 +489,12 @@ function createSeriesGroup<Scale extends ResourceScale>({
|
||||
ISeriesApi<"Baseline" | "Line" | "Histogram" | "Candlestick"> | undefined
|
||||
>[] = new Array(dataset.fetchedJSONs.length);
|
||||
|
||||
let defaultSeriesColor: string | string[] | undefined = undefined;
|
||||
|
||||
const legend = createSeriesLegend({
|
||||
id: stringToId(title),
|
||||
presetId: preset.id,
|
||||
title,
|
||||
seriesList,
|
||||
color: () =>
|
||||
colors || color || defaultSeriesColor || DEFAULT_BASELINE_COLORS,
|
||||
color: colors || color || DEFAULT_BASELINE_COLORS,
|
||||
defaultVisible,
|
||||
disabled,
|
||||
dataset,
|
||||
@@ -448,37 +517,47 @@ function createSeriesGroup<Scale extends ResourceScale>({
|
||||
if (!s) {
|
||||
switch (type) {
|
||||
case SeriesType.Based: {
|
||||
s = createBaseLineSeries(chart, {
|
||||
s = createBaseLineSeries({
|
||||
chart,
|
||||
dark,
|
||||
color,
|
||||
...options,
|
||||
topColor: seriesConfig.topColor,
|
||||
bottomColor: seriesConfig.bottomColor,
|
||||
options,
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
case SeriesType.Candlestick: {
|
||||
const candlestickSeries = createCandlesticksSeries(
|
||||
const candlestickSeries = createCandlesticksSeries({
|
||||
chart,
|
||||
options,
|
||||
);
|
||||
dark,
|
||||
});
|
||||
|
||||
s = candlestickSeries[0];
|
||||
defaultSeriesColor = candlestickSeries[1];
|
||||
|
||||
if (!colors && !color) {
|
||||
legend.color = candlestickSeries[1];
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case SeriesType.Histogram: {
|
||||
s = createHistogramSeries(chart, {
|
||||
color,
|
||||
...options,
|
||||
s = createHistogramSeries({
|
||||
chart,
|
||||
options,
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
case SeriesType.Line: {
|
||||
s = createLineSeries(chart, {
|
||||
s = createLineSeries({
|
||||
chart,
|
||||
color,
|
||||
...options,
|
||||
dark,
|
||||
options,
|
||||
});
|
||||
|
||||
break;
|
||||
@@ -494,9 +573,7 @@ function createSeriesGroup<Scale extends ResourceScale>({
|
||||
|
||||
s.setData(values);
|
||||
|
||||
untrack(() => {
|
||||
debouncedSetMinMaxMarkers();
|
||||
});
|
||||
debouncedSetMinMaxMarkers();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -522,7 +599,7 @@ function createSeriesGroup<Scale extends ResourceScale>({
|
||||
});
|
||||
|
||||
const inRange = createMemo(() => {
|
||||
const range = activeRange();
|
||||
const range = activeIds();
|
||||
|
||||
if (range.length) {
|
||||
const start = chunkIdToIndex(scale, range.at(0)!);
|
||||
|
||||
@@ -540,7 +540,7 @@ export function createPresets<Scale extends ResourceScale>({
|
||||
bottom: [
|
||||
{
|
||||
title: "Concurrent Liveliness 14d Median",
|
||||
color: `${colors.liveliness}66`,
|
||||
color: colors.darkLiveliness,
|
||||
dataset:
|
||||
params.datasets[scale].concurrent_liveliness_2w_median,
|
||||
},
|
||||
@@ -732,13 +732,13 @@ export function createPresets<Scale extends ResourceScale>({
|
||||
bottom: [
|
||||
{
|
||||
title: "Active Supply Net Change",
|
||||
color: `${colors.liveliness}80`,
|
||||
color: colors.liveliness,
|
||||
dataset: params.datasets[scale].active_supply_3m_net_change,
|
||||
seriesType: SeriesType.Based,
|
||||
},
|
||||
{
|
||||
title: "Vaulted Supply Net Change",
|
||||
color: `${colors.vaultedPrice}80`,
|
||||
color: colors.vaultedPrice,
|
||||
seriesType: SeriesType.Based,
|
||||
dataset:
|
||||
params.datasets[scale].vaulted_supply_3m_net_change,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { phone } from "/src/env";
|
||||
import { createRWS } from "/src/solid/rws";
|
||||
|
||||
import { colors } from "../utils/colors";
|
||||
@@ -32,7 +33,7 @@ export function createPresets(): Presets {
|
||||
name: "Charts",
|
||||
tree: [
|
||||
{
|
||||
name: "By Date",
|
||||
name: "By Block Date",
|
||||
tree: [
|
||||
createMarketPresets("date"),
|
||||
createBlocksPresets(),
|
||||
@@ -57,28 +58,30 @@ export function createPresets(): Presets {
|
||||
],
|
||||
} satisfies PartialPresetFolder,
|
||||
{
|
||||
name: "By Height",
|
||||
tree: [
|
||||
createMarketPresets("height"),
|
||||
createMinersPresets("height"),
|
||||
createTransactionsPresets("height"),
|
||||
...createCohortPresetList({
|
||||
scale: "height",
|
||||
color: colors.bitcoin,
|
||||
name: "",
|
||||
datasetKey: "",
|
||||
title: "",
|
||||
}),
|
||||
createLiquidityFolder({
|
||||
scale: "height",
|
||||
color: colors.bitcoin,
|
||||
datasetKey: "",
|
||||
name: "",
|
||||
}),
|
||||
createHodlersPresets({ scale: "height" }),
|
||||
createAddressesPresets({ scale: "height" }),
|
||||
createCoinblocksPresets({ scale: "height" }),
|
||||
],
|
||||
name: "By Block Height - Desktop/Tablet Only",
|
||||
tree: !phone
|
||||
? [
|
||||
createMarketPresets("height"),
|
||||
createMinersPresets("height"),
|
||||
createTransactionsPresets("height"),
|
||||
...createCohortPresetList({
|
||||
scale: "height",
|
||||
color: colors.bitcoin,
|
||||
name: "",
|
||||
datasetKey: "",
|
||||
title: "",
|
||||
}),
|
||||
createLiquidityFolder({
|
||||
scale: "height",
|
||||
color: colors.bitcoin,
|
||||
datasetKey: "",
|
||||
name: "",
|
||||
}),
|
||||
createHodlersPresets({ scale: "height" }),
|
||||
createAddressesPresets({ scale: "height" }),
|
||||
createCoinblocksPresets({ scale: "height" }),
|
||||
]
|
||||
: [],
|
||||
} satisfies PartialPresetFolder,
|
||||
],
|
||||
},
|
||||
@@ -263,7 +266,14 @@ function checkIfDuplicateIds(ids: string[]) {
|
||||
}
|
||||
|
||||
function findInitialPreset(presets: Preset[]): Preset {
|
||||
const urlPreset = document.location.pathname.substring(1);
|
||||
let urlPreset = document.location.pathname.substring(1);
|
||||
|
||||
if (phone && urlPreset.startsWith("height" satisfies ResourceScale)) {
|
||||
urlPreset = urlPreset.replace(
|
||||
"height" satisfies ResourceScale,
|
||||
"date" satisfies ResourceScale,
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
(urlPreset &&
|
||||
|
||||
@@ -45,7 +45,7 @@ function createPresetFolder({
|
||||
key,
|
||||
}: {
|
||||
scale: ResourceScale;
|
||||
color: string;
|
||||
color: Color;
|
||||
name: string;
|
||||
key: AverageName;
|
||||
}) {
|
||||
|
||||
@@ -12,7 +12,7 @@ export function createCohortPresetFolder<Scale extends ResourceScale>({
|
||||
scale: Scale;
|
||||
name: string;
|
||||
datasetKey: AnyPossibleCohortKey;
|
||||
color: string;
|
||||
color: Color;
|
||||
title: string;
|
||||
}) {
|
||||
return {
|
||||
@@ -38,7 +38,7 @@ export function createCohortPresetList<Scale extends ResourceScale>({
|
||||
scale: Scale;
|
||||
datasetKey: AnyPossibleCohortKey;
|
||||
title: string;
|
||||
color: string;
|
||||
color: Color;
|
||||
}) {
|
||||
const datasetPrefix = datasetKey
|
||||
? (`${datasetKey}_` as const)
|
||||
|
||||
Vendored
+2
-2
@@ -25,8 +25,8 @@ type ApplyPreset = (params: {
|
||||
datasets: Datasets;
|
||||
preset: Preset;
|
||||
legendSetter: Setter<SeriesLegend[]>;
|
||||
dark: boolean;
|
||||
activeRange: RWS<number[]>;
|
||||
dark: Accessor<boolean>;
|
||||
activeIds: RWS<number[]>;
|
||||
}) => void;
|
||||
|
||||
interface PartialPresetFolder {
|
||||
|
||||
Reference in New Issue
Block a user