mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-06-16 01:39:44 -07:00
server: api doc part 3
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
use schemars::JsonSchema;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Debug, Serialize, JsonSchema)]
|
||||
/// Metric count statistics - distinct metrics and total metric-index combinations
|
||||
pub struct MetricCount {
|
||||
#[schemars(example = 3141)]
|
||||
/// Number of unique metrics available (e.g., realized_price, market_cap)
|
||||
pub distinct_metrics: usize,
|
||||
#[schemars(example = 21000)]
|
||||
/// Total number of metric-index combinations across all timeframes
|
||||
pub total_endpoints: usize,
|
||||
}
|
||||
@@ -1,241 +0,0 @@
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
fmt::{self, Debug},
|
||||
};
|
||||
|
||||
use brk_error::Error;
|
||||
use brk_structs::{
|
||||
DateIndex, DecadeIndex, DifficultyEpoch, EmptyAddressIndex, EmptyOutputIndex, HalvingEpoch,
|
||||
Height, InputIndex, LoadedAddressIndex, MonthIndex, OpReturnIndex, OutputIndex,
|
||||
P2AAddressIndex, P2MSOutputIndex, P2PK33AddressIndex, P2PK65AddressIndex, P2PKHAddressIndex,
|
||||
P2SHAddressIndex, P2TRAddressIndex, P2WPKHAddressIndex, P2WSHAddressIndex, PrintableIndex,
|
||||
QuarterIndex, SemesterIndex, TxIndex, UnknownOutputIndex, WeekIndex, YearIndex,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Default, Serialize, JsonSchema)]
|
||||
/// Indexes and their accepted variants
|
||||
pub struct Indexes(BTreeMap<Index, &'static [&'static str]>);
|
||||
|
||||
impl Indexes {
|
||||
pub fn new(tree: BTreeMap<Index, &'static [&'static str]>) -> Self {
|
||||
Self(tree)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, JsonSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum Index {
|
||||
#[schemars(description = "Date/day index")]
|
||||
DateIndex,
|
||||
#[schemars(description = "Decade index")]
|
||||
DecadeIndex,
|
||||
#[schemars(description = "Difficulty epoch index (equivalent to ~2 weeks)")]
|
||||
DifficultyEpoch,
|
||||
#[schemars(description = "Empty output index")]
|
||||
EmptyOutputIndex,
|
||||
#[schemars(description = "Halving epoch index (equivalent to ~4 years)")]
|
||||
HalvingEpoch,
|
||||
#[schemars(description = "Height/block index")]
|
||||
Height,
|
||||
#[schemars(description = "Transaction input index (based on total)")]
|
||||
InputIndex,
|
||||
#[schemars(description = "Month index")]
|
||||
MonthIndex,
|
||||
#[schemars(description = "Op return index")]
|
||||
OpReturnIndex,
|
||||
#[schemars(description = "Transaction output index (based on total)")]
|
||||
OutputIndex,
|
||||
#[schemars(description = "Index of P2A address")]
|
||||
P2AAddressIndex,
|
||||
#[schemars(description = "Index of P2MS output")]
|
||||
P2MSOutputIndex,
|
||||
#[schemars(description = "Index of P2PK (33 bytes) address")]
|
||||
P2PK33AddressIndex,
|
||||
#[schemars(description = "Index of P2PK (65 bytes) address")]
|
||||
P2PK65AddressIndex,
|
||||
#[schemars(description = "Index of P2PKH address")]
|
||||
P2PKHAddressIndex,
|
||||
#[schemars(description = "Index of P2SH address")]
|
||||
P2SHAddressIndex,
|
||||
#[schemars(description = "Index of P2TR address")]
|
||||
P2TRAddressIndex,
|
||||
#[schemars(description = "Index of P2WPKH address")]
|
||||
P2WPKHAddressIndex,
|
||||
#[schemars(description = "Index of P2WSH address")]
|
||||
P2WSHAddressIndex,
|
||||
#[schemars(description = "Quarter index")]
|
||||
QuarterIndex,
|
||||
#[schemars(description = "Semester index")]
|
||||
SemesterIndex,
|
||||
#[schemars(description = "Transaction index")]
|
||||
TxIndex,
|
||||
#[schemars(description = "Unknown output index")]
|
||||
UnknownOutputIndex,
|
||||
#[schemars(description = "Week index")]
|
||||
WeekIndex,
|
||||
#[schemars(description = "Year index")]
|
||||
YearIndex,
|
||||
#[schemars(description = "Loaded Address Index")]
|
||||
LoadedAddressIndex,
|
||||
#[schemars(description = "Empty Address Index")]
|
||||
EmptyAddressIndex,
|
||||
}
|
||||
|
||||
impl Index {
|
||||
pub fn all() -> [Self; 27] {
|
||||
[
|
||||
Self::DateIndex,
|
||||
Self::DecadeIndex,
|
||||
Self::DifficultyEpoch,
|
||||
Self::EmptyOutputIndex,
|
||||
Self::HalvingEpoch,
|
||||
Self::Height,
|
||||
Self::InputIndex,
|
||||
Self::MonthIndex,
|
||||
Self::OpReturnIndex,
|
||||
Self::OutputIndex,
|
||||
Self::P2AAddressIndex,
|
||||
Self::P2MSOutputIndex,
|
||||
Self::P2PK33AddressIndex,
|
||||
Self::P2PK65AddressIndex,
|
||||
Self::P2PKHAddressIndex,
|
||||
Self::P2SHAddressIndex,
|
||||
Self::P2TRAddressIndex,
|
||||
Self::P2WPKHAddressIndex,
|
||||
Self::P2WSHAddressIndex,
|
||||
Self::QuarterIndex,
|
||||
Self::SemesterIndex,
|
||||
Self::TxIndex,
|
||||
Self::UnknownOutputIndex,
|
||||
Self::WeekIndex,
|
||||
Self::YearIndex,
|
||||
Self::LoadedAddressIndex,
|
||||
Self::EmptyAddressIndex,
|
||||
]
|
||||
}
|
||||
|
||||
pub fn possible_values(&self) -> &'static [&'static str] {
|
||||
match self {
|
||||
Self::DateIndex => DateIndex::to_possible_strings(),
|
||||
Self::DecadeIndex => DecadeIndex::to_possible_strings(),
|
||||
Self::DifficultyEpoch => DifficultyEpoch::to_possible_strings(),
|
||||
Self::EmptyOutputIndex => EmptyOutputIndex::to_possible_strings(),
|
||||
Self::HalvingEpoch => HalvingEpoch::to_possible_strings(),
|
||||
Self::Height => Height::to_possible_strings(),
|
||||
Self::InputIndex => InputIndex::to_possible_strings(),
|
||||
Self::MonthIndex => MonthIndex::to_possible_strings(),
|
||||
Self::OpReturnIndex => OpReturnIndex::to_possible_strings(),
|
||||
Self::OutputIndex => OutputIndex::to_possible_strings(),
|
||||
Self::P2AAddressIndex => P2AAddressIndex::to_possible_strings(),
|
||||
Self::P2MSOutputIndex => P2MSOutputIndex::to_possible_strings(),
|
||||
Self::P2PK33AddressIndex => P2PK33AddressIndex::to_possible_strings(),
|
||||
Self::P2PK65AddressIndex => P2PK65AddressIndex::to_possible_strings(),
|
||||
Self::P2PKHAddressIndex => P2PKHAddressIndex::to_possible_strings(),
|
||||
Self::P2SHAddressIndex => P2SHAddressIndex::to_possible_strings(),
|
||||
Self::P2TRAddressIndex => P2TRAddressIndex::to_possible_strings(),
|
||||
Self::P2WPKHAddressIndex => P2WPKHAddressIndex::to_possible_strings(),
|
||||
Self::P2WSHAddressIndex => P2WSHAddressIndex::to_possible_strings(),
|
||||
Self::QuarterIndex => QuarterIndex::to_possible_strings(),
|
||||
Self::SemesterIndex => SemesterIndex::to_possible_strings(),
|
||||
Self::TxIndex => TxIndex::to_possible_strings(),
|
||||
Self::UnknownOutputIndex => UnknownOutputIndex::to_possible_strings(),
|
||||
Self::WeekIndex => WeekIndex::to_possible_strings(),
|
||||
Self::YearIndex => YearIndex::to_possible_strings(),
|
||||
Self::LoadedAddressIndex => LoadedAddressIndex::to_possible_strings(),
|
||||
Self::EmptyAddressIndex => EmptyAddressIndex::to_possible_strings(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all_possible_values() -> Vec<&'static str> {
|
||||
Self::all()
|
||||
.into_iter()
|
||||
.flat_map(|i| i.possible_values().iter().cloned())
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
pub fn serialize_short(&self) -> &'static str {
|
||||
self.possible_values()
|
||||
.iter()
|
||||
.find(|str| str.len() > 1)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn serialize_long(&self) -> &'static str {
|
||||
self.possible_values().last().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for Index {
|
||||
type Error = Error;
|
||||
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||
Ok(match value.to_lowercase().as_str() {
|
||||
v if (Self::DateIndex).possible_values().contains(&v) => Self::DateIndex,
|
||||
v if (Self::DecadeIndex).possible_values().contains(&v) => Self::DecadeIndex,
|
||||
v if (Self::DifficultyEpoch).possible_values().contains(&v) => Self::DifficultyEpoch,
|
||||
v if (Self::EmptyOutputIndex).possible_values().contains(&v) => Self::EmptyOutputIndex,
|
||||
v if (Self::HalvingEpoch).possible_values().contains(&v) => Self::HalvingEpoch,
|
||||
v if (Self::Height).possible_values().contains(&v) => Self::Height,
|
||||
v if (Self::InputIndex).possible_values().contains(&v) => Self::InputIndex,
|
||||
v if (Self::MonthIndex).possible_values().contains(&v) => Self::MonthIndex,
|
||||
v if (Self::OpReturnIndex).possible_values().contains(&v) => Self::OpReturnIndex,
|
||||
v if (Self::OutputIndex).possible_values().contains(&v) => Self::OutputIndex,
|
||||
v if (Self::P2AAddressIndex).possible_values().contains(&v) => Self::P2AAddressIndex,
|
||||
v if (Self::P2MSOutputIndex).possible_values().contains(&v) => Self::P2MSOutputIndex,
|
||||
v if (Self::P2PK33AddressIndex).possible_values().contains(&v) => {
|
||||
Self::P2PK33AddressIndex
|
||||
}
|
||||
v if (Self::P2PK65AddressIndex).possible_values().contains(&v) => {
|
||||
Self::P2PK65AddressIndex
|
||||
}
|
||||
v if (Self::P2PKHAddressIndex).possible_values().contains(&v) => {
|
||||
Self::P2PKHAddressIndex
|
||||
}
|
||||
v if (Self::P2SHAddressIndex).possible_values().contains(&v) => Self::P2SHAddressIndex,
|
||||
v if (Self::P2TRAddressIndex).possible_values().contains(&v) => Self::P2TRAddressIndex,
|
||||
v if (Self::P2WPKHAddressIndex).possible_values().contains(&v) => {
|
||||
Self::P2WPKHAddressIndex
|
||||
}
|
||||
v if (Self::P2WSHAddressIndex).possible_values().contains(&v) => {
|
||||
Self::P2WSHAddressIndex
|
||||
}
|
||||
v if (Self::QuarterIndex).possible_values().contains(&v) => Self::QuarterIndex,
|
||||
v if (Self::SemesterIndex).possible_values().contains(&v) => Self::SemesterIndex,
|
||||
v if (Self::TxIndex).possible_values().contains(&v) => Self::TxIndex,
|
||||
v if (Self::WeekIndex).possible_values().contains(&v) => Self::WeekIndex,
|
||||
v if (Self::YearIndex).possible_values().contains(&v) => Self::YearIndex,
|
||||
v if (Self::UnknownOutputIndex).possible_values().contains(&v) => {
|
||||
Self::UnknownOutputIndex
|
||||
}
|
||||
v if (Self::LoadedAddressIndex).possible_values().contains(&v) => {
|
||||
Self::LoadedAddressIndex
|
||||
}
|
||||
v if (Self::EmptyAddressIndex).possible_values().contains(&v) => {
|
||||
Self::EmptyAddressIndex
|
||||
}
|
||||
_ => return Err(Error::Str("Bad index")),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Index {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{self:?}")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Index {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let str = String::deserialize(deserializer)?;
|
||||
if let Ok(index) = Index::try_from(str.as_str()) {
|
||||
// dbg!(index);
|
||||
Ok(index)
|
||||
} else {
|
||||
Err(serde::de::Error::custom("Bad index"))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ use brk_computer::Computer;
|
||||
use brk_error::{Error, Result};
|
||||
use brk_indexer::Indexer;
|
||||
use brk_parser::Parser;
|
||||
use brk_structs::Height;
|
||||
use brk_structs::{Height, Index, IndexInfo};
|
||||
use brk_traversable::TreeNode;
|
||||
use nucleo_matcher::{
|
||||
Config, Matcher,
|
||||
@@ -15,21 +15,20 @@ use nucleo_matcher::{
|
||||
use quick_cache::sync::Cache;
|
||||
use vecdb::{AnyCollectableVec, AnyStoredVec};
|
||||
|
||||
mod count;
|
||||
mod deser;
|
||||
mod format;
|
||||
mod index;
|
||||
mod metrics;
|
||||
mod output;
|
||||
mod pagination;
|
||||
mod params;
|
||||
mod vecs;
|
||||
|
||||
pub use count::*;
|
||||
pub use format::Format;
|
||||
pub use index::*;
|
||||
pub use output::{Output, Value};
|
||||
pub use pagination::{PaginatedIndexParam, PaginationParam};
|
||||
pub use pagination::{PaginatedIndexParam, PaginatedMetrics, PaginationParam};
|
||||
pub use params::{Params, ParamsDeprec, ParamsOpt};
|
||||
pub use vecs::PaginatedMetrics;
|
||||
use vecs::Vecs;
|
||||
|
||||
use crate::vecs::{IndexToVec, MetricToVec};
|
||||
@@ -229,6 +228,13 @@ impl<'a> Interface<'a> {
|
||||
&self.vecs.index_to_metric_to_vec
|
||||
}
|
||||
|
||||
pub fn metric_count(&self) -> MetricCount {
|
||||
MetricCount {
|
||||
distinct_metrics: self.distinct_metric_count(),
|
||||
total_endpoints: self.total_metric_count(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn distinct_metric_count(&self) -> usize {
|
||||
self.vecs.distinct_metric_count
|
||||
}
|
||||
@@ -237,7 +243,7 @@ impl<'a> Interface<'a> {
|
||||
self.vecs.total_metric_count
|
||||
}
|
||||
|
||||
pub fn get_indexes(&self) -> &Indexes {
|
||||
pub fn get_indexes(&self) -> &[IndexInfo] {
|
||||
&self.vecs.indexes
|
||||
}
|
||||
|
||||
@@ -253,7 +259,7 @@ impl<'a> Interface<'a> {
|
||||
self.vecs.index_to_ids(paginated_index)
|
||||
}
|
||||
|
||||
pub fn metric_to_indexes(&self, metric: String) -> Option<&Vec<&'static str>> {
|
||||
pub fn metric_to_indexes(&self, metric: String) -> Option<&Vec<Index>> {
|
||||
self.vecs.metric_to_indexes(metric)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use brk_structs::Index;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{Index, deser::de_unquote_usize};
|
||||
use crate::deser::de_unquote_usize;
|
||||
|
||||
#[derive(Debug, Default, Serialize, Deserialize, JsonSchema)]
|
||||
pub struct PaginationParam {
|
||||
@@ -28,3 +29,17 @@ pub struct PaginatedIndexParam {
|
||||
#[serde(flatten)]
|
||||
pub pagination: PaginationParam,
|
||||
}
|
||||
|
||||
/// A paginated list of available metric names (1000 per page)
|
||||
#[derive(Debug, Serialize, JsonSchema)]
|
||||
pub struct PaginatedMetrics {
|
||||
/// Current page number (0-indexed)
|
||||
#[schemars(example = 0)]
|
||||
pub current_page: usize,
|
||||
/// Maximum valid page index (0-indexed)
|
||||
#[schemars(example = 21000)]
|
||||
pub max_page: usize,
|
||||
/// List of metric names (max 1000 per page)
|
||||
#[schemars(example = ["price_open", "price_close", "realized_price", "..."])]
|
||||
pub metrics: &'static [&'static str],
|
||||
}
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
use std::ops::Deref;
|
||||
|
||||
use brk_structs::Index;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::{
|
||||
Format, Index,
|
||||
Format,
|
||||
deser::{de_unquote_i64, de_unquote_usize},
|
||||
metrics::MaybeMetrics,
|
||||
};
|
||||
|
||||
#[derive(Debug, Deserialize, JsonSchema)]
|
||||
pub struct Params {
|
||||
/// Requested metrics
|
||||
#[serde(alias = "m")]
|
||||
#[schemars(description = "Requested metrics")]
|
||||
pub metrics: MaybeMetrics,
|
||||
|
||||
/// Requested index
|
||||
#[serde(alias = "i")]
|
||||
#[schemars(description = "Requested index")]
|
||||
pub index: Index,
|
||||
|
||||
#[serde(flatten)]
|
||||
@@ -42,26 +43,20 @@ impl From<((Index, String), ParamsOpt)> for Params {
|
||||
|
||||
#[derive(Default, Debug, Deserialize, JsonSchema)]
|
||||
pub struct ParamsOpt {
|
||||
#[serde(default, alias = "f", deserialize_with = "de_unquote_i64")]
|
||||
/// Inclusive starting index, if negative will be from the end
|
||||
#[schemars(description = "Inclusive starting index, if negative will be from the end")]
|
||||
#[serde(default, alias = "f", deserialize_with = "de_unquote_i64")]
|
||||
from: Option<i64>,
|
||||
|
||||
#[serde(default, alias = "t", deserialize_with = "de_unquote_i64")]
|
||||
/// Exclusive ending index, if negative will be from the end, overrides 'count'
|
||||
#[schemars(
|
||||
description = "Exclusive ending index, if negative will be from the end, overrides 'count'"
|
||||
)]
|
||||
#[serde(default, alias = "t", deserialize_with = "de_unquote_i64")]
|
||||
to: Option<i64>,
|
||||
|
||||
#[serde(default, alias = "c", deserialize_with = "de_unquote_usize")]
|
||||
/// Number of values requested
|
||||
#[schemars(description = "Number of values requested")]
|
||||
#[serde(default, alias = "c", deserialize_with = "de_unquote_usize")]
|
||||
count: Option<usize>,
|
||||
|
||||
#[serde(default)]
|
||||
/// Format of the output
|
||||
#[schemars(description = "Format of the output")]
|
||||
#[serde(default)]
|
||||
format: Format,
|
||||
}
|
||||
|
||||
|
||||
@@ -2,29 +2,23 @@ use std::collections::BTreeMap;
|
||||
|
||||
use brk_computer::Computer;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_structs::{Index, IndexInfo};
|
||||
use brk_traversable::{Traversable, TreeNode};
|
||||
use derive_deref::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use serde::Serialize;
|
||||
use vecdb::AnyCollectableVec;
|
||||
|
||||
use crate::{
|
||||
index::Indexes,
|
||||
pagination::{PaginatedIndexParam, PaginationParam},
|
||||
};
|
||||
|
||||
use super::index::Index;
|
||||
use crate::pagination::{PaginatedIndexParam, PaginatedMetrics, PaginationParam};
|
||||
|
||||
#[derive(Default)]
|
||||
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: Indexes,
|
||||
pub indexes: Vec<IndexInfo>,
|
||||
pub distinct_metric_count: usize,
|
||||
pub total_metric_count: usize,
|
||||
pub catalog: Option<TreeNode>,
|
||||
metric_to_indexes: BTreeMap<&'a str, Vec<&'static str>>,
|
||||
metric_to_indexes: BTreeMap<&'a str, Vec<Index>>,
|
||||
index_to_metrics: BTreeMap<Index, Vec<&'a str>>,
|
||||
}
|
||||
|
||||
@@ -67,24 +61,19 @@ impl<'a> Vecs<'a> {
|
||||
.values()
|
||||
.map(|tree| tree.len())
|
||||
.sum::<usize>();
|
||||
this.indexes = Indexes::new(
|
||||
this.index_to_metric_to_vec
|
||||
.keys()
|
||||
.map(|i| (*i, i.possible_values()))
|
||||
.collect::<BTreeMap<_, _>>(),
|
||||
);
|
||||
this.indexes = this
|
||||
.index_to_metric_to_vec
|
||||
.keys()
|
||||
.map(|i| IndexInfo {
|
||||
index: *i,
|
||||
aliases: i.possible_values(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
this.metric_to_indexes = this
|
||||
.metric_to_index_to_vec
|
||||
.iter()
|
||||
.map(|(id, index_to_vec)| {
|
||||
(
|
||||
*id,
|
||||
index_to_vec
|
||||
.keys()
|
||||
.map(|i| i.serialize_long())
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
})
|
||||
.map(|(id, index_to_vec)| (*id, index_to_vec.keys().copied().collect::<Vec<_>>()))
|
||||
.collect();
|
||||
this.index_to_metrics = this
|
||||
.index_to_metric_to_vec
|
||||
@@ -142,12 +131,12 @@ impl<'a> Vecs<'a> {
|
||||
|
||||
PaginatedMetrics {
|
||||
current_page: pagination.page.unwrap_or_default(),
|
||||
total_pages: len / PaginationParam::PER_PAGE,
|
||||
max_page: len.div_ceil(PaginationParam::PER_PAGE).saturating_sub(1),
|
||||
metrics: &self.metrics[start..end],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn metric_to_indexes(&self, metric: String) -> Option<&Vec<&'static str>> {
|
||||
pub fn metric_to_indexes(&self, metric: String) -> Option<&Vec<Index>> {
|
||||
self.metric_to_indexes
|
||||
.get(metric.replace("-", "_").as_str())
|
||||
}
|
||||
@@ -171,17 +160,3 @@ pub struct IndexToVec<'a>(BTreeMap<Index, &'a dyn AnyCollectableVec>);
|
||||
|
||||
#[derive(Default, Deref, DerefMut)]
|
||||
pub struct MetricToVec<'a>(BTreeMap<&'a str, &'a dyn AnyCollectableVec>);
|
||||
|
||||
/// A paginated list of available metric names (1000 per page)
|
||||
#[derive(Debug, Serialize, JsonSchema)]
|
||||
pub struct PaginatedMetrics {
|
||||
/// Current page number (0-indexed)
|
||||
#[schemars(example = 0)]
|
||||
current_page: usize,
|
||||
/// Total number of pages available
|
||||
#[schemars(example = 21000)]
|
||||
total_pages: usize,
|
||||
/// List of metric names (max 1000 per page)
|
||||
#[schemars(example = ["price_open", "price_close", "realized_price", "..."])]
|
||||
metrics: &'static [&'static str],
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user