mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-24 06:39:58 -07:00
bindgen: everything works
This commit is contained in:
99
Cargo.lock
generated
99
Cargo.lock
generated
@@ -916,6 +916,35 @@ dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cookie"
|
||||
version = "0.18.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747"
|
||||
dependencies = [
|
||||
"percent-encoding",
|
||||
"time",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cookie_store"
|
||||
version = "0.22.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "15b2c103cf610ec6cae3da84a766285b42fd16aad564758459e6ecf128c75206"
|
||||
dependencies = [
|
||||
"cookie",
|
||||
"document-features",
|
||||
"idna",
|
||||
"indexmap",
|
||||
"log",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"time",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.9.4"
|
||||
@@ -1090,6 +1119,15 @@ dependencies = [
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c"
|
||||
dependencies = [
|
||||
"powerfmt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_more"
|
||||
version = "2.1.1"
|
||||
@@ -1154,6 +1192,15 @@ dependencies = [
|
||||
"libloading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "document-features"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61"
|
||||
dependencies = [
|
||||
"litrs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dtype_dispatch"
|
||||
version = "0.2.1"
|
||||
@@ -2010,6 +2057,12 @@ version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77"
|
||||
|
||||
[[package]]
|
||||
name = "litrs"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.14"
|
||||
@@ -2145,6 +2198,12 @@ dependencies = [
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050"
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
@@ -2359,6 +2418,12 @@ dependencies = [
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.21"
|
||||
@@ -3031,6 +3096,37 @@ dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa",
|
||||
"num-conv",
|
||||
"powerfmt",
|
||||
"serde_core",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215"
|
||||
dependencies = [
|
||||
"num-conv",
|
||||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinystr"
|
||||
version = "0.8.2"
|
||||
@@ -3274,11 +3370,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdc97a28575b85cfedf2a7e7d3cc64b3e11bd8ac766666318003abbacc7a21fc"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"cookie_store",
|
||||
"flate2",
|
||||
"log",
|
||||
"percent-encoding",
|
||||
"rustls",
|
||||
"rustls-pki-types",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"ureq-proto",
|
||||
"utf-8",
|
||||
"webpki-roots",
|
||||
|
||||
@@ -86,7 +86,7 @@ tokio = { version = "1.50.0", features = ["rt-multi-thread"] }
|
||||
tower-http = { version = "0.6.8", features = ["catch-panic", "compression-br", "compression-gzip", "compression-zstd", "cors", "normalize-path", "timeout", "trace"] }
|
||||
tower-layer = "0.3"
|
||||
tracing = { version = "0.1", default-features = false, features = ["std"] }
|
||||
ureq = "3.2.0"
|
||||
ureq = { version = "3.2.0", features = ["json"] }
|
||||
# vecdb = { version = "0.6.8", features = ["derive", "serde_json", "pco", "schemars"] }
|
||||
vecdb = { path = "../anydb/crates/vecdb", features = ["derive", "serde_json", "pco", "schemars"] }
|
||||
|
||||
|
||||
@@ -92,8 +92,7 @@ impl LanguageSyntax for JavaScriptSyntax {
|
||||
// "ratio_{disc}_bps" → split on {disc} → _m(_m(acc, 'ratio'), disc) then _bps
|
||||
// But this is complex. For embedded disc, use string interpolation.
|
||||
// For suffix disc (ends with {disc}), use _m composition.
|
||||
if template.ends_with("{disc}") {
|
||||
let static_part = &template[..template.len() - "{disc}".len()];
|
||||
if let Some(static_part) = template.strip_suffix("{disc}") {
|
||||
if static_part.is_empty() {
|
||||
format!("_m({}, disc)", var_name)
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! Rust language syntax implementation.
|
||||
|
||||
use crate::{GenericSyntax, LanguageSyntax, to_snake_case};
|
||||
use crate::{GenericSyntax, LanguageSyntax, escape_rust_keyword, to_snake_case};
|
||||
|
||||
/// Rust-specific code generation syntax.
|
||||
pub struct RustSyntax;
|
||||
@@ -15,7 +15,7 @@ fn escape_rust_format(template: &str) -> String {
|
||||
|
||||
impl LanguageSyntax for RustSyntax {
|
||||
fn field_name(&self, name: &str) -> String {
|
||||
to_snake_case(name)
|
||||
escape_rust_keyword(&to_snake_case(name))
|
||||
}
|
||||
|
||||
fn path_expr(&self, base_var: &str, suffix: &str) -> String {
|
||||
|
||||
@@ -183,6 +183,7 @@ function _wrapMetricData(raw) {{
|
||||
* @typedef {{Object}} MetricDataBase
|
||||
* @property {{number}} version - Version of the metric data
|
||||
* @property {{Index}} index - The index type used for this query
|
||||
* @property {{string}} type - Value type (e.g. "f32", "u64", "Sats")
|
||||
* @property {{number}} total - Total number of data points
|
||||
* @property {{number}} start - Start index (inclusive)
|
||||
* @property {{number}} end - End index (exclusive)
|
||||
|
||||
@@ -24,7 +24,7 @@ pub fn generate_tree_typedefs(output: &mut String, catalog: &TreeNode, metadata:
|
||||
"MetricsTree",
|
||||
"",
|
||||
catalog,
|
||||
&pattern_lookup,
|
||||
pattern_lookup,
|
||||
metadata,
|
||||
&mut generated,
|
||||
);
|
||||
@@ -125,7 +125,7 @@ pub fn generate_main_client(
|
||||
"MetricsTree",
|
||||
"",
|
||||
3,
|
||||
&pattern_lookup,
|
||||
pattern_lookup,
|
||||
metadata,
|
||||
&mut generated,
|
||||
);
|
||||
|
||||
@@ -220,6 +220,7 @@ class MetricData(Generic[T]):
|
||||
"""Metric data with range information. Always int-indexed."""
|
||||
version: int
|
||||
index: Index
|
||||
type: str
|
||||
total: int
|
||||
start: int
|
||||
end: int
|
||||
|
||||
@@ -21,7 +21,7 @@ pub fn generate_tree_classes(output: &mut String, catalog: &TreeNode, metadata:
|
||||
"MetricsTree",
|
||||
"",
|
||||
catalog,
|
||||
&pattern_lookup,
|
||||
pattern_lookup,
|
||||
metadata,
|
||||
&mut generated,
|
||||
);
|
||||
|
||||
@@ -4,15 +4,14 @@ use std::fmt::Write;
|
||||
|
||||
use crate::{
|
||||
ClientMetadata, GenericSyntax, IndexSetPattern, RustSyntax, StructuralPattern,
|
||||
generate_parameterized_field, index_to_field_name, to_snake_case,
|
||||
escape_rust_keyword, generate_parameterized_field, index_to_field_name, to_snake_case,
|
||||
};
|
||||
|
||||
/// Generate import statements.
|
||||
pub fn generate_imports(output: &mut String) {
|
||||
writeln!(
|
||||
output,
|
||||
r#"use std::io::Read as _;
|
||||
use std::sync::Arc;
|
||||
r#"use std::sync::Arc;
|
||||
use std::ops::{{Bound, RangeBounds}};
|
||||
use serde::de::DeserializeOwned;
|
||||
pub use brk_cohort::*;
|
||||
@@ -81,40 +80,27 @@ impl BrkClientBase {{
|
||||
.into();
|
||||
Self {{
|
||||
agent,
|
||||
base_url: options.base_url,
|
||||
base_url: options.base_url.trim_end_matches('/').to_string(),
|
||||
}}
|
||||
}}
|
||||
|
||||
fn get(&self, path: &str) -> Result<Vec<u8>> {{
|
||||
let base = self.base_url.trim_end_matches('/');
|
||||
let url = format!("{{}}{{}}", base, path);
|
||||
let mut response = self.agent.get(&url)
|
||||
.call()
|
||||
.map_err(|e| BrkError {{ message: e.to_string() }})?;
|
||||
|
||||
if response.status().as_u16() >= 400 {{
|
||||
return Err(BrkError {{
|
||||
message: format!("HTTP {{}}", response.status().as_u16()),
|
||||
}});
|
||||
}}
|
||||
|
||||
let mut bytes = Vec::new();
|
||||
response.body_mut().as_reader().read_to_end(&mut bytes)
|
||||
.map_err(|e| BrkError {{ message: e.to_string() }})?;
|
||||
Ok(bytes)
|
||||
fn url(&self, path: &str) -> String {{
|
||||
format!("{{}}{{}}", self.base_url, path)
|
||||
}}
|
||||
|
||||
/// Make a GET request and deserialize JSON response.
|
||||
pub fn get_json<T: DeserializeOwned>(&self, path: &str) -> Result<T> {{
|
||||
let bytes = self.get(path)?;
|
||||
serde_json::from_slice(&bytes)
|
||||
self.agent.get(&self.url(path))
|
||||
.call()
|
||||
.and_then(|mut r| r.body_mut().read_json())
|
||||
.map_err(|e| BrkError {{ message: e.to_string() }})
|
||||
}}
|
||||
|
||||
/// Make a GET request and return raw text response.
|
||||
pub fn get_text(&self, path: &str) -> Result<String> {{
|
||||
let bytes = self.get(path)?;
|
||||
String::from_utf8(bytes)
|
||||
self.agent.get(&self.url(path))
|
||||
.call()
|
||||
.and_then(|mut r| r.body_mut().read_to_string())
|
||||
.map_err(|e| BrkError {{ message: e.to_string() }})
|
||||
}}
|
||||
}}
|
||||
@@ -525,7 +511,7 @@ pub fn generate_pattern_structs(
|
||||
writeln!(output, "pub struct {}{} {{", pattern.name, generic_params).unwrap();
|
||||
|
||||
for field in &pattern.fields {
|
||||
let field_name = to_snake_case(&field.name);
|
||||
let field_name = escape_rust_keyword(&to_snake_case(&field.name));
|
||||
let type_annotation = metadata.field_type_annotation(
|
||||
field,
|
||||
pattern.is_generic,
|
||||
|
||||
@@ -7,7 +7,8 @@ use brk_types::TreeNode;
|
||||
|
||||
use crate::{
|
||||
ClientMetadata, GenericSyntax, LanguageSyntax, PatternField, RustSyntax, build_child_path,
|
||||
generate_leaf_field, generate_tree_node_field, prepare_tree_node, to_snake_case,
|
||||
escape_rust_keyword, generate_leaf_field, generate_tree_node_field, prepare_tree_node,
|
||||
to_snake_case,
|
||||
};
|
||||
|
||||
/// Generate tree structs.
|
||||
@@ -21,7 +22,7 @@ pub fn generate_tree(output: &mut String, catalog: &TreeNode, metadata: &ClientM
|
||||
"MetricsTree",
|
||||
"",
|
||||
catalog,
|
||||
&pattern_lookup,
|
||||
pattern_lookup,
|
||||
metadata,
|
||||
&mut generated,
|
||||
);
|
||||
@@ -45,7 +46,7 @@ fn generate_tree_node(
|
||||
writeln!(output, "pub struct {} {{", name).unwrap();
|
||||
|
||||
for child in &ctx.children {
|
||||
let field_name = to_snake_case(child.name);
|
||||
let field_name = escape_rust_keyword(&to_snake_case(child.name));
|
||||
let type_annotation = if child.should_inline {
|
||||
child.inline_type_name.clone()
|
||||
} else {
|
||||
@@ -67,7 +68,7 @@ fn generate_tree_node(
|
||||
|
||||
let syntax = RustSyntax;
|
||||
for child in &ctx.children {
|
||||
let field_name = to_snake_case(child.name);
|
||||
let field_name = escape_rust_keyword(&to_snake_case(child.name));
|
||||
|
||||
if child.is_leaf {
|
||||
if let TreeNode::Leaf(leaf) = child.node {
|
||||
|
||||
@@ -14,25 +14,25 @@ pub fn to_pascal_case(s: &str) -> String {
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Convert a string to snake_case, handling Rust keywords.
|
||||
/// Convert a string to snake_case (no keyword escaping — backends handle that).
|
||||
pub fn to_snake_case(s: &str) -> String {
|
||||
// Convert to lowercase and replace dashes with underscores
|
||||
let sanitized = s.to_lowercase().replace('-', "_");
|
||||
|
||||
// Prefix with _ if starts with digit
|
||||
let sanitized = if sanitized.chars().next().is_some_and(|c| c.is_ascii_digit()) {
|
||||
if sanitized.chars().next().is_some_and(|c| c.is_ascii_digit()) {
|
||||
format!("_{}", sanitized)
|
||||
} else {
|
||||
sanitized
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Handle Rust keywords
|
||||
match sanitized.as_str() {
|
||||
/// Escape Rust reserved keywords with `_` suffix (consistent with Python).
|
||||
pub fn escape_rust_keyword(name: &str) -> String {
|
||||
match name {
|
||||
"type" | "const" | "static" | "match" | "if" | "else" | "loop" | "while" | "for"
|
||||
| "break" | "continue" | "return" | "fn" | "let" | "mut" | "ref" | "self" | "super"
|
||||
| "mod" | "use" | "pub" | "crate" | "extern" | "impl" | "trait" | "struct" | "enum"
|
||||
| "where" | "async" | "await" | "dyn" | "move" => format!("r#{}", sanitized),
|
||||
_ => sanitized,
|
||||
| "where" | "async" | "await" | "dyn" | "move" => format!("{}_", name),
|
||||
_ => name.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -74,10 +74,10 @@ impl StructuralPattern {
|
||||
// Find a template with {disc} and extract the disc from the instance value.
|
||||
// Strip leading underscore since _m() handles separators.
|
||||
for (field_name, template) in templates {
|
||||
if let Some(value) = instance_field_parts.get(field_name) {
|
||||
if let Some(disc) = extract_disc(template, value) {
|
||||
return Some(disc.trim_start_matches('_').to_string());
|
||||
}
|
||||
if let Some(value) = instance_field_parts.get(field_name)
|
||||
&& let Some(disc) = extract_disc(template, value)
|
||||
{
|
||||
return Some(disc.trim_start_matches('_').to_string());
|
||||
}
|
||||
}
|
||||
// If no template matched (all empty templates), disc is empty
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#![allow(clippy::useless_format)]
|
||||
#![allow(clippy::unnecessary_to_owned)]
|
||||
|
||||
use std::io::Read as _;
|
||||
use std::sync::Arc;
|
||||
use std::ops::{Bound, RangeBounds};
|
||||
use serde::de::DeserializeOwned;
|
||||
@@ -69,40 +68,27 @@ impl BrkClientBase {
|
||||
.into();
|
||||
Self {
|
||||
agent,
|
||||
base_url: options.base_url,
|
||||
base_url: options.base_url.trim_end_matches('/').to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn get(&self, path: &str) -> Result<Vec<u8>> {
|
||||
let base = self.base_url.trim_end_matches('/');
|
||||
let url = format!("{}{}", base, path);
|
||||
let mut response = self.agent.get(&url)
|
||||
.call()
|
||||
.map_err(|e| BrkError { message: e.to_string() })?;
|
||||
|
||||
if response.status().as_u16() >= 400 {
|
||||
return Err(BrkError {
|
||||
message: format!("HTTP {}", response.status().as_u16()),
|
||||
});
|
||||
}
|
||||
|
||||
let mut bytes = Vec::new();
|
||||
response.body_mut().as_reader().read_to_end(&mut bytes)
|
||||
.map_err(|e| BrkError { message: e.to_string() })?;
|
||||
Ok(bytes)
|
||||
fn url(&self, path: &str) -> String {
|
||||
format!("{}{}", self.base_url, path)
|
||||
}
|
||||
|
||||
/// Make a GET request and deserialize JSON response.
|
||||
pub fn get_json<T: DeserializeOwned>(&self, path: &str) -> Result<T> {
|
||||
let bytes = self.get(path)?;
|
||||
serde_json::from_slice(&bytes)
|
||||
self.agent.get(&self.url(path))
|
||||
.call()
|
||||
.and_then(|mut r| r.body_mut().read_json())
|
||||
.map_err(|e| BrkError { message: e.to_string() })
|
||||
}
|
||||
|
||||
/// Make a GET request and return raw text response.
|
||||
pub fn get_text(&self, path: &str) -> Result<String> {
|
||||
let bytes = self.get(path)?;
|
||||
String::from_utf8(bytes)
|
||||
self.agent.get(&self.url(path))
|
||||
.call()
|
||||
.and_then(|mut r| r.body_mut().read_to_string())
|
||||
.map_err(|e| BrkError { message: e.to_string() })
|
||||
}
|
||||
}
|
||||
@@ -5397,7 +5383,7 @@ impl MetricsTree_Market_Dca {
|
||||
pub struct MetricsTree_Market_Dca_Period {
|
||||
pub stack: _10y1m1w1y2y3m3y4y5y6m6y8yPattern3,
|
||||
pub cost_basis: MetricsTree_Market_Dca_Period_CostBasis,
|
||||
pub r#return: _10y1m1w1y2y3m3y4y5y6m6y8yPattern2,
|
||||
pub return_: _10y1m1w1y2y3m3y4y5y6m6y8yPattern2,
|
||||
pub cagr: _10y2y3y4y5y6y8yPattern,
|
||||
pub lump_sum_stack: _10y1m1w1y2y3m3y4y5y6m6y8yPattern3,
|
||||
pub lump_sum_return: _10y1m1w1y2y3m3y4y5y6m6y8yPattern2,
|
||||
@@ -5408,7 +5394,7 @@ impl MetricsTree_Market_Dca_Period {
|
||||
Self {
|
||||
stack: _10y1m1w1y2y3m3y4y5y6m6y8yPattern3::new(client.clone(), "dca_stack".to_string()),
|
||||
cost_basis: MetricsTree_Market_Dca_Period_CostBasis::new(client.clone(), format!("{base_path}_cost_basis")),
|
||||
r#return: _10y1m1w1y2y3m3y4y5y6m6y8yPattern2::new(client.clone(), "dca_return".to_string()),
|
||||
return_: _10y1m1w1y2y3m3y4y5y6m6y8yPattern2::new(client.clone(), "dca_return".to_string()),
|
||||
cagr: _10y2y3y4y5y6y8yPattern::new(client.clone(), "dca_cagr".to_string()),
|
||||
lump_sum_stack: _10y1m1w1y2y3m3y4y5y6m6y8yPattern3::new(client.clone(), "lump_sum_stack".to_string()),
|
||||
lump_sum_return: _10y1m1w1y2y3m3y4y5y6m6y8yPattern2::new(client.clone(), "lump_sum_return".to_string()),
|
||||
@@ -5455,7 +5441,7 @@ impl MetricsTree_Market_Dca_Period_CostBasis {
|
||||
pub struct MetricsTree_Market_Dca_Class {
|
||||
pub stack: MetricsTree_Market_Dca_Class_Stack,
|
||||
pub cost_basis: MetricsTree_Market_Dca_Class_CostBasis,
|
||||
pub r#return: MetricsTree_Market_Dca_Class_Return,
|
||||
pub return_: MetricsTree_Market_Dca_Class_Return,
|
||||
}
|
||||
|
||||
impl MetricsTree_Market_Dca_Class {
|
||||
@@ -5463,7 +5449,7 @@ impl MetricsTree_Market_Dca_Class {
|
||||
Self {
|
||||
stack: MetricsTree_Market_Dca_Class_Stack::new(client.clone(), format!("{base_path}_stack")),
|
||||
cost_basis: MetricsTree_Market_Dca_Class_CostBasis::new(client.clone(), format!("{base_path}_cost_basis")),
|
||||
r#return: MetricsTree_Market_Dca_Class_Return::new(client.clone(), format!("{base_path}_return")),
|
||||
return_: MetricsTree_Market_Dca_Class_Return::new(client.clone(), format!("{base_path}_return")),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6232,7 +6218,7 @@ pub struct MetricsTree_Cohorts_Utxo {
|
||||
pub over_amount: MetricsTree_Cohorts_Utxo_OverAmount,
|
||||
pub amount_range: MetricsTree_Cohorts_Utxo_AmountRange,
|
||||
pub under_amount: MetricsTree_Cohorts_Utxo_UnderAmount,
|
||||
pub r#type: MetricsTree_Cohorts_Utxo_Type,
|
||||
pub type_: MetricsTree_Cohorts_Utxo_Type,
|
||||
pub profitability: MetricsTree_Cohorts_Utxo_Profitability,
|
||||
pub matured: MetricsTree_Cohorts_Utxo_Matured,
|
||||
}
|
||||
@@ -6251,7 +6237,7 @@ impl MetricsTree_Cohorts_Utxo {
|
||||
over_amount: MetricsTree_Cohorts_Utxo_OverAmount::new(client.clone(), format!("{base_path}_over_amount")),
|
||||
amount_range: MetricsTree_Cohorts_Utxo_AmountRange::new(client.clone(), format!("{base_path}_amount_range")),
|
||||
under_amount: MetricsTree_Cohorts_Utxo_UnderAmount::new(client.clone(), format!("{base_path}_under_amount")),
|
||||
r#type: MetricsTree_Cohorts_Utxo_Type::new(client.clone(), format!("{base_path}_type")),
|
||||
type_: MetricsTree_Cohorts_Utxo_Type::new(client.clone(), format!("{base_path}_type")),
|
||||
profitability: MetricsTree_Cohorts_Utxo_Profitability::new(client.clone(), format!("{base_path}_profitability")),
|
||||
matured: MetricsTree_Cohorts_Utxo_Matured::new(client.clone(), format!("{base_path}_matured")),
|
||||
}
|
||||
|
||||
@@ -3,7 +3,8 @@ use brk_fetcher::Kraken;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
brk_logger::init(None)?;
|
||||
let _ = dbg!(Kraken::fetch_1d());
|
||||
let _ = dbg!(Kraken::fetch_1mn());
|
||||
let kraken = Kraken::new();
|
||||
let _ = dbg!(kraken.fetch_1d());
|
||||
let _ = dbg!(kraken.fetch_1mn());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -5,22 +5,25 @@ use brk_types::{Date, Height};
|
||||
fn main() -> Result<()> {
|
||||
brk_logger::init(None)?;
|
||||
|
||||
let mut brk = BRK::default();
|
||||
let mut brk = BRK::new();
|
||||
dbg!(brk.get_from_height(Height::new(900_000))?);
|
||||
dbg!(brk.get_from_date(Date::new(2025, 6, 7))?);
|
||||
|
||||
let mut fetcher = Fetcher::new(None)?;
|
||||
|
||||
let _ = Binance::fetch_1d().map(|b| {
|
||||
let binance = Binance::new(None);
|
||||
let kraken = Kraken::new();
|
||||
|
||||
let _ = binance.fetch_1d().map(|b| {
|
||||
dbg!(b.last_key_value());
|
||||
});
|
||||
let _ = Kraken::fetch_1d().map(|b| {
|
||||
let _ = kraken.fetch_1d().map(|b| {
|
||||
dbg!(b.last_key_value());
|
||||
});
|
||||
let _ = Binance::fetch_1mn().map(|b| {
|
||||
let _ = binance.fetch_1mn().map(|b| {
|
||||
dbg!(b.last_key_value());
|
||||
});
|
||||
let _ = Kraken::fetch_1mn().map(|b| {
|
||||
let _ = kraken.fetch_1mn().map(|b| {
|
||||
dbg!(b.last_key_value());
|
||||
});
|
||||
|
||||
|
||||
@@ -26,7 +26,11 @@ pub struct Binance {
|
||||
}
|
||||
|
||||
impl Binance {
|
||||
pub fn new(path: Option<&Path>, agent: Agent) -> Self {
|
||||
pub fn new(path: Option<&Path>) -> Self {
|
||||
Self::new_with_agent(path, crate::new_agent(30))
|
||||
}
|
||||
|
||||
pub fn new_with_agent(path: Option<&Path>, agent: Agent) -> Self {
|
||||
Self {
|
||||
agent,
|
||||
path: path.map(|p| p.to_owned()),
|
||||
|
||||
@@ -19,7 +19,11 @@ pub struct BRK {
|
||||
}
|
||||
|
||||
impl BRK {
|
||||
pub fn new(agent: Agent) -> Self {
|
||||
pub fn new() -> Self {
|
||||
Self::new_with_agent(crate::new_agent(30))
|
||||
}
|
||||
|
||||
pub fn new_with_agent(agent: Agent) -> Self {
|
||||
Self {
|
||||
agent,
|
||||
height_to_ohlc: BTreeMap::new(),
|
||||
|
||||
@@ -19,7 +19,11 @@ pub struct Kraken {
|
||||
}
|
||||
|
||||
impl Kraken {
|
||||
pub fn new(agent: Agent) -> Self {
|
||||
pub fn new() -> Self {
|
||||
Self::new_with_agent(crate::new_agent(30))
|
||||
}
|
||||
|
||||
pub fn new_with_agent(agent: Agent) -> Self {
|
||||
Self {
|
||||
agent,
|
||||
_1mn: None,
|
||||
|
||||
@@ -25,9 +25,11 @@ pub use source::{PriceSource, TrackedSource};
|
||||
const MAX_RETRIES: usize = 12 * 60; // 12 hours of retrying
|
||||
|
||||
/// Create a shared HTTP agent with connection pooling and default timeout.
|
||||
/// Status codes are not treated as errors — callers use `checked_get` for status handling.
|
||||
pub fn new_agent(timeout_secs: u64) -> Agent {
|
||||
Agent::config_builder()
|
||||
.timeout_global(Some(Duration::from_secs(timeout_secs)))
|
||||
.http_status_as_error(false)
|
||||
.build()
|
||||
.into()
|
||||
}
|
||||
@@ -63,9 +65,9 @@ impl Fetcher {
|
||||
pub fn new(hars_path: Option<&Path>) -> Result<Self> {
|
||||
let agent = new_agent(30);
|
||||
Ok(Self {
|
||||
binance: TrackedSource::new(Binance::new(hars_path, agent.clone())),
|
||||
kraken: TrackedSource::new(Kraken::new(agent.clone())),
|
||||
brk: TrackedSource::new(BRK::new(agent.clone())),
|
||||
binance: TrackedSource::new(Binance::new_with_agent(hars_path, agent.clone())),
|
||||
kraken: TrackedSource::new(Kraken::new_with_agent(agent.clone())),
|
||||
brk: TrackedSource::new(BRK::new_with_agent(agent.clone())),
|
||||
agent,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1116,6 +1116,7 @@ function _wrapMetricData(raw) {
|
||||
* @typedef {Object} MetricDataBase
|
||||
* @property {number} version - Version of the metric data
|
||||
* @property {Index} index - The index type used for this query
|
||||
* @property {string} type - Value type (e.g. "f32", "u64", "Sats")
|
||||
* @property {number} total - Total number of data points
|
||||
* @property {number} start - Start index (inclusive)
|
||||
* @property {number} end - End index (exclusive)
|
||||
|
||||
@@ -1270,6 +1270,7 @@ class MetricData(Generic[T]):
|
||||
"""Metric data with range information. Always int-indexed."""
|
||||
version: int
|
||||
index: Index
|
||||
type: str
|
||||
total: int
|
||||
start: int
|
||||
end: int
|
||||
@@ -4253,7 +4254,7 @@ class MetricsTree_Market_Dca_Period:
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.stack: _10y1m1w1y2y3m3y4y5y6m6y8yPattern3 = _10y1m1w1y2y3m3y4y5y6m6y8yPattern3(client, 'dca_stack')
|
||||
self.cost_basis: MetricsTree_Market_Dca_Period_CostBasis = MetricsTree_Market_Dca_Period_CostBasis(client)
|
||||
self.r#return: _10y1m1w1y2y3m3y4y5y6m6y8yPattern2 = _10y1m1w1y2y3m3y4y5y6m6y8yPattern2(client, 'dca_return')
|
||||
self.return_: _10y1m1w1y2y3m3y4y5y6m6y8yPattern2 = _10y1m1w1y2y3m3y4y5y6m6y8yPattern2(client, 'dca_return')
|
||||
self.cagr: _10y2y3y4y5y6y8yPattern = _10y2y3y4y5y6y8yPattern(client, 'dca_cagr')
|
||||
self.lump_sum_stack: _10y1m1w1y2y3m3y4y5y6m6y8yPattern3 = _10y1m1w1y2y3m3y4y5y6m6y8yPattern3(client, 'lump_sum_stack')
|
||||
self.lump_sum_return: _10y1m1w1y2y3m3y4y5y6m6y8yPattern2 = _10y1m1w1y2y3m3y4y5y6m6y8yPattern2(client, 'lump_sum_return')
|
||||
@@ -4315,7 +4316,7 @@ class MetricsTree_Market_Dca_Class:
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.stack: MetricsTree_Market_Dca_Class_Stack = MetricsTree_Market_Dca_Class_Stack(client)
|
||||
self.cost_basis: MetricsTree_Market_Dca_Class_CostBasis = MetricsTree_Market_Dca_Class_CostBasis(client)
|
||||
self.r#return: MetricsTree_Market_Dca_Class_Return = MetricsTree_Market_Dca_Class_Return(client)
|
||||
self.return_: MetricsTree_Market_Dca_Class_Return = MetricsTree_Market_Dca_Class_Return(client)
|
||||
|
||||
class MetricsTree_Market_Dca:
|
||||
"""Metrics tree node."""
|
||||
@@ -5621,7 +5622,7 @@ class MetricsTree_Cohorts_Utxo:
|
||||
self.over_amount: MetricsTree_Cohorts_Utxo_OverAmount = MetricsTree_Cohorts_Utxo_OverAmount(client)
|
||||
self.amount_range: MetricsTree_Cohorts_Utxo_AmountRange = MetricsTree_Cohorts_Utxo_AmountRange(client)
|
||||
self.under_amount: MetricsTree_Cohorts_Utxo_UnderAmount = MetricsTree_Cohorts_Utxo_UnderAmount(client)
|
||||
self.r#type: MetricsTree_Cohorts_Utxo_Type = MetricsTree_Cohorts_Utxo_Type(client)
|
||||
self.type: MetricsTree_Cohorts_Utxo_Type = MetricsTree_Cohorts_Utxo_Type(client)
|
||||
self.profitability: MetricsTree_Cohorts_Utxo_Profitability = MetricsTree_Cohorts_Utxo_Profitability(client)
|
||||
self.matured: MetricsTree_Cohorts_Utxo_Matured = MetricsTree_Cohorts_Utxo_Matured(client)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user