From 380c752bee2ac55363834e5cd42555f83c15ae28 Mon Sep 17 00:00:00 2001 From: Danny Browning Date: Sun, 12 May 2024 06:55:29 -0600 Subject: [PATCH] chore: Update to use latest rust-ceramic --- Cargo.toml | 5 ++- src/api.rs | 10 ++++++ src/lib.rs | 89 ++++++++++++++++++++++++++++++++++-------------------- 3 files changed, 71 insertions(+), 33 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0e1579e..9d4ec36 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,8 +13,11 @@ publish = false [dependencies] anyhow = "1" -ceramic-event = { git = "https://github.com/ceramicnetwork/rust-ceramic", branch = "feat/wasi" } +ceramic-event = { git = "https://github.com/ceramicnetwork/rust-ceramic", branch = "feat/event-builder" } +#ceramic-event = { path = "/Users/dbrowning/code/3box/rust-ceramic/event" } json-patch = { version = "1.2.0", features = ["diff"] } +once_cell = "1.19.0" +rand = "0.8.5" reqwest = { version = "0.11.14", features = ["json"], optional = true } schemars = "0.8.12" serde = { version = "1.0", features = ["derive"] } diff --git a/src/api.rs b/src/api.rs index 5fb3dbf..51a9305 100644 --- a/src/api.rs +++ b/src/api.rs @@ -3,8 +3,18 @@ use ceramic_event::{ Base64String, Base64UrlString, Jws, MultiBase32String, MultiBase36String, StreamId, StreamIdType, }; +use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; use serde_json::Value; +use std::str::FromStr; + +/// Separator used for model and MID +pub const SEP: &str = "model"; + +/// All models have this model StreamId, while all documents have the model stream id of the model +/// they use +pub static PARENT_STREAM_ID: Lazy = + Lazy::new(|| StreamId::from_str("kh4q0ozorrgaq2mezktnrmdwleo1d").unwrap()); /// Header for block data #[derive(Debug, Serialize)] diff --git a/src/lib.rs b/src/lib.rs index bc32a29..7aba7d6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,14 +8,12 @@ pub mod api; mod model_definition; mod query; -use ceramic_event::{ - Base64String, Cid, DeterministicInitEvent, EventArgs, Jws, MultiBase36String, Signer, StreamId, - StreamIdType, -}; +use ceramic_event::{Base64String, Cid, event_builder::*, EventBytes, Jws, MultiBase36String, SignedEvent, Signer, StreamId, StreamIdType}; use serde::Serialize; use std::str::FromStr; +use rand::Fill; -use crate::api::ModelData; +use crate::api::{ModelData, PARENT_STREAM_ID, SEP}; pub use ceramic_event; pub use json_patch; pub use model_definition::{ @@ -27,11 +25,13 @@ pub use schemars; /// Client for interacting with the Ceramic HTTP API #[derive(Clone, Debug)] -pub struct CeramicHttpClient { +pub struct CeramicHttpClient { signer: S, } -impl CeramicHttpClient { +const FAMILY: &str = "rust-client"; + +impl CeramicHttpClient { /// Create a new client, using a signer and private key pub fn new(signer: S) -> Self { Self { signer } @@ -86,17 +86,25 @@ impl CeramicHttpClient { &self, model: &ModelDefinition, ) -> anyhow::Result> { - let args = EventArgs::new(&self.signer); - let commit = args.init_with_data(&model).await?; - let controllers: Vec<_> = args.controllers().map(|c| c.id.clone()).collect(); + let controller = self.signer.id().id.clone(); + let parent: EventBytes = PARENT_STREAM_ID.to_vec()?.into(); + let commit = Builder::default() + .with_controller(controller.clone()) + .with_sep(SEP.to_string()) + .with_additional(SEP.to_string(), parent.into()) + .init() + .with_data(&model) + .build().await?; + let commit = SignedEvent::new(commit.into(), &self.signer).await?; + let controllers: Vec<_> = vec![controller]; let data = Base64String::from(commit.linked_block.as_ref()); - let model = Base64String::from(args.parent().to_vec()?); + let model = Base64String::from(PARENT_STREAM_ID.to_vec()?); Ok(api::CreateRequest { r#type: StreamIdType::Model, block: api::BlockData { header: api::BlockHeader { - family: "test".to_string(), + family: FAMILY.to_string(), controllers, model, }, @@ -124,7 +132,7 @@ impl CeramicHttpClient { request_path: self.index_endpoint().to_string(), request_body: data, }; - let jws = Jws::for_data(&self.signer, &req).await?; + let jws = Jws::builder(&self.signer).build_for_data(&req).await?; api::AdminApiRequest::try_from(jws) } @@ -139,7 +147,7 @@ impl CeramicHttpClient { request_path: self.models_endpoint().to_string(), request_body: data, }; - let jws = Jws::for_data(&self.signer, &req).await?; + let jws = Jws::builder(&self.signer).build_for_data(&req).await?; api::AdminApiRequest::try_from(jws) } @@ -147,19 +155,17 @@ impl CeramicHttpClient { pub async fn create_single_instance_request( &self, model_id: &StreamId, - ) -> anyhow::Result> { + ) -> anyhow::Result> { if !model_id.is_model() { anyhow::bail!("StreamId was not a model"); } - let args = EventArgs::new_with_parent(&self.signer, model_id); - let _commit = args.init()?; - let controllers: Vec<_> = args.controllers().map(|c| c.id.clone()).collect(); + let controllers: Vec<_> = vec![self.signer.id().id.clone()]; let model = Base64String::from(model_id.to_vec()?); Ok(api::CreateRequest { r#type: StreamIdType::ModelInstanceDocument, block: api::BlockData { header: api::BlockHeader { - family: "test".to_string(), + family: FAMILY.to_string(), controllers, model, }, @@ -180,16 +186,31 @@ impl CeramicHttpClient { if !model_id.is_model() { anyhow::bail!("StreamId was not a model"); } - let args = EventArgs::new_with_parent(&self.signer, model_id); - let commit = args.init_with_data(&data).await?; - let controllers: Vec<_> = args.controllers().map(|c| c.id.clone()).collect(); + let model_vec = model_id.to_vec()?; + let model = Base64String::from(model_vec.as_slice()); + let model_bytes = EventBytes::from(model_vec); + let mut rng = rand::thread_rng(); + let mut unique = [0u8; 12]; + unique.try_fill(&mut rng)?; + let unique: EventBytes = unique.to_vec().into(); + let controller = self.signer.id().id.clone(); + let commit = Builder::default() + .with_controller(controller.clone()) + .with_sep(SEP.to_string()) + .with_additional(SEP.to_string(), model_bytes.into()) + .with_additional("unique".to_string(), unique.into()) + .init() + .with_data(data) + .build().await?; + let commit = SignedEvent::new(commit.into(), &self.signer).await?; + let controllers: Vec<_> = vec![controller]; let data = Base64String::from(commit.linked_block.as_ref()); - let model = Base64String::from(model_id.to_vec()?); + Ok(api::CreateRequest { r#type: StreamIdType::ModelInstanceDocument, block: api::BlockData { header: api::BlockHeader { - family: "test".to_string(), + family: FAMILY.to_string(), controllers, model, }, @@ -213,17 +234,21 @@ impl CeramicHttpClient { } if let Some(tip) = get.state.as_ref().and_then(|s| s.log.last()) { let tip = Cid::from_str(tip.cid.as_ref())?; - let args = EventArgs::new_with_parent(&self.signer, model); - let commit = args.update(&get.stream_id.cid, &tip, &patch).await?; - let controllers: Vec<_> = args.controllers().map(|c| c.id.clone()).collect(); + let controller = self.signer.id().id.clone(); + let model_vec = model.to_vec()?; + let model = Base64String::from(model_vec.as_slice()); + let commit = Builder::default() + .data(get.stream_id.cid, tip, patch) + .build().await?; + let commit = SignedEvent::new(commit.into(), &self.signer).await?; + let controllers: Vec<_> = vec![controller]; let data = Base64String::from(commit.linked_block.as_ref()); - let model = Base64String::from(model.to_vec()?); let stream = MultiBase36String::try_from(&get.stream_id)?; Ok(api::UpdateRequest { r#type: StreamIdType::ModelInstanceDocument, block: api::BlockData { header: api::BlockHeader { - family: "test".to_string(), + family: FAMILY.to_string(), controllers, model, }, @@ -285,7 +310,7 @@ impl CeramicHttpClient { request_path: self.node_status_endpoint().to_string(), request_body: data, }; - let jws = Jws::for_data(&self.signer, &req).await?; + let jws = Jws::builder(&self.signer).build_for_data(&req).await?; api::AdminApiRequest::try_from(jws) } } @@ -301,13 +326,13 @@ pub mod remote { #[derive(Clone)] /// Ceramic remote http client - pub struct CeramicRemoteHttpClient { + pub struct CeramicRemoteHttpClient { cli: CeramicHttpClient, remote: reqwest::Client, url: Url, } - impl CeramicRemoteHttpClient { + impl CeramicRemoteHttpClient { /// Create a new ceramic remote http client for a signer, private key, and url pub fn new(signer: S, remote: Url) -> Self { Self {