Skip to content

Commit

Permalink
chore: Update to use latest rust-ceramic
Browse files Browse the repository at this point in the history
  • Loading branch information
dbcfd committed May 12, 2024
1 parent c04bde7 commit 380c752
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 33 deletions.
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"] }
Expand Down
10 changes: 10 additions & 0 deletions src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<StreamId> =
Lazy::new(|| StreamId::from_str("kh4q0ozorrgaq2mezktnrmdwleo1d").unwrap());

/// Header for block data
#[derive(Debug, Serialize)]
Expand Down
89 changes: 57 additions & 32 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand All @@ -27,11 +25,13 @@ pub use schemars;

/// Client for interacting with the Ceramic HTTP API
#[derive(Clone, Debug)]
pub struct CeramicHttpClient<S: Signer> {
pub struct CeramicHttpClient<S> {
signer: S,
}

impl<S: Signer> CeramicHttpClient<S> {
const FAMILY: &str = "rust-client";

impl<S: Signer + Sync> CeramicHttpClient<S> {
/// Create a new client, using a signer and private key
pub fn new(signer: S) -> Self {
Self { signer }
Expand Down Expand Up @@ -86,17 +86,25 @@ impl<S: Signer> CeramicHttpClient<S> {
&self,
model: &ModelDefinition,
) -> anyhow::Result<api::CreateRequest<Base64String>> {
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,
},
Expand Down Expand Up @@ -124,7 +132,7 @@ impl<S: Signer> CeramicHttpClient<S> {
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)
}

Expand All @@ -139,27 +147,25 @@ impl<S: Signer> CeramicHttpClient<S> {
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)
}

/// Create a serde compatible request for a single instance per account creation of a model
pub async fn create_single_instance_request(
&self,
model_id: &StreamId,
) -> anyhow::Result<api::CreateRequest<DeterministicInitEvent>> {
) -> anyhow::Result<api::CreateRequest<()>> {
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,
},
Expand All @@ -180,16 +186,31 @@ impl<S: Signer> CeramicHttpClient<S> {
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,
},
Expand All @@ -213,17 +234,21 @@ impl<S: Signer> CeramicHttpClient<S> {
}
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,
},
Expand Down Expand Up @@ -285,7 +310,7 @@ impl<S: Signer> CeramicHttpClient<S> {
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)
}
}
Expand All @@ -301,13 +326,13 @@ pub mod remote {

#[derive(Clone)]
/// Ceramic remote http client
pub struct CeramicRemoteHttpClient<S: Signer> {
pub struct CeramicRemoteHttpClient<S> {
cli: CeramicHttpClient<S>,
remote: reqwest::Client,
url: Url,
}

impl<S: Signer> CeramicRemoteHttpClient<S> {
impl<S: Signer + Sync> CeramicRemoteHttpClient<S> {
/// Create a new ceramic remote http client for a signer, private key, and url
pub fn new(signer: S, remote: Url) -> Self {
Self {
Expand Down

0 comments on commit 380c752

Please sign in to comment.