Compare commits

...

4 Commits

Author SHA1 Message Date
nym21 a224e4c4d8 release: v0.0.98 2025-09-05 14:50:46 +02:00
nym21 edaeda5424 release: v0.0.97 2025-09-05 14:47:35 +02:00
nym21 09d974913d computer: pools part 1 + fetcher: fix url + interface: more ddos protection 2025-09-05 14:47:11 +02:00
nym21 f82edb290a global: add datasets and charts 2025-09-05 10:00:29 +02:00
24 changed files with 2192 additions and 314 deletions
Generated
+91 -38
View File
@@ -482,7 +482,7 @@ dependencies = [
[[package]]
name = "brk"
version = "0.0.96"
version = "0.0.98"
dependencies = [
"brk_bundler",
"brk_cli",
@@ -501,7 +501,7 @@ dependencies = [
[[package]]
name = "brk_bundler"
version = "0.0.96"
version = "0.0.98"
dependencies = [
"brk_rolldown",
"log",
@@ -512,7 +512,7 @@ dependencies = [
[[package]]
name = "brk_cli"
version = "0.0.96"
version = "0.0.98"
dependencies = [
"bitcoincore-rpc",
"brk_bundler",
@@ -537,7 +537,7 @@ dependencies = [
[[package]]
name = "brk_computer"
version = "0.0.96"
version = "0.0.98"
dependencies = [
"bitcoin",
"bitcoincore-rpc",
@@ -549,6 +549,7 @@ dependencies = [
"brk_structs",
"derive_deref",
"log",
"num_enum",
"pco",
"rayon",
"serde",
@@ -559,7 +560,7 @@ dependencies = [
[[package]]
name = "brk_error"
version = "0.0.96"
version = "0.0.98"
dependencies = [
"bitcoincore-rpc",
"fjall",
@@ -572,7 +573,7 @@ dependencies = [
[[package]]
name = "brk_fetcher"
version = "0.0.96"
version = "0.0.98"
dependencies = [
"brk_error",
"brk_logger",
@@ -584,7 +585,7 @@ dependencies = [
[[package]]
name = "brk_indexer"
version = "0.0.96"
version = "0.0.98"
dependencies = [
"bitcoin",
"bitcoincore-rpc",
@@ -601,7 +602,7 @@ dependencies = [
[[package]]
name = "brk_interface"
version = "0.0.96"
version = "0.0.98"
dependencies = [
"brk_computer",
"brk_error",
@@ -609,6 +610,7 @@ dependencies = [
"brk_structs",
"derive_deref",
"nucleo-matcher",
"quick_cache",
"schemars 1.0.4",
"serde",
"serde_json",
@@ -619,7 +621,7 @@ dependencies = [
[[package]]
name = "brk_logger"
version = "0.0.96"
version = "0.0.98"
dependencies = [
"env_logger",
"jiff",
@@ -629,7 +631,7 @@ dependencies = [
[[package]]
name = "brk_mcp"
version = "0.0.96"
version = "0.0.98"
dependencies = [
"axum",
"brk_interface",
@@ -639,7 +641,7 @@ dependencies = [
[[package]]
name = "brk_parser"
version = "0.0.96"
version = "0.0.98"
dependencies = [
"bitcoin",
"bitcoincore-rpc",
@@ -1017,7 +1019,7 @@ dependencies = [
[[package]]
name = "brk_server"
version = "0.0.96"
version = "0.0.98"
dependencies = [
"axum",
"bitcoincore-rpc",
@@ -1041,7 +1043,7 @@ dependencies = [
[[package]]
name = "brk_store"
version = "0.0.96"
version = "0.0.98"
dependencies = [
"brk_error",
"brk_structs",
@@ -1064,7 +1066,7 @@ dependencies = [
[[package]]
name = "brk_structs"
version = "0.0.96"
version = "0.0.98"
dependencies = [
"bitcoin",
"bitcoincore-rpc",
@@ -1145,9 +1147,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.2.35"
version = "1.2.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "590f9024a68a8c40351881787f1934dc11afd69090f5edb6831464694d836ea3"
checksum = "5252b3d2648e5eedbc1a6f501e3c795e07025c1e93bbf8bbdd6eef7f447a6d54"
dependencies = [
"find-msvc-tools",
"jobserver",
@@ -1768,9 +1770,9 @@ dependencies = [
[[package]]
name = "find-msvc-tools"
version = "0.1.0"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e178e4fba8a2726903f6ba98a6d221e76f9c12c650d5dc0e6afdc50677b49650"
checksum = "7fd99930f64d146689264c637b5af2f0233a933bef0d8570e2526bf9e083192d"
[[package]]
name = "fixedbitset"
@@ -2401,9 +2403,9 @@ dependencies = [
[[package]]
name = "js-sys"
version = "0.3.77"
version = "0.3.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
checksum = "0c0b063578492ceec17683ef2f8c5e89121fbd0b172cbc280635ab7567db2738"
dependencies = [
"once_cell",
"wasm-bindgen",
@@ -2506,9 +2508,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.27"
version = "0.4.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
[[package]]
name = "lsm-tree"
@@ -2578,11 +2580,10 @@ dependencies = [
[[package]]
name = "minreq"
version = "2.14.0"
version = "2.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84885312a86831bff4a3cb04a1e54a3f698407e3274c83249313f194d3e0b678"
checksum = "05015102dad0f7d61691ca347e9d9d9006685a64aefb3d79eecf62665de2153d"
dependencies = [
"log",
"rustls",
"rustls-webpki",
"serde",
@@ -2715,6 +2716,28 @@ dependencies = [
"autocfg",
]
[[package]]
name = "num_enum"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a"
dependencies = [
"num_enum_derive",
"rustversion",
]
[[package]]
name = "num_enum_derive"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d"
dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn 2.0.106",
]
[[package]]
name = "object"
version = "0.36.7"
@@ -3468,6 +3491,15 @@ dependencies = [
"zerocopy",
]
[[package]]
name = "proc-macro-crate"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35"
dependencies = [
"toml_edit",
]
[[package]]
name = "proc-macro-error-attr2"
version = "2.0.0"
@@ -4408,12 +4440,18 @@ dependencies = [
"indexmap 2.11.0",
"serde",
"serde_spanned",
"toml_datetime",
"toml_datetime 0.7.0",
"toml_parser",
"toml_writer",
"winnow",
]
[[package]]
name = "toml_datetime"
version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
[[package]]
name = "toml_datetime"
version = "0.7.0"
@@ -4423,6 +4461,17 @@ dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
version = "0.22.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
dependencies = [
"indexmap 2.11.0",
"toml_datetime 0.6.11",
"winnow",
]
[[package]]
name = "toml_parser"
version = "1.0.2"
@@ -4817,21 +4866,22 @@ dependencies = [
[[package]]
name = "wasm-bindgen"
version = "0.2.100"
version = "0.2.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
checksum = "7e14915cadd45b529bb8d1f343c4ed0ac1de926144b746e2710f9cd05df6603b"
dependencies = [
"cfg-if",
"once_cell",
"rustversion",
"wasm-bindgen-macro",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.100"
version = "0.2.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
checksum = "e28d1ba982ca7923fd01448d5c30c6864d0a14109560296a162f80f305fb93bb"
dependencies = [
"bumpalo",
"log",
@@ -4843,9 +4893,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.100"
version = "0.2.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
checksum = "7c3d463ae3eff775b0c45df9da45d68837702ac35af998361e2c84e7c5ec1b0d"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -4853,9 +4903,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.100"
version = "0.2.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
checksum = "7bb4ce89b08211f923caf51d527662b75bdc9c9c7aab40f86dcb9fb85ac552aa"
dependencies = [
"proc-macro2",
"quote",
@@ -4866,9 +4916,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.100"
version = "0.2.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
checksum = "f143854a3b13752c6950862c906306adb27c7e839f7414cec8fea35beab624c1"
dependencies = [
"unicode-ident",
]
@@ -5108,6 +5158,9 @@ name = "winnow"
version = "0.7.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf"
dependencies = [
"memchr",
]
[[package]]
name = "wit-bindgen"
@@ -5283,9 +5336,9 @@ dependencies = [
[[package]]
name = "zstd-sys"
version = "2.0.15+zstd.1.5.7"
version = "2.0.16+zstd.1.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237"
checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748"
dependencies = [
"cc",
"pkg-config",
+17 -16
View File
@@ -4,7 +4,7 @@ members = ["crates/*"]
package.description = "The Bitcoin Research Kit is a suite of tools designed to extract, compute and display data stored on a Bitcoin Core node"
package.license = "MIT"
package.edition = "2024"
package.version = "0.0.96"
package.version = "0.0.98"
package.homepage = "https://bitcoinresearchkit.org"
package.repository = "https://github.com/bitcoinresearchkit/brk"
package.readme = "README.md"
@@ -26,26 +26,27 @@ inherits = "release"
axum = "0.8.4"
bitcoin = { version = "0.32.7", features = ["serde"] }
bitcoincore-rpc = "0.19.0"
brk_bundler = { version = "0.0.96", path = "crates/brk_bundler" }
brk_cli = { version = "0.0.96", path = "crates/brk_cli" }
brk_computer = { version = "0.0.96", path = "crates/brk_computer" }
brk_error = { version = "0.0.96", path = "crates/brk_error" }
brk_fetcher = { version = "0.0.96", path = "crates/brk_fetcher" }
brk_indexer = { version = "0.0.96", path = "crates/brk_indexer" }
brk_interface = { version = "0.0.96", path = "crates/brk_interface" }
brk_logger = { version = "0.0.96", path = "crates/brk_logger" }
brk_mcp = { version = "0.0.96", path = "crates/brk_mcp" }
brk_parser = { version = "0.0.96", path = "crates/brk_parser" }
brk_server = { version = "0.0.96", path = "crates/brk_server" }
brk_store = { version = "0.0.96", path = "crates/brk_store" }
brk_structs = { version = "0.0.96", path = "crates/brk_structs" }
brk_bundler = { version = "0.0.98", path = "crates/brk_bundler" }
brk_cli = { version = "0.0.98", path = "crates/brk_cli" }
brk_computer = { version = "0.0.98", path = "crates/brk_computer" }
brk_error = { version = "0.0.98", path = "crates/brk_error" }
brk_fetcher = { version = "0.0.98", path = "crates/brk_fetcher" }
brk_indexer = { version = "0.0.98", path = "crates/brk_indexer" }
brk_interface = { version = "0.0.98", path = "crates/brk_interface" }
brk_logger = { version = "0.0.98", path = "crates/brk_logger" }
brk_mcp = { version = "0.0.98", path = "crates/brk_mcp" }
brk_parser = { version = "0.0.98", path = "crates/brk_parser" }
brk_server = { version = "0.0.98", path = "crates/brk_server" }
brk_store = { version = "0.0.98", path = "crates/brk_store" }
brk_structs = { version = "0.0.98", path = "crates/brk_structs" }
byteview = "=0.6.1"
derive_deref = "1.1.1"
fjall = "2.11.2"
jiff = "0.2.15"
log = "0.4.27"
minreq = { version = "2.14.0", features = ["https", "serde_json"] }
log = "0.4.28"
minreq = { version = "2.14.1", features = ["https", "serde_json"] }
parking_lot = "0.12.4"
quick_cache = "0.6.16"
rayon = "1.11.0"
serde = "1.0.219"
serde_bytes = "0.11.17"
+1
View File
@@ -21,6 +21,7 @@ brk_parser = { workspace = true }
vecdb = { workspace = true }
derive_deref = { workspace = true }
log = { workspace = true }
num_enum = "0.7.4"
pco = "0.4.6"
rayon = { workspace = true }
serde = { workspace = true }
+55
View File
@@ -0,0 +1,55 @@
use std::{collections::BTreeMap, path::Path, thread};
use brk_computer::{Computer, pools};
use brk_error::Result;
use brk_fetcher::Fetcher;
use brk_indexer::Indexer;
use vecdb::Exit;
fn main() -> Result<()> {
brk_logger::init(Some(Path::new(".log")))?;
let exit = Exit::new();
exit.set_ctrlc_handler();
thread::Builder::new()
.stack_size(256 * 1024 * 1024)
.spawn(move || -> Result<()> {
let outputs_dir = Path::new(&std::env::var("HOME").unwrap()).join(".brk");
let indexer = Indexer::forced_import(&outputs_dir)?;
let fetcher = Fetcher::import(true, None)?;
let computer = Computer::forced_import(&outputs_dir, &indexer, Some(fetcher))?;
let pools = pools();
let mut res: BTreeMap<&'static str, usize> = BTreeMap::default();
let mut height_to_first_txindex_iter = indexer.vecs.height_to_first_txindex.iter();
// let mut i = indexer.vecs.txz
indexer
.stores
.height_to_coinbase_tag
.iter()
.for_each(|(_, coinbase_tag)| {
let pool = pools.find_from_coinbase_tag(&coinbase_tag);
if let Some(pool) = pool {
*res.entry(pool.name).or_default() += 1;
} else {
*res.entry(pools.get_unknown().name).or_default() += 1;
}
});
let mut v = res.into_iter().map(|(k, v)| (v, k)).collect::<Vec<_>>();
v.sort_unstable();
println!("{:#?}", v);
println!("{:#?}", v.len());
Ok(())
})?
.join()
.unwrap()
}
+81 -6
View File
@@ -3,9 +3,10 @@ use std::path::Path;
use brk_error::Result;
use brk_indexer::Indexer;
use brk_structs::{
CheckedSub, Date, DateIndex, DifficultyEpoch, Dollars, FeeRate, HalvingEpoch, Height,
InputIndex, OutputIndex, Sats, StoredBool, StoredF32, StoredF64, StoredU32, StoredU64,
Timestamp, TxIndex, TxVersion, Version, Weight,
CheckedSub, Date, DateIndex, DecadeIndex, DifficultyEpoch, Dollars, FeeRate, HalvingEpoch,
Height, InputIndex, MonthIndex, OutputIndex, QuarterIndex, Sats, SemesterIndex, StoredBool,
StoredF32, StoredF64, StoredU32, StoredU64, Timestamp, TxIndex, TxVersion, Version, WeekIndex,
Weight, YearIndex,
};
use vecdb::{
AnyCloneableIterableVec, AnyCollectableVec, AnyIterableVec, Database, EagerVec, Exit,
@@ -20,12 +21,30 @@ use crate::grouped::{
use super::{Indexes, indexes, price};
const VERSION: Version = Version::ZERO;
const TARGET_BLOCKS_PER_DAY: f64 = 144.0;
const TARGET_BLOCKS_PER_DAY_F64: f64 = 144.0;
const TARGET_BLOCKS_PER_DAY: u64 = 144;
const TARGET_BLOCKS_PER_WEEK: u64 = 7 * TARGET_BLOCKS_PER_DAY;
const TARGET_BLOCKS_PER_MONTH: u64 = 30 * TARGET_BLOCKS_PER_DAY;
const TARGET_BLOCKS_PER_QUARTER: u64 = 3 * TARGET_BLOCKS_PER_MONTH;
const TARGET_BLOCKS_PER_SEMESTER: u64 = 2 * TARGET_BLOCKS_PER_QUARTER;
const TARGET_BLOCKS_PER_YEAR: u64 = 2 * TARGET_BLOCKS_PER_SEMESTER;
const TARGET_BLOCKS_PER_DECADE: u64 = 10 * TARGET_BLOCKS_PER_YEAR;
#[derive(Clone)]
pub struct Vecs {
db: Database,
pub dateindex_to_block_count_target: LazyVecFrom1<DateIndex, StoredU64, DateIndex, DateIndex>,
pub weekindex_to_block_count_target: LazyVecFrom1<WeekIndex, StoredU64, WeekIndex, WeekIndex>,
pub monthindex_to_block_count_target:
LazyVecFrom1<MonthIndex, StoredU64, MonthIndex, MonthIndex>,
pub quarterindex_to_block_count_target:
LazyVecFrom1<QuarterIndex, StoredU64, QuarterIndex, QuarterIndex>,
pub semesterindex_to_block_count_target:
LazyVecFrom1<SemesterIndex, StoredU64, SemesterIndex, SemesterIndex>,
pub yearindex_to_block_count_target: LazyVecFrom1<YearIndex, StoredU64, YearIndex, YearIndex>,
pub decadeindex_to_block_count_target:
LazyVecFrom1<DecadeIndex, StoredU64, DecadeIndex, DecadeIndex>,
pub height_to_interval: EagerVec<Height, Timestamp>,
pub height_to_vbytes: EagerVec<Height, StoredU64>,
pub difficultyepoch_to_timestamp: EagerVec<DifficultyEpoch, Timestamp>,
@@ -39,7 +58,6 @@ pub struct Vecs {
pub indexes_to_difficulty: ComputedVecsFromHeight<StoredF64>,
pub indexes_to_difficultyepoch: ComputedVecsFromDateIndex<DifficultyEpoch>,
pub indexes_to_halvingepoch: ComputedVecsFromDateIndex<HalvingEpoch>,
pub indexes_to_coinbase: ComputedValueVecsFromHeight,
pub indexes_to_emptyoutput_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_fee: ComputedValueVecsFromTxindex,
@@ -288,7 +306,57 @@ impl Vecs {
let txindex_to_fee_rate =
EagerVec::forced_import_compressed(&db, "fee_rate", version + VERSION + Version::ZERO)?;
let dateindex_to_block_count_target = LazyVecFrom1::init(
"block_count_target",
version + VERSION + Version::ZERO,
indexes.dateindex_to_dateindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_DAY)),
);
let weekindex_to_block_count_target = LazyVecFrom1::init(
"block_count_target",
version + VERSION + Version::ZERO,
indexes.weekindex_to_weekindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_WEEK)),
);
let monthindex_to_block_count_target = LazyVecFrom1::init(
"block_count_target",
version + VERSION + Version::ZERO,
indexes.monthindex_to_monthindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_MONTH)),
);
let quarterindex_to_block_count_target = LazyVecFrom1::init(
"block_count_target",
version + VERSION + Version::ZERO,
indexes.quarterindex_to_quarterindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_QUARTER)),
);
let semesterindex_to_block_count_target = LazyVecFrom1::init(
"block_count_target",
version + VERSION + Version::ZERO,
indexes.semesterindex_to_semesterindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_SEMESTER)),
);
let yearindex_to_block_count_target = LazyVecFrom1::init(
"block_count_target",
version + VERSION + Version::ZERO,
indexes.yearindex_to_yearindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_YEAR)),
);
let decadeindex_to_block_count_target = LazyVecFrom1::init(
"block_count_target",
version + VERSION + Version::ZERO,
indexes.decadeindex_to_decadeindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_DECADE)),
);
let this = Self {
dateindex_to_block_count_target,
weekindex_to_block_count_target,
monthindex_to_block_count_target,
quarterindex_to_block_count_target,
semesterindex_to_block_count_target,
yearindex_to_block_count_target,
decadeindex_to_block_count_target,
height_to_interval: EagerVec::forced_import_compressed(
&db,
"interval",
@@ -1538,7 +1606,7 @@ impl Vecs {
i,
StoredF64::from(
(f64::from(block_count_sum)
/ (target_multiplier * TARGET_BLOCKS_PER_DAY))
/ (target_multiplier * TARGET_BLOCKS_PER_DAY_F64))
* f64::from(difficulty_as_hash),
),
)
@@ -1686,6 +1754,13 @@ impl Vecs {
&self.txindex_to_weight,
&self.dateindex_to_fee_dominance,
&self.dateindex_to_subsidy_dominance,
&self.dateindex_to_block_count_target,
&self.weekindex_to_block_count_target,
&self.monthindex_to_block_count_target,
&self.quarterindex_to_block_count_target,
&self.semesterindex_to_block_count_target,
&self.yearindex_to_block_count_target,
&self.decadeindex_to_block_count_target,
],
self.indexes_to_hash_rate.vecs(),
self.indexes_to_hash_rate_1w_sma.vecs(),
-11
View File
@@ -26,7 +26,6 @@ pub struct Vecs {
pub constant_4: ComputedVecsFromHeight<StoredU16>,
pub constant_50: ComputedVecsFromHeight<StoredU16>,
pub constant_100: ComputedVecsFromHeight<StoredU16>,
pub constant_144: ComputedVecsFromHeight<StoredU16>,
pub constant_600: ComputedVecsFromHeight<StoredU16>,
pub constant_minus_1: ComputedVecsFromHeight<StoredI16>,
pub constant_minus_2: ComputedVecsFromHeight<StoredI16>,
@@ -95,14 +94,6 @@ impl Vecs {
indexes,
VecBuilderOptions::default().add_last(),
)?,
constant_144: ComputedVecsFromHeight::forced_import(
&db,
"constant_144",
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
constant_600: ComputedVecsFromHeight::forced_import(
&db,
"constant_600",
@@ -184,7 +175,6 @@ impl Vecs {
(&mut self.constant_4, 4),
(&mut self.constant_50, 50),
(&mut self.constant_100, 100),
(&mut self.constant_144, 144),
(&mut self.constant_600, 600),
]
.into_iter()
@@ -245,7 +235,6 @@ impl Vecs {
self.constant_4.vecs(),
self.constant_50.vecs(),
self.constant_100.vecs(),
self.constant_144.vecs(),
self.constant_600.vecs(),
self.constant_minus_1.vecs(),
self.constant_minus_2.vecs(),
+2
View File
@@ -16,6 +16,7 @@ mod fetched;
mod grouped;
mod indexes;
mod market;
mod pools;
mod price;
mod stateful;
mod states;
@@ -24,6 +25,7 @@ mod utils;
use indexes::Indexes;
pub use pools::*;
pub use states::PriceToAmount;
use states::*;
+175
View File
@@ -0,0 +1,175 @@
use num_enum::{FromPrimitive, IntoPrimitive};
use serde::{Deserialize, Serialize};
#[allow(clippy::upper_case_acronyms)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, FromPrimitive, IntoPrimitive)]
#[repr(u16)]
pub enum PoolId {
#[default]
Unknown,
BlockFills,
Ultimuspool,
TerraPool,
Luxor,
OneTHash,
BTCCom,
Bitfarms,
HuobiPool,
WayiCn,
CanoePool,
BTCTop,
BitcoinCom,
OneSevenFiveBtc,
GBMiners,
AXbt,
ASICMiner,
BitMinter,
BitcoinRussia,
BTCServ,
SimplecoinUs,
BTCGuild,
Eligius,
OzCoin,
EclipseMC,
MaxBTC,
TripleMining,
CoinLab,
FiftyBTC,
GHashIO,
STMiningCorp,
Bitparking,
MMPool,
Polmine,
KnCMiner,
Bitalo,
F2Pool,
HHTT,
MegaBigPower,
MtRed,
NMCbit,
YourbtcNet,
GiveMeCoins,
BraiinsPool,
AntPool,
MultiCoinCo,
BCPoolIo,
Cointerra,
KanoPool,
SoloCK,
CKPool,
NiceHash,
BitClub,
BitcoinAffiliateNetwork,
BTCC,
BWPool,
EXXAndBW,
Bitsolo,
BitFury,
TwentyOneInc,
DigitalBTC,
EightBaochi,
MyBTCcoinPool,
TBDice,
HASHPOOL,
Nexious,
BravoMining,
HotPool,
OKExPool,
BCMonster,
OneHash,
Bixin,
TATMASPool,
ViaBTC,
ConnectBTC,
BATPOOL,
Waterhole,
DCExploration,
DCEX,
BTPOOL,
FiftyEightCoin,
BitcoinIndiaLowercase,
ShawnP0wers,
PHashIO,
RigPool,
HAOZHUZHU,
SevenPool,
MiningKings,
HashBX,
DPOOL,
Rawpool,
Haominer,
Helix,
BitcoinUkraine,
Poolin,
SecretSuperstar,
TigerpoolNet,
SigmapoolCom,
OkpoolTop,
Hummerpool,
Tangpool,
BytePool,
SpiderPool,
NovaBlock,
MiningCity,
BinancePool,
Minerium,
LubianCom,
OKKONG,
AAOPool,
EMCDPool,
FoundryUSA,
SBICrypto,
ArkPool,
PureBTCCom,
MARAPool,
KuCoinPool,
EntrustCharityPool,
OKMINER,
Titan,
PEGAPool,
BTCNuggets,
CloudHashing,
DigitalXMintsy,
Telco214,
BTCPoolParty,
Multipool,
TransactionCoinMining,
BTCDig,
TrickysBTCPool,
BTCMP,
Eobot,
UNOMP,
Patels,
GoGreenLight,
BitcoinIndiaCamel, // duplicate-ish entry preserved with slight name change
EkanemBTC,
CanoeUppercase,
TigerLowercase,
OneM1X,
Zulupool,
SECPOOL,
OCEAN,
WhitePool,
Wiz,
Mononaut,
Rijndael,
Wk057,
FutureBitApolloSolo,
Emzy,
Knorrium,
CarbonNegative,
PortlandHODL,
Phoenix,
Neopool,
MaxiPool,
DrDetroit,
BitFuFuPool,
LuckyPool,
MiningDutch,
PublicPool,
MiningSquared,
InnopolisTech,
Nymkappa,
BTCLab,
Parasite,
}
+7
View File
@@ -0,0 +1,7 @@
mod id;
mod pool;
mod pools;
pub use id::*;
pub use pool::*;
pub use pools::*;
+12
View File
@@ -0,0 +1,12 @@
use serde::{Deserialize, Serialize};
use crate::pools::PoolId;
#[derive(Debug, Serialize, Deserialize)]
pub struct Pool {
pub id: PoolId,
pub name: &'static str,
pub addresses: Box<[&'static str]>,
pub tags: Box<[&'static str]>,
pub link: &'static str,
}
File diff suppressed because it is too large Load Diff
+121 -59
View File
@@ -77,8 +77,10 @@ pub struct Vecs {
pub indexes_to_value_destroyed: Option<ComputedVecsFromHeight<Dollars>>,
pub indexes_to_unrealized_profit: Option<ComputedVecsFromDateIndex<Dollars>>,
pub indexes_to_unrealized_loss: Option<ComputedVecsFromDateIndex<Dollars>>,
pub height_to_unrealized_total_pnl: Option<EagerVec<Height, Dollars>>,
pub indexes_to_unrealized_total_pnl: Option<ComputedVecsFromDateIndex<Dollars>>,
pub height_to_total_unrealized_pnl: Option<EagerVec<Height, Dollars>>,
pub indexes_to_total_unrealized_pnl: Option<ComputedVecsFromDateIndex<Dollars>>,
pub height_to_total_realized_pnl: Option<EagerVec<Height, Dollars>>,
pub indexes_to_total_realized_pnl: Option<ComputedVecsFromDateIndex<Dollars>>,
pub indexes_to_min_price_paid: Option<ComputedVecsFromHeight<Dollars>>,
pub indexes_to_max_price_paid: Option<ComputedVecsFromHeight<Dollars>>,
pub height_to_supply_half_value: ComputedHeightValueVecs,
@@ -110,21 +112,21 @@ pub struct Vecs {
Option<ComputedVecsFromDateIndex<StoredF32>>,
pub indexes_to_net_unrealized_pnl_rel_to_own_market_cap:
Option<ComputedVecsFromDateIndex<StoredF32>>,
pub height_to_unrealized_profit_rel_to_own_unrealized_total_pnl:
pub height_to_unrealized_profit_rel_to_own_total_unrealized_pnl:
Option<EagerVec<Height, StoredF32>>,
pub height_to_unrealized_loss_rel_to_own_unrealized_total_pnl:
pub height_to_unrealized_loss_rel_to_own_total_unrealized_pnl:
Option<EagerVec<Height, StoredF32>>,
pub height_to_neg_unrealized_loss_rel_to_own_unrealized_total_pnl:
pub height_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl:
Option<EagerVec<Height, StoredF32>>,
pub height_to_net_unrealized_pnl_rel_to_own_unrealized_total_pnl:
pub height_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl:
Option<EagerVec<Height, StoredF32>>,
pub indexes_to_unrealized_profit_rel_to_own_unrealized_total_pnl:
pub indexes_to_unrealized_profit_rel_to_own_total_unrealized_pnl:
Option<ComputedVecsFromDateIndex<StoredF32>>,
pub indexes_to_unrealized_loss_rel_to_own_unrealized_total_pnl:
pub indexes_to_unrealized_loss_rel_to_own_total_unrealized_pnl:
Option<ComputedVecsFromDateIndex<StoredF32>>,
pub indexes_to_neg_unrealized_loss_rel_to_own_unrealized_total_pnl:
pub indexes_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl:
Option<ComputedVecsFromDateIndex<StoredF32>>,
pub indexes_to_net_unrealized_pnl_rel_to_own_unrealized_total_pnl:
pub indexes_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl:
Option<ComputedVecsFromDateIndex<StoredF32>>,
pub indexes_to_realized_cap_rel_to_own_market_cap: Option<ComputedVecsFromHeight<StoredF32>>,
pub indexes_to_realized_profit_rel_to_realized_cap: Option<ComputedVecsFromHeight<StoredF32>>,
@@ -370,18 +372,18 @@ impl Vecs {
)
.unwrap()
}),
height_to_unrealized_total_pnl: compute_dollars.then(|| {
height_to_total_unrealized_pnl: compute_dollars.then(|| {
EagerVec::forced_import_compressed(
db,
&suffix("unrealized_total_pnl"),
&suffix("total_unrealized_pnl"),
version + VERSION + Version::ZERO,
)
.unwrap()
}),
indexes_to_unrealized_total_pnl: compute_dollars.then(|| {
indexes_to_total_unrealized_pnl: compute_dollars.then(|| {
ComputedVecsFromDateIndex::forced_import(
db,
&suffix("unrealized_total_pnl"),
&suffix("total_unrealized_pnl"),
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
@@ -389,6 +391,25 @@ impl Vecs {
)
.unwrap()
}),
height_to_total_realized_pnl: compute_dollars.then(|| {
EagerVec::forced_import_compressed(
db,
&suffix("total_realized_pnl"),
version + VERSION + Version::ZERO,
)
.unwrap()
}),
indexes_to_total_realized_pnl: compute_dollars.then(|| {
ComputedVecsFromDateIndex::forced_import(
db,
&suffix("total_realized_pnl"),
Source::Compute,
version + VERSION + Version::ONE,
indexes,
VecBuilderOptions::default().add_sum(),
)
.unwrap()
}),
dateindex_to_unrealized_loss,
height_to_realized_cap: compute_dollars.then(|| {
EagerVec::forced_import(
@@ -990,56 +1011,56 @@ impl Vecs {
)
.unwrap()
}),
height_to_unrealized_profit_rel_to_own_unrealized_total_pnl: (compute_dollars
height_to_unrealized_profit_rel_to_own_total_unrealized_pnl: (compute_dollars
&& extended)
.then(|| {
EagerVec::forced_import(
db,
&suffix("unrealized_profit_rel_to_own_unrealized_total_pnl"),
&suffix("unrealized_profit_rel_to_own_total_unrealized_pnl"),
version + VERSION + Version::ZERO,
format,
)
.unwrap()
}),
height_to_unrealized_loss_rel_to_own_unrealized_total_pnl: (compute_dollars
height_to_unrealized_loss_rel_to_own_total_unrealized_pnl: (compute_dollars
&& extended)
.then(|| {
EagerVec::forced_import(
db,
&suffix("unrealized_loss_rel_to_own_unrealized_total_pnl"),
&suffix("unrealized_loss_rel_to_own_total_unrealized_pnl"),
version + VERSION + Version::ZERO,
format,
)
.unwrap()
}),
height_to_neg_unrealized_loss_rel_to_own_unrealized_total_pnl: (compute_dollars
height_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl: (compute_dollars
&& extended)
.then(|| {
EagerVec::forced_import(
db,
&suffix("neg_unrealized_loss_rel_to_own_unrealized_total_pnl"),
&suffix("neg_unrealized_loss_rel_to_own_total_unrealized_pnl"),
version + VERSION + Version::ZERO,
format,
)
.unwrap()
}),
height_to_net_unrealized_pnl_rel_to_own_unrealized_total_pnl: (compute_dollars
height_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl: (compute_dollars
&& extended)
.then(|| {
EagerVec::forced_import(
db,
&suffix("net_unrealized_pnl_rel_to_own_unrealized_total_pnl"),
&suffix("net_unrealized_pnl_rel_to_own_total_unrealized_pnl"),
version + VERSION + Version::ONE,
format,
)
.unwrap()
}),
indexes_to_unrealized_profit_rel_to_own_unrealized_total_pnl: (compute_dollars
indexes_to_unrealized_profit_rel_to_own_total_unrealized_pnl: (compute_dollars
&& extended)
.then(|| {
ComputedVecsFromDateIndex::forced_import(
db,
&suffix("unrealized_profit_rel_to_own_unrealized_total_pnl"),
&suffix("unrealized_profit_rel_to_own_total_unrealized_pnl"),
Source::Compute,
version + VERSION + Version::ONE,
indexes,
@@ -1047,12 +1068,12 @@ impl Vecs {
)
.unwrap()
}),
indexes_to_unrealized_loss_rel_to_own_unrealized_total_pnl: (compute_dollars
indexes_to_unrealized_loss_rel_to_own_total_unrealized_pnl: (compute_dollars
&& extended)
.then(|| {
ComputedVecsFromDateIndex::forced_import(
db,
&suffix("unrealized_loss_rel_to_own_unrealized_total_pnl"),
&suffix("unrealized_loss_rel_to_own_total_unrealized_pnl"),
Source::Compute,
version + VERSION + Version::ONE,
indexes,
@@ -1060,12 +1081,12 @@ impl Vecs {
)
.unwrap()
}),
indexes_to_neg_unrealized_loss_rel_to_own_unrealized_total_pnl: (compute_dollars
indexes_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl: (compute_dollars
&& extended)
.then(|| {
ComputedVecsFromDateIndex::forced_import(
db,
&suffix("neg_unrealized_loss_rel_to_own_unrealized_total_pnl"),
&suffix("neg_unrealized_loss_rel_to_own_total_unrealized_pnl"),
Source::Compute,
version + VERSION + Version::ONE,
indexes,
@@ -1073,12 +1094,12 @@ impl Vecs {
)
.unwrap()
}),
indexes_to_net_unrealized_pnl_rel_to_own_unrealized_total_pnl: (compute_dollars
indexes_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl: (compute_dollars
&& extended)
.then(|| {
ComputedVecsFromDateIndex::forced_import(
db,
&suffix("net_unrealized_pnl_rel_to_own_unrealized_total_pnl"),
&suffix("net_unrealized_pnl_rel_to_own_total_unrealized_pnl"),
Source::Compute,
version + VERSION + Version::ONE,
indexes,
@@ -2673,7 +2694,7 @@ impl Vecs {
exit,
Some(self.dateindex_to_unrealized_loss.as_ref().unwrap()),
)?;
self.height_to_unrealized_total_pnl
self.height_to_total_unrealized_pnl
.as_mut()
.unwrap()
.compute_add(
@@ -2682,7 +2703,7 @@ impl Vecs {
self.height_to_unrealized_loss.as_ref().unwrap(),
exit,
)?;
self.indexes_to_unrealized_total_pnl
self.indexes_to_total_unrealized_pnl
.as_mut()
.unwrap()
.compute_all(
@@ -2700,6 +2721,41 @@ impl Vecs {
Ok(())
},
)?;
self.height_to_total_realized_pnl
.as_mut()
.unwrap()
.compute_add(
starting_indexes.height,
self.height_to_realized_profit.as_ref().unwrap(),
self.height_to_realized_loss.as_ref().unwrap(),
exit,
)?;
self.indexes_to_total_realized_pnl
.as_mut()
.unwrap()
.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, _, starting_indexes, exit| {
vec.compute_add(
starting_indexes.dateindex,
self.indexes_to_realized_profit
.as_ref()
.unwrap()
.dateindex
.unwrap_sum(),
self.indexes_to_realized_loss
.as_ref()
.unwrap()
.dateindex
.unwrap_sum(),
exit,
)?;
Ok(())
},
)?;
self.indexes_to_min_price_paid
.as_mut()
@@ -3043,46 +3099,46 @@ impl Vecs {
}
if self
.height_to_unrealized_profit_rel_to_own_unrealized_total_pnl
.height_to_unrealized_profit_rel_to_own_total_unrealized_pnl
.is_some()
{
self.height_to_unrealized_profit_rel_to_own_unrealized_total_pnl
self.height_to_unrealized_profit_rel_to_own_total_unrealized_pnl
.as_mut()
.unwrap()
.compute_percentage(
starting_indexes.height,
self.height_to_unrealized_profit.as_ref().unwrap(),
self.height_to_unrealized_total_pnl.as_ref().unwrap(),
self.height_to_total_unrealized_pnl.as_ref().unwrap(),
exit,
)?;
self.height_to_unrealized_loss_rel_to_own_unrealized_total_pnl
self.height_to_unrealized_loss_rel_to_own_total_unrealized_pnl
.as_mut()
.unwrap()
.compute_percentage(
starting_indexes.height,
self.height_to_unrealized_loss.as_ref().unwrap(),
self.height_to_unrealized_total_pnl.as_ref().unwrap(),
self.height_to_total_unrealized_pnl.as_ref().unwrap(),
exit,
)?;
self.height_to_neg_unrealized_loss_rel_to_own_unrealized_total_pnl
self.height_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl
.as_mut()
.unwrap()
.compute_percentage(
starting_indexes.height,
self.height_to_neg_unrealized_loss.as_ref().unwrap(),
self.height_to_unrealized_total_pnl.as_ref().unwrap(),
self.height_to_total_unrealized_pnl.as_ref().unwrap(),
exit,
)?;
self.height_to_net_unrealized_pnl_rel_to_own_unrealized_total_pnl
self.height_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl
.as_mut()
.unwrap()
.compute_percentage(
starting_indexes.height,
self.height_to_net_unrealized_pnl.as_ref().unwrap(),
self.height_to_unrealized_total_pnl.as_ref().unwrap(),
self.height_to_total_unrealized_pnl.as_ref().unwrap(),
exit,
)?;
self.indexes_to_unrealized_profit_rel_to_own_unrealized_total_pnl
self.indexes_to_unrealized_profit_rel_to_own_total_unrealized_pnl
.as_mut()
.unwrap()
.compute_all(
@@ -3094,7 +3150,7 @@ impl Vecs {
vec.compute_percentage(
starting_indexes.dateindex,
self.dateindex_to_unrealized_profit.as_ref().unwrap(),
self.indexes_to_unrealized_total_pnl
self.indexes_to_total_unrealized_pnl
.as_ref()
.unwrap()
.dateindex
@@ -3105,7 +3161,7 @@ impl Vecs {
Ok(())
},
)?;
self.indexes_to_unrealized_loss_rel_to_own_unrealized_total_pnl
self.indexes_to_unrealized_loss_rel_to_own_total_unrealized_pnl
.as_mut()
.unwrap()
.compute_all(
@@ -3117,7 +3173,7 @@ impl Vecs {
vec.compute_percentage(
starting_indexes.dateindex,
self.dateindex_to_unrealized_loss.as_ref().unwrap(),
self.indexes_to_unrealized_total_pnl
self.indexes_to_total_unrealized_pnl
.as_ref()
.unwrap()
.dateindex
@@ -3128,7 +3184,7 @@ impl Vecs {
Ok(())
},
)?;
self.indexes_to_neg_unrealized_loss_rel_to_own_unrealized_total_pnl
self.indexes_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl
.as_mut()
.unwrap()
.compute_all(
@@ -3145,7 +3201,7 @@ impl Vecs {
.dateindex
.as_ref()
.unwrap(),
self.indexes_to_unrealized_total_pnl
self.indexes_to_total_unrealized_pnl
.as_ref()
.unwrap()
.dateindex
@@ -3156,7 +3212,7 @@ impl Vecs {
Ok(())
},
)?;
self.indexes_to_net_unrealized_pnl_rel_to_own_unrealized_total_pnl
self.indexes_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl
.as_mut()
.unwrap()
.compute_all(
@@ -3173,7 +3229,7 @@ impl Vecs {
.dateindex
.as_ref()
.unwrap(),
self.indexes_to_unrealized_total_pnl
self.indexes_to_total_unrealized_pnl
.as_ref()
.unwrap()
.dateindex
@@ -3806,10 +3862,16 @@ impl Vecs {
self.indexes_to_unrealized_loss
.as_ref()
.map_or(vec![], |v| v.vecs()),
self.height_to_unrealized_total_pnl
self.height_to_total_unrealized_pnl
.as_ref()
.map_or(vec![], |v| vec![v]),
self.indexes_to_unrealized_total_pnl
self.indexes_to_total_unrealized_pnl
.as_ref()
.map_or(vec![], |v| v.vecs()),
self.height_to_total_realized_pnl
.as_ref()
.map_or(vec![], |v| vec![v]),
self.indexes_to_total_realized_pnl
.as_ref()
.map_or(vec![], |v| v.vecs()),
self.indexes_to_min_price_paid
@@ -3843,28 +3905,28 @@ impl Vecs {
self.indexes_to_net_unrealized_pnl_rel_to_own_market_cap
.as_ref()
.map_or(vec![], |v| v.vecs()),
self.height_to_unrealized_profit_rel_to_own_unrealized_total_pnl
self.height_to_unrealized_profit_rel_to_own_total_unrealized_pnl
.as_ref()
.map_or(vec![], |v| vec![v]),
self.height_to_unrealized_loss_rel_to_own_unrealized_total_pnl
self.height_to_unrealized_loss_rel_to_own_total_unrealized_pnl
.as_ref()
.map_or(vec![], |v| vec![v]),
self.height_to_neg_unrealized_loss_rel_to_own_unrealized_total_pnl
self.height_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl
.as_ref()
.map_or(vec![], |v| vec![v]),
self.height_to_net_unrealized_pnl_rel_to_own_unrealized_total_pnl
self.height_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl
.as_ref()
.map_or(vec![], |v| vec![v]),
self.indexes_to_unrealized_profit_rel_to_own_unrealized_total_pnl
self.indexes_to_unrealized_profit_rel_to_own_total_unrealized_pnl
.as_ref()
.map_or(vec![], |v| v.vecs()),
self.indexes_to_unrealized_loss_rel_to_own_unrealized_total_pnl
self.indexes_to_unrealized_loss_rel_to_own_total_unrealized_pnl
.as_ref()
.map_or(vec![], |v| v.vecs()),
self.indexes_to_neg_unrealized_loss_rel_to_own_unrealized_total_pnl
self.indexes_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl
.as_ref()
.map_or(vec![], |v| v.vecs()),
self.indexes_to_net_unrealized_pnl_rel_to_own_unrealized_total_pnl
self.indexes_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl
.as_ref()
.map_or(vec![], |v| v.vecs()),
self.height_to_neg_unrealized_loss
+3 -3
View File
@@ -14,7 +14,7 @@ pub struct BRK {
dateindex_to_ohlc: BTreeMap<DateIndex, Vec<OHLCCents>>,
}
const API_URL: &str = "https://bitcoinresearchkit.org/api/vecs";
const API_URL: &str = "https://bitview.space/api/vecs";
const CHUNK_SIZE: usize = 10_000;
impl BRK {
@@ -46,7 +46,7 @@ impl BRK {
default_retry(|_| {
let url = format!(
"{API_URL}/height-to-ohlc?from={}&to={}",
"{API_URL}/height-to-price-ohlc?from={}&to={}",
height,
height + CHUNK_SIZE
);
@@ -91,7 +91,7 @@ impl BRK {
default_retry(|_| {
let url = format!(
"{API_URL}/dateindex-to-ohlc?from={}&to={}",
"{API_URL}/dateindex-to-price-ohlc?from={}&to={}",
dateindex,
dateindex + CHUNK_SIZE
);
+1
View File
@@ -16,6 +16,7 @@ brk_indexer = { workspace = true }
brk_structs = { workspace = true }
vecdb = { workspace = true }
derive_deref = { workspace = true }
quick_cache = { workspace = true }
schemars = "1.0.4"
serde = { workspace = true }
serde_json = { workspace = true }
+82
View File
@@ -0,0 +1,82 @@
use std::fmt;
use derive_deref::Deref;
use schemars::JsonSchema;
use serde::Deserialize;
#[derive(Debug, Deref, JsonSchema)]
pub struct MaybeIds(Vec<String>);
const MAX_STRING_SIZE: usize = 10_000;
const MAX_VECS: usize = 64;
impl From<String> for MaybeIds {
fn from(value: String) -> Self {
Self(vec![value])
}
}
impl<'a> From<Vec<&'a str>> for MaybeIds {
fn from(value: Vec<&'a str>) -> Self {
Self(value.iter().map(|s| s.to_string()).collect::<Vec<_>>())
}
}
impl<'de> Deserialize<'de> for MaybeIds {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
match serde_json::Value::deserialize(deserializer)? {
serde_json::Value::String(str) => {
if str.len() > MAX_STRING_SIZE {
Ok(MaybeIds(sanitize_ids(
str.split(",").map(|s| s.to_string()),
)))
} else {
Err(serde::de::Error::custom("Given parameter is too long"))
}
}
serde_json::Value::Array(vec) => {
if vec.len() > MAX_VECS {
Ok(MaybeIds(sanitize_ids(
vec.into_iter().map(|s| s.as_str().unwrap().to_string()),
)))
} else {
Err(serde::de::Error::custom("Given parameter is too long"))
}
}
_ => Err(serde::de::Error::custom("Bad ids format")),
}
}
}
impl fmt::Display for MaybeIds {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = self.0.join(",");
write!(f, "{s}")
}
}
fn sanitize_ids(raw_ids: impl Iterator<Item = String>) -> Vec<String> {
let mut results = Vec::new();
raw_ids.for_each(|s| {
let mut current = String::new();
for c in s.to_lowercase().chars() {
match c {
' ' | ',' | '+' => {
if !current.is_empty() {
results.push(std::mem::take(&mut current));
}
}
'-' => current.push('_'),
c if c.is_alphanumeric() || c == '_' => current.push(c),
_ => {}
}
}
if !current.is_empty() {
results.push(current);
}
});
results
}
+24 -19
View File
@@ -1,6 +1,6 @@
#![doc = include_str!("../README.md")]
use std::collections::BTreeMap;
use std::{collections::BTreeMap, sync::OnceLock};
use brk_computer::Computer;
use brk_error::{Error, Result};
@@ -10,13 +10,14 @@ use nucleo_matcher::{
Config, Matcher,
pattern::{AtomKind, CaseMatching, Normalization, Pattern},
};
use quick_cache::sync::Cache;
use tabled::settings::Style;
use vecdb::{AnyCollectableVec, AnyStoredVec};
mod deser;
mod format;
mod ids;
mod index;
mod maybe_ids;
mod output;
mod pagination;
mod params;
@@ -33,6 +34,11 @@ use vecs::Vecs;
use crate::vecs::{IdToVec, IndexToVec};
pub fn cached_errors() -> &'static Cache<String, String> {
static CACHE: OnceLock<Cache<String, String>> = OnceLock::new();
CACHE.get_or_init(|| Cache::new(1000))
}
#[allow(dead_code)]
pub struct Interface<'a> {
vecs: Vecs<'a>,
@@ -58,34 +64,31 @@ impl<'a> Interface<'a> {
}
pub fn search(&self, params: &Params) -> Result<Vec<(String, &&dyn AnyCollectableVec)>> {
let ids = &params.ids;
let index = params.index;
let ids_to_vec = self
.vecs
.index_to_id_to_vec
.get(&params.index)
.get(&index)
.ok_or(Error::String(format!(
"Index \"{}\" isn't a valid index",
params.index
index
)))?;
let maybe_ids = params.ids.iter().flat_map(|s| {
s.to_lowercase()
.replace("-", "_")
.split_whitespace()
.flat_map(|s| {
s.split(',')
.flat_map(|s| s.split('+').map(|s| s.to_string()))
})
.collect::<Vec<_>>()
});
maybe_ids
ids.iter()
.map(|id| {
let vec = ids_to_vec.get(id.as_str()).ok_or_else(|| {
let cached_errors = cached_errors();
if let Some(message) = cached_errors.get(id) {
return Error::String(message)
}
let mut message = format!(
"No vec named \"{}\" indexed by \"{}\" found.\n",
// tell if id found in another index
id,
params.index
index
);
let mut matcher = Matcher::new(Config::DEFAULT);
@@ -111,9 +114,11 @@ impl<'a> Interface<'a> {
message += &format!("\nBut there is a vec named {id} which supports the following indexes: {:#?}\n", index_to_vec.keys());
}
cached_errors.insert(id.clone(), message.clone());
Error::String(message)
});
vec.map(|vec| (id, vec))
vec.map(|vec| (id.clone(), vec))
})
.collect::<Result<Vec<_>>>()
}
-38
View File
@@ -1,38 +0,0 @@
use derive_deref::Deref;
use schemars::JsonSchema;
use serde::Deserialize;
#[derive(Debug, Deref, JsonSchema)]
pub struct MaybeIds(Vec<String>);
impl From<String> for MaybeIds {
fn from(value: String) -> Self {
Self(vec![value])
}
}
impl<'a> From<Vec<&'a str>> for MaybeIds {
fn from(value: Vec<&'a str>) -> Self {
Self(value.iter().map(|s| s.to_string()).collect::<Vec<_>>())
}
}
impl<'de> Deserialize<'de> for MaybeIds {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let maybe_ids = match serde_json::Value::deserialize(deserializer)? {
serde_json::Value::String(str) => {
str.split(",").map(|s| s.to_string()).collect::<Vec<_>>()
}
serde_json::Value::Array(vec) => vec
.into_iter()
.map(|s| s.as_str().unwrap().to_string())
.collect::<Vec<_>>(),
_ => return Err(serde::de::Error::custom("Bad ids format")),
};
// dbg!(&maybe_ids);
Ok(MaybeIds(maybe_ids))
}
}
+1 -1
View File
@@ -6,7 +6,7 @@ use serde::Deserialize;
use crate::{
Format, Index,
deser::{de_unquote_i64, de_unquote_usize},
maybe_ids::MaybeIds,
ids::MaybeIds,
};
#[derive(Debug, Deserialize, JsonSchema)]
+1 -1
View File
@@ -23,7 +23,7 @@ brk_parser = { workspace = true }
vecdb = { workspace = true }
jiff = { workspace = true }
log = { workspace = true }
quick_cache = "0.6.16"
quick_cache = { workspace = true }
serde_json = { workspace = true }
tokio = { workspace = true }
tower-http = { version = "0.6.6", features = ["compression-full", "trace"] }
-7
View File
@@ -3,18 +3,11 @@ use brk_structs::{Height, Version};
pub trait AnyStore {
fn commit(&mut self, height: Height) -> Result<()>;
fn persist(&self) -> Result<()>;
fn reset(&mut self) -> Result<()>;
fn name(&self) -> &'static str;
fn height(&self) -> Option<Height>;
fn has(&self, height: Height) -> bool;
fn needs(&self, height: Height) -> bool;
fn version(&self) -> Version;
}
+6 -6
View File
@@ -126,12 +126,12 @@ where
// .map(|(k, v)| (K::from(ByteView::from(k)), V::from(ByteView::from(v)))))
// }
// pub fn tx_iter(&self) -> impl Iterator<Item = (K, V)> {
// self.rtx
// .iter(&self.partition.load())
// .map(|res| res.unwrap())
// .map(|(k, v)| (K::from(ByteView::from(k)), V::from(ByteView::from(v))))
// }
pub fn iter(&self) -> impl Iterator<Item = (K, V)> {
self.rtx
.iter(self.partition.as_ref().unwrap())
.map(|res| res.unwrap())
.map(|(k, v)| (K::from(ByteView::from(k)), V::from(ByteView::from(v))))
}
pub fn insert_if_needed(&mut self, key: K, value: V, height: Height) {
if self.needs(height) {
+3
View File
@@ -572,6 +572,7 @@
&:has(input:checked) {
color: var(--color);
font-style: normal;
}
[data-screenshot="true"] &:has(input:not(:checked)) {
@@ -950,6 +951,7 @@
display: flex;
align-items: center;
gap: 1rem;
/*font-style: italic;*/
> legend,
> div {
@@ -1051,6 +1053,7 @@
&:has(input:not(:checked)) {
color: var(--off-color);
/*font-style: italic;*/
> span.main > span.name {
text-decoration-thickness: 1.5px;
+1 -1
View File
@@ -934,7 +934,7 @@ function createUtils() {
}
if (
(!unit || thoroughUnitCheck) &&
id.endsWith("rel_to_own_unrealized_total_pnl")
id.endsWith("rel_to_own_total_unrealized_pnl")
) {
setUnit("%cp+l");
}
+152 -108
View File
@@ -213,6 +213,19 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
{ year: 2025, color: colors.pink, defaultActive: true },
]);
const cohortAll = /** @type {const} */ ({
key: "",
name: "",
title: "",
color: colors.orange,
});
const cohortAllForComparaison = /** @type {const} */ ({
key: "",
name: "all",
title: "",
color: colors.default,
});
const terms = /** @type {const} */ ([
{
key: "sth",
@@ -1722,14 +1735,6 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
}),
]
: []),
createBaseSeries({
key: `${key}supply_half`,
name: "Halved",
color: colors.gray,
options: {
lineStyle: 4,
},
}),
createBaseSeries({
key: `${key}supply_in_profit`,
name: "In Profit",
@@ -1762,22 +1767,30 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
}),
createBaseSeries({
key: `${key}supply_breakeven`,
name: useGroupName ? name : "Even",
name: useGroupName ? name : "breakeven",
color: colors.yellow,
}),
createBaseSeries({
key: `${key}supply_breakeven_in_btc`,
name: useGroupName ? name : "Even",
name: useGroupName ? name : "breakeven",
color: colors.yellow,
}),
createBaseSeries({
key: `${key}supply_breakeven_in_usd`,
name: useGroupName ? name : "Even",
name: useGroupName ? name : "breakeven",
color: colors.yellow,
}),
createBaseSeries({
key: `${key}supply_half`,
name: "half",
color: colors.gray,
options: {
lineStyle: 4,
},
}),
createBaseSeries({
key: `${key}supply_half_in_btc`,
name: useGroupName ? name : "Halved",
name: useGroupName ? name : "half",
color: "list" in args ? color : colors.gray,
options: {
lineStyle: 4,
@@ -1785,7 +1798,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
}),
createBaseSeries({
key: `${key}supply_half_in_usd`,
name: useGroupName ? name : "Halved",
name: useGroupName ? name : "half",
color: "list" in args ? color : colors.gray,
options: {
lineStyle: 4,
@@ -1805,7 +1818,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
}),
createBaseSeries({
key: `${key}supply_breakeven_rel_to_circulating_supply`,
name: "Even",
name: "breakeven",
color: colors.yellow,
}),
]
@@ -1822,7 +1835,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
}),
createBaseSeries({
key: `${key}supply_breakeven_rel_to_own_supply`,
name: "Even",
name: "breakeven",
color: colors.yellow,
}),
createPriceLine({
@@ -1862,15 +1875,18 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
name,
color,
}),
...(key
? [
createBaseSeries({
key: `${key}supply_rel_to_circulating_supply`,
name,
color,
}),
]
: []),
key
? createBaseSeries({
key: `${key}supply_rel_to_circulating_supply`,
name,
color,
})
: createBaseSeries({
unit: "%all",
key: "constant_100",
name,
color,
}),
]);
}),
},
@@ -1904,11 +1920,6 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
}),
]
: []),
createBaseSeries({
key: `${key}supply_in_profit_rel_to_own_supply`,
name,
color,
}),
]);
}),
},
@@ -1942,17 +1953,12 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
}),
]
: []),
createBaseSeries({
key: `${key}supply_in_loss_rel_to_own_supply`,
name,
color,
}),
]);
}),
},
{
name: "even",
title: `Even Supply ${title}`,
name: "breakeven",
title: `Supply At Breaken ${title}`,
bottom: list.flatMap(({ color, name, key: _key }) => {
const key = fixKey(_key);
return /** @type {const} */ ([
@@ -2006,11 +2012,11 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
},
...(list.filter(
({ key }) => `${fixKey(key)}addr_count` in vecIdToIndexes,
).length
).length > ("list" in args ? 1 : 0)
? !("list" in args) ||
list.filter(
({ key }) => `${fixKey(key)}empty_addr_count` in vecIdToIndexes,
).length == 0
).length <= 1
? [
{
name: "address count",
@@ -2103,7 +2109,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
{
name: "Price",
title: `Realized Price ${title}`,
top: args.list.map(({ color, name, key }) =>
top: list.map(({ color, name, key }) =>
createBaseSeries({
key: `${fixKey(key)}realized_price`,
name,
@@ -2111,6 +2117,23 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
}),
),
},
{
name: "Ratio",
title: `Realized Price Ratio ${title}`,
bottom: [
...list.map(({ color, name, key }) =>
createBaseSeries({
key: `${fixKey(key)}realized_price_ratio`,
name,
color,
}),
),
createPriceLine({
unit: "Ratio",
number: 1,
}),
],
},
]
: createPriceWithRatioOptions({
title: `Realized Price ${title}`,
@@ -2144,23 +2167,6 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
}),
]
: []),
...(`${key}realized_cap_rel_to_own_market_cap` in
vecIdToIndexes
? [
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `${key}realized_cap_rel_to_own_market_cap`,
title: "ratio",
options: { baseValue: { price: 100 } },
colors: [colors.red, colors.green],
}),
createPriceLine({
unit: "%cmcap",
defaultActive: true,
number: 100,
}),
]
: []),
]);
}),
},
@@ -2175,29 +2181,35 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
name: "Profit",
color: colors.green,
}),
createBaseSeries({
key: `${fixKey(args.key)}realized_profit_cumulative`,
name: "Cumulative Profit",
color: colors.green,
defaultActive: false,
}),
createBaseSeries({
key: `${fixKey(args.key)}realized_loss`,
name: "Loss",
color: colors.red,
defaultActive: false,
}),
createBaseSeries({
key: `${fixKey(args.key)}total_realized_pnl`,
name: "Total",
color: colors.default,
defaultActive: false,
}),
createBaseSeries({
key: `${fixKey(args.key)}neg_realized_loss`,
name: "Negative Loss",
color: colors.red,
}),
createBaseSeries({
key: `${fixKey(args.key)}realized_profit_cumulative`,
name: "Cumulative Profit",
color: colors.green,
defaultActive: false,
}),
createBaseSeries({
key: `${fixKey(args.key)}realized_loss_cumulative`,
name: "Cumulative Loss",
color: colors.red,
defaultActive: false,
}),
createBaseSeries({
key: `${fixKey(args.key)}neg_realized_loss`,
name: "Negative Loss",
color: colors.red,
}),
createBaseSeries({
key: `${fixKey(args.key)}neg_realized_loss_cumulative`,
name: "Cumulative Negative Loss",
@@ -2433,6 +2445,22 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
}),
],
},
{
name: "Total pnl",
title: `Total Realized Profit And Loss Loss ${title}`,
bottom: [
...list.flatMap(({ color, name, key: _key }) => {
const key = fixKey(_key);
return /** @type {const} */ ([
createBaseSeries({
key: `${key}total_realized_pnl`,
name,
color,
}),
]);
}),
],
},
{
name: "Net pnl",
title: `Net Realized Profit And Loss ${title}`,
@@ -2613,7 +2641,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
]),
{
name: "Sell Side Risk Ratio",
name: "Sell Side Risk",
title: `Sell Side Risk Ratio ${title}`,
bottom: !("list" in args)
? list.flatMap(({ key }) => [
@@ -2655,8 +2683,8 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
title: `Unrealized Profit And Loss ${title}`,
bottom: [
createBaseSeries({
key: `${fixKey(args.key)}unrealized_total_pnl`,
name: "profit+loss",
key: `${fixKey(args.key)}total_unrealized_pnl`,
name: "total",
color: colors.default,
}),
createBaseSeries({
@@ -2719,22 +2747,22 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
}),
]
: []),
...(`${fixKey(args.key)}unrealized_profit_rel_to_own_unrealized_total_pnl` in
...(`${fixKey(args.key)}unrealized_profit_rel_to_own_total_unrealized_pnl` in
vecIdToIndexes
? [
createBaseSeries({
key: `${fixKey(args.key)}unrealized_profit_rel_to_own_unrealized_total_pnl`,
key: `${fixKey(args.key)}unrealized_profit_rel_to_own_total_unrealized_pnl`,
name: "Profit",
color: colors.green,
}),
createBaseSeries({
key: `${fixKey(args.key)}unrealized_loss_rel_to_own_unrealized_total_pnl`,
key: `${fixKey(args.key)}unrealized_loss_rel_to_own_total_unrealized_pnl`,
name: "Loss",
color: colors.red,
defaultActive: false,
}),
createBaseSeries({
key: `${fixKey(args.key)}neg_unrealized_loss_rel_to_own_unrealized_total_pnl`,
key: `${fixKey(args.key)}neg_unrealized_loss_rel_to_own_total_unrealized_pnl`,
name: "Negative Loss",
color: colors.red,
}),
@@ -2767,8 +2795,8 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
return /** @type {const} */ ([
createBaseSeries({
key: `${key}unrealized_profit`,
name: useGroupName ? name : "Profit",
color: useGroupName ? color : colors.green,
name,
color,
}),
]);
}),
@@ -2781,8 +2809,22 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
return /** @type {const} */ ([
createBaseSeries({
key: `${key}unrealized_loss`,
name: useGroupName ? name : "Loss",
color: useGroupName ? color : colors.red,
name,
color,
}),
]);
}),
},
{
name: "total pnl",
title: `Unrealized Total Profit And Loss ${title}`,
bottom: list.flatMap(({ color, name, key: _key }) => {
const key = fixKey(_key);
return /** @type {const} */ ([
createBaseSeries({
key: `${key}total_unrealized_pnl`,
name,
color,
}),
]);
}),
@@ -2821,14 +2863,14 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
}),
]
: []),
...(`${fixKey(key)}net_unrealized_pnl_rel_to_own_unrealized_total_pnl` in
...(`${fixKey(key)}net_unrealized_pnl_rel_to_own_total_unrealized_pnl` in
vecIdToIndexes
? [
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `${fixKey(
key,
)}net_unrealized_pnl_rel_to_own_unrealized_total_pnl`,
)}net_unrealized_pnl_rel_to_own_total_unrealized_pnl`,
title: useGroupName ? name : "Net",
color: useGroupName ? color : undefined,
}),
@@ -3293,10 +3335,13 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
...createSumCumulativeSeries({
concat: "block_count",
}),
createPriceLine({
unit: "Count",
createBaseSeries({
key: "block_count_target",
name: "Target",
number: 144,
color: colors.gray,
options: {
lineStyle: 4,
},
}),
],
},
@@ -3722,19 +3767,14 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
{
name: "Cohorts",
tree: [
createCohortGroupFolder({
key: "",
name: "",
title: "",
color: colors.orange,
}),
createCohortGroupFolder(cohortAll),
{
name: "terms",
tree: [
createCohortGroupFolder({
name: "Compare",
title: "UTXOs Term",
list: terms,
list: [...terms, cohortAllForComparaison],
}),
...terms.map(createCohortGroupFolder),
],
@@ -3745,7 +3785,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
createCohortGroupFolder({
name: "Compare",
title: "Epoch",
list: epoch,
list: [...epoch, cohortAllForComparaison],
}),
...epoch.map(createCohortGroupFolder),
],
@@ -3756,7 +3796,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
createCohortGroupFolder({
name: "Compare",
title: "Type",
list: type,
list: [...type, cohortAllForComparaison],
}),
...type.map(createCohortGroupFolder),
],
@@ -3767,7 +3807,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
createCohortGroupFolder({
name: "Compare",
title: "UTXOs Up To Age",
list: upToDate,
list: [...upToDate, cohortAllForComparaison],
}),
...upToDate.map(createCohortGroupFolder),
],
@@ -3778,7 +3818,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
createCohortGroupFolder({
name: "Compare",
title: "UTXOs from age",
list: fromDate,
list: [...fromDate, cohortAllForComparaison],
}),
...fromDate.map(createCohortGroupFolder),
],
@@ -3789,7 +3829,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
createCohortGroupFolder({
name: "Compare",
title: "UTXOs Age Range",
list: dateRange,
list: [...dateRange, cohortAllForComparaison],
}),
...dateRange.map(createCohortGroupFolder),
],
@@ -3800,7 +3840,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
createCohortGroupFolder({
name: "Compare",
title: "UTXOs under amount",
list: utxosUnderAmount,
list: [...utxosUnderAmount, cohortAllForComparaison],
}),
...utxosUnderAmount.map(createCohortGroupFolder),
],
@@ -3811,7 +3851,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
createCohortGroupFolder({
name: "Compare",
title: "UTXOs Above Amount",
list: utxosAboveAmount,
list: [...utxosAboveAmount, cohortAllForComparaison],
}),
...utxosAboveAmount.map(createCohortGroupFolder),
],
@@ -3822,7 +3862,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
createCohortGroupFolder({
name: "Compare",
title: "UTXOs between amounts",
list: utxosAmountRanges,
list: [...utxosAmountRanges, cohortAllForComparaison],
}),
...utxosAmountRanges.map(createCohortGroupFolder),
],
@@ -3833,7 +3873,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
createCohortGroupFolder({
name: "Compare",
title: "Addresses under Amount",
list: addressesUnderAmount,
list: [...addressesUnderAmount, cohortAllForComparaison],
}),
...addressesUnderAmount.map(createCohortGroupFolder),
],
@@ -3844,7 +3884,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
createCohortGroupFolder({
name: "Compare",
title: "Addresses above amount",
list: addressesAboveAmount,
list: [...addressesAboveAmount, cohortAllForComparaison],
}),
...addressesAboveAmount.map(createCohortGroupFolder),
],
@@ -3855,7 +3895,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
createCohortGroupFolder({
name: "Compare",
title: "Addresses between amounts",
list: addressesAmountRanges,
list: [...addressesAmountRanges, cohortAllForComparaison],
}),
...addressesAmountRanges.map(createCohortGroupFolder),
],
@@ -4160,10 +4200,10 @@ export function initOptions({
.split("/")
.filter((v) => v);
const urlPath = urlPath_.length ? urlPath_ : undefined;
const savedPath = utils.storage
.read(LS_SELECTED_KEY)
?.split("/")
.filter((v) => v);
const savedPath = /** @type {string[]} */ (
JSON.parse(utils.storage.read(LS_SELECTED_KEY) || "[]") || []
).filter((v) => v);
console.log(savedPath);
/** @type {Signal<Option>} */
const selected = signals.createSignal(/** @type {any} */ (undefined));
@@ -4196,6 +4236,7 @@ export function initOptions({
function selectOption(option) {
utils.url.pushHistory(option.path);
utils.url.resetParams(option);
utils.storage.write(LS_SELECTED_KEY, JSON.stringify(option.path));
selected.set(option);
}
@@ -4308,11 +4349,11 @@ export function initOptions({
);
const serName = utils.stringToId(anyPartial.name);
const path = [...parentPath, serName];
const childOptionsCount = recursiveProcessPartialTree(
anyPartial.tree,
passedDetails,
[...parentPath, serName],
path,
depth + 1,
);
@@ -4325,7 +4366,10 @@ export function initOptions({
}
signals.createEffect(selected, (selected) => {
if (selected.path[depth] === serName) {
if (
path.length <= selected.path.length &&
path.every((v, i) => selected.path.at(i) === v)
) {
li.dataset.highlight = "";
} else {
delete li.dataset.highlight;