clients: snapshot

This commit is contained in:
nym21
2026-01-14 00:39:28 +01:00
parent 524ab3de05
commit 3a836ab0f4
15 changed files with 869 additions and 896 deletions
+1
View File
@@ -3,3 +3,4 @@ clients/
/*.js
/*.rs
/*.py
tests/output/
+15 -24
View File
@@ -97,33 +97,24 @@ pub fn generate_tree_node_field<S: LanguageSyntax>(
let type_ann = metadata.field_type_annotation(field, false, None, syntax.generic_syntax());
let value = if metadata.is_pattern_type(&field.rust_type) {
// Check if this pattern is parameterizable
let pattern = metadata.find_pattern(&field.rust_type);
let is_parameterizable = pattern.is_some_and(|p| p.is_parameterizable());
// Use metric base only for parameterizable patterns
let use_base = metadata
.find_pattern(&field.rust_type)
.is_some_and(|p| p.is_parameterizable())
&& pattern_base.is_some();
if is_parameterizable {
if let Some(base) = pattern_base {
// Use the detected metric base
let path = syntax.string_literal(base);
syntax.constructor(&field.rust_type, &path)
} else {
// Fallback to tree path
let path_expr = syntax.path_expr("base_path", &path_suffix(child_name));
syntax.constructor(&field.rust_type, &path_expr)
}
let path_arg = if use_base {
syntax.string_literal(pattern_base.unwrap())
} else {
let path_expr = syntax.path_expr("base_path", &path_suffix(child_name));
syntax.constructor(&field.rust_type, &path_expr)
}
syntax.path_expr("base_path", &path_suffix(child_name))
};
syntax.constructor(&field.rust_type, &path_arg)
} else if let Some(accessor) = metadata.find_index_set_pattern(&field.indexes) {
// Leaf field - use actual metric name if provided
if let Some(metric_name) = pattern_base {
let path = syntax.string_literal(metric_name);
syntax.constructor(&accessor.name, &path)
} else {
let path_expr = syntax.path_expr("base_path", &path_suffix(child_name));
syntax.constructor(&accessor.name, &path_expr)
}
// Leaf field - use metric name if provided, else tree path
let path_arg = pattern_base
.map(|name| syntax.string_literal(name))
.unwrap_or_else(|| syntax.path_expr("base_path", &path_suffix(child_name)));
syntax.constructor(&accessor.name, &path_arg)
} else if field.is_branch() {
// Non-pattern branch - instantiate the nested struct
let path_expr = syntax.path_expr("base_path", &path_suffix(child_name));
@@ -4,7 +4,7 @@ use std::fmt::Write;
use serde_json::Value;
use crate::{TypeSchemas, generators::{MANUAL_GENERIC_TYPES, write_description}, ref_to_type_name, to_camel_case};
use crate::{TypeSchemas, generators::{MANUAL_GENERIC_TYPES, write_description}, get_union_variants, ref_to_type_name, to_camel_case};
/// Generate JSDoc type definitions from OpenAPI schemas.
pub fn generate_type_definitions(output: &mut String, schemas: &TypeSchemas) {
@@ -165,11 +165,7 @@ pub fn schema_to_js_type(schema: &Value, current_type: Option<&str>) -> String {
}
}
if let Some(variants) = schema
.get("anyOf")
.or_else(|| schema.get("oneOf"))
.and_then(|v| v.as_array())
{
if let Some(variants) = get_union_variants(schema) {
let types: Vec<String> = variants
.iter()
.map(|v| schema_to_js_type(v, current_type))
@@ -5,7 +5,7 @@ use std::fmt::Write;
use serde_json::Value;
use crate::{TypeSchemas, escape_python_keyword, generators::MANUAL_GENERIC_TYPES, ref_to_type_name};
use crate::{TypeSchemas, escape_python_keyword, generators::MANUAL_GENERIC_TYPES, get_union_variants, ref_to_type_name};
/// Generate type definitions from schemas.
pub fn generate_type_definitions(output: &mut String, schemas: &TypeSchemas) {
@@ -36,7 +36,7 @@ pub fn generate_type_definitions(output: &mut String, schemas: &TypeSchemas) {
for name in type_aliases {
let schema = &schemas[&name];
let type_desc = schema.get("description").and_then(|d| d.as_str());
let py_type = schema_to_python_type_quoting(schema, Some(&name), &typed_dict_set);
let py_type = schema_to_python_type(schema, Some(&name), Some(&typed_dict_set));
if let Some(desc) = type_desc {
for line in desc.lines() {
writeln!(output, "# {}", line).unwrap();
@@ -87,7 +87,7 @@ pub fn generate_type_definitions(output: &mut String, schemas: &TypeSchemas) {
}
for (prop_name, prop_schema) in props {
let prop_type = schema_to_python_type_ctx(prop_schema, Some(&name));
let prop_type = schema_to_python_type(prop_schema, Some(&name), None);
let safe_name = escape_python_keyword(prop_name);
writeln!(output, " {}: {}", safe_name, prop_type).unwrap();
}
@@ -193,13 +193,13 @@ fn json_type_to_python(ty: &str, schema: &Value, current_type: Option<&str>) ->
"array" => {
let item_type = schema
.get("items")
.map(|s| schema_to_python_type_ctx(s, current_type))
.map(|s| schema_to_python_type(s, current_type, None))
.unwrap_or_else(|| "Any".to_string());
format!("List[{}]", item_type)
}
"object" => {
if let Some(add_props) = schema.get("additionalProperties") {
let value_type = schema_to_python_type_ctx(add_props, current_type);
let value_type = schema_to_python_type(add_props, current_type, None);
return format!("dict[str, {}]", value_type);
}
"dict".to_string()
@@ -208,15 +208,18 @@ fn json_type_to_python(ty: &str, schema: &Value, current_type: Option<&str>) ->
}
}
/// Convert JSON Schema to Python type, quoting types in the given set
fn schema_to_python_type_quoting(
/// Convert JSON Schema to Python type.
///
/// - `current_type`: Used to detect and quote self-references for recursive types
/// - `quote_types`: Optional set of additional type names that should be quoted
pub fn schema_to_python_type(
schema: &Value,
current_type: Option<&str>,
quote_types: &HashSet<String>,
quote_types: Option<&HashSet<String>>,
) -> String {
if let Some(all_of) = schema.get("allOf").and_then(|v| v.as_array()) {
for item in all_of {
let resolved = schema_to_python_type_quoting(item, current_type, quote_types);
let resolved = schema_to_python_type(item, current_type, quote_types);
if resolved != "Any" {
return resolved;
}
@@ -227,67 +230,9 @@ fn schema_to_python_type_quoting(
if let Some(ref_path) = schema.get("$ref").and_then(|r| r.as_str()) {
let type_name = ref_to_type_name(ref_path).unwrap_or("Any");
// Quote self-references or types in quote_types set
if current_type == Some(type_name) || quote_types.contains(type_name) {
return format!("\"{}\"", type_name);
}
return type_name.to_string();
}
// Handle enum (array of string values)
if let Some(enum_values) = schema.get("enum").and_then(|e| e.as_array()) {
let literals: Vec<String> = enum_values
.iter()
.filter_map(|v| v.as_str())
.map(|s| format!("\"{}\"", s))
.collect();
if !literals.is_empty() {
return format!("Literal[{}]", literals.join(", "));
}
}
if let Some(variants) = schema
.get("anyOf")
.or_else(|| schema.get("oneOf"))
.and_then(|v| v.as_array())
{
let types: Vec<String> = variants
.iter()
.map(|v| schema_to_python_type_quoting(v, current_type, quote_types))
.collect();
let filtered: Vec<_> = types.iter().filter(|t| *t != "Any").collect();
if !filtered.is_empty() {
return format!(
"Union[{}]",
filtered
.iter()
.map(|s| s.as_str())
.collect::<Vec<_>>()
.join(", ")
);
}
return format!("Union[{}]", types.join(", "));
}
// Fall back to regular conversion for other cases
schema_to_python_type_ctx(schema, current_type)
}
/// Convert JSON Schema to Python type with context for detecting self-references
pub fn schema_to_python_type_ctx(schema: &Value, current_type: Option<&str>) -> String {
if let Some(all_of) = schema.get("allOf").and_then(|v| v.as_array()) {
for item in all_of {
let resolved = schema_to_python_type_ctx(item, current_type);
if resolved != "Any" {
return resolved;
}
}
}
// Handle $ref
if let Some(ref_path) = schema.get("$ref").and_then(|r| r.as_str()) {
let type_name = ref_to_type_name(ref_path).unwrap_or("Any");
// Quote self-references to handle recursive types
if current_type == Some(type_name) {
let should_quote = current_type == Some(type_name)
|| quote_types.is_some_and(|qt| qt.contains(type_name));
if should_quote {
return format!("\"{}\"", type_name);
}
return type_name.to_string();
@@ -310,7 +255,7 @@ pub fn schema_to_python_type_ctx(schema: &Value, current_type: Option<&str>) ->
let types: Vec<String> = type_array
.iter()
.filter_map(|t| t.as_str())
.filter(|t| *t != "null") // Filter out null for cleaner Optional handling
.filter(|t| *t != "null")
.map(|t| json_type_to_python(t, schema, current_type))
.collect();
let has_null = type_array.iter().any(|t| t.as_str() == Some("null"));
@@ -337,14 +282,10 @@ pub fn schema_to_python_type_ctx(schema: &Value, current_type: Option<&str>) ->
}
}
if let Some(variants) = schema
.get("anyOf")
.or_else(|| schema.get("oneOf"))
.and_then(|v| v.as_array())
{
if let Some(variants) = get_union_variants(schema) {
let types: Vec<String> = variants
.iter()
.map(|v| schema_to_python_type_ctx(v, current_type))
.map(|v| schema_to_python_type(v, current_type, quote_types))
.collect();
let filtered: Vec<_> = types.iter().filter(|t| *t != "Any").collect();
if !filtered.is_empty() {
+11 -18
View File
@@ -165,24 +165,17 @@ pub fn extract_endpoints(spec: &Spec) -> Vec<Endpoint> {
endpoints
}
fn get_operations(path_item: &PathItem) -> Vec<(String, &Operation)> {
let mut ops = Vec::new();
if let Some(op) = &path_item.get {
ops.push(("GET".to_string(), op));
}
if let Some(op) = &path_item.post {
ops.push(("POST".to_string(), op));
}
if let Some(op) = &path_item.put {
ops.push(("PUT".to_string(), op));
}
if let Some(op) = &path_item.delete {
ops.push(("DELETE".to_string(), op));
}
if let Some(op) = &path_item.patch {
ops.push(("PATCH".to_string(), op));
}
ops
fn get_operations(path_item: &PathItem) -> Vec<(&'static str, &Operation)> {
[
("GET", &path_item.get),
("POST", &path_item.post),
("PUT", &path_item.put),
("DELETE", &path_item.delete),
("PATCH", &path_item.patch),
]
.into_iter()
.filter_map(|(method, op)| op.as_ref().map(|o| (method, o)))
.collect()
}
fn extract_endpoint(path: &str, method: &str, operation: &Operation) -> Option<Endpoint> {
+8
View File
@@ -33,3 +33,11 @@ pub fn extract_inner_type(type_str: &str) -> String {
pub fn ref_to_type_name(ref_path: &str) -> Option<&str> {
ref_path.rsplit('/').next()
}
/// Get union variants from anyOf or oneOf schema.
pub fn get_union_variants(schema: &Value) -> Option<&Vec<Value>> {
schema
.get("anyOf")
.or_else(|| schema.get("oneOf"))
.and_then(|v| v.as_array())
}
+15 -15
View File
@@ -371,9 +371,11 @@ fn test_generated_rust_output() {
);
println!(" Output size: {} bytes", rust_output.len());
// Write output to actual client location
let output_path = concat!(env!("CARGO_MANIFEST_DIR"), "/../brk_client/src/lib.rs");
std::fs::write(output_path, &rust_output).expect("Failed to write client output");
// Write output to test directory (not actual client)
let output_dir = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/output");
std::fs::create_dir_all(output_dir).ok();
let output_path = format!("{}/rust_client.rs", output_dir);
std::fs::write(&output_path, &rust_output).expect("Failed to write client output");
println!(" Wrote output to: {}", output_path);
// Verify the output contains the key components
@@ -468,12 +470,11 @@ fn test_generated_javascript_output() {
println!(" Output size: {} bytes", js_output.len());
println!(" Output lines: {}", js_output.lines().count());
// Write output to actual client location
let output_path = concat!(
env!("CARGO_MANIFEST_DIR"),
"/../../modules/brk-client/index.js"
);
std::fs::write(output_path, &js_output).expect("Failed to write JS client output");
// Write output to test directory (not actual client)
let output_dir = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/output");
std::fs::create_dir_all(output_dir).ok();
let output_path = format!("{}/js_client.js", output_dir);
std::fs::write(&output_path, &js_output).expect("Failed to write JS client output");
println!(" Wrote output to: {}", output_path);
// Verify the output contains key components
@@ -562,12 +563,11 @@ fn test_generated_python_output() {
println!(" Output size: {} bytes", py_output.len());
println!(" Output lines: {}", py_output.lines().count());
// Write output to actual client location
let output_path = concat!(
env!("CARGO_MANIFEST_DIR"),
"/../../packages/brk_client/brk_client/__init__.py"
);
std::fs::write(output_path, &py_output).expect("Failed to write Python client output");
// Write output to test directory (not actual client)
let output_dir = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/output");
std::fs::create_dir_all(output_dir).ok();
let output_path = format!("{}/python_client.py", output_dir);
std::fs::write(&output_path, &py_output).expect("Failed to write Python client output");
println!(" Wrote output to: {}", output_path);
// Verify the output contains key components
+271 -269
View File
@@ -2642,56 +2642,6 @@ impl Price111dSmaPattern {
}
}
/// Pattern struct for repeated tree structure.
pub struct PercentilesPattern {
pub pct05: MetricPattern4<Dollars>,
pub pct10: MetricPattern4<Dollars>,
pub pct15: MetricPattern4<Dollars>,
pub pct20: MetricPattern4<Dollars>,
pub pct25: MetricPattern4<Dollars>,
pub pct30: MetricPattern4<Dollars>,
pub pct35: MetricPattern4<Dollars>,
pub pct40: MetricPattern4<Dollars>,
pub pct45: MetricPattern4<Dollars>,
pub pct50: MetricPattern4<Dollars>,
pub pct55: MetricPattern4<Dollars>,
pub pct60: MetricPattern4<Dollars>,
pub pct65: MetricPattern4<Dollars>,
pub pct70: MetricPattern4<Dollars>,
pub pct75: MetricPattern4<Dollars>,
pub pct80: MetricPattern4<Dollars>,
pub pct85: MetricPattern4<Dollars>,
pub pct90: MetricPattern4<Dollars>,
pub pct95: MetricPattern4<Dollars>,
}
impl PercentilesPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
pct05: MetricPattern4::new(client.clone(), _m(&acc, "pct05")),
pct10: MetricPattern4::new(client.clone(), _m(&acc, "pct10")),
pct15: MetricPattern4::new(client.clone(), _m(&acc, "pct15")),
pct20: MetricPattern4::new(client.clone(), _m(&acc, "pct20")),
pct25: MetricPattern4::new(client.clone(), _m(&acc, "pct25")),
pct30: MetricPattern4::new(client.clone(), _m(&acc, "pct30")),
pct35: MetricPattern4::new(client.clone(), _m(&acc, "pct35")),
pct40: MetricPattern4::new(client.clone(), _m(&acc, "pct40")),
pct45: MetricPattern4::new(client.clone(), _m(&acc, "pct45")),
pct50: MetricPattern4::new(client.clone(), _m(&acc, "pct50")),
pct55: MetricPattern4::new(client.clone(), _m(&acc, "pct55")),
pct60: MetricPattern4::new(client.clone(), _m(&acc, "pct60")),
pct65: MetricPattern4::new(client.clone(), _m(&acc, "pct65")),
pct70: MetricPattern4::new(client.clone(), _m(&acc, "pct70")),
pct75: MetricPattern4::new(client.clone(), _m(&acc, "pct75")),
pct80: MetricPattern4::new(client.clone(), _m(&acc, "pct80")),
pct85: MetricPattern4::new(client.clone(), _m(&acc, "pct85")),
pct90: MetricPattern4::new(client.clone(), _m(&acc, "pct90")),
pct95: MetricPattern4::new(client.clone(), _m(&acc, "pct95")),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct ActivePriceRatioPattern {
pub ratio: MetricPattern4<StoredF32>,
@@ -2742,6 +2692,56 @@ impl ActivePriceRatioPattern {
}
}
/// Pattern struct for repeated tree structure.
pub struct PercentilesPattern {
pub pct05: MetricPattern4<Dollars>,
pub pct10: MetricPattern4<Dollars>,
pub pct15: MetricPattern4<Dollars>,
pub pct20: MetricPattern4<Dollars>,
pub pct25: MetricPattern4<Dollars>,
pub pct30: MetricPattern4<Dollars>,
pub pct35: MetricPattern4<Dollars>,
pub pct40: MetricPattern4<Dollars>,
pub pct45: MetricPattern4<Dollars>,
pub pct50: MetricPattern4<Dollars>,
pub pct55: MetricPattern4<Dollars>,
pub pct60: MetricPattern4<Dollars>,
pub pct65: MetricPattern4<Dollars>,
pub pct70: MetricPattern4<Dollars>,
pub pct75: MetricPattern4<Dollars>,
pub pct80: MetricPattern4<Dollars>,
pub pct85: MetricPattern4<Dollars>,
pub pct90: MetricPattern4<Dollars>,
pub pct95: MetricPattern4<Dollars>,
}
impl PercentilesPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
pct05: MetricPattern4::new(client.clone(), _m(&acc, "pct05")),
pct10: MetricPattern4::new(client.clone(), _m(&acc, "pct10")),
pct15: MetricPattern4::new(client.clone(), _m(&acc, "pct15")),
pct20: MetricPattern4::new(client.clone(), _m(&acc, "pct20")),
pct25: MetricPattern4::new(client.clone(), _m(&acc, "pct25")),
pct30: MetricPattern4::new(client.clone(), _m(&acc, "pct30")),
pct35: MetricPattern4::new(client.clone(), _m(&acc, "pct35")),
pct40: MetricPattern4::new(client.clone(), _m(&acc, "pct40")),
pct45: MetricPattern4::new(client.clone(), _m(&acc, "pct45")),
pct50: MetricPattern4::new(client.clone(), _m(&acc, "pct50")),
pct55: MetricPattern4::new(client.clone(), _m(&acc, "pct55")),
pct60: MetricPattern4::new(client.clone(), _m(&acc, "pct60")),
pct65: MetricPattern4::new(client.clone(), _m(&acc, "pct65")),
pct70: MetricPattern4::new(client.clone(), _m(&acc, "pct70")),
pct75: MetricPattern4::new(client.clone(), _m(&acc, "pct75")),
pct80: MetricPattern4::new(client.clone(), _m(&acc, "pct80")),
pct85: MetricPattern4::new(client.clone(), _m(&acc, "pct85")),
pct90: MetricPattern4::new(client.clone(), _m(&acc, "pct90")),
pct95: MetricPattern4::new(client.clone(), _m(&acc, "pct95")),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct RelativePattern5 {
pub neg_unrealized_loss_rel_to_market_cap: MetricPattern1<StoredF32>,
@@ -2993,17 +2993,17 @@ impl<T: DeserializeOwned> ClassAveragePricePattern<T> {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
_2015: MetricPattern4::new(client.clone(), _m(&acc, "2015_average_price")),
_2016: MetricPattern4::new(client.clone(), _m(&acc, "2016_average_price")),
_2017: MetricPattern4::new(client.clone(), _m(&acc, "2017_average_price")),
_2018: MetricPattern4::new(client.clone(), _m(&acc, "2018_average_price")),
_2019: MetricPattern4::new(client.clone(), _m(&acc, "2019_average_price")),
_2020: MetricPattern4::new(client.clone(), _m(&acc, "2020_average_price")),
_2021: MetricPattern4::new(client.clone(), _m(&acc, "2021_average_price")),
_2022: MetricPattern4::new(client.clone(), _m(&acc, "2022_average_price")),
_2023: MetricPattern4::new(client.clone(), _m(&acc, "2023_average_price")),
_2024: MetricPattern4::new(client.clone(), _m(&acc, "2024_average_price")),
_2025: MetricPattern4::new(client.clone(), _m(&acc, "2025_average_price")),
_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")),
}
}
}
@@ -3168,36 +3168,6 @@ impl AddrCountPattern {
}
}
/// Pattern struct for repeated tree structure.
pub struct FullnessPattern<T> {
pub average: MetricPattern2<T>,
pub base: MetricPattern11<T>,
pub max: MetricPattern2<T>,
pub median: MetricPattern6<T>,
pub min: MetricPattern2<T>,
pub pct10: MetricPattern6<T>,
pub pct25: MetricPattern6<T>,
pub pct75: MetricPattern6<T>,
pub pct90: MetricPattern6<T>,
}
impl<T: DeserializeOwned> FullnessPattern<T> {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
average: MetricPattern2::new(client.clone(), _m(&acc, "average")),
base: MetricPattern11::new(client.clone(), acc.clone()),
max: MetricPattern2::new(client.clone(), _m(&acc, "max")),
median: MetricPattern6::new(client.clone(), _m(&acc, "median")),
min: MetricPattern2::new(client.clone(), _m(&acc, "min")),
pct10: MetricPattern6::new(client.clone(), _m(&acc, "pct10")),
pct25: MetricPattern6::new(client.clone(), _m(&acc, "pct25")),
pct75: MetricPattern6::new(client.clone(), _m(&acc, "pct75")),
pct90: MetricPattern6::new(client.clone(), _m(&acc, "pct90")),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct FeeRatePattern<T> {
pub average: MetricPattern1<T>,
@@ -3228,6 +3198,36 @@ impl<T: DeserializeOwned> FeeRatePattern<T> {
}
}
/// Pattern struct for repeated tree structure.
pub struct FullnessPattern<T> {
pub average: MetricPattern2<T>,
pub base: MetricPattern11<T>,
pub max: MetricPattern2<T>,
pub median: MetricPattern6<T>,
pub min: MetricPattern2<T>,
pub pct10: MetricPattern6<T>,
pub pct25: MetricPattern6<T>,
pub pct75: MetricPattern6<T>,
pub pct90: MetricPattern6<T>,
}
impl<T: DeserializeOwned> FullnessPattern<T> {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
average: MetricPattern2::new(client.clone(), _m(&acc, "average")),
base: MetricPattern11::new(client.clone(), acc.clone()),
max: MetricPattern2::new(client.clone(), _m(&acc, "max")),
median: MetricPattern6::new(client.clone(), _m(&acc, "median")),
min: MetricPattern2::new(client.clone(), _m(&acc, "min")),
pct10: MetricPattern6::new(client.clone(), _m(&acc, "pct10")),
pct25: MetricPattern6::new(client.clone(), _m(&acc, "pct25")),
pct75: MetricPattern6::new(client.clone(), _m(&acc, "pct75")),
pct90: MetricPattern6::new(client.clone(), _m(&acc, "pct90")),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct _0satsPattern {
pub activity: ActivityPattern2,
@@ -3256,32 +3256,6 @@ impl _0satsPattern {
}
}
/// Pattern struct for repeated tree structure.
pub struct PeriodCagrPattern {
pub _10y: MetricPattern4<StoredF32>,
pub _2y: MetricPattern4<StoredF32>,
pub _3y: MetricPattern4<StoredF32>,
pub _4y: MetricPattern4<StoredF32>,
pub _5y: MetricPattern4<StoredF32>,
pub _6y: MetricPattern4<StoredF32>,
pub _8y: MetricPattern4<StoredF32>,
}
impl PeriodCagrPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
_10y: MetricPattern4::new(client.clone(), _p("10y", &acc)),
_2y: MetricPattern4::new(client.clone(), _p("2y", &acc)),
_3y: MetricPattern4::new(client.clone(), _p("3y", &acc)),
_4y: MetricPattern4::new(client.clone(), _p("4y", &acc)),
_5y: MetricPattern4::new(client.clone(), _p("5y", &acc)),
_6y: MetricPattern4::new(client.clone(), _p("6y", &acc)),
_8y: MetricPattern4::new(client.clone(), _p("8y", &acc)),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct _100btcPattern {
pub activity: ActivityPattern2,
@@ -3308,6 +3282,58 @@ impl _100btcPattern {
}
}
/// 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<BrkClientBase>, 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 PeriodCagrPattern {
pub _10y: MetricPattern4<StoredF32>,
pub _2y: MetricPattern4<StoredF32>,
pub _3y: MetricPattern4<StoredF32>,
pub _4y: MetricPattern4<StoredF32>,
pub _5y: MetricPattern4<StoredF32>,
pub _6y: MetricPattern4<StoredF32>,
pub _8y: MetricPattern4<StoredF32>,
}
impl PeriodCagrPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
_10y: MetricPattern4::new(client.clone(), _p("10y", &acc)),
_2y: MetricPattern4::new(client.clone(), _p("2y", &acc)),
_3y: MetricPattern4::new(client.clone(), _p("3y", &acc)),
_4y: MetricPattern4::new(client.clone(), _p("4y", &acc)),
_5y: MetricPattern4::new(client.clone(), _p("5y", &acc)),
_6y: MetricPattern4::new(client.clone(), _p("6y", &acc)),
_8y: MetricPattern4::new(client.clone(), _p("8y", &acc)),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct _0satsPattern2 {
pub activity: ActivityPattern2,
@@ -3360,32 +3386,6 @@ impl UnrealizedPattern {
}
}
/// 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<BrkClientBase>, 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 _10yPattern {
pub activity: ActivityPattern2,
@@ -3454,6 +3454,96 @@ impl<T: DeserializeOwned> SplitPattern2<T> {
}
}
/// Pattern struct for repeated tree structure.
pub struct ActiveSupplyPattern {
pub bitcoin: MetricPattern1<Bitcoin>,
pub dollars: MetricPattern1<Dollars>,
pub sats: MetricPattern1<Sats>,
}
impl ActiveSupplyPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, 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 CoinbasePattern {
pub bitcoin: BitcoinPattern,
pub dollars: DollarsPattern<Dollars>,
pub sats: DollarsPattern<Sats>,
}
impl CoinbasePattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
bitcoin: BitcoinPattern::new(client.clone(), _m(&acc, "btc")),
dollars: DollarsPattern::new(client.clone(), _m(&acc, "usd")),
sats: DollarsPattern::new(client.clone(), acc.clone()),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct CoinbasePattern2 {
pub bitcoin: BlockCountPattern<Bitcoin>,
pub dollars: BlockCountPattern<Dollars>,
pub sats: BlockCountPattern<Sats>,
}
impl CoinbasePattern2 {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, 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 SegwitAdoptionPattern {
pub base: MetricPattern11<StoredF32>,
pub cumulative: MetricPattern2<StoredF32>,
pub sum: MetricPattern2<StoredF32>,
}
impl SegwitAdoptionPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, 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 CostBasisPattern2 {
pub max: MetricPattern1<Dollars>,
pub min: MetricPattern1<Dollars>,
pub percentiles: PercentilesPattern,
}
impl CostBasisPattern2 {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
max: MetricPattern1::new(client.clone(), _m(&acc, "max_cost_basis")),
min: MetricPattern1::new(client.clone(), _m(&acc, "min_cost_basis")),
percentiles: PercentilesPattern::new(client.clone(), _m(&acc, "cost_basis")),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct UnclaimedRewardsPattern {
pub bitcoin: BitcoinPattern2<Bitcoin>,
@@ -3490,96 +3580,6 @@ impl _2015Pattern {
}
}
/// Pattern struct for repeated tree structure.
pub struct CoinbasePattern {
pub bitcoin: BitcoinPattern,
pub dollars: DollarsPattern<Dollars>,
pub sats: DollarsPattern<Sats>,
}
impl CoinbasePattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
bitcoin: BitcoinPattern::new(client.clone(), _m(&acc, "btc")),
dollars: DollarsPattern::new(client.clone(), _m(&acc, "usd")),
sats: DollarsPattern::new(client.clone(), acc.clone()),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct CostBasisPattern2 {
pub max: MetricPattern1<Dollars>,
pub min: MetricPattern1<Dollars>,
pub percentiles: PercentilesPattern,
}
impl CostBasisPattern2 {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
max: MetricPattern1::new(client.clone(), _m(&acc, "max_cost_basis")),
min: MetricPattern1::new(client.clone(), _m(&acc, "min_cost_basis")),
percentiles: PercentilesPattern::new(client.clone(), _m(&acc, "cost_basis")),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct SegwitAdoptionPattern {
pub base: MetricPattern11<StoredF32>,
pub cumulative: MetricPattern2<StoredF32>,
pub sum: MetricPattern2<StoredF32>,
}
impl SegwitAdoptionPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, 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<Bitcoin>,
pub dollars: MetricPattern1<Dollars>,
pub sats: MetricPattern1<Sats>,
}
impl ActiveSupplyPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, 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 CoinbasePattern2 {
pub bitcoin: BlockCountPattern<Bitcoin>,
pub dollars: BlockCountPattern<Dollars>,
pub sats: BlockCountPattern<Sats>,
}
impl CoinbasePattern2 {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, 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 _1dReturns1mSdPattern {
pub sd: MetricPattern4<StoredF32>,
@@ -3596,6 +3596,22 @@ impl _1dReturns1mSdPattern {
}
}
/// Pattern struct for repeated tree structure.
pub struct RelativePattern4 {
pub supply_in_loss_rel_to_own_supply: MetricPattern1<StoredF64>,
pub supply_in_profit_rel_to_own_supply: MetricPattern1<StoredF64>,
}
impl RelativePattern4 {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, 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,
@@ -3628,38 +3644,6 @@ impl CostBasisPattern {
}
}
/// Pattern struct for repeated tree structure.
pub struct RelativePattern4 {
pub supply_in_loss_rel_to_own_supply: MetricPattern1<StoredF64>,
pub supply_in_profit_rel_to_own_supply: MetricPattern1<StoredF64>,
}
impl RelativePattern4 {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, 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 SatsPattern<T> {
pub ohlc: MetricPattern1<T>,
pub split: SplitPattern2<T>,
}
impl<T: DeserializeOwned> SatsPattern<T> {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
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 BlockCountPattern<T> {
pub cumulative: MetricPattern1<T>,
@@ -3693,15 +3677,17 @@ impl<T: DeserializeOwned> BitcoinPattern2<T> {
}
/// Pattern struct for repeated tree structure.
pub struct OutputsPattern {
pub utxo_count: MetricPattern1<StoredU64>,
pub struct SatsPattern<T> {
pub ohlc: MetricPattern1<T>,
pub split: SplitPattern2<T>,
}
impl OutputsPattern {
impl<T: DeserializeOwned> SatsPattern<T> {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
utxo_count: MetricPattern1::new(client.clone(), acc.clone()),
ohlc: MetricPattern1::new(client.clone(), _m(&acc, "ohlc_sats")),
split: SplitPattern2::new(client.clone(), _m(&acc, "sats")),
}
}
}
@@ -3720,6 +3706,20 @@ impl RealizedPriceExtraPattern {
}
}
/// Pattern struct for repeated tree structure.
pub struct OutputsPattern {
pub utxo_count: MetricPattern1<StoredU64>,
}
impl OutputsPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
utxo_count: MetricPattern1::new(client.clone(), acc.clone()),
}
}
}
// Metrics tree
/// Metrics tree node.
@@ -6266,6 +6266,7 @@ impl MetricsTree_Price_Cents_Split {
/// Metrics tree node.
pub struct MetricsTree_Price_Oracle {
pub ohlc_cents: MetricPattern6<OHLCCents>,
pub ohlc_dollars: MetricPattern6<OHLCDollars>,
pub price_cents: MetricPattern11<Cents>,
pub tx_count: MetricPattern6<StoredU32>,
}
@@ -6274,6 +6275,7 @@ impl MetricsTree_Price_Oracle {
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
Self {
ohlc_cents: MetricPattern6::new(client.clone(), "oracle_ohlc_cents".to_string()),
ohlc_dollars: MetricPattern6::new(client.clone(), "oracle_ohlc_dollars".to_string()),
price_cents: MetricPattern11::new(client.clone(), "orange_price_cents".to_string()),
tx_count: MetricPattern6::new(client.clone(), "oracle_tx_count".to_string()),
}
@@ -7,5 +7,6 @@ use crate::internal::ComputedFromDateLast;
/// Price lookback metrics
#[derive(Clone, Traversable)]
pub struct Vecs {
#[traversable(flatten)]
pub price_ago: ByLookbackPeriod<ComputedFromDateLast<Dollars>>,
}
@@ -20,6 +20,9 @@ use super::{
};
use crate::{ComputeIndexes, indexes};
/// Flush interval for periodic writes during oracle computation.
const FLUSH_INTERVAL: usize = 10_000;
impl Vecs {
/// Compute oracle prices from on-chain data
pub fn compute(
@@ -275,9 +278,15 @@ impl Vecs {
self.price_cents
.truncate_push_at(height.to_usize(), price_cents)?;
// Periodic flush to avoid data loss on long computations
if height.to_usize() % FLUSH_INTERVAL == 0 {
let _lock = exit.lock();
self.price_cents.write()?;
}
}
// Write height prices
// Final write
{
let _lock = exit.lock();
self.price_cents.write()?;
+10 -2
View File
@@ -1,6 +1,6 @@
use brk_error::Result;
use brk_types::Version;
use vecdb::{BytesVec, Database, ImportableVec, PcoVec};
use brk_types::{DateIndex, OHLCCents, OHLCDollars, Version};
use vecdb::{BytesVec, Database, ImportableVec, IterableCloneableVec, LazyVecFrom1, PcoVec};
use super::Vecs;
@@ -10,9 +10,17 @@ impl Vecs {
let ohlc_cents = BytesVec::forced_import(db, "oracle_ohlc_cents", version)?;
let tx_count = PcoVec::forced_import(db, "oracle_tx_count", version)?;
let ohlc_dollars = LazyVecFrom1::init(
"oracle_ohlc",
version,
ohlc_cents.boxed_clone(),
|di: DateIndex, iter| iter.get(di).map(|o: OHLCCents| OHLCDollars::from(o)),
);
Ok(Self {
price_cents,
ohlc_cents,
ohlc_dollars,
tx_count,
})
}
+5 -2
View File
@@ -1,6 +1,6 @@
use brk_traversable::Traversable;
use brk_types::{Cents, DateIndex, Height, OHLCCents, StoredU32};
use vecdb::{BytesVec, PcoVec};
use brk_types::{Cents, DateIndex, Height, OHLCCents, OHLCDollars, StoredU32};
use vecdb::{BytesVec, LazyVecFrom1, PcoVec};
/// Vectors storing UTXOracle-derived price data
#[derive(Clone, Traversable)]
@@ -13,6 +13,9 @@ pub struct Vecs {
/// Uses BytesVec because OHLCCents is a complex type
pub ohlc_cents: BytesVec<DateIndex, OHLCCents>,
/// Daily OHLC in dollars (lazy conversion from cents)
pub ohlc_dollars: LazyVecFrom1<DateIndex, OHLCDollars, DateIndex, OHLCCents>,
/// Number of qualifying transactions per day (for confidence)
pub tx_count: PcoVec<DateIndex, StoredU32>,
}