diff --git a/Cargo.lock b/Cargo.lock index 4e13a3f82..5f97daa65 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -85,54 +85,10 @@ dependencies = [ ] [[package]] -name = "anstream" -version = "0.6.21" +name = "anyhow" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" - -[[package]] -name = "anstyle-parse" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" -dependencies = [ - "anstyle", - "once_cell_polyfill", - "windows-sys 0.61.2", -] +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "arrayvec" @@ -435,13 +391,13 @@ dependencies = [ "oas3", "serde", "serde_json", - "tracing", ] [[package]] name = "brk_cli" version = "0.1.0-alpha.3" dependencies = [ + "anyhow", "brk_alloc", "brk_computer", "brk_error", @@ -454,8 +410,8 @@ dependencies = [ "brk_reader", "brk_rpc", "brk_server", - "clap", - "color-eyre", + "brk_types", + "lexopt", "serde", "tokio", "toml", @@ -729,7 +685,6 @@ dependencies = [ "derive_more", "itoa", "jiff", - "num_enum", "rapidhash", "ryu", "schemars", @@ -854,46 +809,6 @@ dependencies = [ "libloading", ] -[[package]] -name = "clap" -version = "4.5.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.5.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_derive" -version = "4.5.49" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "clap_lex" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3e64b0cc0439b12df2fa678eae89a1c56a529fd067a9115f7827f1fffd22b32" - [[package]] name = "color-eyre" version = "0.6.5" @@ -927,12 +842,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" -[[package]] -name = "colorchoice" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" - [[package]] name = "compare" version = "0.0.6" @@ -1877,12 +1786,6 @@ dependencies = [ "compare", ] -[[package]] -name = "is_terminal_polyfill" -version = "1.70.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" - [[package]] name = "itertools" version = "0.13.0" @@ -1905,7 +1808,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e67e8da4c49d6d9909fe03361f9b620f58898859f5c7aded68351e85e71ecf50" dependencies = [ "jiff-static", - "jiff-tzdb-platform", "log", "portable-atomic", "portable-atomic-util", @@ -1924,21 +1826,6 @@ dependencies = [ "syn", ] -[[package]] -name = "jiff-tzdb" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68971ebff725b9e2ca27a601c5eb38a4c5d64422c4cbab0c535f248087eda5c2" - -[[package]] -name = "jiff-tzdb-platform" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8" -dependencies = [ - "jiff-tzdb", -] - [[package]] name = "jobserver" version = "0.1.34" @@ -1983,6 +1870,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "lexopt" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa0e2a1fcbe2f6be6c42e342259976206b383122fc152e872795338b5a3f3a7" + [[package]] name = "libc" version = "0.2.180" @@ -2229,28 +2122,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "num_enum" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" -dependencies = [ - "num_enum_derive", - "rustversion", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "oas3" version = "0.20.1" @@ -2298,12 +2169,6 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" -[[package]] -name = "once_cell_polyfill" -version = "1.70.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" - [[package]] name = "option-ext" version = "0.2.0" @@ -2492,15 +2357,6 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "proc-macro-crate" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" -dependencies = [ - "toml_edit", -] - [[package]] name = "proc-macro2" version = "1.0.105" @@ -3052,12 +2908,6 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - [[package]] name = "strum" version = "0.27.2" @@ -3272,18 +3122,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "toml_edit" -version = "0.23.10+spec-1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" -dependencies = [ - "indexmap", - "toml_datetime", - "toml_parser", - "winnow", -] - [[package]] name = "toml_parser" version = "1.0.6+spec-1.1.0" @@ -3312,7 +3150,6 @@ dependencies = [ "tokio", "tower-layer", "tower-service", - "tracing", ] [[package]] @@ -3355,7 +3192,6 @@ version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ - "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -3485,12 +3321,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" -[[package]] -name = "utf8parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" - [[package]] name = "valuable" version = "0.1.1" @@ -3883,9 +3713,6 @@ name = "winnow" version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" -dependencies = [ - "memchr", -] [[package]] name = "wio" diff --git a/Cargo.toml b/Cargo.toml index 2dd1b6867..f9b19dedf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,7 @@ debug = true [workspace.dependencies] aide = { version = "0.16.0-alpha.2", features = ["axum-json", "axum-query"] } -axum = "0.8.8" +axum = { version = "0.8.8", default-features = false, features = ["http1", "json", "query", "tokio", "tracing"] } bitcoin = { version = "0.32.8", features = ["serde"] } bitcoincore-rpc = "0.19.0" brk_alloc = { version = "0.1.0-alpha.3", path = "crates/brk_alloc" } @@ -65,7 +65,7 @@ byteview = "0.10.0" color-eyre = "0.6.5" derive_more = { version = "2.1.1", features = ["deref", "deref_mut"] } fjall = "3.0.1" -jiff = "0.2.18" +jiff = { version = "0.2.18", features = ["perf-inline", "tz-system"], default-features = false } minreq = { version = "2.14.1", features = ["https", "serde_json"] } parking_lot = "0.12.5" rayon = "1.11.0" diff --git a/crates/brk_bindgen/Cargo.toml b/crates/brk_bindgen/Cargo.toml index 544472f62..dec77bf70 100644 --- a/crates/brk_bindgen/Cargo.toml +++ b/crates/brk_bindgen/Cargo.toml @@ -14,4 +14,3 @@ brk_types = { workspace = true } oas3 = "0.20" serde = { workspace = true } serde_json = { workspace = true } -tracing = { workspace = true } diff --git a/crates/brk_cli/Cargo.toml b/crates/brk_cli/Cargo.toml index 34f4372bc..4652f2a8b 100644 --- a/crates/brk_cli/Cargo.toml +++ b/crates/brk_cli/Cargo.toml @@ -8,9 +8,10 @@ homepage.workspace = true repository.workspace = true [dependencies] +anyhow = "1.0" brk_alloc = { workspace = true } brk_computer = { workspace = true } -brk_error = { workspace = true } +brk_error = { workspace = true, features = ["tokio", "vecdb"] } brk_fetcher = { workspace = true } brk_indexer = { workspace = true } brk_iterator = { workspace = true } @@ -20,8 +21,8 @@ brk_query = { workspace = true } brk_reader = { workspace = true } brk_rpc = { workspace = true } brk_server = { workspace = true } -clap = { version = "4.5.54", features = ["derive", "string"] } -color-eyre = { workspace = true } +brk_types = { workspace = true } +lexopt = "0.3" tracing = { workspace = true } serde = { workspace = true } tokio = { workspace = true } diff --git a/crates/brk_cli/README.md b/crates/brk_cli/README.md index 3af82ef5e..0c20a71f7 100644 --- a/crates/brk_cli/README.md +++ b/crates/brk_cli/README.md @@ -35,39 +35,21 @@ brk Indexes the blockchain, computes datasets, starts the server on `localhost:3110`, and waits for new blocks. -## Help - -``` -brk -h Show all options -brk -V Show version -``` - ## Options +```bash +brk -h # Show all options +brk -V # Show version +``` + Options are saved to `~/.brk/config.toml` after first use. -``` ---bitcoindir Bitcoin data directory ---blocksdir Blocks directory (default: bitcoindir/blocks) ---brkdir Output directory (default: ~/.brk) - ---rpcconnect RPC host (default: localhost) ---rpcport RPC port (default: 8332) ---rpccookiefile RPC cookie file (default: bitcoindir/.cookie) ---rpcuser RPC username ---rpcpassword RPC password - --F, --fetch Fetch price data (default: true) ---exchanges Fetch from exchange APIs (default: true) --w, --website Serve web interface (default: true) -``` - ## Files ``` ~/.brk/ ├── config.toml Configuration -└── log/ Logs +└── log Logs / Indexed data (default: ~/.brk) ``` diff --git a/crates/brk_cli/src/config.rs b/crates/brk_cli/src/config.rs index c78fd2606..c59689387 100644 --- a/crates/brk_cli/src/config.rs +++ b/crates/brk_cli/src/config.rs @@ -6,78 +6,53 @@ use std::{ use brk_error::{Error, Result}; use brk_fetcher::Fetcher; use brk_rpc::{Auth, Client}; -use clap::Parser; +use brk_types::Port; use serde::{Deserialize, Deserializer, Serialize}; use crate::{default_brk_path, dot_brk_path, fix_user_path, website::WebsiteArg}; -#[derive(Parser, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize)] -#[command(version, about)] +#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize)] pub struct Config { - /// Bitcoin main directory path, defaults: ~/.bitcoin, ~/Library/Application\ Support/Bitcoin, saved #[serde(default, deserialize_with = "default_on_error")] - #[arg(long, value_name = "PATH")] - bitcoindir: Option, - - /// Bitcoin blocks directory path, default: --bitcoindir/blocks, saved - #[serde(default, deserialize_with = "default_on_error")] - #[arg(long, value_name = "PATH")] - blocksdir: Option, - - /// Bitcoin Research Kit outputs directory path, default: ~/.brk, saved - #[serde(default, deserialize_with = "default_on_error")] - #[arg(long, value_name = "PATH")] brkdir: Option, - /// Activate fetching prices from BRK's API and the computation of all price related datasets, default: true, saved #[serde(default, deserialize_with = "default_on_error")] - #[arg(short = 'F', long, value_name = "BOOL")] - fetch: Option, + brkport: Option, - /// Activate fetching prices from exchanges APIs if `fetch` is also set to `true`, default: true, saved #[serde(default, deserialize_with = "default_on_error")] - #[arg(long, value_name = "BOOL")] - exchanges: Option, - - /// Website served by the server: true (default), false, or PATH, saved - #[serde(default, deserialize_with = "default_on_error")] - #[arg(short, long, value_name = "BOOL|PATH")] website: Option, - /// Bitcoin RPC ip, default: localhost, saved #[serde(default, deserialize_with = "default_on_error")] - #[arg(long, value_name = "IP")] + fetch: Option, + + #[serde(default, deserialize_with = "default_on_error")] + bitcoindir: Option, + + #[serde(default, deserialize_with = "default_on_error")] + blocksdir: Option, + + #[serde(default, deserialize_with = "default_on_error")] rpcconnect: Option, - /// Bitcoin RPC port, default: 8332, saved #[serde(default, deserialize_with = "default_on_error")] - #[arg(long, value_name = "PORT")] rpcport: Option, - /// Bitcoin RPC cookie file, default: --bitcoindir/.cookie, saved #[serde(default, deserialize_with = "default_on_error")] - #[arg(long, value_name = "PATH")] rpccookiefile: Option, - /// Bitcoin RPC username, saved #[serde(default, deserialize_with = "default_on_error")] - #[arg(long, value_name = "USERNAME")] rpcuser: Option, - /// Bitcoin RPC password, saved #[serde(default, deserialize_with = "default_on_error")] - #[arg(long, value_name = "PASSWORD")] rpcpassword: Option, - /// DEV: Activate checking address hashes for collisions when indexing, default: false, saved #[serde(default, deserialize_with = "default_on_error")] - #[arg(skip)] check_collisions: Option, } impl Config { pub fn import() -> Result { - let config_args = Some(Config::parse()); + let config_args = Self::parse_args(); let path = dot_brk_path(); @@ -85,64 +60,44 @@ impl Config { let path = path.join("config.toml"); - let mut config_saved = Self::read(&path); + let mut config = Self::read(&path); - if let Some(mut config_args) = config_args { - if let Some(bitcoindir) = config_args.bitcoindir.take() { - config_saved.bitcoindir = Some(bitcoindir); - } - - if let Some(blocksdir) = config_args.blocksdir.take() { - config_saved.blocksdir = Some(blocksdir); - } - - if let Some(brkdir) = config_args.brkdir.take() { - config_saved.brkdir = Some(brkdir); - } - - if let Some(fetch) = config_args.fetch.take() { - config_saved.fetch = Some(fetch); - } - - if let Some(exchanges) = config_args.exchanges.take() { - config_saved.exchanges = Some(exchanges); - } - - if let Some(website) = config_args.website.take() { - config_saved.website = Some(website); - } - - if let Some(rpcconnect) = config_args.rpcconnect.take() { - config_saved.rpcconnect = Some(rpcconnect); - } - - if let Some(rpcport) = config_args.rpcport.take() { - config_saved.rpcport = Some(rpcport); - } - - if let Some(rpccookiefile) = config_args.rpccookiefile.take() { - config_saved.rpccookiefile = Some(rpccookiefile); - } - - if let Some(rpcuser) = config_args.rpcuser.take() { - config_saved.rpcuser = Some(rpcuser); - } - - if let Some(rpcpassword) = config_args.rpcpassword.take() { - config_saved.rpcpassword = Some(rpcpassword); - } - - if let Some(check_collisions) = config_args.check_collisions.take() { - config_saved.check_collisions = Some(check_collisions); - } - - if config_args != Config::default() { - dbg!(config_args); - panic!("Didn't consume the full config") - } + if let Some(v) = config_args.brkdir { + config.brkdir = Some(v); + } + if let Some(v) = config_args.brkport { + config.brkport = Some(v); + } + if let Some(v) = config_args.website { + config.website = Some(v); + } + if let Some(v) = config_args.fetch { + config.fetch = Some(v); + } + if let Some(v) = config_args.bitcoindir { + config.bitcoindir = Some(v); + } + if let Some(v) = config_args.blocksdir { + config.blocksdir = Some(v); + } + if let Some(v) = config_args.rpcconnect { + config.rpcconnect = Some(v); + } + if let Some(v) = config_args.rpcport { + config.rpcport = Some(v); + } + if let Some(v) = config_args.rpccookiefile { + config.rpccookiefile = Some(v); + } + if let Some(v) = config_args.rpcuser { + config.rpcuser = Some(v); + } + if let Some(v) = config_args.rpcpassword { + config.rpcpassword = Some(v); + } + if let Some(v) = config_args.check_collisions { + config.check_collisions = Some(v); } - - let config = config_saved; config.check(); @@ -151,6 +106,73 @@ impl Config { Ok(config) } + fn parse_args() -> Self { + use lexopt::prelude::*; + + let mut config = Self::default(); + let mut parser = lexopt::Parser::from_env(); + + while let Some(arg) = parser.next().unwrap() { + match arg { + Short('h') | Long("help") => { + Self::print_help(); + std::process::exit(0); + } + Short('V') | Long("version") => { + println!("brk {}", env!("CARGO_PKG_VERSION")); + std::process::exit(0); + } + Long("brkdir") => config.brkdir = Some(parser.value().unwrap().parse().unwrap()), + Long("brkport") => config.brkport = Some(parser.value().unwrap().parse().unwrap()), + Long("website") => config.website = Some(parser.value().unwrap().parse().unwrap()), + Long("fetch") => config.fetch = Some(parser.value().unwrap().parse().unwrap()), + Long("bitcoindir") => config.bitcoindir = Some(parser.value().unwrap().parse().unwrap()), + Long("blocksdir") => config.blocksdir = Some(parser.value().unwrap().parse().unwrap()), + Long("rpcconnect") => config.rpcconnect = Some(parser.value().unwrap().parse().unwrap()), + Long("rpcport") => config.rpcport = Some(parser.value().unwrap().parse().unwrap()), + Long("rpccookiefile") => config.rpccookiefile = Some(parser.value().unwrap().parse().unwrap()), + Long("rpcuser") => config.rpcuser = Some(parser.value().unwrap().parse().unwrap()), + Long("rpcpassword") => config.rpcpassword = Some(parser.value().unwrap().parse().unwrap()), + Long("check-collisions") => config.check_collisions = Some(parser.value().unwrap().parse().unwrap()), + _ => { + eprintln!("{}", arg.unexpected()); + std::process::exit(1); + } + } + } + + config + } + + fn print_help() { + println!( + "brk {} +Bitcoin Research Kit + +USAGE: + brk [OPTIONS] + +OPTIONS: + -h, --help Print help + -V, --version Print version + + --brkdir Output directory [~/.brk] + --brkport Server port [3110] + --website Website: true, false, or path [true] + --fetch Fetch prices [true] + + --bitcoindir Bitcoin directory [~/.bitcoin, ~/Library/Application Support/Bitcoin] + --blocksdir Blocks directory [/blocks] + + --rpcconnect RPC host [localhost] + --rpcport RPC port [8332] + --rpccookiefile RPC cookie file [/.cookie] + --rpcuser RPC username + --rpcpassword RPC password", + env!("CARGO_PKG_VERSION") + ); + } + fn check(&self) { if !self.bitcoindir().is_dir() { println!("{:?} isn't a valid directory", self.bitcoindir()); @@ -262,17 +284,17 @@ Finally, you can run the program with '-h' for help." self.website.clone().unwrap_or_default() } + pub fn brkport(&self) -> Option { + self.brkport + } + pub fn fetch(&self) -> bool { self.fetch.is_none_or(|b| b) } - pub fn exchanges(&self) -> bool { - self.exchanges.is_none_or(|b| b) - } - pub fn fetcher(&self) -> Option { self.fetch() - .then(|| Fetcher::import(self.exchanges(), Some(self.harsdir().as_path())).unwrap()) + .then(|| Fetcher::import(Some(self.harsdir().as_path())).unwrap()) } pub fn check_collisions(&self) -> bool { diff --git a/crates/brk_cli/src/main.rs b/crates/brk_cli/src/main.rs index a136b853e..5d87f754b 100644 --- a/crates/brk_cli/src/main.rs +++ b/crates/brk_cli/src/main.rs @@ -24,7 +24,7 @@ mod website; use crate::{config::Config, paths::*, website::WebsiteArg}; -pub fn main() -> color_eyre::Result<()> { +pub fn main() -> anyhow::Result<()> { // Can't increase main thread's stack size, thus we need to use another thread thread::Builder::new() .stack_size(512 * 1024 * 1024) @@ -33,9 +33,7 @@ pub fn main() -> color_eyre::Result<()> { .unwrap() } -pub fn run() -> color_eyre::Result<()> { - color_eyre::install()?; - +pub fn run() -> anyhow::Result<()> { fs::create_dir_all(dot_brk_path())?; brk_logger::init(Some(&dot_brk_log_path()))?; @@ -72,11 +70,13 @@ pub fn run() -> color_eyre::Result<()> { WebsiteArg::Path(p) => Website::Filesystem(p), }; + let port = config.brkport(); + let future = async move { let server = Server::new(&query, data_path, website); tokio::spawn(async move { - server.serve().await.unwrap(); + server.serve(port).await.unwrap(); }); Ok(()) as Result<()> diff --git a/crates/brk_client/src/lib.rs b/crates/brk_client/src/lib.rs index a00573e1d..3e433a486 100644 --- a/crates/brk_client/src/lib.rs +++ b/crates/brk_client/src/lib.rs @@ -1600,40 +1600,6 @@ impl BitcoinPattern { } } -/// Pattern struct for repeated tree structure. -pub struct ClassAveragePricePattern { - pub _2015: MetricPattern4, - pub _2016: MetricPattern4, - pub _2017: MetricPattern4, - pub _2018: MetricPattern4, - pub _2019: MetricPattern4, - pub _2020: MetricPattern4, - pub _2021: MetricPattern4, - pub _2022: MetricPattern4, - pub _2023: MetricPattern4, - pub _2024: MetricPattern4, - pub _2025: MetricPattern4, -} - -impl ClassAveragePricePattern { - /// Create a new pattern node with accumulated metric name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - _2015: MetricPattern4::new(client.clone(), _m(&acc, "2015_returns")), - _2016: MetricPattern4::new(client.clone(), _m(&acc, "2016_returns")), - _2017: MetricPattern4::new(client.clone(), _m(&acc, "2017_returns")), - _2018: MetricPattern4::new(client.clone(), _m(&acc, "2018_returns")), - _2019: MetricPattern4::new(client.clone(), _m(&acc, "2019_returns")), - _2020: MetricPattern4::new(client.clone(), _m(&acc, "2020_returns")), - _2021: MetricPattern4::new(client.clone(), _m(&acc, "2021_returns")), - _2022: MetricPattern4::new(client.clone(), _m(&acc, "2022_returns")), - _2023: MetricPattern4::new(client.clone(), _m(&acc, "2023_returns")), - _2024: MetricPattern4::new(client.clone(), _m(&acc, "2024_returns")), - _2025: MetricPattern4::new(client.clone(), _m(&acc, "2025_returns")), - } - } -} - /// Pattern struct for repeated tree structure. pub struct DollarsPattern { pub average: MetricPattern2, @@ -1669,33 +1635,35 @@ impl DollarsPattern { } /// Pattern struct for repeated tree structure. -pub struct RelativePattern2 { - pub neg_unrealized_loss_rel_to_own_market_cap: MetricPattern1, - pub neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1, - pub net_unrealized_pnl_rel_to_own_market_cap: MetricPattern1, - pub net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern1, - pub supply_in_loss_rel_to_own_supply: MetricPattern1, - pub supply_in_profit_rel_to_own_supply: MetricPattern1, - pub unrealized_loss_rel_to_own_market_cap: MetricPattern1, - pub unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1, - pub unrealized_profit_rel_to_own_market_cap: MetricPattern1, - pub unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern1, +pub struct ClassAveragePricePattern { + pub _2015: MetricPattern4, + pub _2016: MetricPattern4, + pub _2017: MetricPattern4, + pub _2018: MetricPattern4, + pub _2019: MetricPattern4, + pub _2020: MetricPattern4, + pub _2021: MetricPattern4, + pub _2022: MetricPattern4, + pub _2023: MetricPattern4, + pub _2024: MetricPattern4, + pub _2025: MetricPattern4, } -impl RelativePattern2 { +impl ClassAveragePricePattern { /// Create a new pattern node with accumulated metric name. pub fn new(client: Arc, acc: String) -> Self { Self { - neg_unrealized_loss_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "neg_unrealized_loss_rel_to_own_market_cap")), - neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "neg_unrealized_loss_rel_to_own_total_unrealized_pnl")), - net_unrealized_pnl_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "net_unrealized_pnl_rel_to_own_market_cap")), - net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "net_unrealized_pnl_rel_to_own_total_unrealized_pnl")), - supply_in_loss_rel_to_own_supply: MetricPattern1::new(client.clone(), _m(&acc, "supply_in_loss_rel_to_own_supply")), - supply_in_profit_rel_to_own_supply: MetricPattern1::new(client.clone(), _m(&acc, "supply_in_profit_rel_to_own_supply")), - unrealized_loss_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_loss_rel_to_own_market_cap")), - unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_loss_rel_to_own_total_unrealized_pnl")), - unrealized_profit_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_profit_rel_to_own_market_cap")), - unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_profit_rel_to_own_total_unrealized_pnl")), + _2015: MetricPattern4::new(client.clone(), _m(&acc, "2015_returns")), + _2016: MetricPattern4::new(client.clone(), _m(&acc, "2016_returns")), + _2017: MetricPattern4::new(client.clone(), _m(&acc, "2017_returns")), + _2018: MetricPattern4::new(client.clone(), _m(&acc, "2018_returns")), + _2019: MetricPattern4::new(client.clone(), _m(&acc, "2019_returns")), + _2020: MetricPattern4::new(client.clone(), _m(&acc, "2020_returns")), + _2021: MetricPattern4::new(client.clone(), _m(&acc, "2021_returns")), + _2022: MetricPattern4::new(client.clone(), _m(&acc, "2022_returns")), + _2023: MetricPattern4::new(client.clone(), _m(&acc, "2023_returns")), + _2024: MetricPattern4::new(client.clone(), _m(&acc, "2024_returns")), + _2025: MetricPattern4::new(client.clone(), _m(&acc, "2025_returns")), } } } @@ -1732,6 +1700,38 @@ impl RelativePattern { } } +/// Pattern struct for repeated tree structure. +pub struct RelativePattern2 { + pub neg_unrealized_loss_rel_to_own_market_cap: MetricPattern1, + pub neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1, + pub net_unrealized_pnl_rel_to_own_market_cap: MetricPattern1, + pub net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern1, + pub supply_in_loss_rel_to_own_supply: MetricPattern1, + pub supply_in_profit_rel_to_own_supply: MetricPattern1, + pub unrealized_loss_rel_to_own_market_cap: MetricPattern1, + pub unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1, + pub unrealized_profit_rel_to_own_market_cap: MetricPattern1, + pub unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern1, +} + +impl RelativePattern2 { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + neg_unrealized_loss_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "neg_unrealized_loss_rel_to_own_market_cap")), + neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "neg_unrealized_loss_rel_to_own_total_unrealized_pnl")), + net_unrealized_pnl_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "net_unrealized_pnl_rel_to_own_market_cap")), + net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "net_unrealized_pnl_rel_to_own_total_unrealized_pnl")), + supply_in_loss_rel_to_own_supply: MetricPattern1::new(client.clone(), _m(&acc, "supply_in_loss_rel_to_own_supply")), + supply_in_profit_rel_to_own_supply: MetricPattern1::new(client.clone(), _m(&acc, "supply_in_profit_rel_to_own_supply")), + unrealized_loss_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_loss_rel_to_own_market_cap")), + unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_loss_rel_to_own_total_unrealized_pnl")), + unrealized_profit_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_profit_rel_to_own_market_cap")), + unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_profit_rel_to_own_total_unrealized_pnl")), + } + } +} + /// Pattern struct for repeated tree structure. pub struct CountPattern2 { pub average: MetricPattern1, @@ -1910,32 +1910,6 @@ impl PhaseDailyCentsPattern { } } -/// Pattern struct for repeated tree structure. -pub struct _10yPattern { - pub activity: ActivityPattern2, - pub cost_basis: CostBasisPattern, - pub outputs: OutputsPattern, - pub realized: RealizedPattern4, - pub relative: RelativePattern, - pub supply: SupplyPattern2, - pub unrealized: UnrealizedPattern, -} - -impl _10yPattern { - /// Create a new pattern node with accumulated metric name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - activity: ActivityPattern2::new(client.clone(), acc.clone()), - cost_basis: CostBasisPattern::new(client.clone(), acc.clone()), - outputs: OutputsPattern::new(client.clone(), _m(&acc, "utxo_count")), - realized: RealizedPattern4::new(client.clone(), acc.clone()), - relative: RelativePattern::new(client.clone(), acc.clone()), - supply: SupplyPattern2::new(client.clone(), _m(&acc, "supply")), - unrealized: UnrealizedPattern::new(client.clone(), acc.clone()), - } - } -} - /// Pattern struct for repeated tree structure. pub struct PeriodCagrPattern { pub _10y: MetricPattern4, @@ -1962,32 +1936,6 @@ impl PeriodCagrPattern { } } -/// Pattern struct for repeated tree structure. -pub struct _10yTo12yPattern { - pub activity: ActivityPattern2, - pub cost_basis: CostBasisPattern2, - pub outputs: OutputsPattern, - pub realized: RealizedPattern2, - pub relative: RelativePattern2, - pub supply: SupplyPattern2, - pub unrealized: UnrealizedPattern, -} - -impl _10yTo12yPattern { - /// Create a new pattern node with accumulated metric name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - activity: ActivityPattern2::new(client.clone(), acc.clone()), - cost_basis: CostBasisPattern2::new(client.clone(), acc.clone()), - outputs: OutputsPattern::new(client.clone(), _m(&acc, "utxo_count")), - realized: RealizedPattern2::new(client.clone(), acc.clone()), - relative: RelativePattern2::new(client.clone(), acc.clone()), - supply: SupplyPattern2::new(client.clone(), _m(&acc, "supply")), - unrealized: UnrealizedPattern::new(client.clone(), acc.clone()), - } - } -} - /// Pattern struct for repeated tree structure. pub struct _0satsPattern2 { pub activity: ActivityPattern2, @@ -2015,27 +1963,53 @@ impl _0satsPattern2 { } /// Pattern struct for repeated tree structure. -pub struct UnrealizedPattern { - pub neg_unrealized_loss: MetricPattern1, - pub net_unrealized_pnl: MetricPattern1, - pub supply_in_loss: ActiveSupplyPattern, - pub supply_in_profit: ActiveSupplyPattern, - pub total_unrealized_pnl: MetricPattern1, - pub unrealized_loss: MetricPattern1, - pub unrealized_profit: MetricPattern1, +pub struct _10yPattern { + pub activity: ActivityPattern2, + pub cost_basis: CostBasisPattern, + pub outputs: OutputsPattern, + pub realized: RealizedPattern4, + pub relative: RelativePattern, + pub supply: SupplyPattern2, + pub unrealized: UnrealizedPattern, } -impl UnrealizedPattern { +impl _10yPattern { /// Create a new pattern node with accumulated metric name. pub fn new(client: Arc, acc: String) -> Self { Self { - neg_unrealized_loss: MetricPattern1::new(client.clone(), _m(&acc, "neg_unrealized_loss")), - net_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "net_unrealized_pnl")), - supply_in_loss: ActiveSupplyPattern::new(client.clone(), _m(&acc, "supply_in_loss")), - supply_in_profit: ActiveSupplyPattern::new(client.clone(), _m(&acc, "supply_in_profit")), - total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "total_unrealized_pnl")), - unrealized_loss: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_loss")), - unrealized_profit: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_profit")), + activity: ActivityPattern2::new(client.clone(), acc.clone()), + cost_basis: CostBasisPattern::new(client.clone(), acc.clone()), + outputs: OutputsPattern::new(client.clone(), _m(&acc, "utxo_count")), + realized: RealizedPattern4::new(client.clone(), acc.clone()), + relative: RelativePattern::new(client.clone(), acc.clone()), + supply: SupplyPattern2::new(client.clone(), _m(&acc, "supply")), + unrealized: UnrealizedPattern::new(client.clone(), acc.clone()), + } + } +} + +/// Pattern struct for repeated tree structure. +pub struct _10yTo12yPattern { + pub activity: ActivityPattern2, + pub cost_basis: CostBasisPattern2, + pub outputs: OutputsPattern, + pub realized: RealizedPattern2, + pub relative: RelativePattern2, + pub supply: SupplyPattern2, + pub unrealized: UnrealizedPattern, +} + +impl _10yTo12yPattern { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + activity: ActivityPattern2::new(client.clone(), acc.clone()), + cost_basis: CostBasisPattern2::new(client.clone(), acc.clone()), + outputs: OutputsPattern::new(client.clone(), _m(&acc, "utxo_count")), + realized: RealizedPattern2::new(client.clone(), acc.clone()), + relative: RelativePattern2::new(client.clone(), acc.clone()), + supply: SupplyPattern2::new(client.clone(), _m(&acc, "supply")), + unrealized: UnrealizedPattern::new(client.clone(), acc.clone()), } } } @@ -2066,6 +2040,32 @@ impl _100btcPattern { } } +/// Pattern struct for repeated tree structure. +pub struct UnrealizedPattern { + pub neg_unrealized_loss: MetricPattern1, + pub net_unrealized_pnl: MetricPattern1, + pub supply_in_loss: ActiveSupplyPattern, + pub supply_in_profit: ActiveSupplyPattern, + pub total_unrealized_pnl: MetricPattern1, + pub unrealized_loss: MetricPattern1, + pub unrealized_profit: MetricPattern1, +} + +impl UnrealizedPattern { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + neg_unrealized_loss: MetricPattern1::new(client.clone(), _m(&acc, "neg_unrealized_loss")), + net_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "net_unrealized_pnl")), + supply_in_loss: ActiveSupplyPattern::new(client.clone(), _m(&acc, "supply_in_loss")), + supply_in_profit: ActiveSupplyPattern::new(client.clone(), _m(&acc, "supply_in_profit")), + total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "total_unrealized_pnl")), + unrealized_loss: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_loss")), + unrealized_profit: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_profit")), + } + } +} + /// Pattern struct for repeated tree structure. pub struct ActivityPattern2 { pub coinblocks_destroyed: BlockCountPattern, @@ -2108,60 +2108,6 @@ impl SplitPattern2 { } } -/// Pattern struct for repeated tree structure. -pub struct SegwitAdoptionPattern { - pub base: MetricPattern11, - pub cumulative: MetricPattern2, - pub sum: MetricPattern2, -} - -impl SegwitAdoptionPattern { - /// Create a new pattern node with accumulated metric name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - base: MetricPattern11::new(client.clone(), acc.clone()), - cumulative: MetricPattern2::new(client.clone(), _m(&acc, "cumulative")), - sum: MetricPattern2::new(client.clone(), _m(&acc, "sum")), - } - } -} - -/// Pattern struct for repeated tree structure. -pub struct ActiveSupplyPattern { - pub bitcoin: MetricPattern1, - pub dollars: MetricPattern1, - pub sats: MetricPattern1, -} - -impl ActiveSupplyPattern { - /// Create a new pattern node with accumulated metric name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - bitcoin: MetricPattern1::new(client.clone(), _m(&acc, "btc")), - dollars: MetricPattern1::new(client.clone(), _m(&acc, "usd")), - sats: MetricPattern1::new(client.clone(), acc.clone()), - } - } -} - -/// Pattern struct for repeated tree structure. -pub struct _2015Pattern { - pub bitcoin: MetricPattern4, - pub dollars: MetricPattern4, - pub sats: MetricPattern4, -} - -impl _2015Pattern { - /// Create a new pattern node with accumulated metric name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - bitcoin: MetricPattern4::new(client.clone(), _m(&acc, "btc")), - dollars: MetricPattern4::new(client.clone(), _m(&acc, "usd")), - sats: MetricPattern4::new(client.clone(), acc.clone()), - } - } -} - /// Pattern struct for repeated tree structure. pub struct CostBasisPattern2 { pub max: MetricPattern1, @@ -2180,24 +2126,6 @@ impl CostBasisPattern2 { } } -/// Pattern struct for repeated tree structure. -pub struct CoinbasePattern2 { - pub bitcoin: BlockCountPattern, - pub dollars: BlockCountPattern, - pub sats: BlockCountPattern, -} - -impl CoinbasePattern2 { - /// Create a new pattern node with accumulated metric name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - bitcoin: BlockCountPattern::new(client.clone(), _m(&acc, "btc")), - dollars: BlockCountPattern::new(client.clone(), _m(&acc, "usd")), - sats: BlockCountPattern::new(client.clone(), acc.clone()), - } - } -} - /// Pattern struct for repeated tree structure. pub struct CoinbasePattern { pub bitcoin: BitcoinPattern, @@ -2216,6 +2144,24 @@ impl CoinbasePattern { } } +/// Pattern struct for repeated tree structure. +pub struct ActiveSupplyPattern { + pub bitcoin: MetricPattern1, + pub dollars: MetricPattern1, + pub sats: MetricPattern1, +} + +impl ActiveSupplyPattern { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + bitcoin: MetricPattern1::new(client.clone(), _m(&acc, "btc")), + dollars: MetricPattern1::new(client.clone(), _m(&acc, "usd")), + sats: MetricPattern1::new(client.clone(), acc.clone()), + } + } +} + /// Pattern struct for repeated tree structure. pub struct UnclaimedRewardsPattern { pub bitcoin: BitcoinPattern2, @@ -2234,6 +2180,60 @@ impl UnclaimedRewardsPattern { } } +/// Pattern struct for repeated tree structure. +pub struct CoinbasePattern2 { + pub bitcoin: BlockCountPattern, + pub dollars: BlockCountPattern, + pub sats: BlockCountPattern, +} + +impl CoinbasePattern2 { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + bitcoin: BlockCountPattern::new(client.clone(), _m(&acc, "btc")), + dollars: BlockCountPattern::new(client.clone(), _m(&acc, "usd")), + sats: BlockCountPattern::new(client.clone(), acc.clone()), + } + } +} + +/// Pattern struct for repeated tree structure. +pub struct _2015Pattern { + pub bitcoin: MetricPattern4, + pub dollars: MetricPattern4, + pub sats: MetricPattern4, +} + +impl _2015Pattern { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + bitcoin: MetricPattern4::new(client.clone(), _m(&acc, "btc")), + dollars: MetricPattern4::new(client.clone(), _m(&acc, "usd")), + sats: MetricPattern4::new(client.clone(), acc.clone()), + } + } +} + +/// Pattern struct for repeated tree structure. +pub struct SegwitAdoptionPattern { + pub base: MetricPattern11, + pub cumulative: MetricPattern2, + pub sum: MetricPattern2, +} + +impl SegwitAdoptionPattern { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + base: MetricPattern11::new(client.clone(), acc.clone()), + cumulative: MetricPattern2::new(client.clone(), _m(&acc, "cumulative")), + sum: MetricPattern2::new(client.clone(), _m(&acc, "sum")), + } + } +} + /// Pattern struct for repeated tree structure. pub struct _1dReturns1mSdPattern { pub sd: MetricPattern4, @@ -2250,22 +2250,6 @@ impl _1dReturns1mSdPattern { } } -/// Pattern struct for repeated tree structure. -pub struct RelativePattern4 { - pub supply_in_loss_rel_to_own_supply: MetricPattern1, - pub supply_in_profit_rel_to_own_supply: MetricPattern1, -} - -impl RelativePattern4 { - /// Create a new pattern node with accumulated metric name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - supply_in_loss_rel_to_own_supply: MetricPattern1::new(client.clone(), _m(&acc, "loss_rel_to_own_supply")), - supply_in_profit_rel_to_own_supply: MetricPattern1::new(client.clone(), _m(&acc, "profit_rel_to_own_supply")), - } - } -} - /// Pattern struct for repeated tree structure. pub struct CostBasisPattern { pub max: MetricPattern1, @@ -2282,6 +2266,22 @@ impl CostBasisPattern { } } +/// Pattern struct for repeated tree structure. +pub struct RelativePattern4 { + pub supply_in_loss_rel_to_own_supply: MetricPattern1, + pub supply_in_profit_rel_to_own_supply: MetricPattern1, +} + +impl RelativePattern4 { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + supply_in_loss_rel_to_own_supply: MetricPattern1::new(client.clone(), _m(&acc, "loss_rel_to_own_supply")), + supply_in_profit_rel_to_own_supply: MetricPattern1::new(client.clone(), _m(&acc, "profit_rel_to_own_supply")), + } + } +} + /// Pattern struct for repeated tree structure. pub struct SupplyPattern2 { pub halved: ActiveSupplyPattern, @@ -2298,22 +2298,6 @@ impl SupplyPattern2 { } } -/// Pattern struct for repeated tree structure. -pub struct BlockCountPattern { - pub cumulative: MetricPattern1, - pub sum: MetricPattern1, -} - -impl BlockCountPattern { - /// Create a new pattern node with accumulated metric name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - cumulative: MetricPattern1::new(client.clone(), _m(&acc, "cumulative")), - sum: MetricPattern1::new(client.clone(), acc.clone()), - } - } -} - /// Pattern struct for repeated tree structure. pub struct BitcoinPattern2 { pub cumulative: MetricPattern2, @@ -2340,22 +2324,24 @@ impl SatsPattern { /// Create a new pattern node with accumulated metric name. pub fn new(client: Arc, acc: String) -> Self { Self { - ohlc: MetricPattern1::new(client.clone(), _m(&acc, "ohlc")), - split: SplitPattern2::new(client.clone(), acc.clone()), + ohlc: MetricPattern1::new(client.clone(), _m(&acc, "ohlc_sats")), + split: SplitPattern2::new(client.clone(), _m(&acc, "sats")), } } } /// Pattern struct for repeated tree structure. -pub struct RealizedPriceExtraPattern { - pub ratio: MetricPattern4, +pub struct BlockCountPattern { + pub cumulative: MetricPattern1, + pub sum: MetricPattern1, } -impl RealizedPriceExtraPattern { +impl BlockCountPattern { /// Create a new pattern node with accumulated metric name. pub fn new(client: Arc, acc: String) -> Self { Self { - ratio: MetricPattern4::new(client.clone(), acc.clone()), + cumulative: MetricPattern1::new(client.clone(), _m(&acc, "cumulative")), + sum: MetricPattern1::new(client.clone(), acc.clone()), } } } @@ -2374,6 +2360,20 @@ impl OutputsPattern { } } +/// Pattern struct for repeated tree structure. +pub struct RealizedPriceExtraPattern { + pub ratio: MetricPattern4, +} + +impl RealizedPriceExtraPattern { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + ratio: MetricPattern4::new(client.clone(), acc.clone()), + } + } +} + // Metrics tree /// Metrics tree node. @@ -4942,8 +4942,8 @@ impl MetricsTree_Positions { pub struct MetricsTree_Price { pub cents: MetricsTree_Price_Cents, pub oracle: MetricsTree_Price_Oracle, - pub sats: MetricsTree_Price_Sats, - pub usd: SatsPattern, + pub sats: SatsPattern, + pub usd: MetricsTree_Price_Usd, } impl MetricsTree_Price { @@ -4951,8 +4951,8 @@ impl MetricsTree_Price { Self { cents: MetricsTree_Price_Cents::new(client.clone(), format!("{base_path}_cents")), oracle: MetricsTree_Price_Oracle::new(client.clone(), format!("{base_path}_oracle")), - sats: MetricsTree_Price_Sats::new(client.clone(), format!("{base_path}_sats")), - usd: SatsPattern::new(client.clone(), "price".to_string()), + sats: SatsPattern::new(client.clone(), "price".to_string()), + usd: MetricsTree_Price_Usd::new(client.clone(), format!("{base_path}_usd")), } } } @@ -5055,16 +5055,16 @@ impl MetricsTree_Price_Oracle { } /// Metrics tree node. -pub struct MetricsTree_Price_Sats { - pub ohlc: MetricPattern1, - pub split: SplitPattern2, +pub struct MetricsTree_Price_Usd { + pub ohlc: MetricPattern1, + pub split: SplitPattern2, } -impl MetricsTree_Price_Sats { +impl MetricsTree_Price_Usd { pub fn new(client: Arc, base_path: String) -> Self { Self { - ohlc: MetricPattern1::new(client.clone(), "price_ohlc_sats".to_string()), - split: SplitPattern2::new(client.clone(), "price_sats".to_string()), + ohlc: MetricPattern1::new(client.clone(), "price_ohlc".to_string()), + split: SplitPattern2::new(client.clone(), "price".to_string()), } } } diff --git a/crates/brk_cohort/Cargo.toml b/crates/brk_cohort/Cargo.toml index ca5568103..5f8dfdf6f 100644 --- a/crates/brk_cohort/Cargo.toml +++ b/crates/brk_cohort/Cargo.toml @@ -8,7 +8,7 @@ homepage.workspace = true repository.workspace = true [dependencies] -brk_error = { workspace = true } +brk_error = { workspace = true, features = ["vecdb"] } brk_types = { workspace = true } brk_traversable = { workspace = true } vecdb = { workspace = true } diff --git a/crates/brk_computer/Cargo.toml b/crates/brk_computer/Cargo.toml index 83a43dbaf..b3ff312ab 100644 --- a/crates/brk_computer/Cargo.toml +++ b/crates/brk_computer/Cargo.toml @@ -9,7 +9,7 @@ repository.workspace = true [dependencies] bitcoin = { workspace = true } -brk_error = { workspace = true } +brk_error = { workspace = true, features = ["vecdb"] } brk_fetcher = { workspace = true } brk_cohort = { workspace = true } brk_indexer = { workspace = true } diff --git a/crates/brk_computer/examples/computer.rs b/crates/brk_computer/examples/computer.rs index 274bfea44..a6cb99b37 100644 --- a/crates/brk_computer/examples/computer.rs +++ b/crates/brk_computer/examples/computer.rs @@ -48,7 +48,7 @@ fn run() -> Result<()> { let mut indexer = Indexer::forced_import(&outputs_dir)?; - let fetcher = Fetcher::import(true, None)?; + let fetcher = Fetcher::import(None)?; let exit = Exit::new(); exit.set_ctrlc_handler(); diff --git a/crates/brk_computer/examples/computer_bench.rs b/crates/brk_computer/examples/computer_bench.rs index 37cb24ae6..4220084fc 100644 --- a/crates/brk_computer/examples/computer_bench.rs +++ b/crates/brk_computer/examples/computer_bench.rs @@ -42,7 +42,7 @@ fn run() -> Result<()> { let mut indexer = Indexer::forced_import(&outputs_dir)?; - let fetcher = Fetcher::import(true, None)?; + let fetcher = Fetcher::import(None)?; let mut computer = Computer::forced_import(&outputs_benches_dir, &indexer, Some(fetcher))?; diff --git a/crates/brk_computer/examples/computer_read.rs b/crates/brk_computer/examples/computer_read.rs index 5e79eb676..9918dc524 100644 --- a/crates/brk_computer/examples/computer_read.rs +++ b/crates/brk_computer/examples/computer_read.rs @@ -22,7 +22,7 @@ fn run() -> Result<()> { let indexer = Indexer::forced_import(&outputs_dir)?; - let fetcher = Fetcher::import(true, None)?; + let fetcher = Fetcher::import(None)?; let exit = Exit::new(); exit.set_ctrlc_handler(); diff --git a/crates/brk_computer/examples/full_bench.rs b/crates/brk_computer/examples/full_bench.rs index 265a193ab..03c3a715a 100644 --- a/crates/brk_computer/examples/full_bench.rs +++ b/crates/brk_computer/examples/full_bench.rs @@ -60,7 +60,7 @@ fn run() -> Result<()> { let blocks = Blocks::new(&client, &reader); - let fetcher = Fetcher::import(true, None)?; + let fetcher = Fetcher::import(None)?; info!("Ping: {:?}", fetcher.brk.ping()?); diff --git a/crates/brk_error/Cargo.toml b/crates/brk_error/Cargo.toml index efab1fe21..fd4f5d535 100644 --- a/crates/brk_error/Cargo.toml +++ b/crates/brk_error/Cargo.toml @@ -7,13 +7,23 @@ license.workspace = true homepage.workspace = true repository.workspace = true +[features] +bitcoin = ["dep:bitcoin"] +bitcoincore-rpc = ["dep:bitcoincore-rpc"] +fjall = ["dep:fjall"] +jiff = ["dep:jiff"] +minreq = ["dep:minreq"] +serde_json = ["dep:serde_json"] +tokio = ["dep:tokio"] +vecdb = ["dep:vecdb"] + [dependencies] -bitcoin = { workspace = true } -bitcoincore-rpc = { workspace = true } -fjall = { workspace = true } -jiff = { workspace = true } -minreq = { workspace = true } -serde_json = { workspace = true } +bitcoin = { workspace = true, optional = true } +bitcoincore-rpc = { workspace = true, optional = true } +fjall = { workspace = true, optional = true } +jiff = { workspace = true, optional = true } +minreq = { workspace = true, optional = true } +serde_json = { workspace = true, optional = true } thiserror = "2.0" -tokio = { workspace = true } -vecdb = { workspace = true } +tokio = { workspace = true, optional = true } +vecdb = { workspace = true, optional = true } diff --git a/crates/brk_error/src/lib.rs b/crates/brk_error/src/lib.rs index 4244fd330..a1cdad6d2 100644 --- a/crates/brk_error/src/lib.rs +++ b/crates/brk_error/src/lib.rs @@ -11,45 +11,58 @@ pub enum Error { #[error(transparent)] IO(#[from] io::Error), + #[cfg(feature = "bitcoincore-rpc")] #[error(transparent)] BitcoinRPC(#[from] bitcoincore_rpc::Error), + #[cfg(feature = "jiff")] #[error(transparent)] Jiff(#[from] jiff::Error), + #[cfg(feature = "fjall")] #[error(transparent)] Fjall(#[from] fjall::Error), + #[cfg(feature = "vecdb")] #[error(transparent)] VecDB(#[from] vecdb::Error), + #[cfg(feature = "vecdb")] #[error(transparent)] RawDB(#[from] vecdb::RawDBError), + #[cfg(feature = "minreq")] #[error(transparent)] Minreq(#[from] minreq::Error), #[error(transparent)] SystemTimeError(#[from] time::SystemTimeError), + #[cfg(feature = "bitcoin")] #[error(transparent)] BitcoinConsensusEncode(#[from] bitcoin::consensus::encode::Error), + #[cfg(feature = "bitcoin")] #[error(transparent)] BitcoinBip34Error(#[from] bitcoin::block::Bip34Error), + #[cfg(feature = "bitcoin")] #[error(transparent)] BitcoinHexError(#[from] bitcoin::consensus::encode::FromHexError), + #[cfg(feature = "bitcoin")] #[error(transparent)] BitcoinFromScriptError(#[from] bitcoin::address::FromScriptError), + #[cfg(feature = "bitcoin")] #[error(transparent)] BitcoinHexToArrayError(#[from] bitcoin::hex::HexToArrayError), + #[cfg(feature = "serde_json")] #[error(transparent)] SerdeJSON(#[from] serde_json::Error), + #[cfg(feature = "tokio")] #[error(transparent)] TokioJoin(#[from] tokio::task::JoinError), @@ -139,12 +152,14 @@ pub enum Error { impl Error { /// Returns true if this error is due to a file lock (another process has the database open). /// Lock errors are transient and should not trigger data deletion. + #[cfg(feature = "vecdb")] pub fn is_lock_error(&self) -> bool { matches!(self, Error::VecDB(e) if e.is_lock_error()) } /// Returns true if this error indicates data corruption or version incompatibility. /// These errors may require resetting/deleting the data to recover. + #[cfg(feature = "vecdb")] pub fn is_data_error(&self) -> bool { matches!(self, Error::VecDB(e) if e.is_data_error()) } @@ -154,6 +169,7 @@ impl Error { /// Returns false for transient errors worth retrying (timeouts, rate limits, server errors). pub fn is_network_permanently_blocked(&self) -> bool { match self { + #[cfg(feature = "minreq")] Error::Minreq(e) => is_minreq_error_permanent(e), Error::IO(e) => is_io_error_permanent(e), // 403 Forbidden suggests IP/geo blocking; 429 and 5xx are transient @@ -164,6 +180,7 @@ impl Error { } } +#[cfg(feature = "minreq")] fn is_minreq_error_permanent(e: &minreq::Error) -> bool { use minreq::Error::*; match e { diff --git a/crates/brk_fetcher/Cargo.toml b/crates/brk_fetcher/Cargo.toml index 51e03ca19..bf115c0a6 100644 --- a/crates/brk_fetcher/Cargo.toml +++ b/crates/brk_fetcher/Cargo.toml @@ -8,7 +8,7 @@ homepage.workspace = true repository.workspace = true [dependencies] -brk_error = { workspace = true } +brk_error = { workspace = true, features = ["minreq", "serde_json"] } brk_logger = { workspace = true } brk_types = { workspace = true } tracing = { workspace = true } diff --git a/crates/brk_fetcher/README.md b/crates/brk_fetcher/README.md index f3c0f24ad..6a808c9d7 100644 --- a/crates/brk_fetcher/README.md +++ b/crates/brk_fetcher/README.md @@ -17,7 +17,7 @@ Fetch OHLC (Open/High/Low/Close) price data from Binance, Kraken, or BRK's own A ## Core API ```rust,ignore -let mut fetcher = Fetcher::import(true, Some(&hars_path))?; +let mut fetcher = Fetcher::import(Some(&hars_path))?; // Daily price let ohlc = fetcher.get_date(Date::new(2024, 4, 20))?; diff --git a/crates/brk_fetcher/examples/fetcher.rs b/crates/brk_fetcher/examples/fetcher.rs index 1283ebf2c..a1ecbb8af 100644 --- a/crates/brk_fetcher/examples/fetcher.rs +++ b/crates/brk_fetcher/examples/fetcher.rs @@ -9,7 +9,7 @@ fn main() -> Result<()> { dbg!(brk.get_from_height(Height::new(900_000))?); dbg!(brk.get_from_date(Date::new(2025, 6, 7))?); - let mut fetcher = Fetcher::new(true, None)?; + let mut fetcher = Fetcher::new(None)?; let _ = Binance::fetch_1d().map(|b| { dbg!(b.last_key_value()); diff --git a/crates/brk_fetcher/src/lib.rs b/crates/brk_fetcher/src/lib.rs index a85e62b09..abacf1823 100644 --- a/crates/brk_fetcher/src/lib.rs +++ b/crates/brk_fetcher/src/lib.rs @@ -37,20 +37,20 @@ pub fn check_response(response: minreq::Response, url: &str) -> Result> #[derive(Clone)] pub struct Fetcher { - pub binance: Option>, - pub kraken: Option>, + pub binance: TrackedSource, + pub kraken: TrackedSource, pub brk: TrackedSource, } impl Fetcher { - pub fn import(exchanges: bool, hars_path: Option<&Path>) -> Result { - Self::new(exchanges, hars_path) + pub fn import(hars_path: Option<&Path>) -> Result { + Self::new(hars_path) } - pub fn new(exchanges: bool, hars_path: Option<&Path>) -> Result { + pub fn new(hars_path: Option<&Path>) -> Result { Ok(Self { - binance: exchanges.then(|| TrackedSource::new(Binance::init(hars_path))), - kraken: exchanges.then(|| TrackedSource::new(Kraken::default())), + binance: TrackedSource::new(Binance::init(hars_path)), + kraken: TrackedSource::new(Kraken::default()), brk: TrackedSource::new(BRK::default()), }) } @@ -60,12 +60,8 @@ impl Fetcher { where F: FnMut(&mut dyn PriceSource), { - if let Some(binance) = &mut self.binance { - f(binance); - } - if let Some(kraken) = &mut self.kraken { - f(kraken); - } + f(&mut self.binance); + f(&mut self.kraken); f(&mut self.brk); } @@ -74,14 +70,10 @@ impl Fetcher { where F: FnMut(&mut dyn PriceSource) -> Option>, { - if let Some(binance) = &mut self.binance - && let Some(Ok(ohlc)) = fetch(binance) - { + if let Some(Ok(ohlc)) = fetch(&mut self.binance) { return Some(Ok(ohlc)); } - if let Some(kraken) = &mut self.kraken - && let Some(Ok(ohlc)) = fetch(kraken) - { + if let Some(Ok(ohlc)) = fetch(&mut self.kraken) { return Some(Ok(ohlc)); } if let Some(Ok(ohlc)) = fetch(&mut self.brk) { @@ -168,30 +160,20 @@ How to fix this: /// Clear caches and reset health state for all sources pub fn clear(&mut self) { - if let Some(binance) = &mut self.binance { - binance.clear(); - binance.reset_health(); - } - if let Some(kraken) = &mut self.kraken { - kraken.clear(); - kraken.reset_health(); - } + self.binance.clear(); + self.binance.reset_health(); + self.kraken.clear(); + self.kraken.reset_health(); self.brk.clear(); self.brk.reset_health(); } /// Ping all sources and return results for each pub fn ping(&self) -> Vec<(&'static str, Result<()>)> { - let mut results = Vec::new(); - - if let Some(binance) = &self.binance { - results.push((binance.name(), binance.ping())); - } - if let Some(kraken) = &self.kraken { - results.push((kraken.name(), kraken.ping())); - } - results.push((self.brk.name(), self.brk.ping())); - - results + vec![ + (self.binance.name(), self.binance.ping()), + (self.kraken.name(), self.kraken.ping()), + (self.brk.name(), self.brk.ping()), + ] } } diff --git a/crates/brk_indexer/Cargo.toml b/crates/brk_indexer/Cargo.toml index e9d93415a..4f075d3e4 100644 --- a/crates/brk_indexer/Cargo.toml +++ b/crates/brk_indexer/Cargo.toml @@ -9,7 +9,7 @@ repository.workspace = true [dependencies] bitcoin = { workspace = true } -brk_error = { workspace = true } +brk_error = { workspace = true, features = ["fjall", "vecdb"] } brk_cohort = { workspace = true } brk_iterator = { workspace = true } brk_logger = { workspace = true } diff --git a/crates/brk_query/Cargo.toml b/crates/brk_query/Cargo.toml index 76ca8ff76..0fcaefbf2 100644 --- a/crates/brk_query/Cargo.toml +++ b/crates/brk_query/Cargo.toml @@ -13,7 +13,7 @@ tokio = ["dep:tokio"] [dependencies] bitcoin = { workspace = true } brk_computer = { workspace = true } -brk_error = { workspace = true } +brk_error = { workspace = true, features = ["jiff", "vecdb"] } brk_indexer = { workspace = true } brk_mempool = { workspace = true } brk_reader = { workspace = true } diff --git a/crates/brk_rpc/Cargo.toml b/crates/brk_rpc/Cargo.toml index b2c6df973..8aff82f66 100644 --- a/crates/brk_rpc/Cargo.toml +++ b/crates/brk_rpc/Cargo.toml @@ -10,7 +10,7 @@ repository.workspace = true [dependencies] bitcoin = { workspace = true } bitcoincore-rpc = { workspace = true } -brk_error = { workspace = true } +brk_error = { workspace = true, features = ["bitcoincore-rpc"] } brk_logger = { workspace = true } brk_types = { workspace = true } tracing = { workspace = true } diff --git a/crates/brk_server/Cargo.toml b/crates/brk_server/Cargo.toml index f89ffe144..00e498f30 100644 --- a/crates/brk_server/Cargo.toml +++ b/crates/brk_server/Cargo.toml @@ -13,7 +13,7 @@ aide = { workspace = true } axum = { workspace = true } brk_bindgen = { workspace = true } brk_computer = { workspace = true } -brk_error = { workspace = true } +brk_error = { workspace = true, features = ["jiff", "serde_json", "tokio", "vecdb"] } brk_fetcher = { workspace = true } brk_indexer = { workspace = true } brk_logger = { workspace = true } @@ -34,7 +34,7 @@ serde = { workspace = true } serde_json = { workspace = true } tokio = { workspace = true } tracing = { workspace = true } -tower-http = { version = "0.6.8", features = ["catch-panic", "compression-full", "cors", "normalize-path", "timeout", "trace"] } +tower-http = { version = "0.6.8", features = ["catch-panic", "compression-br", "compression-gzip", "compression-zstd", "cors", "normalize-path", "timeout", "trace"] } tower-layer = "0.3" [dev-dependencies] diff --git a/crates/brk_server/examples/server.rs b/crates/brk_server/examples/server.rs index 8743473d0..3f9c41a97 100644 --- a/crates/brk_server/examples/server.rs +++ b/crates/brk_server/examples/server.rs @@ -34,7 +34,7 @@ fn run() -> Result<()> { let reader = Reader::new(bitcoin_dir.join("blocks"), &client); let indexer = Indexer::forced_import(&outputs_dir)?; - let fetcher = Some(Fetcher::import(true, None)?); + let fetcher = Some(Fetcher::import(None)?); let computer = Computer::forced_import(&outputs_dir, &indexer, fetcher)?; let mempool = Mempool::new(&client); diff --git a/crates/brk_server/src/lib.rs b/crates/brk_server/src/lib.rs index a72a2f7e8..323cb6e80 100644 --- a/crates/brk_server/src/lib.rs +++ b/crates/brk_server/src/lib.rs @@ -40,6 +40,7 @@ mod files; mod state; use api::*; +pub use brk_types::Port; pub use cache::{CacheParams, CacheStrategy}; pub use error::{Error, Result}; use extended::*; @@ -65,12 +66,11 @@ impl Server { }) } - pub async fn serve(self) -> brk_error::Result<()> { + pub async fn serve(self, port: Option) -> brk_error::Result<()> { let state = self.0; let compression_layer = CompressionLayer::new() .br(true) - .deflate(true) .gzip(true) .zstd(true); @@ -138,15 +138,23 @@ impl Server { .layer(TimeoutLayer::with_status_code(StatusCode::GATEWAY_TIMEOUT, Duration::from_secs(5))) .layer(CorsLayer::permissive()); - const BASE_PORT: u16 = 3110; - const MAX_PORT: u16 = BASE_PORT + 100; - - let mut port = BASE_PORT; - let listener = loop { - match TcpListener::bind(format!("0.0.0.0:{port}")).await { - Ok(l) => break l, - Err(_) if port < MAX_PORT => port += 1, - Err(e) => return Err(e.into()), + let (listener, port) = match port { + Some(port) => { + let listener = TcpListener::bind(format!("0.0.0.0:{port}")).await?; + (listener, *port) + } + None => { + let base_port: u16 = *Port::DEFAULT; + let max_port: u16 = base_port + 100; + let mut port = base_port; + let listener = loop { + match TcpListener::bind(format!("0.0.0.0:{port}")).await { + Ok(l) => break l, + Err(_) if port < max_port => port += 1, + Err(e) => return Err(e.into()), + } + }; + (listener, port) } }; diff --git a/crates/brk_store/Cargo.toml b/crates/brk_store/Cargo.toml index a67b570e1..8293234a1 100644 --- a/crates/brk_store/Cargo.toml +++ b/crates/brk_store/Cargo.toml @@ -10,7 +10,7 @@ homepage.workspace = true repository.workspace = true [dependencies] -brk_error = { workspace = true } +brk_error = { workspace = true, features = ["fjall"] } brk_types = { workspace = true } byteview = { workspace = true } fjall = { workspace = true } diff --git a/crates/brk_types/Cargo.toml b/crates/brk_types/Cargo.toml index bc6ca071a..fb33ff170 100644 --- a/crates/brk_types/Cargo.toml +++ b/crates/brk_types/Cargo.toml @@ -9,12 +9,11 @@ repository.workspace = true [dependencies] bitcoin = { workspace = true } -brk_error = { workspace = true } +brk_error = { workspace = true, features = ["bitcoin", "jiff", "serde_json", "vecdb"] } byteview = { workspace = true } derive_more = { workspace = true } itoa = "1.0.17" jiff = { workspace = true } -num_enum = "0.7.5" rapidhash = "4.2.1" ryu = "1.0.22" schemars = { workspace = true } diff --git a/crates/brk_types/src/lib.rs b/crates/brk_types/src/lib.rs index 8786bbf28..b54dd1149 100644 --- a/crates/brk_types/src/lib.rs +++ b/crates/brk_types/src/lib.rs @@ -115,6 +115,7 @@ mod paginationindex; mod percentile; mod pool; mod pooldetail; +mod port; mod poolinfo; mod pools; mod poolslug; @@ -285,6 +286,7 @@ pub use percentile::*; pub use pool::*; pub use pooldetail::*; pub use poolinfo::*; +pub use port::*; pub use pools::*; pub use poolslug::*; pub use poolslugparam::*; diff --git a/crates/brk_types/src/poolslug.rs b/crates/brk_types/src/poolslug.rs index 54f61dff3..f8068aa19 100644 --- a/crates/brk_types/src/poolslug.rs +++ b/crates/brk_types/src/poolslug.rs @@ -1,4 +1,3 @@ -use num_enum::{FromPrimitive, IntoPrimitive}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use strum::Display; @@ -19,8 +18,6 @@ use vecdb::{Bytes, Formattable}; Serialize, Deserialize, JsonSchema, - FromPrimitive, - IntoPrimitive, )] #[serde(rename_all = "lowercase")] #[strum(serialize_all = "lowercase")] @@ -412,3 +409,18 @@ impl Bytes for PoolSlug { Ok(s) } } + +impl From for PoolSlug { + #[inline] + fn from(val: u8) -> Self { + // SAFETY: PoolSlug is repr(u8) and all 256 values are valid (includes dummy variants) + unsafe { std::mem::transmute(val) } + } +} + +impl From for u8 { + #[inline] + fn from(val: PoolSlug) -> u8 { + val as u8 + } +} diff --git a/crates/brk_types/src/port.rs b/crates/brk_types/src/port.rs new file mode 100644 index 000000000..070bfcae5 --- /dev/null +++ b/crates/brk_types/src/port.rs @@ -0,0 +1,49 @@ +use std::{fmt, str::FromStr}; + +use derive_more::Deref; +use serde::{Deserialize, Serialize}; + +/// Server port. Defaults to 3110. +#[derive(Debug, Clone, Copy, Deref, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord)] +#[serde(transparent)] +pub struct Port(u16); + +impl Port { + pub const DEFAULT: Self = Self(3110); + + pub const fn new(port: u16) -> Self { + Self(port) + } +} + +impl Default for Port { + fn default() -> Self { + Self::DEFAULT + } +} + +impl fmt::Display for Port { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +impl From for Port { + fn from(value: u16) -> Self { + Self(value) + } +} + +impl From for u16 { + fn from(value: Port) -> Self { + value.0 + } +} + +impl FromStr for Port { + type Err = std::num::ParseIntError; + + fn from_str(s: &str) -> Result { + s.parse::().map(Self) + } +} diff --git a/modules/.gitignore b/modules/.gitignore index b1337dbe4..848b0b9d1 100644 --- a/modules/.gitignore +++ b/modules/.gitignore @@ -1,7 +1,6 @@ LICENSE **/*.*.*/*.json *webcomponent* -README*.md cli* extras/ *.cjs diff --git a/modules/brk-client/index.js b/modules/brk-client/index.js index 5644f32bd..6f9187c2c 100644 --- a/modules/brk-client/index.js +++ b/modules/brk-client/index.js @@ -2005,45 +2005,6 @@ function createBitcoinPattern(client, acc) { }; } -/** - * @template T - * @typedef {Object} ClassAveragePricePattern - * @property {MetricPattern4} _2015 - * @property {MetricPattern4} _2016 - * @property {MetricPattern4} _2017 - * @property {MetricPattern4} _2018 - * @property {MetricPattern4} _2019 - * @property {MetricPattern4} _2020 - * @property {MetricPattern4} _2021 - * @property {MetricPattern4} _2022 - * @property {MetricPattern4} _2023 - * @property {MetricPattern4} _2024 - * @property {MetricPattern4} _2025 - */ - -/** - * Create a ClassAveragePricePattern pattern node - * @template T - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {ClassAveragePricePattern} - */ -function createClassAveragePricePattern(client, acc) { - return { - _2015: createMetricPattern4(client, _m(acc, '2015_returns')), - _2016: createMetricPattern4(client, _m(acc, '2016_returns')), - _2017: createMetricPattern4(client, _m(acc, '2017_returns')), - _2018: createMetricPattern4(client, _m(acc, '2018_returns')), - _2019: createMetricPattern4(client, _m(acc, '2019_returns')), - _2020: createMetricPattern4(client, _m(acc, '2020_returns')), - _2021: createMetricPattern4(client, _m(acc, '2021_returns')), - _2022: createMetricPattern4(client, _m(acc, '2022_returns')), - _2023: createMetricPattern4(client, _m(acc, '2023_returns')), - _2024: createMetricPattern4(client, _m(acc, '2024_returns')), - _2025: createMetricPattern4(client, _m(acc, '2025_returns')), - }; -} - /** * @template T * @typedef {Object} DollarsPattern @@ -2084,37 +2045,41 @@ function createDollarsPattern(client, acc) { } /** - * @typedef {Object} RelativePattern2 - * @property {MetricPattern1} negUnrealizedLossRelToOwnMarketCap - * @property {MetricPattern1} negUnrealizedLossRelToOwnTotalUnrealizedPnl - * @property {MetricPattern1} netUnrealizedPnlRelToOwnMarketCap - * @property {MetricPattern1} netUnrealizedPnlRelToOwnTotalUnrealizedPnl - * @property {MetricPattern1} supplyInLossRelToOwnSupply - * @property {MetricPattern1} supplyInProfitRelToOwnSupply - * @property {MetricPattern1} unrealizedLossRelToOwnMarketCap - * @property {MetricPattern1} unrealizedLossRelToOwnTotalUnrealizedPnl - * @property {MetricPattern1} unrealizedProfitRelToOwnMarketCap - * @property {MetricPattern1} unrealizedProfitRelToOwnTotalUnrealizedPnl + * @template T + * @typedef {Object} ClassAveragePricePattern + * @property {MetricPattern4} _2015 + * @property {MetricPattern4} _2016 + * @property {MetricPattern4} _2017 + * @property {MetricPattern4} _2018 + * @property {MetricPattern4} _2019 + * @property {MetricPattern4} _2020 + * @property {MetricPattern4} _2021 + * @property {MetricPattern4} _2022 + * @property {MetricPattern4} _2023 + * @property {MetricPattern4} _2024 + * @property {MetricPattern4} _2025 */ /** - * Create a RelativePattern2 pattern node + * Create a ClassAveragePricePattern pattern node + * @template T * @param {BrkClientBase} client * @param {string} acc - Accumulated metric name - * @returns {RelativePattern2} + * @returns {ClassAveragePricePattern} */ -function createRelativePattern2(client, acc) { +function createClassAveragePricePattern(client, acc) { return { - negUnrealizedLossRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_market_cap')), - negUnrealizedLossRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_total_unrealized_pnl')), - netUnrealizedPnlRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_market_cap')), - netUnrealizedPnlRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_total_unrealized_pnl')), - supplyInLossRelToOwnSupply: createMetricPattern1(client, _m(acc, 'supply_in_loss_rel_to_own_supply')), - supplyInProfitRelToOwnSupply: createMetricPattern1(client, _m(acc, 'supply_in_profit_rel_to_own_supply')), - unrealizedLossRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_market_cap')), - unrealizedLossRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_total_unrealized_pnl')), - unrealizedProfitRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_market_cap')), - unrealizedProfitRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_total_unrealized_pnl')), + _2015: createMetricPattern4(client, _m(acc, '2015_returns')), + _2016: createMetricPattern4(client, _m(acc, '2016_returns')), + _2017: createMetricPattern4(client, _m(acc, '2017_returns')), + _2018: createMetricPattern4(client, _m(acc, '2018_returns')), + _2019: createMetricPattern4(client, _m(acc, '2019_returns')), + _2020: createMetricPattern4(client, _m(acc, '2020_returns')), + _2021: createMetricPattern4(client, _m(acc, '2021_returns')), + _2022: createMetricPattern4(client, _m(acc, '2022_returns')), + _2023: createMetricPattern4(client, _m(acc, '2023_returns')), + _2024: createMetricPattern4(client, _m(acc, '2024_returns')), + _2025: createMetricPattern4(client, _m(acc, '2025_returns')), }; } @@ -2153,6 +2118,41 @@ function createRelativePattern(client, acc) { }; } +/** + * @typedef {Object} RelativePattern2 + * @property {MetricPattern1} negUnrealizedLossRelToOwnMarketCap + * @property {MetricPattern1} negUnrealizedLossRelToOwnTotalUnrealizedPnl + * @property {MetricPattern1} netUnrealizedPnlRelToOwnMarketCap + * @property {MetricPattern1} netUnrealizedPnlRelToOwnTotalUnrealizedPnl + * @property {MetricPattern1} supplyInLossRelToOwnSupply + * @property {MetricPattern1} supplyInProfitRelToOwnSupply + * @property {MetricPattern1} unrealizedLossRelToOwnMarketCap + * @property {MetricPattern1} unrealizedLossRelToOwnTotalUnrealizedPnl + * @property {MetricPattern1} unrealizedProfitRelToOwnMarketCap + * @property {MetricPattern1} unrealizedProfitRelToOwnTotalUnrealizedPnl + */ + +/** + * Create a RelativePattern2 pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {RelativePattern2} + */ +function createRelativePattern2(client, acc) { + return { + negUnrealizedLossRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_market_cap')), + negUnrealizedLossRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_total_unrealized_pnl')), + netUnrealizedPnlRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_market_cap')), + netUnrealizedPnlRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_total_unrealized_pnl')), + supplyInLossRelToOwnSupply: createMetricPattern1(client, _m(acc, 'supply_in_loss_rel_to_own_supply')), + supplyInProfitRelToOwnSupply: createMetricPattern1(client, _m(acc, 'supply_in_profit_rel_to_own_supply')), + unrealizedLossRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_market_cap')), + unrealizedLossRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_total_unrealized_pnl')), + unrealizedProfitRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_market_cap')), + unrealizedProfitRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_total_unrealized_pnl')), + }; +} + /** * @template T * @typedef {Object} CountPattern2 @@ -2357,35 +2357,6 @@ function createPhaseDailyCentsPattern(client, acc) { }; } -/** - * @typedef {Object} _10yPattern - * @property {ActivityPattern2} activity - * @property {CostBasisPattern} costBasis - * @property {OutputsPattern} outputs - * @property {RealizedPattern4} realized - * @property {RelativePattern} relative - * @property {SupplyPattern2} supply - * @property {UnrealizedPattern} unrealized - */ - -/** - * Create a _10yPattern pattern node - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {_10yPattern} - */ -function create_10yPattern(client, acc) { - return { - activity: createActivityPattern2(client, acc), - costBasis: createCostBasisPattern(client, acc), - outputs: createOutputsPattern(client, _m(acc, 'utxo_count')), - realized: createRealizedPattern4(client, acc), - relative: createRelativePattern(client, acc), - supply: createSupplyPattern2(client, _m(acc, 'supply')), - unrealized: createUnrealizedPattern(client, acc), - }; -} - /** * @typedef {Object} PeriodCagrPattern * @property {MetricPattern4} _10y @@ -2415,35 +2386,6 @@ function createPeriodCagrPattern(client, acc) { }; } -/** - * @typedef {Object} _10yTo12yPattern - * @property {ActivityPattern2} activity - * @property {CostBasisPattern2} costBasis - * @property {OutputsPattern} outputs - * @property {RealizedPattern2} realized - * @property {RelativePattern2} relative - * @property {SupplyPattern2} supply - * @property {UnrealizedPattern} unrealized - */ - -/** - * Create a _10yTo12yPattern pattern node - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {_10yTo12yPattern} - */ -function create_10yTo12yPattern(client, acc) { - return { - activity: createActivityPattern2(client, acc), - costBasis: createCostBasisPattern2(client, acc), - outputs: createOutputsPattern(client, _m(acc, 'utxo_count')), - realized: createRealizedPattern2(client, acc), - relative: createRelativePattern2(client, acc), - supply: createSupplyPattern2(client, _m(acc, 'supply')), - unrealized: createUnrealizedPattern(client, acc), - }; -} - /** * @typedef {Object} _0satsPattern2 * @property {ActivityPattern2} activity @@ -2474,31 +2416,60 @@ function create_0satsPattern2(client, acc) { } /** - * @typedef {Object} UnrealizedPattern - * @property {MetricPattern1} negUnrealizedLoss - * @property {MetricPattern1} netUnrealizedPnl - * @property {ActiveSupplyPattern} supplyInLoss - * @property {ActiveSupplyPattern} supplyInProfit - * @property {MetricPattern1} totalUnrealizedPnl - * @property {MetricPattern1} unrealizedLoss - * @property {MetricPattern1} unrealizedProfit + * @typedef {Object} _10yPattern + * @property {ActivityPattern2} activity + * @property {CostBasisPattern} costBasis + * @property {OutputsPattern} outputs + * @property {RealizedPattern4} realized + * @property {RelativePattern} relative + * @property {SupplyPattern2} supply + * @property {UnrealizedPattern} unrealized */ /** - * Create a UnrealizedPattern pattern node + * Create a _10yPattern pattern node * @param {BrkClientBase} client * @param {string} acc - Accumulated metric name - * @returns {UnrealizedPattern} + * @returns {_10yPattern} */ -function createUnrealizedPattern(client, acc) { +function create_10yPattern(client, acc) { return { - negUnrealizedLoss: createMetricPattern1(client, _m(acc, 'neg_unrealized_loss')), - netUnrealizedPnl: createMetricPattern1(client, _m(acc, 'net_unrealized_pnl')), - supplyInLoss: createActiveSupplyPattern(client, _m(acc, 'supply_in_loss')), - supplyInProfit: createActiveSupplyPattern(client, _m(acc, 'supply_in_profit')), - totalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'total_unrealized_pnl')), - unrealizedLoss: createMetricPattern1(client, _m(acc, 'unrealized_loss')), - unrealizedProfit: createMetricPattern1(client, _m(acc, 'unrealized_profit')), + activity: createActivityPattern2(client, acc), + costBasis: createCostBasisPattern(client, acc), + outputs: createOutputsPattern(client, _m(acc, 'utxo_count')), + realized: createRealizedPattern4(client, acc), + relative: createRelativePattern(client, acc), + supply: createSupplyPattern2(client, _m(acc, 'supply')), + unrealized: createUnrealizedPattern(client, acc), + }; +} + +/** + * @typedef {Object} _10yTo12yPattern + * @property {ActivityPattern2} activity + * @property {CostBasisPattern2} costBasis + * @property {OutputsPattern} outputs + * @property {RealizedPattern2} realized + * @property {RelativePattern2} relative + * @property {SupplyPattern2} supply + * @property {UnrealizedPattern} unrealized + */ + +/** + * Create a _10yTo12yPattern pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {_10yTo12yPattern} + */ +function create_10yTo12yPattern(client, acc) { + return { + activity: createActivityPattern2(client, acc), + costBasis: createCostBasisPattern2(client, acc), + outputs: createOutputsPattern(client, _m(acc, 'utxo_count')), + realized: createRealizedPattern2(client, acc), + relative: createRelativePattern2(client, acc), + supply: createSupplyPattern2(client, _m(acc, 'supply')), + unrealized: createUnrealizedPattern(client, acc), }; } @@ -2531,6 +2502,35 @@ function create_100btcPattern(client, acc) { }; } +/** + * @typedef {Object} UnrealizedPattern + * @property {MetricPattern1} negUnrealizedLoss + * @property {MetricPattern1} netUnrealizedPnl + * @property {ActiveSupplyPattern} supplyInLoss + * @property {ActiveSupplyPattern} supplyInProfit + * @property {MetricPattern1} totalUnrealizedPnl + * @property {MetricPattern1} unrealizedLoss + * @property {MetricPattern1} unrealizedProfit + */ + +/** + * Create a UnrealizedPattern pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {UnrealizedPattern} + */ +function createUnrealizedPattern(client, acc) { + return { + negUnrealizedLoss: createMetricPattern1(client, _m(acc, 'neg_unrealized_loss')), + netUnrealizedPnl: createMetricPattern1(client, _m(acc, 'net_unrealized_pnl')), + supplyInLoss: createActiveSupplyPattern(client, _m(acc, 'supply_in_loss')), + supplyInProfit: createActiveSupplyPattern(client, _m(acc, 'supply_in_profit')), + totalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'total_unrealized_pnl')), + unrealizedLoss: createMetricPattern1(client, _m(acc, 'unrealized_loss')), + unrealizedProfit: createMetricPattern1(client, _m(acc, 'unrealized_profit')), + }; +} + /** * @typedef {Object} ActivityPattern2 * @property {BlockCountPattern} coinblocksDestroyed @@ -2581,69 +2581,6 @@ function createSplitPattern2(client, acc) { }; } -/** - * @typedef {Object} SegwitAdoptionPattern - * @property {MetricPattern11} base - * @property {MetricPattern2} cumulative - * @property {MetricPattern2} sum - */ - -/** - * Create a SegwitAdoptionPattern pattern node - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {SegwitAdoptionPattern} - */ -function createSegwitAdoptionPattern(client, acc) { - return { - base: createMetricPattern11(client, acc), - cumulative: createMetricPattern2(client, _m(acc, 'cumulative')), - sum: createMetricPattern2(client, _m(acc, 'sum')), - }; -} - -/** - * @typedef {Object} ActiveSupplyPattern - * @property {MetricPattern1} bitcoin - * @property {MetricPattern1} dollars - * @property {MetricPattern1} sats - */ - -/** - * Create a ActiveSupplyPattern pattern node - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {ActiveSupplyPattern} - */ -function createActiveSupplyPattern(client, acc) { - return { - bitcoin: createMetricPattern1(client, _m(acc, 'btc')), - dollars: createMetricPattern1(client, _m(acc, 'usd')), - sats: createMetricPattern1(client, acc), - }; -} - -/** - * @typedef {Object} _2015Pattern - * @property {MetricPattern4} bitcoin - * @property {MetricPattern4} dollars - * @property {MetricPattern4} sats - */ - -/** - * Create a _2015Pattern pattern node - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {_2015Pattern} - */ -function create_2015Pattern(client, acc) { - return { - bitcoin: createMetricPattern4(client, _m(acc, 'btc')), - dollars: createMetricPattern4(client, _m(acc, 'usd')), - sats: createMetricPattern4(client, acc), - }; -} - /** * @typedef {Object} CostBasisPattern2 * @property {MetricPattern1} max @@ -2665,27 +2602,6 @@ function createCostBasisPattern2(client, acc) { }; } -/** - * @typedef {Object} CoinbasePattern2 - * @property {BlockCountPattern} bitcoin - * @property {BlockCountPattern} dollars - * @property {BlockCountPattern} sats - */ - -/** - * Create a CoinbasePattern2 pattern node - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {CoinbasePattern2} - */ -function createCoinbasePattern2(client, acc) { - return { - bitcoin: createBlockCountPattern(client, _m(acc, 'btc')), - dollars: createBlockCountPattern(client, _m(acc, 'usd')), - sats: createBlockCountPattern(client, acc), - }; -} - /** * @typedef {Object} CoinbasePattern * @property {BitcoinPattern} bitcoin @@ -2707,6 +2623,27 @@ function createCoinbasePattern(client, acc) { }; } +/** + * @typedef {Object} ActiveSupplyPattern + * @property {MetricPattern1} bitcoin + * @property {MetricPattern1} dollars + * @property {MetricPattern1} sats + */ + +/** + * Create a ActiveSupplyPattern pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {ActiveSupplyPattern} + */ +function createActiveSupplyPattern(client, acc) { + return { + bitcoin: createMetricPattern1(client, _m(acc, 'btc')), + dollars: createMetricPattern1(client, _m(acc, 'usd')), + sats: createMetricPattern1(client, acc), + }; +} + /** * @typedef {Object} UnclaimedRewardsPattern * @property {BitcoinPattern2} bitcoin @@ -2728,6 +2665,69 @@ function createUnclaimedRewardsPattern(client, acc) { }; } +/** + * @typedef {Object} CoinbasePattern2 + * @property {BlockCountPattern} bitcoin + * @property {BlockCountPattern} dollars + * @property {BlockCountPattern} sats + */ + +/** + * Create a CoinbasePattern2 pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {CoinbasePattern2} + */ +function createCoinbasePattern2(client, acc) { + return { + bitcoin: createBlockCountPattern(client, _m(acc, 'btc')), + dollars: createBlockCountPattern(client, _m(acc, 'usd')), + sats: createBlockCountPattern(client, acc), + }; +} + +/** + * @typedef {Object} _2015Pattern + * @property {MetricPattern4} bitcoin + * @property {MetricPattern4} dollars + * @property {MetricPattern4} sats + */ + +/** + * Create a _2015Pattern pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {_2015Pattern} + */ +function create_2015Pattern(client, acc) { + return { + bitcoin: createMetricPattern4(client, _m(acc, 'btc')), + dollars: createMetricPattern4(client, _m(acc, 'usd')), + sats: createMetricPattern4(client, acc), + }; +} + +/** + * @typedef {Object} SegwitAdoptionPattern + * @property {MetricPattern11} base + * @property {MetricPattern2} cumulative + * @property {MetricPattern2} sum + */ + +/** + * Create a SegwitAdoptionPattern pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {SegwitAdoptionPattern} + */ +function createSegwitAdoptionPattern(client, acc) { + return { + base: createMetricPattern11(client, acc), + cumulative: createMetricPattern2(client, _m(acc, 'cumulative')), + sum: createMetricPattern2(client, _m(acc, 'sum')), + }; +} + /** * @typedef {Object} _1dReturns1mSdPattern * @property {MetricPattern4} sd @@ -2747,25 +2747,6 @@ function create_1dReturns1mSdPattern(client, acc) { }; } -/** - * @typedef {Object} RelativePattern4 - * @property {MetricPattern1} supplyInLossRelToOwnSupply - * @property {MetricPattern1} supplyInProfitRelToOwnSupply - */ - -/** - * Create a RelativePattern4 pattern node - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {RelativePattern4} - */ -function createRelativePattern4(client, acc) { - return { - supplyInLossRelToOwnSupply: createMetricPattern1(client, _m(acc, 'loss_rel_to_own_supply')), - supplyInProfitRelToOwnSupply: createMetricPattern1(client, _m(acc, 'profit_rel_to_own_supply')), - }; -} - /** * @typedef {Object} CostBasisPattern * @property {MetricPattern1} max @@ -2785,6 +2766,25 @@ function createCostBasisPattern(client, acc) { }; } +/** + * @typedef {Object} RelativePattern4 + * @property {MetricPattern1} supplyInLossRelToOwnSupply + * @property {MetricPattern1} supplyInProfitRelToOwnSupply + */ + +/** + * Create a RelativePattern4 pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {RelativePattern4} + */ +function createRelativePattern4(client, acc) { + return { + supplyInLossRelToOwnSupply: createMetricPattern1(client, _m(acc, 'loss_rel_to_own_supply')), + supplyInProfitRelToOwnSupply: createMetricPattern1(client, _m(acc, 'profit_rel_to_own_supply')), + }; +} + /** * @typedef {Object} SupplyPattern2 * @property {ActiveSupplyPattern} halved @@ -2804,27 +2804,6 @@ function createSupplyPattern2(client, acc) { }; } -/** - * @template T - * @typedef {Object} BlockCountPattern - * @property {MetricPattern1} cumulative - * @property {MetricPattern1} sum - */ - -/** - * Create a BlockCountPattern pattern node - * @template T - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {BlockCountPattern} - */ -function createBlockCountPattern(client, acc) { - return { - cumulative: createMetricPattern1(client, _m(acc, 'cumulative')), - sum: createMetricPattern1(client, acc), - }; -} - /** * @template T * @typedef {Object} BitcoinPattern2 @@ -2862,25 +2841,29 @@ function createBitcoinPattern2(client, acc) { */ function createSatsPattern(client, acc) { return { - ohlc: createMetricPattern1(client, _m(acc, 'ohlc')), - split: createSplitPattern2(client, acc), + ohlc: createMetricPattern1(client, _m(acc, 'ohlc_sats')), + split: createSplitPattern2(client, _m(acc, 'sats')), }; } /** - * @typedef {Object} RealizedPriceExtraPattern - * @property {MetricPattern4} ratio + * @template T + * @typedef {Object} BlockCountPattern + * @property {MetricPattern1} cumulative + * @property {MetricPattern1} sum */ /** - * Create a RealizedPriceExtraPattern pattern node + * Create a BlockCountPattern pattern node + * @template T * @param {BrkClientBase} client * @param {string} acc - Accumulated metric name - * @returns {RealizedPriceExtraPattern} + * @returns {BlockCountPattern} */ -function createRealizedPriceExtraPattern(client, acc) { +function createBlockCountPattern(client, acc) { return { - ratio: createMetricPattern4(client, acc), + cumulative: createMetricPattern1(client, _m(acc, 'cumulative')), + sum: createMetricPattern1(client, acc), }; } @@ -2901,6 +2884,23 @@ function createOutputsPattern(client, acc) { }; } +/** + * @typedef {Object} RealizedPriceExtraPattern + * @property {MetricPattern4} ratio + */ + +/** + * Create a RealizedPriceExtraPattern pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {RealizedPriceExtraPattern} + */ +function createRealizedPriceExtraPattern(client, acc) { + return { + ratio: createMetricPattern4(client, acc), + }; +} + // Catalog tree typedefs /** @@ -4056,8 +4056,8 @@ function createOutputsPattern(client, acc) { * @typedef {Object} MetricsTree_Price * @property {MetricsTree_Price_Cents} cents * @property {MetricsTree_Price_Oracle} oracle - * @property {MetricsTree_Price_Sats} sats - * @property {SatsPattern} usd + * @property {SatsPattern} sats + * @property {MetricsTree_Price_Usd} usd */ /** @@ -4105,9 +4105,9 @@ function createOutputsPattern(client, acc) { */ /** - * @typedef {Object} MetricsTree_Price_Sats - * @property {MetricPattern1} ohlc - * @property {SplitPattern2} split + * @typedef {Object} MetricsTree_Price_Usd + * @property {MetricPattern1} ohlc + * @property {SplitPattern2} split */ /** @@ -6087,11 +6087,11 @@ class BrkClient extends BrkClientBase { priceCents: createMetricPattern11(this, 'oracle_price_cents'), txCount: createMetricPattern6(this, 'oracle_tx_count'), }, - sats: { - ohlc: createMetricPattern1(this, 'price_ohlc_sats'), - split: createSplitPattern2(this, 'price_sats'), + sats: createSatsPattern(this, 'price'), + usd: { + ohlc: createMetricPattern1(this, 'price_ohlc'), + split: createSplitPattern2(this, 'price'), }, - usd: createSatsPattern(this, 'price'), }, scripts: { count: { diff --git a/packages/brk_client/README.md b/packages/brk_client/README.md index bb2895c46..2a9432218 100644 --- a/packages/brk_client/README.md +++ b/packages/brk_client/README.md @@ -18,6 +18,7 @@ uv add brk-client from brk_client import BrkClient # Use the free public API or your own instance +# Has optional `, timeout=60.0` argument client = BrkClient("https://bitview.space") # Blockchain data (mempool.space compatible) @@ -34,18 +35,3 @@ prices = client.metrics.price.usd.split.close \ # Generic metric fetching data = client.get_metric("price_close", "dateindex", -30) ``` - -## API - -```python -# Range methods -.head(n) # First n items -.tail(n) # Last n items -.fetch() # Execute the request -``` - -## Configuration - -```python -client = BrkClient("https://bitview.space", timeout=60.0) -``` diff --git a/packages/brk_client/brk_client/__init__.py b/packages/brk_client/brk_client/__init__.py index 9a5b5014a..0639d0b73 100644 --- a/packages/brk_client/brk_client/__init__.py +++ b/packages/brk_client/brk_client/__init__.py @@ -2049,23 +2049,6 @@ class BitcoinPattern: self.pct90: MetricPattern6[Bitcoin] = MetricPattern6(client, _m(acc, 'pct90')) self.sum: MetricPattern2[Bitcoin] = MetricPattern2(client, _m(acc, 'sum')) -class ClassAveragePricePattern(Generic[T]): - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated metric name.""" - self._2015: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2015_returns')) - self._2016: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2016_returns')) - self._2017: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2017_returns')) - self._2018: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2018_returns')) - self._2019: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2019_returns')) - self._2020: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2020_returns')) - self._2021: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2021_returns')) - self._2022: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2022_returns')) - self._2023: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2023_returns')) - self._2024: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2024_returns')) - self._2025: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2025_returns')) - class DollarsPattern(Generic[T]): """Pattern struct for repeated tree structure.""" @@ -2083,21 +2066,22 @@ class DollarsPattern(Generic[T]): self.pct90: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct90')) self.sum: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'sum')) -class RelativePattern2: +class ClassAveragePricePattern(Generic[T]): """Pattern struct for repeated tree structure.""" def __init__(self, client: BrkClientBase, acc: str): """Create pattern node with accumulated metric name.""" - self.neg_unrealized_loss_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_market_cap')) - self.neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_total_unrealized_pnl')) - self.net_unrealized_pnl_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_market_cap')) - self.net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_total_unrealized_pnl')) - self.supply_in_loss_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'supply_in_loss_rel_to_own_supply')) - self.supply_in_profit_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'supply_in_profit_rel_to_own_supply')) - self.unrealized_loss_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_market_cap')) - self.unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_total_unrealized_pnl')) - self.unrealized_profit_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_market_cap')) - self.unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_total_unrealized_pnl')) + self._2015: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2015_returns')) + self._2016: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2016_returns')) + self._2017: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2017_returns')) + self._2018: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2018_returns')) + self._2019: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2019_returns')) + self._2020: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2020_returns')) + self._2021: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2021_returns')) + self._2022: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2022_returns')) + self._2023: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2023_returns')) + self._2024: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2024_returns')) + self._2025: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2025_returns')) class RelativePattern: """Pattern struct for repeated tree structure.""" @@ -2115,6 +2099,22 @@ class RelativePattern: self.unrealized_loss_rel_to_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_market_cap')) self.unrealized_profit_rel_to_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_market_cap')) +class RelativePattern2: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self.neg_unrealized_loss_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_market_cap')) + self.neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_total_unrealized_pnl')) + self.net_unrealized_pnl_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_market_cap')) + self.net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_total_unrealized_pnl')) + self.supply_in_loss_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'supply_in_loss_rel_to_own_supply')) + self.supply_in_profit_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'supply_in_profit_rel_to_own_supply')) + self.unrealized_loss_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_market_cap')) + self.unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_total_unrealized_pnl')) + self.unrealized_profit_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_market_cap')) + self.unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_total_unrealized_pnl')) + class CountPattern2(Generic[T]): """Pattern struct for repeated tree structure.""" @@ -2204,19 +2204,6 @@ class PhaseDailyCentsPattern(Generic[T]): self.pct75: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct75')) self.pct90: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct90')) -class _10yPattern: - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated metric name.""" - self.activity: ActivityPattern2 = ActivityPattern2(client, acc) - self.cost_basis: CostBasisPattern = CostBasisPattern(client, acc) - self.outputs: OutputsPattern = OutputsPattern(client, _m(acc, 'utxo_count')) - self.realized: RealizedPattern4 = RealizedPattern4(client, acc) - self.relative: RelativePattern = RelativePattern(client, acc) - self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply')) - self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc) - class PeriodCagrPattern: """Pattern struct for repeated tree structure.""" @@ -2230,6 +2217,32 @@ class PeriodCagrPattern: self._6y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('6y', acc)) self._8y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('8y', acc)) +class _0satsPattern2: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self.activity: ActivityPattern2 = ActivityPattern2(client, acc) + self.cost_basis: CostBasisPattern = CostBasisPattern(client, acc) + self.outputs: OutputsPattern = OutputsPattern(client, _m(acc, 'utxo_count')) + self.realized: RealizedPattern = RealizedPattern(client, acc) + self.relative: RelativePattern4 = RelativePattern4(client, _m(acc, 'supply_in')) + self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply')) + self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc) + +class _10yPattern: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self.activity: ActivityPattern2 = ActivityPattern2(client, acc) + self.cost_basis: CostBasisPattern = CostBasisPattern(client, acc) + self.outputs: OutputsPattern = OutputsPattern(client, _m(acc, 'utxo_count')) + self.realized: RealizedPattern4 = RealizedPattern4(client, acc) + self.relative: RelativePattern = RelativePattern(client, acc) + self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply')) + self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc) + class _10yTo12yPattern: """Pattern struct for repeated tree structure.""" @@ -2243,7 +2256,7 @@ class _10yTo12yPattern: self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply')) self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc) -class _0satsPattern2: +class _100btcPattern: """Pattern struct for repeated tree structure.""" def __init__(self, client: BrkClientBase, acc: str): @@ -2252,7 +2265,7 @@ class _0satsPattern2: self.cost_basis: CostBasisPattern = CostBasisPattern(client, acc) self.outputs: OutputsPattern = OutputsPattern(client, _m(acc, 'utxo_count')) self.realized: RealizedPattern = RealizedPattern(client, acc) - self.relative: RelativePattern4 = RelativePattern4(client, _m(acc, 'supply_in')) + self.relative: RelativePattern = RelativePattern(client, acc) self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply')) self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc) @@ -2269,19 +2282,6 @@ class UnrealizedPattern: self.unrealized_loss: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'unrealized_loss')) self.unrealized_profit: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'unrealized_profit')) -class _100btcPattern: - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated metric name.""" - self.activity: ActivityPattern2 = ActivityPattern2(client, acc) - self.cost_basis: CostBasisPattern = CostBasisPattern(client, acc) - self.outputs: OutputsPattern = OutputsPattern(client, _m(acc, 'utxo_count')) - self.realized: RealizedPattern = RealizedPattern(client, acc) - self.relative: RelativePattern = RelativePattern(client, acc) - self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply')) - self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc) - class ActivityPattern2: """Pattern struct for repeated tree structure.""" @@ -2303,33 +2303,6 @@ class SplitPattern2(Generic[T]): self.low: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'low')) self.open: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'open')) -class SegwitAdoptionPattern: - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated metric name.""" - self.base: MetricPattern11[StoredF32] = MetricPattern11(client, acc) - self.cumulative: MetricPattern2[StoredF32] = MetricPattern2(client, _m(acc, 'cumulative')) - self.sum: MetricPattern2[StoredF32] = MetricPattern2(client, _m(acc, 'sum')) - -class ActiveSupplyPattern: - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated metric name.""" - self.bitcoin: MetricPattern1[Bitcoin] = MetricPattern1(client, _m(acc, 'btc')) - self.dollars: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'usd')) - self.sats: MetricPattern1[Sats] = MetricPattern1(client, acc) - -class _2015Pattern: - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated metric name.""" - self.bitcoin: MetricPattern4[Bitcoin] = MetricPattern4(client, _m(acc, 'btc')) - self.dollars: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'usd')) - self.sats: MetricPattern4[Sats] = MetricPattern4(client, acc) - class CostBasisPattern2: """Pattern struct for repeated tree structure.""" @@ -2339,15 +2312,6 @@ class CostBasisPattern2: self.min: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'min_cost_basis')) self.percentiles: PercentilesPattern = PercentilesPattern(client, _m(acc, 'cost_basis')) -class CoinbasePattern2: - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated metric name.""" - self.bitcoin: BlockCountPattern[Bitcoin] = BlockCountPattern(client, _m(acc, 'btc')) - self.dollars: BlockCountPattern[Dollars] = BlockCountPattern(client, _m(acc, 'usd')) - self.sats: BlockCountPattern[Sats] = BlockCountPattern(client, acc) - class CoinbasePattern: """Pattern struct for repeated tree structure.""" @@ -2357,6 +2321,15 @@ class CoinbasePattern: self.dollars: DollarsPattern[Dollars] = DollarsPattern(client, _m(acc, 'usd')) self.sats: DollarsPattern[Sats] = DollarsPattern(client, acc) +class ActiveSupplyPattern: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self.bitcoin: MetricPattern1[Bitcoin] = MetricPattern1(client, _m(acc, 'btc')) + self.dollars: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'usd')) + self.sats: MetricPattern1[Sats] = MetricPattern1(client, acc) + class UnclaimedRewardsPattern: """Pattern struct for repeated tree structure.""" @@ -2366,6 +2339,33 @@ class UnclaimedRewardsPattern: self.dollars: BlockCountPattern[Dollars] = BlockCountPattern(client, _m(acc, 'usd')) self.sats: BlockCountPattern[Sats] = BlockCountPattern(client, acc) +class CoinbasePattern2: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self.bitcoin: BlockCountPattern[Bitcoin] = BlockCountPattern(client, _m(acc, 'btc')) + self.dollars: BlockCountPattern[Dollars] = BlockCountPattern(client, _m(acc, 'usd')) + self.sats: BlockCountPattern[Sats] = BlockCountPattern(client, acc) + +class _2015Pattern: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self.bitcoin: MetricPattern4[Bitcoin] = MetricPattern4(client, _m(acc, 'btc')) + self.dollars: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'usd')) + self.sats: MetricPattern4[Sats] = MetricPattern4(client, acc) + +class SegwitAdoptionPattern: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self.base: MetricPattern11[StoredF32] = MetricPattern11(client, acc) + self.cumulative: MetricPattern2[StoredF32] = MetricPattern2(client, _m(acc, 'cumulative')) + self.sum: MetricPattern2[StoredF32] = MetricPattern2(client, _m(acc, 'sum')) + class _1dReturns1mSdPattern: """Pattern struct for repeated tree structure.""" @@ -2374,14 +2374,6 @@ class _1dReturns1mSdPattern: self.sd: MetricPattern4[StoredF32] = MetricPattern4(client, _m(acc, 'sd')) self.sma: MetricPattern4[StoredF32] = MetricPattern4(client, _m(acc, 'sma')) -class RelativePattern4: - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated metric name.""" - self.supply_in_loss_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'loss_rel_to_own_supply')) - self.supply_in_profit_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'profit_rel_to_own_supply')) - class CostBasisPattern: """Pattern struct for repeated tree structure.""" @@ -2390,6 +2382,14 @@ class CostBasisPattern: self.max: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'max_cost_basis')) self.min: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'min_cost_basis')) +class RelativePattern4: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self.supply_in_loss_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'loss_rel_to_own_supply')) + self.supply_in_profit_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'profit_rel_to_own_supply')) + class SupplyPattern2: """Pattern struct for repeated tree structure.""" @@ -2398,14 +2398,6 @@ class SupplyPattern2: self.halved: ActiveSupplyPattern = ActiveSupplyPattern(client, _m(acc, 'halved')) self.total: ActiveSupplyPattern = ActiveSupplyPattern(client, acc) -class BlockCountPattern(Generic[T]): - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated metric name.""" - self.cumulative: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'cumulative')) - self.sum: MetricPattern1[T] = MetricPattern1(client, acc) - class BitcoinPattern2(Generic[T]): """Pattern struct for repeated tree structure.""" @@ -2419,15 +2411,16 @@ class SatsPattern(Generic[T]): def __init__(self, client: BrkClientBase, acc: str): """Create pattern node with accumulated metric name.""" - self.ohlc: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'ohlc')) - self.split: SplitPattern2[T] = SplitPattern2(client, acc) + self.ohlc: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'ohlc_sats')) + self.split: SplitPattern2[T] = SplitPattern2(client, _m(acc, 'sats')) -class RealizedPriceExtraPattern: +class BlockCountPattern(Generic[T]): """Pattern struct for repeated tree structure.""" def __init__(self, client: BrkClientBase, acc: str): """Create pattern node with accumulated metric name.""" - self.ratio: MetricPattern4[StoredF32] = MetricPattern4(client, acc) + self.cumulative: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'cumulative')) + self.sum: MetricPattern1[T] = MetricPattern1(client, acc) class OutputsPattern: """Pattern struct for repeated tree structure.""" @@ -2436,6 +2429,13 @@ class OutputsPattern: """Create pattern node with accumulated metric name.""" self.utxo_count: MetricPattern1[StoredU64] = MetricPattern1(client, acc) +class RealizedPriceExtraPattern: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self.ratio: MetricPattern4[StoredF32] = MetricPattern4(client, acc) + # Metrics tree classes class MetricsTree_Addresses: @@ -3702,12 +3702,12 @@ class MetricsTree_Price_Oracle: self.price_cents: MetricPattern11[Cents] = MetricPattern11(client, 'oracle_price_cents') self.tx_count: MetricPattern6[StoredU32] = MetricPattern6(client, 'oracle_tx_count') -class MetricsTree_Price_Sats: +class MetricsTree_Price_Usd: """Metrics tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self.ohlc: MetricPattern1[OHLCSats] = MetricPattern1(client, 'price_ohlc_sats') - self.split: SplitPattern2[Sats] = SplitPattern2(client, 'price_sats') + self.ohlc: MetricPattern1[OHLCDollars] = MetricPattern1(client, 'price_ohlc') + self.split: SplitPattern2[Dollars] = SplitPattern2(client, 'price') class MetricsTree_Price: """Metrics tree node.""" @@ -3715,8 +3715,8 @@ class MetricsTree_Price: def __init__(self, client: BrkClientBase, base_path: str = ''): self.cents: MetricsTree_Price_Cents = MetricsTree_Price_Cents(client) self.oracle: MetricsTree_Price_Oracle = MetricsTree_Price_Oracle(client) - self.sats: MetricsTree_Price_Sats = MetricsTree_Price_Sats(client) - self.usd: SatsPattern[OHLCDollars] = SatsPattern(client, 'price') + self.sats: SatsPattern[OHLCSats] = SatsPattern(client, 'price') + self.usd: MetricsTree_Price_Usd = MetricsTree_Price_Usd(client) class MetricsTree_Scripts_Count: """Metrics tree node.""" diff --git a/website/service-worker.js b/website/service-worker.js index 6a10647bd..50483d117 100644 --- a/website/service-worker.js +++ b/website/service-worker.js @@ -2,17 +2,6 @@ const CACHE = "v1"; const ROOT = "/"; const API = "/api"; -const BYPASS = new Set([ - "/changelog", - "/crate", - "/discord", - "/github", - "/install", - "/nostr", - "/service", - "/status", -]); - // Match hashed filenames: name.abc12345.js/mjs/css const HASHED_RE = /\.[0-9a-f]{8}\.(js|mjs|css)$/; @@ -59,7 +48,7 @@ sw.addEventListener("fetch", (event) => { const path = url.pathname; // Bypass API and redirects - if (path.startsWith(API) || BYPASS.has(path)) return; + if (path.startsWith(API)) return; // Navigation: network-first for shell if (req.mode === "navigate") {