From 351da4db5a62433a726766a2f8b060e7a7ca7a03 Mon Sep 17 00:00:00 2001 From: Himanshu Goyal Date: Tue, 12 Mar 2024 13:09:08 -0400 Subject: [PATCH] define api --- src/events.rs | 123 +++++++++++++++++++++++++++++++++++++++++++ src/events_info.rs | 15 +----- src/events_source.rs | 1 + 3 files changed, 125 insertions(+), 14 deletions(-) create mode 100644 src/events.rs diff --git a/src/events.rs b/src/events.rs new file mode 100644 index 0000000..1e851f6 --- /dev/null +++ b/src/events.rs @@ -0,0 +1,123 @@ +use std::{fmt::Display, path::PathBuf}; + +use clap::Args; +use derive_more::From; +use futures::FutureExt; +use hotshot_types::{ + traits::{node_implementation::NodeType, signature_key::SignatureKey}, + utils::BuilderCommitment, +}; +use serde::{Deserialize, Serialize}; +use snafu::{ResultExt, Snafu}; +use tagged_base64::TaggedBase64; +use tide_disco::{ + api::ApiError, + method::{ReadState, WriteState}, + Api, RequestError, StatusCode, +}; + +use crate::{ + api::load_api, + events_source::{EventsSource}, +}; + +#[derive(Args, Default)] +pub struct Options { + #[arg(long = "hotshot-events-service-api-path", env = "HOTSHOT_EVENTS_SERVICE_API_PATH")] + pub api_path: Option, + + /// Additional API specification files to merge with `hotshot-events-service-api-path`. + /// + /// These optional files may contain route definitions for application-specific routes that have + /// been added as extensions to the basic hotshot-events-service API. + #[arg( + long = "hotshot-events-extension", + env = "HOTSHOT_EVENTS_SERVICE_EXTENSIONS", + value_delimiter = ',' + )] + pub extensions: Vec, +} + +#[derive(Clone, Debug, Snafu, Deserialize, Serialize)] +#[snafu(visibility(pub))] +pub enum EventError { + /// The requested resource does not exist or is not known to this hotshot node. + NotFound, + /// The requested resource exists but is not currently available. + Missing, + /// There was an error while trying to fetch the requested resource. + #[snafu(display("Failed to fetch requested resource: {message}"))] + Error { message: String }, +} + + +#[derive(Clone, Debug, From, Snafu, Deserialize, Serialize)] +#[snafu(visibility(pub))] +pub enum Error { + Request { + source: RequestError, + }, + #[snafu(display("error receiving events {resource}: {source}"))] + #[from(ignore)] + EventAvailable { + source: EventError, + resource: String, + }, + Custom { + message: String, + status: StatusCode, + }, +} + +impl tide_disco::error::Error for Error { + fn catch_all(status: StatusCode, msg: String) -> Self { + Error::Custom { + message: msg, + status, + } + } + + fn status(&self) -> StatusCode { + match self { + Error::Request { .. } => StatusCode::BadRequest, + Error::EventAvailable { source, .. } => match source + { + EventError::NotFound => StatusCode::NotFound, + EventError::Missing => StatusCode::NotFound, + EventError::Error { .. } => StatusCode::InternalServerError, + }, + } + } +} + +pub fn define_api(options: &Options) -> Result, ApiError> +where + State: 'static + Send + Sync + ReadState, + ::State: Send + Sync + BuilderDataSource, + Types: NodeType, + <::SignatureKey as SignatureKey>::PureAssembledSignatureType: + for<'a> TryFrom<&'a TaggedBase64> + Into + Display, + for<'a> <<::SignatureKey as SignatureKey>::PureAssembledSignatureType as TryFrom< + &'a TaggedBase64, + >>::Error: Display, +{ + let mut api = load_api::( + options.api_path.as_ref(), + include_str!("../api/hotshot_events.toml"), + options.extensions.clone(), + )?; + api.with_version("0.0.1".parse().unwrap()) + .get("available_hotshot_events", |req, state| { + async move { + let view_number = req.blob_param("view_number")?; + state + .get_available_hotshot_events(&view_number) + .await + .context(AvailableEventSnafu { + resource: view_number.to_string(), + }) + } + .boxed() + })?; + Ok(api) +} \ No newline at end of file diff --git a/src/events_info.rs b/src/events_info.rs index dd6254b..4506e08 100644 --- a/src/events_info.rs +++ b/src/events_info.rs @@ -3,7 +3,6 @@ use std::{hash::Hash, marker::PhantomData}; use hotshot_types::event::Event; use serde::{Deserialize, Serialize}; use snafu::{ResultExt, Snafu}; - #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, Hash)] #[serde(bound = "")] pub struct EventInfo { @@ -11,16 +10,4 @@ pub struct EventInfo { pub signature: <::SignatureKey as SignatureKey>::PureAssembledSignatureType, pub sender: ::SignatureKey, pub _phantom: PhantomData, -} - -#[derive(Clone, Debug, Snafu, Deserialize, Serialize)] -#[snafu(visibility(pub))] -pub enum EventError { - /// The requested resource does not exist or is not known to this hotshot node. - NotFound, - /// The requested resource exists but is not currently available. - Missing, - /// There was an error while trying to fetch the requested resource. - #[snafu(display("Failed to fetch requested resource: {message}"))] - Error { message: String }, -} +} \ No newline at end of file diff --git a/src/events_source.rs b/src/events_source.rs index 6819641..0142d84 100644 --- a/src/events_source.rs +++ b/src/events_source.rs @@ -14,5 +14,6 @@ where { async fn get_available_hotshot_events( &self, + view_number: I::Time, ) -> Result>, EventError>; } \ No newline at end of file