// Integrity
use hdi::prelude::*;
#[hdk_entry_helper]
struct Comment {
comment: String
}
#[hdk_entry_helper]
// We only need a string
struct Anchor(String);
#[hdk_entry_defs]
#[unit_enum(UnitEntryTypes)]
enum EntryTypes {
Comment(Comment),
Anchor(Anchor),
}
#[hdk_link_types]
enum LinkTypes {
AnchorToComment,
}
// Coordinator
use hdk::prelude::*;
#[hdk_extern]
fn create_comment(comment: Comment) -> ExternResult<ActionHash> {
let comment_action_hash = create_entry(EntryTypes::Comment(comment))?;
let anchor = Anchor(String::from("all_comments"));
let _action_hash = create_entry(EntryTypes::Anchor(anchor))?; // This hash is not
// deterministic: it will be
// different every time this
// function is executed
let anchor_entry_hash = hash_entry(anchor)?; // This hash is deterministic: it will be the
// same independently of which cells executes
// this function
create_link(anchor_entry_hash, comment_action_hash, LinkTypes::AnchorToComment, ())?;
Ok(comment_action_hash)
}
#[hdk_extern]
fn get_all_comments_hashes(_: ()) -> ExternResult<Vec<ActionHash>> {
let anchor = Anchor(String::from("all_comments")); // Must use the same string as
// the create function
let anchor_hash = hash_entry(anchor)?;
let links = get_links(anchor_hash, LinkTypes::AnchorToComment, None)?; // Get all the links
// created above
let action_hashes: Vec<ActionHash> = links.into_iter()
.map(|link| ActionHash::from(link.target))
.collect(); // Extract the action hash from the links
Ok(action_hashes)
}
use hdk::prelude::*;
use integrity_zome::*; // Import the types defined in our integrity zome
use chrono::*; // Import the chrono crate for time related utilites
#[hdk_extern]
fn create_comment(comment: Comment) -> ExternResult<ActionHash> {
let comment_action_hash = create_entry(EntryTypes::Comment(comment))?;
let (secs, nsecs) = sys_time()?.as_seconds_and_nanos(); // Get the current timestamp
// in microseconds
let dt: DateTime<Utc> = DateTime::from_utc(NaiveDateTime::from_timestamp(secs, nsecs), Utc);
let path = Path::from(
format!("all_comments.{}.{}", dt.year(), dt.month()) // The '.' is the separator
// between components
); // Builds the path "all_comments.2022.7"
let typed_path = path.typed(LinkTypes::PathTimeIndex)?; // "TypedPath" is a path with all the
// links of a certain †ype
typed_path.ensure()?; // Creates the path tree structure, and all the necessary links
create_link(
typed_path.path_entry_hash()?, // Entry hash of the path
comment_action_hash,
LinkTypes::PathToComment,
()
)?;
Ok(comment_action_hash)
}
#[hdk_extern]
fn get_comments_by_year(year: u32) -> ExternResult<Vec<ActionHash>> {
let year_path = Path::from(
format!("all_comments.{}", year) // Build the anchor in the intermediate node
).typed(LinkTypes::PathTimeIndex);
let month_paths: Vec<Path> = year_path.children_paths()?; // Retrieves all the children
// node month paths
let mut all_links: Vec<Link> = vec![];
for path in month_paths {
let last_component: Component = path.leaf() // Returns an "Option<Component>" with
// the last component of this path
.ok_or(wasm_error!(WasmErrorInner::Guest(String::from("The path is empty"))))?.clone();
let month = String::try_from(last_component) // Converts the component's byte array
// to a string
.map_err(|err| wasm_error!(err))?;
let mut links = get_links(
path.path_entry_hash()?, LinkTypes::PathToComment, None
)?; // Get all the links created above
all_links.append(&mut links); // Collect the links
}
let all_links: Vec<ActionHash> = links.into_iter()
.map(|link| ActionHash::from(link.target))
.collect(); // Extract the action hash from the links
Ok(action_hashes)
}