mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-24 06:39:58 -07:00
global: fixes
This commit is contained in:
@@ -96,7 +96,7 @@ impl BRK {
|
||||
dateindex + CHUNK_SIZE
|
||||
);
|
||||
|
||||
let body: Value = sonic_rs::from_str(minreq::get(url).send()?.json()?)?;
|
||||
let body: Value = sonic_rs::from_str(minreq::get(url).send()?.as_str()?)?;
|
||||
|
||||
body.as_array()
|
||||
.ok_or(Error::Str("Expect to be an array"))?
|
||||
|
||||
@@ -228,25 +228,17 @@ impl<'a> Interface<'a> {
|
||||
}
|
||||
|
||||
pub fn distinct_metric_count(&self) -> usize {
|
||||
self.vecs.metric_count
|
||||
self.vecs.distinct_metric_count
|
||||
}
|
||||
|
||||
pub fn total_metric_count(&self) -> usize {
|
||||
self.vecs.vec_count
|
||||
self.vecs.total_metric_count
|
||||
}
|
||||
|
||||
pub fn index_count(&self) -> usize {
|
||||
self.vecs.index_count
|
||||
}
|
||||
|
||||
pub fn get_indexes(&self) -> &[&'static str] {
|
||||
pub fn get_indexes(&self) -> &BTreeMap<&'static str, &'static [&'static str]> {
|
||||
&self.vecs.indexes
|
||||
}
|
||||
|
||||
pub fn get_accepted_indexes(&self) -> &BTreeMap<&'static str, &'static [&'static str]> {
|
||||
&self.vecs.accepted_indexes
|
||||
}
|
||||
|
||||
pub fn get_metrics(&self, pagination: PaginationParam) -> &[&str] {
|
||||
self.vecs.metrics(pagination)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::fmt;
|
||||
use derive_deref::Deref;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use sonic_rs::{JsonContainerTrait, JsonValueTrait, Value};
|
||||
use serde_json::Value;
|
||||
|
||||
#[derive(Debug, Deref, JsonSchema)]
|
||||
pub struct MaybeMetrics(Vec<String>);
|
||||
@@ -46,7 +46,7 @@ impl<'de> Deserialize<'de> for MaybeMetrics {
|
||||
} else if let Some(vec) = value.as_array() {
|
||||
if vec.len() <= MAX_VECS {
|
||||
Ok(MaybeMetrics(sanitize_metrics(
|
||||
vec.into_iter().map(|s| s.as_str().unwrap().to_string()),
|
||||
vec.iter().map(|s| s.as_str().unwrap().to_string()),
|
||||
)))
|
||||
} else {
|
||||
Err(serde::de::Error::custom("Given parameter is too long"))
|
||||
|
||||
@@ -14,11 +14,9 @@ pub struct Vecs<'a> {
|
||||
pub metric_to_index_to_vec: BTreeMap<&'a str, IndexToVec<'a>>,
|
||||
pub index_to_metric_to_vec: BTreeMap<Index, MetricToVec<'a>>,
|
||||
pub metrics: Vec<&'a str>,
|
||||
pub indexes: Vec<&'static str>,
|
||||
pub accepted_indexes: BTreeMap<&'static str, &'static [&'static str]>,
|
||||
pub index_count: usize,
|
||||
pub metric_count: usize,
|
||||
pub vec_count: usize,
|
||||
pub indexes: BTreeMap<&'static str, &'static [&'static str]>,
|
||||
pub distinct_metric_count: usize,
|
||||
pub total_metric_count: usize,
|
||||
metric_to_indexes: BTreeMap<&'a str, Vec<&'static str>>,
|
||||
index_to_metrics: BTreeMap<Index, Vec<&'a str>>,
|
||||
}
|
||||
@@ -53,19 +51,13 @@ impl<'a> Vecs<'a> {
|
||||
sort_ids(&mut ids);
|
||||
|
||||
this.metrics = ids;
|
||||
this.metric_count = this.metric_to_index_to_vec.keys().count();
|
||||
this.index_count = this.index_to_metric_to_vec.keys().count();
|
||||
this.vec_count = this
|
||||
this.distinct_metric_count = this.metric_to_index_to_vec.keys().count();
|
||||
this.total_metric_count = this
|
||||
.index_to_metric_to_vec
|
||||
.values()
|
||||
.map(|tree| tree.len())
|
||||
.sum::<usize>();
|
||||
this.indexes = this
|
||||
.index_to_metric_to_vec
|
||||
.keys()
|
||||
.map(|i| i.serialize_long())
|
||||
.collect::<Vec<_>>();
|
||||
this.accepted_indexes = this
|
||||
.index_to_metric_to_vec
|
||||
.keys()
|
||||
.map(|i| (i.serialize_long(), i.possible_values()))
|
||||
|
||||
@@ -32,38 +32,27 @@ impl MCP {
|
||||
}
|
||||
|
||||
#[tool(description = "
|
||||
Get the count of all existing indexes.
|
||||
")]
|
||||
async fn get_index_count(&self) -> Result<CallToolResult, McpError> {
|
||||
info!("mcp: get_index_count");
|
||||
Ok(CallToolResult::success(vec![
|
||||
Content::json(self.interface.index_count()).unwrap(),
|
||||
]))
|
||||
}
|
||||
|
||||
#[tool(description = "
|
||||
Get the count of all existing metrics.
|
||||
Get the count of unique metrics.
|
||||
")]
|
||||
async fn get_metric_count(&self) -> Result<CallToolResult, McpError> {
|
||||
info!("mcp: get_metric_count");
|
||||
info!("mcp: distinct_metric_count");
|
||||
Ok(CallToolResult::success(vec![
|
||||
Content::json(self.interface.distinct_metric_count()).unwrap(),
|
||||
]))
|
||||
}
|
||||
|
||||
#[tool(description = "
|
||||
Get the count of all existing vecs.
|
||||
Equals to the sum of supported Indexes of each vec id.
|
||||
Get the count of all metrics. (distinct metrics multiplied by the number of indexes supported by each one)
|
||||
")]
|
||||
async fn get_vec_count(&self) -> Result<CallToolResult, McpError> {
|
||||
info!("mcp: get_vec_count");
|
||||
info!("mcp: total_metric_count");
|
||||
Ok(CallToolResult::success(vec![
|
||||
Content::json(self.interface.total_metric_count()).unwrap(),
|
||||
]))
|
||||
}
|
||||
|
||||
#[tool(description = "
|
||||
Get the list of all existing indexes.
|
||||
Get the list of all existing indexes and their accepted variants.
|
||||
")]
|
||||
async fn get_indexes(&self) -> Result<CallToolResult, McpError> {
|
||||
info!("mcp: get_indexes");
|
||||
@@ -72,16 +61,6 @@ Get the list of all existing indexes.
|
||||
]))
|
||||
}
|
||||
|
||||
#[tool(description = "
|
||||
Get an object which has all existing indexes as keys and a list of their accepted variants as values.
|
||||
")]
|
||||
async fn get_accepted_indexes(&self) -> Result<CallToolResult, McpError> {
|
||||
info!("mcp: get_accepted_indexes");
|
||||
Ok(CallToolResult::success(vec![
|
||||
Content::json(self.interface.get_accepted_indexes()).unwrap(),
|
||||
]))
|
||||
}
|
||||
|
||||
#[tool(description = "
|
||||
Get a paginated list of all existing vec ids.
|
||||
There are up to 1,000 values per page.
|
||||
|
||||
@@ -32,7 +32,7 @@ impl ApiMetricsRoutes for Router<AppState> {
|
||||
.route(
|
||||
"/api/metrics/indexes",
|
||||
get(async |State(app_state): State<AppState>| -> Response {
|
||||
Json(app_state.interface.get_accepted_indexes()).into_response()
|
||||
Json(app_state.interface.get_indexes()).into_response()
|
||||
}),
|
||||
)
|
||||
// .route(
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
- _COMPUTER_
|
||||
- BUG: **add rollback of states (in stateful)**
|
||||
- FEAT: add support for per index computation
|
||||
- FEAT: Add percentiles of cost basis weighted by amount invested compared to total invested
|
||||
- BUG: fix min fee_rate which is always ZERO due to coinbase transaction
|
||||
- BUG: before computing multiple sources check their length, panic if not equal
|
||||
- DX: create usd versions of vecs structs instead of having options everywhere
|
||||
@@ -136,9 +137,11 @@
|
||||
- FEAT: Add ?
|
||||
- NAV
|
||||
- UX: move share button to footer ?
|
||||
- FEAT: add hide sidebar button
|
||||
- BUG: when clicking on already selected option, pushes to history, bad !
|
||||
- GLOBAL
|
||||
- BUG: improve behavior when local storage is unavailable by having a global state, otherwise the website forgets/don't save user's settings
|
||||
- FEAT: Add manual theme switcher, maybe in a smart way to avoid using real estate ?
|
||||
- UI: font:
|
||||
- https://fonts.google.com/specimen/Space+Mono
|
||||
- PERF: keep as many files as possible [under 14kb](https://endtimes.dev/why-your-website-should-be-under-14kb-in-size/)
|
||||
|
||||
@@ -2551,37 +2551,85 @@ export function createPartialOptions({ colors, brk }) {
|
||||
],
|
||||
},
|
||||
]),
|
||||
{
|
||||
name: "Coins Destroyed",
|
||||
title: `Coins Destroyed ${title}`,
|
||||
bottom: list.flatMap(({ color, name, id: _id }) => {
|
||||
const id = fixId(_id);
|
||||
return /** @type {const} */ ([
|
||||
createBaseSeries({
|
||||
metric: `${id}coinblocks_destroyed`,
|
||||
name: useGroupName ? name : "sum",
|
||||
color,
|
||||
}),
|
||||
createBaseSeries({
|
||||
metric: `${id}coinblocks_destroyed_cumulative`,
|
||||
name: useGroupName ? name : "cumulative",
|
||||
color,
|
||||
defaultActive: false,
|
||||
}),
|
||||
createBaseSeries({
|
||||
metric: `${id}coindays_destroyed`,
|
||||
name: useGroupName ? name : "sum",
|
||||
color,
|
||||
}),
|
||||
createBaseSeries({
|
||||
metric: `${id}coindays_destroyed_cumulative`,
|
||||
name: useGroupName ? name : "cumulative",
|
||||
color,
|
||||
defaultActive: false,
|
||||
}),
|
||||
]);
|
||||
}),
|
||||
},
|
||||
...("list" in args
|
||||
? [
|
||||
{
|
||||
name: "Coins Destroyed",
|
||||
tree: [
|
||||
{
|
||||
name: "Sum",
|
||||
title: `Sum of Coins Destroyed ${title}`,
|
||||
bottom: list.flatMap(({ color, name, id: _id }) => {
|
||||
const id = fixId(_id);
|
||||
return /** @type {const} */ ([
|
||||
createBaseSeries({
|
||||
metric: `${id}coinblocks_destroyed`,
|
||||
name,
|
||||
color,
|
||||
}),
|
||||
createBaseSeries({
|
||||
metric: `${id}coindays_destroyed`,
|
||||
name,
|
||||
color,
|
||||
}),
|
||||
]);
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: `Cumulative Coins Destroyed ${title}`,
|
||||
bottom: list.flatMap(({ color, name, id: _id }) => {
|
||||
const id = fixId(_id);
|
||||
return /** @type {const} */ ([
|
||||
createBaseSeries({
|
||||
metric: `${id}coinblocks_destroyed_cumulative`,
|
||||
name,
|
||||
color,
|
||||
}),
|
||||
createBaseSeries({
|
||||
metric: `${id}coindays_destroyed_cumulative`,
|
||||
name,
|
||||
color,
|
||||
}),
|
||||
]);
|
||||
}),
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
: [
|
||||
{
|
||||
name: "Coins Destroyed",
|
||||
title: `Coins Destroyed ${title}`,
|
||||
bottom: list.flatMap(({ color, name, id: _id }) => {
|
||||
const id = fixId(_id);
|
||||
return /** @type {const} */ ([
|
||||
createBaseSeries({
|
||||
metric: `${id}coinblocks_destroyed`,
|
||||
name: "sum",
|
||||
color,
|
||||
}),
|
||||
createBaseSeries({
|
||||
metric: `${id}coinblocks_destroyed_cumulative`,
|
||||
name: "cumulative",
|
||||
color,
|
||||
defaultActive: false,
|
||||
}),
|
||||
createBaseSeries({
|
||||
metric: `${id}coindays_destroyed`,
|
||||
name: "sum",
|
||||
color,
|
||||
}),
|
||||
createBaseSeries({
|
||||
metric: `${id}coindays_destroyed_cumulative`,
|
||||
name: "cumulative",
|
||||
color,
|
||||
defaultActive: false,
|
||||
}),
|
||||
]);
|
||||
}),
|
||||
},
|
||||
]),
|
||||
],
|
||||
});
|
||||
}
|
||||
@@ -2713,24 +2761,22 @@ export function createPartialOptions({ colors, brk }) {
|
||||
bottom: [
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
metric: `${id}_price_returns`,
|
||||
title: "Returns",
|
||||
title: "total",
|
||||
type: "Baseline",
|
||||
}),
|
||||
createPriceLine({
|
||||
unit: "percentage",
|
||||
}),
|
||||
...(brk.hasMetric(cagr)
|
||||
? [
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
metric: cagr,
|
||||
title: "cagr",
|
||||
type: "Baseline",
|
||||
}),
|
||||
createPriceLine({
|
||||
unit: "percentage",
|
||||
colors: [colors.lime, colors.pink],
|
||||
}),
|
||||
]
|
||||
: []),
|
||||
createPriceLine({
|
||||
unit: "percentage",
|
||||
}),
|
||||
],
|
||||
};
|
||||
}),
|
||||
|
||||
@@ -234,10 +234,6 @@ export function init({
|
||||
iseries.update(last);
|
||||
break;
|
||||
}
|
||||
case "dateindex": {
|
||||
iseries.update(last);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (index === "weekindex") {
|
||||
date.setUTCDate(date.getUTCDate() - ((date.getUTCDay() + 6) % 7));
|
||||
@@ -257,7 +253,7 @@ export function init({
|
||||
0,
|
||||
1,
|
||||
);
|
||||
} else {
|
||||
} else if (index !== "dateindex") {
|
||||
throw Error("Unsupported");
|
||||
}
|
||||
|
||||
@@ -270,7 +266,7 @@ export function init({
|
||||
}
|
||||
iseries.update(last);
|
||||
} else {
|
||||
latest.time = time;
|
||||
last.time = time;
|
||||
iseries.update(last);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user