Holochain Development
SKILL.md
Holochain Development Skill
Patterns for developing Holochain 0.6 hApps with HDI 0.7 integrity zomes and HDK 0.6 coordinator zomes.
Environment
This project uses Nix flakes (flake.nix), not shell.nix:
nix develop # Enter dev shell
nix develop --command bun test:unit # Run unit tests in Nix
bun build:zomes # Build Rust zomes
bun build:happ # Build complete hApp
Key Reference Files
- Integrity zome:
dnas/requests_and_offers/zomes/integrity/service_types/src/lib.rs - Coordinator zome:
dnas/requests_and_offers/zomes/coordinator/requests/src/lib.rs - Coordinator CRUD:
dnas/requests_and_offers/zomes/coordinator/requests/src/request.rs - Entry types:
dnas/requests_and_offers/zomes/integrity/requests/src/request.rs - Shared utils:
dnas/requests_and_offers/zomes/coordinator/utils/ - Tryorama tests:
tests/src/requests_and_offers/
Holochain 0.6 Key Patterns
Integrity Zome (HDI 0.7)
Uses hdi::prelude::* (NOT hdk):
use hdi::prelude::*;
#[derive(Serialize, Deserialize)]
#[serde(tag = "type")]
#[hdk_entry_types]
#[unit_enum(UnitEntryTypes)]
pub enum EntryTypes {
MyEntry(MyEntry),
}
#[hdk_entry_helper]
#[derive(Clone, PartialEq)]
pub struct MyEntry {
pub name: String,
pub description: String,
}
#[derive(Serialize, Deserialize)]
#[hdk_link_types]
pub enum LinkTypes {
MyEntryUpdates,
AllMyEntries,
}
#[hdk_extern]
pub fn validate(op: Op) -> ExternResult<ValidateCallbackResult> {
match op.flattened::<EntryTypes, LinkTypes>()? {
FlatOp::StoreEntry(store_entry) => match store_entry {
OpEntry::CreateEntry { app_entry, .. } |
OpEntry::UpdateEntry { app_entry, .. } => match app_entry {
EntryTypes::MyEntry(entry) => validate_my_entry(entry),
},
_ => Ok(ValidateCallbackResult::Valid),
},
_ => Ok(ValidateCallbackResult::Valid),
}
}
Coordinator Zome (HDK 0.6)
Uses hdk::prelude::*:
use hdk::prelude::*;
use my_integrity::*;
// Create: create_entry + get + create_link to path
#[hdk_extern]
pub fn create_my_entry(input: MyEntryInput) -> ExternResult<Record> {
let hash = create_entry(&EntryTypes::MyEntry(input.entry))?;
let record = get(hash.clone(), GetOptions::default())?
.ok_or(wasm_error!(WasmErrorInner::Guest("Entry not found".into())))?;
let path = Path::from("my_entries.active");
create_link(path.path_entry_hash()?, hash, LinkTypes::AllMyEntries, ())?;
Ok(record)
}
// Read: get with GetOptions::default()
#[hdk_extern]
pub fn get_my_entry(hash: ActionHash) -> ExternResult<Option<Record>> {
get(hash, GetOptions::default())
}
// List: LinkQuery::new() with GetStrategy
#[hdk_extern]
pub fn get_all_my_entries() -> ExternResult<Vec<Record>> {
let path = Path::from("my_entries.active");
let link_filter = LinkTypes::AllMyEntries.try_into_filter()
.map_err(|e| wasm_error!(WasmErrorInner::Guest(e.to_string())))?;
let links = get_links(LinkQuery::new(path.path_entry_hash()?, link_filter)
.get_options(GetStrategy::Local))?;
let get_input: Vec<GetInput> = links.into_iter()
.filter_map(|link| link.target.into_action_hash())
.map(|hash| GetInput::new(hash.into(), GetOptions::default()))
.collect();
let records: Vec<Record> = HDK.with(|hdk| hdk.borrow().get(get_input))?
.into_iter().flatten().collect();
Ok(records)
}
// Update: update_entry + create tracking link
#[hdk_extern]
pub fn update_my_entry(input: UpdateInput) -> ExternResult<Record> {
update_entry(input.previous_hash, &input.updated_entry)?;
// ... get and return updated record
}
// Delete link: requires GetOptions::default()
delete_link(create_link_hash, GetOptions::default())?;
Signals & Post-Commit
See coordinator-zome.template.rs for Signal enum and post_commit pattern.
Project Structure
Integrity zomes (hdi) define types + validation; coordinator zomes (hdk) implement business logic.
DNA manifest at dnas/requests_and_offers/workdir/dna/dna.yaml uses path field (not bundled).
Common Tasks
- Add entry type: Create struct with
#[hdk_entry_helper]in integrity, add toEntryTypesenum - Add link type: Add variant to
LinkTypesenum in integrity, use in coordinator - Add zome function: Add
#[hdk_extern]function in coordinator, call from frontend service - Path indexing: Use
Path::from("entity.status")for collection queries - Batch get: Use
HDK.with(|hdk| hdk.borrow().get(get_input))?for efficient multi-get
Troubleshooting
- Build failures: Ensure
nix developshell is active - DHT sync in tests: Add
dhtSync()calls between agent operations - Link queries: Use
GetStrategy::Localfor reading own data,GetStrategy::Networkfor others - Permission errors: Check
agent_info()?.agent_initial_pubkeymatches expected author
Weekly Installs
0
Repository
happenings-comm…d-offersGitHub Stars
12
First Seen
Jan 1, 1970
Security Audits