bitview: reorg part 10 + api changes

This commit is contained in:
nym21
2025-10-02 17:40:23 +02:00
parent c4ce718bb2
commit 16b14b1fe1
18 changed files with 5035 additions and 5095 deletions
Generated
+35 -34
View File
@@ -108,9 +108,9 @@ dependencies = [
[[package]]
name = "anstyle"
version = "1.0.11"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd"
checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
[[package]]
name = "anstyle-parse"
@@ -229,9 +229,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
[[package]]
name = "axum"
version = "0.8.5"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98e529aee37b5c8206bb4bf4c44797127566d72f76952c970bd3d1e85de8f4e2"
checksum = "8a18ed336352031311f4e0b4dd2ff392d4fbb370777c9d18d7fc9d7359f73871"
dependencies = [
"axum-core",
"bytes",
@@ -262,9 +262,9 @@ dependencies = [
[[package]]
name = "axum-core"
version = "0.5.4"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ac7a6beb1182c7e30253ee75c3e918080bfb83f5a3023bcdf7209d85fd147e6"
checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22"
dependencies = [
"bytes",
"futures-core",
@@ -687,6 +687,7 @@ dependencies = [
"quick_cache",
"schemars 1.0.4",
"serde",
"serde_json",
"serde_with",
"sonic-rs 0.5.5",
"vecdb",
@@ -2750,18 +2751,18 @@ dependencies = [
[[package]]
name = "munge"
version = "0.4.6"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7feb0b48aa0a25f9fe0899482c6e1379ee7a11b24a53073eacdecb9adb6dc60"
checksum = "5e17401f259eba956ca16491461b6e8f72913a0a114e39736ce404410f915a0c"
dependencies = [
"munge_macro",
]
[[package]]
name = "munge_macro"
version = "0.4.6"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2e3795a5d2da581a8b252fec6022eee01aea10161a4d1bf237d4cbe47f7e988"
checksum = "4568f25ccbd45ab5d5603dc34318c1ec56b117531781260002151b8530a9f931"
dependencies = [
"proc-macro2",
"quote",
@@ -2938,9 +2939,9 @@ checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e"
[[package]]
name = "owo-colors"
version = "4.2.2"
version = "4.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48dd4f4a2c8405440fd0462561f0e5806bd0f77e86f51c761481bdd4018b545e"
checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52"
[[package]]
name = "oxc"
@@ -2984,9 +2985,9 @@ dependencies = [
[[package]]
name = "oxc-miette"
version = "2.5.0"
version = "2.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d5495f6099fa0b25fa25755c1d59ed79ffa64dda80f5366a4cdfc8fc20f5932"
checksum = "5c42cefdcbebec6b0b72229ac0e02261a6770cb7ba39ccc5475a856164066db1"
dependencies = [
"cfg-if",
"owo-colors",
@@ -2999,9 +3000,9 @@ dependencies = [
[[package]]
name = "oxc-miette-derive"
version = "2.5.0"
version = "2.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dbbc96af6e37c35f2303b2bedbf8ce9cc563e4fbbf7776be6f0803cb0095652"
checksum = "05bbaa5b6b98826bb62b164406f703bee72c5287af9986f9c863fa8ea992b476"
dependencies = [
"proc-macro2",
"quote",
@@ -3268,9 +3269,9 @@ dependencies = [
[[package]]
name = "oxc_resolver"
version = "11.8.4"
version = "11.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "743c415f2237308d3a50d15d5ab5e432fd44c3b2c77042b01bbbd4e5e7d1ca0f"
checksum = "9bc696688fc6cbab56971f02badc233541f964f4705240c986abc02535a3728e"
dependencies = [
"cfg-if",
"indexmap 2.11.4",
@@ -3538,9 +3539,9 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
[[package]]
name = "petgraph"
version = "0.8.2"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54acf3a685220b533e437e264e4d932cfbdc4cc7ec0cd232ed73c08d03b8a7ca"
checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455"
dependencies = [
"fixedbitset",
"hashbrown 0.15.5",
@@ -3707,18 +3708,18 @@ dependencies = [
[[package]]
name = "ptr_meta"
version = "0.3.0"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe9e76f66d3f9606f44e45598d155cb13ecf09f4a28199e48daf8c8fc937ea90"
checksum = "0b9a0cf95a1196af61d4f1cbdab967179516d9a4a4312af1f31948f8f6224a79"
dependencies = [
"ptr_meta_derive",
]
[[package]]
name = "ptr_meta_derive"
version = "0.3.0"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca414edb151b4c8d125c12566ab0d74dc9cdba36fb80eb7b848c15f495fd32d1"
checksum = "7347867d0a7e1208d93b46767be83e2b8f978c3dad35f775ac8d8847551d6fe1"
dependencies = [
"proc-macro2",
"quote",
@@ -3764,9 +3765,9 @@ dependencies = [
[[package]]
name = "rancor"
version = "0.1.0"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "caf5f7161924b9d1cea0e4cabc97c372cea92b5f927fc13c6bca67157a0ad947"
checksum = "a063ea72381527c2a0561da9c80000ef822bdd7c3241b1cc1b12100e3df081ee"
dependencies = [
"ptr_meta",
]
@@ -3958,9 +3959,9 @@ dependencies = [
[[package]]
name = "rend"
version = "0.5.2"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a35e8a6bf28cd121053a66aa2e6a2e3eaffad4a60012179f0e864aa5ffeff215"
checksum = "cadadef317c2f20755a64d7fdc48f9e7178ee6b0e1f7fce33fa60f1d68a276e6"
[[package]]
name = "ring"
@@ -3978,9 +3979,9 @@ dependencies = [
[[package]]
name = "rkyv"
version = "0.8.11"
version = "0.8.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19f5c3e5da784cd8c69d32cdc84673f3204536ca56e1fa01be31a74b92c932ac"
checksum = "35a640b26f007713818e9a9b65d34da1cf58538207b052916a83d80e43f3ffa4"
dependencies = [
"bytes",
"hashbrown 0.15.5",
@@ -3996,9 +3997,9 @@ dependencies = [
[[package]]
name = "rkyv_derive"
version = "0.8.11"
version = "0.8.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4270433626cffc9c4c1d3707dd681f2a2718d3d7b09ad754bec137acecda8d22"
checksum = "bd83f5f173ff41e00337d97f6572e416d022ef8a19f371817259ae960324c482"
dependencies = [
"proc-macro2",
"quote",
@@ -4990,9 +4991,9 @@ dependencies = [
[[package]]
name = "typenum"
version = "1.18.0"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
[[package]]
name = "unicode-id-start"
+2 -1
View File
@@ -42,7 +42,7 @@ debug-assertions = false
[workspace.dependencies]
allocative = { version = "0.3.4", features = ["parking_lot"] }
axum = "0.8.5"
axum = "0.8.6"
bitcoin = { version = "0.32.7", features = ["serde"] }
bitcoincore-rpc = "0.19.0"
brk_binder = { version = "0.0.109", path = "crates/brk_binder" }
@@ -72,6 +72,7 @@ schemars = "1.0.4"
serde = "1.0.228"
serde_bytes = "0.11.19"
serde_derive = "1.0.228"
serde_json = { version = "1.0.145", features = ["float_roundtrip"] }
sonic-rs = "0.5.5"
tokio = { version = "1.47.1", features = ["rt-multi-thread"] }
# vecdb = { path = "../seqdb/crates/vecdb", features = ["derive"]}
+1
View File
@@ -21,6 +21,7 @@ derive_deref = { workspace = true }
quick_cache = { workspace = true }
schemars = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
sonic-rs = { workspace = true }
serde_with = "3.14.1"
nucleo-matcher = "0.3.1"
+2 -2
View File
@@ -38,12 +38,12 @@ pub fn main() -> Result<()> {
dbg!(interface.search_and_format(Params {
index: Index::Height,
ids: vec!["date"].into(),
metrics: vec!["date"].into(),
rest: ParamsOpt::default().set_from(-1),
})?);
dbg!(interface.search_and_format(Params {
index: Index::Height,
ids: vec!["date", "timestamp"].into(),
metrics: vec!["date", "timestamp"].into(),
rest: ParamsOpt::default().set_from(-10).set_count(5),
})?);
+1 -1
View File
@@ -1,5 +1,5 @@
use serde::{Deserialize, Deserializer};
use sonic_rs::{JsonValueTrait, Value};
use serde_json::Value;
pub fn de_unquote_i64<'de, D>(deserializer: D) -> Result<Option<i64>, D::Error>
where
+24 -19
View File
@@ -16,8 +16,8 @@ use vecdb::{AnyCollectableVec, AnyStoredVec};
mod deser;
mod format;
mod ids;
mod index;
mod metrics;
mod output;
mod pagination;
mod params;
@@ -27,7 +27,7 @@ pub use format::Format;
pub use index::Index;
pub use output::{Output, Value};
pub use pagination::{PaginatedIndexParam, PaginationParam};
pub use params::{Params, ParamsOpt};
pub use params::{Params, ParamsDeprec, ParamsOpt};
use vecs::Vecs;
use crate::vecs::{IndexToVec, MetricToVec};
@@ -65,7 +65,7 @@ impl<'a> Interface<'a> {
}
pub fn search(&self, params: &Params) -> Result<Vec<(String, &&dyn AnyCollectableVec)>> {
let ids = &params.ids;
let metrics = &params.metrics;
let index = params.index;
let ids_to_vec = self
@@ -77,25 +77,25 @@ impl<'a> Interface<'a> {
index
)))?;
ids.iter()
.map(|id| {
let vec = ids_to_vec.get(id.as_str()).ok_or_else(|| {
metrics.iter()
.map(|metric| {
let vec = ids_to_vec.get(metric.as_str()).ok_or_else(|| {
let cached_errors = cached_errors();
if let Some(message) = cached_errors.get(id) {
if let Some(message) = cached_errors.get(metric) {
return Error::String(message)
}
let mut message = format!(
"No vec named \"{}\" indexed by \"{}\" found.\n",
id,
metric,
index
);
let mut matcher = Matcher::new(Config::DEFAULT);
let matches = Pattern::new(
id.as_str(),
metric.as_str(),
CaseMatching::Ignore,
Normalization::Smart,
AtomKind::Fuzzy,
@@ -111,33 +111,35 @@ impl<'a> Interface<'a> {
&format!("\nMaybe you meant one of the following: {matches:#?} ?\n");
}
if let Some(index_to_vec) = self.metric_to_index_to_vec().get(id.as_str()) {
message += &format!("\nBut there is a vec named {id} which supports the following indexes: {:#?}\n", index_to_vec.keys());
if let Some(index_to_vec) = self.metric_to_index_to_vec().get(metric.as_str()) {
message += &format!("\nBut there is a vec named {metric} which supports the following indexes: {:#?}\n", index_to_vec.keys());
}
cached_errors.insert(id.clone(), message.clone());
cached_errors.insert(metric.clone(), message.clone());
Error::String(message)
});
vec.map(|vec| (id.clone(), vec))
vec.map(|vec| (metric.clone(), vec))
})
.collect::<Result<Vec<_>>>()
}
pub fn format(
&self,
vecs: Vec<(String, &&dyn AnyCollectableVec)>,
metrics: Vec<(String, &&dyn AnyCollectableVec)>,
params: &ParamsOpt,
) -> Result<Output> {
let from = params.from().map(|from| {
vecs.iter()
metrics
.iter()
.map(|(_, v)| v.i64_to_usize(from))
.min()
.unwrap_or_default()
});
let to = params.to().map(|to| {
vecs.iter()
metrics
.iter()
.map(|(_, v)| v.i64_to_usize(to))
.min()
.unwrap_or_default()
@@ -147,8 +149,11 @@ impl<'a> Interface<'a> {
Ok(match format {
Format::CSV => {
let headers = vecs.iter().map(|(id, _)| id.as_str()).collect::<Vec<_>>();
let mut values = vecs
let headers = metrics
.iter()
.map(|(id, _)| id.as_str())
.collect::<Vec<_>>();
let mut values = metrics
.iter()
.map(|(_, vec)| Ok(vec.collect_range_string(from, to)?))
.collect::<Result<Vec<_>>>()?;
@@ -190,7 +195,7 @@ impl<'a> Interface<'a> {
Output::CSV(csv)
}
Format::JSON => {
let mut values = vecs
let mut values = metrics
.iter()
.map(|(_, vec)| -> Result<Vec<u8>> {
Ok(vec.collect_range_json_bytes(from, to)?)
@@ -6,24 +6,29 @@ use serde::Deserialize;
use sonic_rs::{JsonContainerTrait, JsonValueTrait, Value};
#[derive(Debug, Deref, JsonSchema)]
pub struct MaybeIds(Vec<String>);
pub struct MaybeMetrics(Vec<String>);
const MAX_VECS: usize = 32;
const MAX_STRING_SIZE: usize = 64 * MAX_VECS;
impl From<String> for MaybeIds {
impl From<String> for MaybeMetrics {
fn from(value: String) -> Self {
Self(vec![value])
Self(vec![value.replace("-", "_").to_lowercase()])
}
}
impl<'a> From<Vec<&'a str>> for MaybeIds {
impl<'a> From<Vec<&'a str>> for MaybeMetrics {
fn from(value: Vec<&'a str>) -> Self {
Self(value.iter().map(|s| s.to_string()).collect::<Vec<_>>())
Self(
value
.iter()
.map(|s| s.replace("-", "_").to_lowercase())
.collect::<Vec<_>>(),
)
}
}
impl<'de> Deserialize<'de> for MaybeIds {
impl<'de> Deserialize<'de> for MaybeMetrics {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
@@ -32,7 +37,7 @@ impl<'de> Deserialize<'de> for MaybeIds {
if let Some(str) = value.as_str() {
if str.len() <= MAX_STRING_SIZE {
Ok(MaybeIds(sanitize_ids(
Ok(MaybeMetrics(sanitize_metrics(
str.split(",").map(|s| s.to_string()),
)))
} else {
@@ -40,7 +45,7 @@ impl<'de> Deserialize<'de> for MaybeIds {
}
} else if let Some(vec) = value.as_array() {
if vec.len() <= MAX_VECS {
Ok(MaybeIds(sanitize_ids(
Ok(MaybeMetrics(sanitize_metrics(
vec.into_iter().map(|s| s.as_str().unwrap().to_string()),
)))
} else {
@@ -52,14 +57,14 @@ impl<'de> Deserialize<'de> for MaybeIds {
}
}
impl fmt::Display for MaybeIds {
impl fmt::Display for MaybeMetrics {
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> {
fn sanitize_metrics(raw_ids: impl Iterator<Item = String>) -> Vec<String> {
let mut results = Vec::new();
raw_ids.for_each(|s| {
let mut current = String::new();
+29 -10
View File
@@ -6,23 +6,22 @@ use serde::Deserialize;
use crate::{
Format, Index,
deser::{de_unquote_i64, de_unquote_usize},
ids::MaybeIds,
metrics::MaybeMetrics,
};
#[derive(Debug, Deserialize, JsonSchema)]
pub struct Params {
#[serde(alias = "i")]
#[schemars(description = "Index of requested vecs")]
pub index: Index,
#[serde(alias = "m")]
#[schemars(description = "Requested metrics")]
pub metrics: MaybeMetrics,
#[serde(alias = "v")]
#[schemars(description = "Ids of requested vecs")]
pub ids: MaybeIds,
#[serde(alias = "i")]
#[schemars(description = "Requested index")]
pub index: Index,
#[serde(flatten)]
pub rest: ParamsOpt,
}
serde_with::flattened_maybe!(deserialize_rest, "rest");
impl Deref for Params {
type Target = ParamsOpt;
@@ -32,10 +31,10 @@ impl Deref for Params {
}
impl From<((Index, String), ParamsOpt)> for Params {
fn from(((index, id), rest): ((Index, String), ParamsOpt)) -> Self {
fn from(((index, metric), rest): ((Index, String), ParamsOpt)) -> Self {
Self {
index,
ids: MaybeIds::from(id),
metrics: MaybeMetrics::from(metric),
rest,
}
}
@@ -106,3 +105,23 @@ impl ParamsOpt {
self.format
}
}
#[derive(Debug, Deserialize)]
pub struct ParamsDeprec {
#[serde(alias = "i")]
pub index: Index,
#[serde(alias = "v")]
pub ids: MaybeMetrics,
#[serde(flatten)]
pub rest: ParamsOpt,
}
impl From<ParamsDeprec> for Params {
fn from(value: ParamsDeprec) -> Self {
Params {
index: value.index,
metrics: value.ids,
rest: value.rest,
}
}
}
+1 -1
View File
@@ -13,4 +13,4 @@ build = "build.rs"
env_logger = "0.11.8"
jiff = { workspace = true }
log = { workspace = true }
owo-colors = "4.2.2"
owo-colors = "4.2.3"
+1 -1
View File
@@ -19,7 +19,7 @@ brk_rmcp = { version = "0.7.1", features = [
log = { workspace = true }
schemars = { workspace = true }
serde = { workspace = true }
serde_json = { version = "1.0.145", features = ["float_roundtrip"] }
serde_json = { workspace = true }
[package.metadata.cargo-machete]
ignored = ["serde_json"]
+59 -39
View File
@@ -5,7 +5,7 @@ use axum::{
response::{IntoResponse, Response},
routing::get,
};
use brk_interface::{Index, PaginatedIndexParam, PaginationParam, Params, ParamsOpt};
use brk_interface::{Index, PaginatedIndexParam, PaginationParam, Params, ParamsDeprec, ParamsOpt};
use super::AppState;
@@ -35,26 +35,26 @@ impl ApiMetricsRoutes for Router<AppState> {
Json(app_state.interface.get_accepted_indexes()).into_response()
}),
)
.route(
"/api/vecs/metrics",
get(
async |State(app_state): State<AppState>,
Query(pagination): Query<PaginationParam>|
-> Response {
Json(app_state.interface.get_metrics(pagination)).into_response()
},
),
)
.route(
"/api/vecs/index-to-metrics",
get(
async |State(app_state): State<AppState>,
Query(paginated_index): Query<PaginatedIndexParam>|
-> Response {
Json(app_state.interface.get_index_to_vecids(paginated_index)).into_response()
},
),
)
// .route(
// "/api/vecs/metrics",
// get(
// async |State(app_state): State<AppState>,
// Query(pagination): Query<PaginationParam>|
// -> Response {
// Json(app_state.interface.get_metrics(pagination)).into_response()
// },
// ),
// )
// .route(
// "/api/vecs/index-to-metrics",
// get(
// async |State(app_state): State<AppState>,
// Query(paginated_index): Query<PaginatedIndexParam>|
// -> Response {
// Json(app_state.interface.get_index_to_vecids(paginated_index)).into_response()
// },
// ),
// )
.route(
"/api/metrics/{metric}",
get(
@@ -64,25 +64,44 @@ impl ApiMetricsRoutes for Router<AppState> {
},
),
)
.route("/api/metrics/bulk", get(data::handler))
.route(
"/api/metrics/{metric}/{index}",
get(
async |State(app_state): State<AppState>,
Path((metric, index)): Path<(String, Index)>|
async |uri: Uri,
headers: HeaderMap,
state: State<AppState>,
Path((metric, index)): Path<(String, Index)>,
Query(params_opt): Query<ParamsOpt>|
-> Response {
// If not found do fuzzy search but here or in interface ?
Json(
format!("{metric}/{index}"), // app_state
// .interface
// .metric_to_indexes(metric.replace("-", "_")),
data::handler(
uri,
headers,
Query(Params::from(((index, metric), params_opt))),
state,
)
.into_response()
.await
},
),
)
// !!!
// DEPRECATED
.route("/api/vecs/query", get(data::handler))
// !!!
.route(
"/api/vecs/query",
get(
async |uri: Uri,
headers: HeaderMap,
Query(params): Query<ParamsDeprec>,
state: State<AppState>|
-> Response {
data::handler(uri, headers, Query(params.into()), state).await
},
),
)
// !!!
// DEPRECATED
// !!!
.route(
"/api/vecs/{variant}",
get(
@@ -95,15 +114,16 @@ impl ApiMetricsRoutes for Router<AppState> {
let variant = variant.replace("-", "_");
let mut split = variant.split(TO_SEPARATOR);
if let Ok(index) = Index::try_from(split.next().unwrap()) {
let params = Params::from((
(index, split.collect::<Vec<_>>().join(TO_SEPARATOR)),
params_opt,
));
data::handler(uri, headers, Query(params), state).await
} else {
"Bad variant".into_response()
}
let ser_index = split.next().unwrap();
let Ok(index) = Index::try_from(ser_index) else {
return format!("Index {ser_index} doesn't exist").into_response();
};
let params = Params::from((
(index, split.collect::<Vec<_>>().join(TO_SEPARATOR)),
params_opt,
));
data::handler(uri, headers, Query(params), state).await
},
),
)
+66 -70
View File
@@ -3,18 +3,18 @@
- __CRATES__
- _BUNDLER_
- _CLI_
- launch
- UX: launch
- if first, test read/write speed, add warning if too low (<2gb/s)
- check available disk space
- pull latest version and notify if out of date
- add custom path support for config.toml
- FEAT: add custom path support for config.toml
- _COMPUTER_
- **add rollback of states (in stateful)**
- add support for per index computation
- fix min fee_rate which is always ZERO due to coinbase transaction
- before computing multiple sources check their length, panic if not equal
- create usd versions of vecs structs instead of having options everywhere
- datasets
- BUG: **add rollback of states (in stateful)**
- FEAT: add support for per index computation
- BUG: fix min fee_rate which is always ZERO due to coinbase transaction
- BUG: before computing multiple sources check their length, panic if not equal
- DX: create usd versions of vecs structs instead of having options everywhere
- FEAT: datasets
- `sats` version of all price datasets (average and co)
- pools
- highest dominance
@@ -41,10 +41,10 @@
- _ERROR_
- _FETCHER_
- _INDEXER_
- parse only the needed block number instead the last 100 blocks
- PERF: parse only the needed block number instead the last 100 blocks
- maybe using https://developer.bitcoin.org/reference/rpc/getblockhash.html
- _INTERFACE_
- Maybe change `json` to:
- DX: Maybe change `json` to:
```json
{
"price_close": {
@@ -57,97 +57,93 @@
}
}
```
- create pagination enum
- DX: create pagination enum
- from to
- from option<count>
- to option<count>
- page + option<per page> default 1000 max 1000
- from/to/count params dont cap all combinations
- BUG: from/to/count params dont cap all combinations
- example: from -10,000 count 10, wont work if underlying vec isnt 10k or more long
- _LOGGER_
- remove colors from file
- BUG: remove colors from file
- _MCP_
- _PARSER_
- _SERVER_
- api
- copy mempool's rest api
- FEAT: copy mempool's rest api
- https://mempool.space/docs/api/rest
- add extensions support (.json .csv …) instead of only format
- if format instead of extension then don't download file
- ddos protection
- FEAT: add extensions support (.json .csv …) instead of only format
- FEAT: if format instead of extension then don't download file
- BUG: ddos protection
- against API params varying in range
- search
- fuzzy on typo
- https://github.com/rapidfuzz/strsim-rs or stick with current impl
- create map of all single words
- do some kind of score with that ?
- discoverability
- FEAT: discoverability
- catalog (tree/groups)
- search
- failover to `/api`
- no HTML / redirects ?
- change `/api/vecs/{index}-to-{metric}` to `/api/{metric}/index`
- change `/api/vecs/query` to `/api/bulk`
- support keyed version when fetching dataset: {date: value} / {date: [value]}
- add support for https (rustls)
- BUG: failover to `/api`
- ???: no HTML / redirects ?
- FEAT: support keyed version when fetching dataset: {date: value} / {date: [value]}
- FEAT: add support for https (rustls)
- _STORE_
- save height and version in one file
- FEAT: save height and version in one file
- _STRUCTS_
- _GLOBAL_
- https://davidlattimore.github.io/posts/2025/09/02/rustforge-wild-performance-tricks.html
- PERF: https://davidlattimore.github.io/posts/2025/09/02/rustforge-wild-performance-tricks.html
- __DOCS__
- _README_
- add a comparison table with alternatives
- add contribution section where help is needed
- documentation/mcp/datasets/different front ends
- add faq
- FEAT: add a comparison table with alternatives
- FEAT: add faq
- __WEBSITES__
- _PACKAGES_
- move the fetching logic from `bitview` website to an independent `brk` package which could be published to npm
- DX: move the fetching logic from `bitview` website to an independent `brk` package which could be published to npm
- https://www.npmjs.com/package/@mempool/mempool.js
- auto publish with github actions
- _BITVIEW_
- explorer
- blocks (interval as length between)
- transactions
- addresses
- miners
- maybe xpubs
- charts
- 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)
- shows certain series as [scatter plots](https://github.com/tradingview/lightweight-charts/issues/1662) with a solid sma/ema
- EXPLORER
- FEAT: blocks (interval as length between)
- FEAT: transactions
- FEAT: addresses
- FEAT: miners
- FEAT: xpubs ?
- CHART
- FEAT: Make candlesticks a bi-series with a candlestick series and a line when too zoomed out (like the auto mode)
- FEAT: Add min/max markers back now that they can be ignored when scaling the chart (to avoids stuttering)
- BUG: selected unit sometimes changes when going back end forth
- FEAT: add support for custom charts
- BUG: price scale format depends on unit, hide digits for sats for example (if/when possible)
- FEAT: shows certain series as [scatter plots](https://github.com/tradingview/lightweight-charts/issues/1662) with a solid sma/ema
- mainly datasets with a big variance like raw `hash_rate`
- hide pane if no series on it
- fix (and reset) pane size (50/50) when changing charts
- units: add short name / long name / title
- verify that "compare" folders aren't missing charts/datasets
- legend
- add link to explanation for each name (to glassnode ?)
- table
- pagination
- exports (.json, .csv,…)
- improve dataset selection
- display 1k values (instead of 10k) but to avoid caching multiple times the same values apply everywhere
- search
- improve
- datasets add legend, and keywords ?
- support height/address/txid
- api
- add api page with interactivity
- glossary ?
- nav
- move share button to footer ?
- when clicking on already selected option, pushes to history, bad !
- global
- improve behavior when local storage is unavailable
- by having a global state
- font:
- BUG: hide pane if no series on it
- BUG: fix (and reset) pane size (50/50) when changing charts
- UX: units: add short name / long name / title
- BUG: verify that "compare" folders aren't missing charts/datasets
- LEGEND
- UX: add link to explanation for each name (to glassnode ?)
- TABLE
- FEAT: pagination
- FEAT: exports (.json, .csv,…)
- UX: improve dataset selection
- UX: display 1k values (instead of 10k) but to avoid caching multiple times the same values apply everywhere
- SEARCH
- UX: improve
- UX:datasets add legend, and keywords ?
- FEAT: support height/address/txid
- GLOSSARY
- FEAT: Add ?
- NAV
- UX: move share button to footer ?
- BUG: when clicking on already selected option, pushes to history, bad !
- GLOBAL
- BUG: improve behavior when local storage is unavailable by having a global state, otherwise the website forgets/don't save user's settings
- UI: font:
- https://fonts.google.com/specimen/Space+Mono
- keep as many files as possible [under 14kb](https://endtimes.dev/why-your-website-should-be-under-14kb-in-size/)
- [No classes](https://news.ycombinator.com/item?id=45287155)
- [Organic animations](https://courses.joshwcomeau.com/playground/magic-wand-final)
- PERF: keep as many files as possible [under 14kb](https://endtimes.dev/why-your-website-should-be-under-14kb-in-size/)
- DX: [No classes](https://news.ycombinator.com/item?id=45287155)
- UX: [Organic animations](https://courses.joshwcomeau.com/playground/magic-wand-final)
- __GLOBAL__
- check `TODO`s in codebase
- rename `output` to `txout` or `vout`, `input` to `txin` or `vin`
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -1,13 +1,15 @@
/** @import { IChartApi, ISeriesApi as _ISeriesApi, SeriesDefinition, SingleValueData as _SingleValueData, CandlestickData as _CandlestickData, BaselineData as _BaselineData, HistogramData as _HistogramData, SeriesType, IPaneApi, LineSeriesPartialOptions as _LineSeriesPartialOptions, HistogramSeriesPartialOptions as _HistogramSeriesPartialOptions, BaselineSeriesPartialOptions as _BaselineSeriesPartialOptions, CandlestickSeriesPartialOptions as _CandlestickSeriesPartialOptions, WhitespaceData, DeepPartial, ChartOptions, Time, LineData as _LineData } from '../../modules/lightweight-charts/5.0.8/dist/typings' */
/** @import { IChartApi, ISeriesApi as _ISeriesApi, SeriesDefinition, SingleValueData as _SingleValueData, CandlestickData as _CandlestickData, BaselineData as _BaselineData, HistogramData as _HistogramData, SeriesType, IPaneApi, LineSeriesPartialOptions as _LineSeriesPartialOptions, HistogramSeriesPartialOptions as _HistogramSeriesPartialOptions, BaselineSeriesPartialOptions as _BaselineSeriesPartialOptions, CandlestickSeriesPartialOptions as _CandlestickSeriesPartialOptions, WhitespaceData, DeepPartial, ChartOptions, Time, LineData as _LineData, createChart as CreateChart } from '../../modules/lightweight-charts/5.0.9/dist/typings' */
import {
createChart,
createChart as _createChart,
CandlestickSeries,
HistogramSeries,
LineSeries,
BaselineSeries,
// } from "../modules/lightweight-charts/5.0.8/dist/lightweight-charts.standalone.development.mjs";
} from "../../modules/lightweight-charts/5.0.8/dist/lightweight-charts.standalone.production.mjs";
// } from "../modules/lightweight-charts/5.0.9/dist/lightweight-charts.standalone.development.mjs";
} from "../../modules/lightweight-charts/5.0.9/dist/lightweight-charts.standalone.production.mjs";
const createChart = /** @type {CreateChart} */ (_createChart);
import {
createHorizontalChoiceField,
@@ -96,7 +98,6 @@ function createChartElement({
const legendBottom = createLegend(signals);
div.append(legendBottom.element);
/** @type {IChartApi} */
const ichart = createChart(
chartDiv,
/** @satisfies {DeepPartial<ChartOptions>} */ ({
@@ -139,7 +140,6 @@ function createChartElement({
// ..._options,
}),
);
// Takes a bit more space sometimes but it's better UX than having the scale being resized on option change
ichart.priceScale("right").applyOptions({
minimumWidth: 80,
+1 -1
View File
@@ -16,7 +16,7 @@
<div id="chart" style="height: 100%; width: 100%"></div>
</body>
<script type="module">
import * as lc from "https://unpkg.com/lightweight-charts@5.0.8/dist/lightweight-charts.standalone.development.mjs";
import * as lc from "https://unpkg.com/lightweight-charts@5.0.9/dist/lightweight-charts.standalone.development.mjs";
const chartOptions = {
layout: {