mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-06-08 14:11:56 -07:00
websites: snapshot + todo: init
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
# TODO
|
||||
|
||||
- __crates__
|
||||
- _cli_
|
||||
- check disk space on first launch
|
||||
- add custom path support for config.toml
|
||||
- maybe add bitcoind download and launch support
|
||||
- via: https://github.com/rust-bitcoin/corepc/blob/master/node
|
||||
- test read/write speed, add warning if too low (<2gb/s)
|
||||
- pull latest version and notify is out of date
|
||||
- _computer_
|
||||
- **add rollback of states (in stateful)**
|
||||
- add support for per index computation
|
||||
- fix feerate which is always ZERO due to coinbase transaction
|
||||
- before computing multiple sources check their length, panic if not equal
|
||||
- add oracle price dataset (https://utxo.live/oracle/UTXOracle.py)
|
||||
- add address counts relative to all datasets
|
||||
- make decade, quarter, year datasets `computed` instead of `eager`
|
||||
- add 6 months interval datasets to builder
|
||||
- add revived/sent supply datasets
|
||||
- add `in-sats` version of all price datasets (average and co)
|
||||
- add `p2pk` group (sum of `p2pk33` and `p2pk65`)
|
||||
- add more date ranges (3-6 months and more)
|
||||
- add puell multiple dataset
|
||||
- add pi cycle dataset
|
||||
- add all possible charts from:
|
||||
- https://mainnet.observer
|
||||
- https://glassnode.com
|
||||
- https://checkonchain.com
|
||||
- https://researchbitcoin.net/exciting-update-coming-to-the-bitcoin-lab/
|
||||
- https://mempool.space/research
|
||||
- _indexer_
|
||||
- parse only the needed block number
|
||||
- maybe using https://developer.bitcoin.org/reference/rpc/getblockhash.html
|
||||
- _interface_
|
||||
- create pagination enum
|
||||
- from to
|
||||
- from option<count>
|
||||
- to option<count>
|
||||
- page + option<per page> default 1000 max 1000
|
||||
- from/to/count params don’t cap all combinations
|
||||
- example: from -10,000 count 10, won’t work if underlying vec isn’t 10k or more long
|
||||
- _parser_
|
||||
- save `vec` file instead of `json`
|
||||
- support lock file, process in read only if already opened in write mode
|
||||
- if less than X (10 maybe ?) get block using rpc instead of parsing the block files
|
||||
- _server_
|
||||
- api
|
||||
- add extensions support (.json .csv …)
|
||||
- if format instead of extension then don't download file
|
||||
- _vec_
|
||||
- add native lock file support (once it's available in stable rust)
|
||||
- improve compressed mode (slow reads)
|
||||
- __docs__
|
||||
- _README_
|
||||
- add a comparison table with alternatives
|
||||
- add contribution section where help is needed
|
||||
- documentation/mcp/datasets/different front ends
|
||||
- add faq
|
||||
- __websites__
|
||||
- _default_
|
||||
- explorer
|
||||
- blocks
|
||||
- transactions
|
||||
- addresses
|
||||
- miners
|
||||
- maybe xpubs
|
||||
- charts
|
||||
- improve some names and colors
|
||||
- remove `sum` series when it's a duplicate of the `base` (in subsidy for example)
|
||||
- selected unit sometimes changes when going back end forth
|
||||
- add support for custom charts
|
||||
- price scale format depends on unit, hide digits for sats for example (if/when possible)
|
||||
- table
|
||||
- pagination
|
||||
- exports (.json, .csv,…)
|
||||
- search
|
||||
- datasets add legend, and keywords ?
|
||||
- height/address/txid
|
||||
- api
|
||||
- add api page with interactivity
|
||||
- global
|
||||
- **fix navigation/history**
|
||||
- move share button to footer ?
|
||||
- improve behavior when local storage is unavailable
|
||||
- by having a global state
|
||||
@@ -24,6 +24,7 @@ where
|
||||
pub difficultyepoch: ComputedVecBuilder<DifficultyEpoch, T>,
|
||||
pub monthindex: ComputedVecBuilder<MonthIndex, T>,
|
||||
pub quarterindex: ComputedVecBuilder<QuarterIndex, T>,
|
||||
// 6 months
|
||||
pub yearindex: ComputedVecBuilder<YearIndex, T>,
|
||||
// TODO: pub halvingepoch: StorableVecGeneator<Halvingepoch, T>,
|
||||
pub decadeindex: ComputedVecBuilder<DecadeIndex, T>,
|
||||
@@ -144,9 +145,9 @@ where
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
height: Option<&impl AnyIterableVec<Height, T>>,
|
||||
height_vec: Option<&impl AnyIterableVec<Height, T>>,
|
||||
) -> color_eyre::Result<()> {
|
||||
if let Some(height) = height {
|
||||
if let Some(height) = height_vec {
|
||||
self.height_extra
|
||||
.extend(starting_indexes.height, height, exit)?;
|
||||
|
||||
|
||||
@@ -10,7 +10,9 @@ use brk_vec::{
|
||||
use crate::{
|
||||
states::AddressCohortState,
|
||||
vecs::{
|
||||
Indexes, fetched, indexes, market,
|
||||
Indexes, fetched,
|
||||
grouped::{ComputedVecsFromHeight, StorableVecGeneatorOptions},
|
||||
indexes, market,
|
||||
stateful::{
|
||||
common,
|
||||
r#trait::{CohortVecs, DynCohortVecs},
|
||||
@@ -26,9 +28,10 @@ pub struct Vecs {
|
||||
|
||||
pub state: AddressCohortState,
|
||||
|
||||
pub height_to_address_count: EagerVec<Height, StoredUsize>,
|
||||
|
||||
pub inner: common::Vecs,
|
||||
|
||||
pub height_to_address_count: EagerVec<Height, StoredUsize>,
|
||||
pub indexes_to_address_count: ComputedVecsFromHeight<StoredUsize>,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
@@ -60,6 +63,14 @@ impl Vecs {
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
)?,
|
||||
indexes_to_address_count: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
&suffix("address_count"),
|
||||
false,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
inner: common::Vecs::forced_import(
|
||||
path,
|
||||
cohort_name,
|
||||
@@ -160,12 +171,24 @@ impl DynCohortVecs for Vecs {
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> color_eyre::Result<()> {
|
||||
self.indexes_to_address_count.compute_rest(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(&self.height_to_address_count),
|
||||
)?;
|
||||
|
||||
self.inner
|
||||
.compute_rest_part1(indexer, indexes, fetched, starting_indexes, exit)
|
||||
}
|
||||
|
||||
fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
||||
[self.inner.vecs(), vec![&self.height_to_address_count]].concat()
|
||||
[
|
||||
self.inner.vecs(),
|
||||
self.indexes_to_address_count.vecs(),
|
||||
vec![&self.height_to_address_count],
|
||||
]
|
||||
.concat()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::{cmp::Ordering, collections::BTreeMap, mem, path::Path, thread};
|
||||
|
||||
use brk_core::{
|
||||
AddressData, CheckedSub, DateIndex, Dollars, EmptyAddressData, GroupedByAddressType, Height,
|
||||
InputIndex, OutputIndex, OutputType, Result, Sats, TypeIndex, Version,
|
||||
InputIndex, OutputIndex, OutputType, Result, Sats, StoredUsize, TypeIndex, Version,
|
||||
};
|
||||
use brk_exit::Exit;
|
||||
use brk_indexer::Indexer;
|
||||
@@ -17,6 +17,7 @@ use crate::{
|
||||
BlockState, SupplyState, Transacted,
|
||||
stores::Stores,
|
||||
vecs::{
|
||||
grouped::ComputedVecsFromHeight,
|
||||
market,
|
||||
stateful::{
|
||||
addresstype_to_addresscount::AddressTypeToAddressCount,
|
||||
@@ -52,18 +53,19 @@ const VERSION: Version = Version::new(11);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Vecs {
|
||||
chain_state: StoredVec<Height, SupplyState>,
|
||||
pub chain_state: StoredVec<Height, SupplyState>,
|
||||
|
||||
pub height_to_unspendable_supply: EagerVec<Height, Sats>,
|
||||
pub indexes_to_unspendable_supply: ComputedValueVecsFromHeight,
|
||||
pub height_to_opreturn_supply: EagerVec<Height, Sats>,
|
||||
pub indexes_to_opreturn_supply: ComputedValueVecsFromHeight,
|
||||
// pub height_to_address_count: EagerVec<Height, StoredUsize>,
|
||||
// pub height_to_empty_address_count: EagerVec<Height, StoredUsize>,
|
||||
pub addresstype_to_height_to_address_count: AddressTypeToAddressCountVec,
|
||||
pub addresstype_to_height_to_empty_address_count: AddressTypeToAddressCountVec,
|
||||
pub utxo_vecs: utxo_cohorts::Vecs,
|
||||
pub address_vecs: address_cohorts::Vecs,
|
||||
|
||||
pub indexes_to_address_count: ComputedVecsFromHeight<StoredUsize>,
|
||||
pub indexes_to_empty_address_count: ComputedVecsFromHeight<StoredUsize>,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
@@ -119,18 +121,22 @@ impl Vecs {
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
compute_dollars,
|
||||
)?,
|
||||
// height_to_address_count: EagerVec::forced_import(
|
||||
// path,
|
||||
// "address_count",
|
||||
// version + VERSION + Version::ZERO,
|
||||
// format,
|
||||
// )?,
|
||||
// height_to_empty_address_count: EagerVec::forced_import(
|
||||
// path,
|
||||
// "empty_address_count",
|
||||
// version + VERSION + Version::ZERO,
|
||||
// format,
|
||||
// )?,
|
||||
indexes_to_address_count: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"address_count",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_empty_address_count: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"empty_address_count",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
addresstype_to_height_to_address_count: AddressTypeToAddressCountVec::from(
|
||||
GroupedByAddressType {
|
||||
p2pk65: EagerVec::forced_import(
|
||||
@@ -976,6 +982,7 @@ impl Vecs {
|
||||
.as_mut()
|
||||
.map(|v| is_date_last_height.then(|| *v.unwrap_get_inner(dateindex)));
|
||||
|
||||
let dateindex = is_date_last_height.then_some(dateindex);
|
||||
separate_utxo_vecs
|
||||
.into_par_iter()
|
||||
.map(|(_, v)| v as &mut dyn DynCohortVecs).chain(
|
||||
@@ -987,7 +994,7 @@ impl Vecs {
|
||||
v.compute_then_force_push_unrealized_states(
|
||||
height,
|
||||
price,
|
||||
is_date_last_height.then_some(dateindex),
|
||||
dateindex,
|
||||
date_price,
|
||||
exit,
|
||||
)
|
||||
@@ -1039,6 +1046,44 @@ impl Vecs {
|
||||
|
||||
info!("Computing rest part 1...");
|
||||
|
||||
self.indexes_to_address_count.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_sum_of_others(
|
||||
starting_indexes.height,
|
||||
&self
|
||||
.addresstype_to_height_to_address_count
|
||||
.as_typed_vec()
|
||||
.into_iter()
|
||||
.map(|(_, v)| v)
|
||||
.collect::<Vec<_>>(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_empty_address_count.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_sum_of_others(
|
||||
starting_indexes.height,
|
||||
&self
|
||||
.addresstype_to_height_to_empty_address_count
|
||||
.as_typed_vec()
|
||||
.into_iter()
|
||||
.map(|(_, v)| v)
|
||||
.collect::<Vec<_>>(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
thread::scope(|scope| {
|
||||
scope.spawn(|| {
|
||||
self.utxo_vecs
|
||||
@@ -1194,6 +1239,8 @@ impl Vecs {
|
||||
.collect::<Vec<_>>(),
|
||||
self.indexes_to_unspendable_supply.vecs(),
|
||||
self.indexes_to_opreturn_supply.vecs(),
|
||||
self.indexes_to_address_count.vecs(),
|
||||
self.indexes_to_empty_address_count.vecs(),
|
||||
self.addresstype_to_height_to_address_count
|
||||
.as_typed_vec()
|
||||
.into_iter()
|
||||
@@ -1207,8 +1254,6 @@ impl Vecs {
|
||||
vec![
|
||||
&self.height_to_unspendable_supply,
|
||||
&self.height_to_opreturn_supply,
|
||||
// &self.height_to_address_count,
|
||||
// &self.height_to_empty_address_count,
|
||||
],
|
||||
]
|
||||
.into_iter()
|
||||
|
||||
+38
-10
@@ -274,8 +274,6 @@
|
||||
--default-main-width: 25rem;
|
||||
|
||||
--bottom-area: 69vh;
|
||||
|
||||
--cube: 50px;
|
||||
}
|
||||
|
||||
[data-resize] {
|
||||
@@ -1370,41 +1368,71 @@
|
||||
}
|
||||
|
||||
#explorer {
|
||||
--cube: 4.5rem;
|
||||
|
||||
#chain {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: calc(var(--cube) * 1.1);
|
||||
padding: 1rem;
|
||||
flex-direction: column-reverse;
|
||||
gap: calc(var(--cube) * 0.66);
|
||||
padding: 2rem;
|
||||
|
||||
.cube {
|
||||
width: var(--cube);
|
||||
height: var(--cube);
|
||||
overflow: hidden;
|
||||
font-size: var(--font-size-sm);
|
||||
line-height: var(--line-height-sm);
|
||||
--color: var(--dark-gray);
|
||||
color: var(--white);
|
||||
|
||||
.face {
|
||||
transform-origin: 0 0;
|
||||
position: absolute;
|
||||
width: var(--cube);
|
||||
height: var(--cube);
|
||||
padding: 0.1rem;
|
||||
}
|
||||
.front {
|
||||
background-color: var(--orange);
|
||||
.right {
|
||||
background-color: var(--color);
|
||||
transform: rotate(-30deg) skewX(-30deg)
|
||||
translate(calc(var(--cube) * 1.3), calc(var(--cube) * 1.725))
|
||||
scaleY(0.864);
|
||||
}
|
||||
.top {
|
||||
background-color: var(--yellow);
|
||||
background-color: oklch(
|
||||
from var(--color) calc(l + 0.122) c calc(h + 6)
|
||||
);
|
||||
/* background-color: var(--yellow); */
|
||||
transform: rotate(30deg) skew(-30deg)
|
||||
translate(calc(var(--cube) * 0.99), calc(var(--cube) * -0.265))
|
||||
scaleY(0.864);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
font-weight: 900;
|
||||
text-transform: uppercase;
|
||||
font-size: var(--font-size-xs);
|
||||
line-height: var(--line-height-xs);
|
||||
}
|
||||
.side {
|
||||
background-color: var(--amber);
|
||||
.left {
|
||||
font-size: var(--font-size-xs);
|
||||
line-height: var(--line-height-xs);
|
||||
background-color: oklch(
|
||||
from var(--color) calc(l + 0.066) c calc(h + 3)
|
||||
);
|
||||
/* background-color: var(--amber); */
|
||||
transform: rotate(30deg) skewX(30deg)
|
||||
translate(calc(var(--cube) * 0.3), calc(var(--cube) * 0.6))
|
||||
scaleY(0.864);
|
||||
}
|
||||
.fees {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,27 +27,90 @@ export function init({
|
||||
chain.id = "chain";
|
||||
elements.explorer.append(chain);
|
||||
|
||||
chain.append(createCube());
|
||||
chain.append(createCube());
|
||||
chain.append(createCube());
|
||||
chain.append(createCube());
|
||||
chain.append(createCube());
|
||||
// vecsResources.getOrCreate(/** @satisfies {Height}*/ (5), "height");
|
||||
//
|
||||
const miners = [
|
||||
{ name: "Foundry USA", color: "orange" },
|
||||
{ name: "Via BTC", color: "teal" },
|
||||
{ name: "Ant Pool", color: "emerald" },
|
||||
{ name: "F2Pool", color: "indigo" },
|
||||
{ name: "Spider Pool", color: "yellow" },
|
||||
{ name: "Mara Pool", color: "amber" },
|
||||
{ name: "SEC Pool", color: "violet" },
|
||||
{ name: "Luxor", color: "orange" },
|
||||
{ name: "Brains Pool", color: "cyan" },
|
||||
];
|
||||
|
||||
for (let i = 0; i <= 10; i++) {
|
||||
const { name, color } = utils.array.random(miners);
|
||||
const { cubeElement, leftFaceElement, rightFaceElement, topFaceElement } =
|
||||
createCube();
|
||||
|
||||
// cubeElement.style.setProperty("--color", `var(--${color})`);
|
||||
|
||||
const heightElement = window.document.createElement("p");
|
||||
const height = (1_000_002 - i).toString();
|
||||
const prefixLength = 7 - height.length;
|
||||
const spanPrefix = window.document.createElement("span");
|
||||
spanPrefix.style.opacity = "0.5";
|
||||
spanPrefix.style.userSelect = "none";
|
||||
heightElement.append(spanPrefix);
|
||||
spanPrefix.innerHTML = "#" + "0".repeat(prefixLength);
|
||||
const spanHeight = window.document.createElement("span");
|
||||
heightElement.append(spanHeight);
|
||||
spanHeight.innerHTML = height;
|
||||
rightFaceElement.append(heightElement);
|
||||
|
||||
const feesElement = window.document.createElement("div");
|
||||
feesElement.classList.add("fees");
|
||||
leftFaceElement.append(feesElement);
|
||||
const averageFeeElement = window.document.createElement("p");
|
||||
feesElement.append(averageFeeElement);
|
||||
averageFeeElement.innerHTML = `~1.41`;
|
||||
const feeRangeElement = window.document.createElement("p");
|
||||
feesElement.append(feeRangeElement);
|
||||
const minFeeElement = window.document.createElement("span");
|
||||
minFeeElement.innerHTML = `0.11`;
|
||||
feeRangeElement.append(minFeeElement);
|
||||
const dashElement = window.document.createElement("span");
|
||||
dashElement.style.opacity = "0.5";
|
||||
dashElement.innerHTML = `-`;
|
||||
feeRangeElement.append(dashElement);
|
||||
const maxFeeElement = window.document.createElement("span");
|
||||
maxFeeElement.innerHTML = `12.1`;
|
||||
feeRangeElement.append(maxFeeElement);
|
||||
const feeUnitElement = window.document.createElement("p");
|
||||
feesElement.append(feeUnitElement);
|
||||
feeUnitElement.style.opacity = "0.5";
|
||||
feeUnitElement.innerHTML = `sat/vB`;
|
||||
|
||||
const spanMiner = window.document.createElement("span");
|
||||
spanMiner.innerHTML = name;
|
||||
topFaceElement.append(spanMiner);
|
||||
|
||||
chain.prepend(cubeElement);
|
||||
}
|
||||
}
|
||||
|
||||
function createCube() {
|
||||
const cubeElement = window.document.createElement("div");
|
||||
cubeElement.classList.add("cube");
|
||||
const faceFrontElement = window.document.createElement("div");
|
||||
faceFrontElement.classList.add("face");
|
||||
faceFrontElement.classList.add("front");
|
||||
cubeElement.append(faceFrontElement);
|
||||
const faceSideElement = window.document.createElement("div");
|
||||
faceSideElement.classList.add("face");
|
||||
faceSideElement.classList.add("side");
|
||||
cubeElement.append(faceSideElement);
|
||||
const faceTopElement = window.document.createElement("div");
|
||||
faceTopElement.classList.add("face");
|
||||
faceTopElement.classList.add("top");
|
||||
cubeElement.append(faceTopElement);
|
||||
return cubeElement;
|
||||
const rightFaceElement = window.document.createElement("div");
|
||||
rightFaceElement.classList.add("face");
|
||||
rightFaceElement.classList.add("right");
|
||||
cubeElement.append(rightFaceElement);
|
||||
const leftFaceElement = window.document.createElement("div");
|
||||
leftFaceElement.classList.add("face");
|
||||
leftFaceElement.classList.add("left");
|
||||
cubeElement.append(leftFaceElement);
|
||||
const topFaceElement = window.document.createElement("div");
|
||||
topFaceElement.classList.add("face");
|
||||
topFaceElement.classList.add("top");
|
||||
cubeElement.append(topFaceElement);
|
||||
return {
|
||||
cubeElement,
|
||||
leftFaceElement,
|
||||
rightFaceElement,
|
||||
topFaceElement,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -149,6 +149,13 @@ function createUtils() {
|
||||
}
|
||||
return range;
|
||||
},
|
||||
/**
|
||||
* @template T
|
||||
* @param {T[]} array
|
||||
*/
|
||||
random(array) {
|
||||
return array[Math.floor(Math.random() * array.length)];
|
||||
},
|
||||
};
|
||||
|
||||
const dom = {
|
||||
|
||||
@@ -1300,20 +1300,19 @@ function createPartialOptions({ env, colors }) {
|
||||
* @property {readonly UTXOGroupObject[]} args.list
|
||||
*/
|
||||
|
||||
/**
|
||||
* @template {"" | CohortId} T
|
||||
* @param {T} _key
|
||||
*/
|
||||
const fixKey = (_key) =>
|
||||
_key !== ""
|
||||
? /** @type {Exclude<"" | `${T}_`, "_">} */ (`${_key}_`)
|
||||
: /** @type {const} */ ("");
|
||||
|
||||
/**
|
||||
* @param {UTXOGroupObject | UTXOGroupsObject} args
|
||||
*/
|
||||
function createUTXOGroupFolder(args) {
|
||||
/**
|
||||
* @template {"" | CohortId} T
|
||||
* @param {T} _key
|
||||
*/
|
||||
const fixKey = (_key) =>
|
||||
_key !== ""
|
||||
? /** @type {Exclude<"" | `${T}_`, "_">} */ (`${_key}_`)
|
||||
: /** @type {const} */ ("");
|
||||
0;
|
||||
|
||||
function createCohortGroupFolder(args) {
|
||||
const list = "list" in args ? args.list : [args];
|
||||
const useGroupName = "list" in args;
|
||||
|
||||
@@ -1474,6 +1473,35 @@ function createPartialOptions({ env, colors }) {
|
||||
]);
|
||||
}),
|
||||
},
|
||||
// list.filter(({ key }) => key.endsWith("address_count")).map(callbackfn),
|
||||
// {
|
||||
// name: "loaded",
|
||||
// title: `${args.title} Loaded Address Count`,
|
||||
// bottom: list.flatMap(({ color, name, key: _key }) => {
|
||||
// const key = fixKey(_key);
|
||||
// return /** @type {const} */ ([
|
||||
// createBaseSeries({
|
||||
// key: `${key}address_count`,
|
||||
// name: useGroupName ? name : "Loaded",
|
||||
// color,
|
||||
// }),
|
||||
// createBaseSeries({
|
||||
// key: `${key}empty_address_count`,
|
||||
// name: useGroupName ? name : "Empty",
|
||||
// color,
|
||||
// }),
|
||||
// ]);
|
||||
// }),
|
||||
// },
|
||||
// {
|
||||
// name: "empty",
|
||||
// title: `${args.title} Empty Address Count`,
|
||||
// bottom: list.flatMap(({ color, name, key: _key }) => {
|
||||
// const key = fixKey(_key);
|
||||
// return /** @type {const} */ ([
|
||||
// ]);
|
||||
// }),
|
||||
// },
|
||||
{
|
||||
name: "Realized",
|
||||
tree: [
|
||||
@@ -2980,9 +3008,9 @@ function createPartialOptions({ env, colors }) {
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "UTXOs",
|
||||
name: "Cohorts",
|
||||
tree: [
|
||||
createUTXOGroupFolder({
|
||||
createCohortGroupFolder({
|
||||
key: "",
|
||||
name: "",
|
||||
title: "",
|
||||
@@ -2991,100 +3019,181 @@ function createPartialOptions({ env, colors }) {
|
||||
{
|
||||
name: "term",
|
||||
tree: [
|
||||
createUTXOGroupFolder({
|
||||
createCohortGroupFolder({
|
||||
name: "Compare",
|
||||
title: "Compare By Term",
|
||||
list: terms,
|
||||
}),
|
||||
...terms.map(createUTXOGroupFolder),
|
||||
...terms.map(createCohortGroupFolder),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Up to date",
|
||||
tree: [
|
||||
createUTXOGroupFolder({
|
||||
createCohortGroupFolder({
|
||||
name: "Compare",
|
||||
title: "Compare By Up To",
|
||||
list: upToDate,
|
||||
}),
|
||||
...upToDate.map(createUTXOGroupFolder),
|
||||
...upToDate.map(createCohortGroupFolder),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "From Date",
|
||||
tree: [
|
||||
createUTXOGroupFolder({
|
||||
createCohortGroupFolder({
|
||||
name: "Compare",
|
||||
title: "Compare By From",
|
||||
list: fromDate,
|
||||
}),
|
||||
...fromDate.map(createUTXOGroupFolder),
|
||||
...fromDate.map(createCohortGroupFolder),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Date Range",
|
||||
tree: [
|
||||
createUTXOGroupFolder({
|
||||
createCohortGroupFolder({
|
||||
name: "Compare",
|
||||
title: "Compare By Range",
|
||||
list: dateRange,
|
||||
}),
|
||||
...dateRange.map(createUTXOGroupFolder),
|
||||
...dateRange.map(createCohortGroupFolder),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Epoch",
|
||||
tree: [
|
||||
createUTXOGroupFolder({
|
||||
createCohortGroupFolder({
|
||||
name: "Compare",
|
||||
title: "Compare By Epoch",
|
||||
list: epoch,
|
||||
}),
|
||||
...epoch.map(createUTXOGroupFolder),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Up to size",
|
||||
tree: [
|
||||
createUTXOGroupFolder({
|
||||
name: "Compare",
|
||||
title: "Compare By Up To Size",
|
||||
list: upToSize,
|
||||
}),
|
||||
...upToSize.map(createUTXOGroupFolder),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "From size",
|
||||
tree: [
|
||||
createUTXOGroupFolder({
|
||||
name: "Compare",
|
||||
title: "Compare By From Size",
|
||||
list: fromSize,
|
||||
}),
|
||||
...fromSize.map(createUTXOGroupFolder),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Size range",
|
||||
tree: [
|
||||
createUTXOGroupFolder({
|
||||
name: "Compare",
|
||||
title: "Compare By Size Range",
|
||||
list: sizeRanges,
|
||||
}),
|
||||
...sizeRanges.map(createUTXOGroupFolder),
|
||||
...epoch.map(createCohortGroupFolder),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "type",
|
||||
tree: [
|
||||
createUTXOGroupFolder({
|
||||
createCohortGroupFolder({
|
||||
name: "Compare",
|
||||
title: "Compare By Type",
|
||||
list: type,
|
||||
}),
|
||||
...type.map(createUTXOGroupFolder),
|
||||
...type.map(createCohortGroupFolder),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "UTXOs Up to size",
|
||||
tree: [
|
||||
createCohortGroupFolder({
|
||||
name: "Compare",
|
||||
title: "Compare UTXOs By Up To Size",
|
||||
list: upToSize,
|
||||
}),
|
||||
...upToSize.map(createCohortGroupFolder),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "UTXOs From size",
|
||||
tree: [
|
||||
createCohortGroupFolder({
|
||||
name: "Compare",
|
||||
title: "Compare UTXOs By From Size",
|
||||
list: fromSize,
|
||||
}),
|
||||
...fromSize.map(createCohortGroupFolder),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "UTXOs Size range",
|
||||
tree: [
|
||||
createCohortGroupFolder({
|
||||
name: "Compare",
|
||||
title: "Compare UTXOs By Size Range",
|
||||
list: sizeRanges,
|
||||
}),
|
||||
...sizeRanges.map(createCohortGroupFolder),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Addresses Up to size",
|
||||
tree: [
|
||||
createCohortGroupFolder({
|
||||
name: "Compare",
|
||||
title: "Compare Addresses By Up To Size",
|
||||
list: upToSize.map(
|
||||
(obj) =>
|
||||
/** @type {const} */ ({
|
||||
...obj,
|
||||
key: `addresses_${obj.key}`,
|
||||
title: `Addresses ${obj.title}`,
|
||||
}),
|
||||
),
|
||||
}),
|
||||
...upToSize
|
||||
.map(
|
||||
(obj) =>
|
||||
/** @type {const} */ ({
|
||||
...obj,
|
||||
key: `addresses_${obj.key}`,
|
||||
title: `Addresses ${obj.title}`,
|
||||
}),
|
||||
)
|
||||
.map(createCohortGroupFolder),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Addresses From size",
|
||||
tree: [
|
||||
createCohortGroupFolder({
|
||||
name: "Compare",
|
||||
title: "Compare Addresses By From Size",
|
||||
list: fromSize.map(
|
||||
(obj) =>
|
||||
/** @type {const} */ ({
|
||||
...obj,
|
||||
key: `addresses_${obj.key}`,
|
||||
title: `Addresses ${obj.title}`,
|
||||
}),
|
||||
),
|
||||
}),
|
||||
...fromSize
|
||||
.map(
|
||||
(obj) =>
|
||||
/** @type {const} */ ({
|
||||
...obj,
|
||||
key: `addresses_${obj.key}`,
|
||||
title: `Addresses ${obj.title}`,
|
||||
}),
|
||||
)
|
||||
.map(createCohortGroupFolder),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Addresses Size range",
|
||||
tree: [
|
||||
createCohortGroupFolder({
|
||||
name: "Compare",
|
||||
title: "Compare Addresses By Size Range",
|
||||
list: sizeRanges.map(
|
||||
(obj) =>
|
||||
/** @type {const} */ ({
|
||||
...obj,
|
||||
key: `addresses_${obj.key}`,
|
||||
title: `Addresses ${obj.title}`,
|
||||
}),
|
||||
),
|
||||
}),
|
||||
...sizeRanges
|
||||
.map(
|
||||
(obj) =>
|
||||
/** @type {const} */ ({
|
||||
...obj,
|
||||
key: `addresses_${obj.key}`,
|
||||
title: `Addresses ${obj.title}`,
|
||||
}),
|
||||
)
|
||||
.map(createCohortGroupFolder),
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
@@ -29,11 +29,11 @@ function createTable({
|
||||
keyPrefix: "table",
|
||||
key: "index",
|
||||
},
|
||||
}
|
||||
},
|
||||
)
|
||||
);
|
||||
const index = signals.createMemo(() =>
|
||||
serializedIndexToIndex(serializedIndex())
|
||||
serializedIndexToIndex(serializedIndex()),
|
||||
);
|
||||
|
||||
const table = window.document.createElement("table");
|
||||
@@ -73,7 +73,7 @@ function createTable({
|
||||
table.append(tbody);
|
||||
|
||||
const rowElements = signals.createSignal(
|
||||
/** @type {HTMLTableRowElement[]} */ ([])
|
||||
/** @type {HTMLTableRowElement[]} */ ([]),
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -322,11 +322,11 @@ function createTable({
|
||||
unit,
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
return () => vecId;
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -340,9 +340,7 @@ function createTable({
|
||||
columns().forEach((vecId, colIndex) => addCol(vecId, colIndex));
|
||||
|
||||
obj.addRandomCol = function () {
|
||||
const vecId =
|
||||
possibleVecIds[Math.floor(Math.random() * possibleVecIds.length)];
|
||||
addCol(vecId);
|
||||
addCol(utils.array.random(possibleVecIds));
|
||||
};
|
||||
|
||||
return () => index;
|
||||
@@ -393,7 +391,7 @@ export function init({
|
||||
},
|
||||
inside: span,
|
||||
title: "Click or tap to add a column to the table",
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -498,7 +496,7 @@ function createIndexToVecIds(vecIdToIndexes) {
|
||||
});
|
||||
return arr;
|
||||
},
|
||||
/** @type {VecId[][]} */ (Array.from({ length: 24 }))
|
||||
/** @type {VecId[][]} */ (Array.from({ length: 24 })),
|
||||
);
|
||||
indexToVecIds.forEach((arr) => {
|
||||
arr.sort();
|
||||
|
||||
Reference in New Issue
Block a user