hotshot_query_service/
merklized_state.rs1use std::{fmt::Display, path::PathBuf};
19
20use futures::FutureExt;
21use hotshot_types::traits::node_implementation::NodeType;
22use snafu::ResultExt;
23use tagged_base64::TaggedBase64;
24use tide_disco::{Api, StatusCode, api::ApiError, method::ReadState};
25use vbs::version::StaticVersionType;
26
27use crate::api::load_api;
28
29pub(crate) mod data_source;
30pub use data_source::*;
31pub use hotshot_query_service_types::merklized_state::*;
32
33#[derive(Default)]
34pub struct Options {
35 pub api_path: Option<PathBuf>,
36
37 pub extensions: Vec<toml::Value>,
42}
43
44pub fn define_api<
45 State,
46 Types: NodeType,
47 M: MerklizedState<Types, ARITY>,
48 Ver: StaticVersionType + 'static,
49 const ARITY: usize,
50>(
51 options: &Options,
52 api_ver: semver::Version,
53) -> Result<Api<State, Error, Ver>, ApiError>
54where
55 State: 'static + Send + Sync + ReadState,
56 <State as ReadState>::State:
57 MerklizedStateDataSource<Types, M, ARITY> + MerklizedStateHeightPersistence + Send + Sync,
58 for<'a> <M::Commit as TryFrom<&'a TaggedBase64>>::Error: Display,
59{
60 let mut api = load_api::<State, Error, Ver>(
61 options.api_path.as_ref(),
62 include_str!("../api/state.toml"),
63 options.extensions.clone(),
64 )?;
65
66 api.with_version(api_ver)
67 .get("get_path", move |req, state| {
68 async move {
69 let snapshot = if let Some(height) = req.opt_integer_param("height")? {
71 Snapshot::Index(height)
72 } else {
73 Snapshot::Commit(req.blob_param("commit")?)
74 };
75
76 let key = req.string_param("key")?;
77 let key = key.parse::<M::Key>().map_err(|_| Error::Custom {
78 message: "failed to parse Key param".to_string(),
79 status: StatusCode::INTERNAL_SERVER_ERROR,
80 })?;
81
82 state.get_path(snapshot, key).await.context(QuerySnafu)
83 }
84 .boxed()
85 })?
86 .get("get_height", move |_, state| {
87 async move { state.get_last_state_height().await.context(QuerySnafu) }.boxed()
88 })?;
89
90 Ok(api)
91}