mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-06-08 06:01:57 -07:00
bitview: reorg part 10 + api changes
This commit is contained in:
Generated
+35
-34
@@ -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
@@ -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"]}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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 = ¶ms.ids;
|
||||
let metrics = ¶ms.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();
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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
@@ -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 don’t cap all combinations
|
||||
- BUG: 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
|
||||
- _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`
|
||||
|
||||
-8
File diff suppressed because one or more lines are too long
-4892
File diff suppressed because it is too large
Load Diff
+7
File diff suppressed because one or more lines are too long
+4785
File diff suppressed because it is too large
Load Diff
@@ -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,
|
||||
|
||||
@@ -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: {
|
||||
|
||||
Reference in New Issue
Block a user