Rust分布式应用开发库holochain_zome_types的使用,构建去中心化应用的数据类型与Zome功能支持
holochain_zome_types
这个crate提供了Holochain应用开发者在zome代码中所需的基本类型,除此之外没有其他内容。
这个crate特意保持最小化,因为它通常作为依赖项包含在Holochain Zomes中,而Zomes是作为Wasm块进行分发的。相比之下,holochain_types crate包含了更多由Holochain本身使用的类型。
贡献
Holochain是一个开源项目。我们欢迎各种形式的参与,并正在积极扩大接受参与的范围。请参阅我们的贡献指南,了解我们在社区参与方面的一般实践和协议,以及关于代码格式化、测试实践、持续集成等方面的具体期望。
许可证
版权所有 © 2019 - 2024, Holochain Foundation
安装
在项目目录中运行以下Cargo命令:
cargo add holochain_zome_types
或者在Cargo.toml中添加:
holochain_zome_types = "0.5.4"
完整示例代码
以下是一个使用holochain_zome_types构建去中心化应用数据类型和Zome功能支持的完整示例:
use holochain_zome_types::{
entry::Entry,
zome::ZomeName,
link::Link,
timestamp::Timestamp,
header::Header,
element::Element,
signature::Signature,
};
// 定义一个自定义数据类型
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Post {
pub content: String,
pub author: String,
pub timestamp: Timestamp,
}
// 创建Zome函数
#[hdk_extern]
pub fn create_post(content: String) -> ExternResult<HeaderHash> {
let author = agent_info()?.agent_latest_pubkey;
let post = Post {
content,
author,
timestamp: sys_time()?,
};
// 创建条目
let entry = Entry::App(post.try_into()?);
// 创建头信息
let header = Header::Create(
Create {
entry_type: EntryType::App(AppEntryType::new(
"post".into(),
ZomeName::from("blog"),
1.into(),
)),
entry_hash: hash_entry(&entry)?,
author: author,
timestamp: post.timestamp,
}
);
// 创建元素并提交到DHT
let element = Element::new(header.clone(), Some(entry));
create_element(element)?;
Ok(hash_header(&header)?)
}
// 查询帖子
#[hdk_extern]
pub fn get_post(post_hash: HeaderHash) -> ExternResult<Option<Post>> {
let element = get(post_hash, GetOptions::content())?;
match element {
Some(el) => {
let post: Post = el.entry().to_app_option()?.ok_or(WasmError::Guest("No post found".into()))?;
Ok(Some(post))
},
None => Ok(None),
}
}
// 创建链接
#[hdk_extern]
pub fn link_author_to_post(author: AgentPubKey, post_hash: HeaderHash) -> ExternResult<HeaderHash> {
let link = Link {
base: author,
target: post_hash,
tag: LinkTag::new("authored_post"),
};
create_link(link)
}
// 获取作者的所有帖子
#[hdk_extern]
pub fn get_posts_by_author(author: AgentPubKey) -> ExternResult<Vec<Post>> {
let links = get_links(author, Some(LinkTag::new("authored_post")))?;
let mut posts = Vec::new();
for link in links {
if let Some(post) = get_post(link.target)? {
posts.push(post);
}
}
Ok(posts)
}
这个示例展示了如何使用holochain_zome_types中的关键类型来构建一个简单的博客应用,包括:
- 定义自定义数据类型(Post)
- 创建Zome函数来处理数据
- 使用Entry、Header、Element等核心类型
- 创建和查询链接关系
- 处理时间戳和签名
每个函数都展示了如何使用holochain_zome_types中的不同类型来实现去中心化应用的基本功能。
holochain_zome_types:Rust分布式应用开发的核心数据类型库
概述
holochain_zome_types
是 Holochain 生态系统的核心库之一,为开发去中心化应用(DApp)提供了基础数据类型和 Zome 功能支持。它定义了在 Holochain 应用中使用的各种数据结构、序列化格式和功能接口。
主要功能
- 基础数据类型:定义 Holochain 应用中使用的核心数据结构
- Zome 功能支持:提供开发 Zome(Holochain 的智能合约模块)所需的类型和工具
- 序列化/反序列化:支持 Holochain 数据的跨网络传输
- 错误处理:标准化的错误类型和结果处理
安装
在 Cargo.toml 中添加依赖:
[dependencies]
holochain_zome_types = "0.2.0"
核心数据类型示例
1. Entry 类型
use holochain_zome_types::entry::Entry;
// 创建简单的应用Entry
let entry = Entry::App("example data".into());
2. Header 类型
use holochain_zome_types::header::Header;
// 创建Create header
let header = Header::Create {
author: AgentPubKey::from_raw_32(vec![0; 32]),
timestamp: Timestamp::now(),
header_seq: 0,
prev_header: HeaderHash::from_raw_36(vec![0; 36]),
entry_type: EntryType::App(AppEntryType::new(
0.into(),
"example_entry".into(),
EntryVisibility::Public,
)),
entry_hash: EntryHash::from_raw_36(vec![0; 36]),
};
3. Zome 调用
use holochain_zome_types::zome::ZomeCall;
// 构建Zome调用
let zome_call = ZomeCall {
cell_id: CellId::new(
DnaHash::from_raw_36(vec![0; 36]),
AgentPubKey::from_raw_32(vec![0; 32]),
),
zome_name: "example_zome".into(),
fn_name: "create_example".into(),
payload: ExternIO::encode("example payload").unwrap(),
cap_secret: None,
provenance: AgentPubKey::from_raw_32(vec![0; 32]),
};
Zome 功能开发示例
1. 定义 Entry 类型
use holochain_zome_types::prelude::*;
#[derive(Serialize, Deserialize, Debug, SerializedBytes)]
struct MyEntry {
content: String,
timestamp: u64,
}
// 注册Entry类型
#[hdk_entry_defs]
#[unit_enum(UnitEntryTypes)]
pub enum EntryTypes {
#[entry_def(required_validations = 5, visibility = "public")]
MyEntry(MyEntry),
}
2. 定义 Zome 函数
use holochain_zome_types::prelude::*;
#[hdk_extern]
pub fn create_entry(input: MyEntry) -> ExternResult<HeaderHash> {
let entry = EntryTypes::MyEntry(input);
create_entry(entry)
}
#[hdk_extern]
pub fn get_entry(header_hash: HeaderHash) -> ExternResult<Option<MyEntry>> {
let element = get(header_hash, GetOptions::default())?;
match element {
Some(element) => {
let entry = element.entry().to_app_option()?;
Ok(entry)
}
None => Ok(None),
}
}
高级用法
1. 链接操作
use holochain_zome_types::link::Link;
#[hdk_extern]
pub fn create_link(
base: EntryHash,
target: EntryHash,
tag: LinkTag,
) -> ExternResult<HeaderHash> {
create_link(base, target, tag)
}
#[hdk_extern]
pub fn get_links(
base: EntryHash,
tag: Option<LinkTag>,
) -> ExternResult<Vec<Link>> {
let links = get_links(base, tag)?;
Ok(links)
}
2. 信号发送
use holochain_zome_types::signal::Signal;
#[hdk_extern]
pub fn send_signal(message: String) -> ExternResult<()> {
let signal = Signal::App(message.into());
emit_signal(&signal)?;
Ok(())
}
错误处理
use holochain_zome_types::prelude::*;
#[hdk_extern]
pub fn fallible_operation(input: String) -> ExternResult<String> {
if input.is_empty() {
Err(WasmError::Guest("Input cannot be empty".into()))
} else {
Ok(format!("Processed: {}", input))
}
}
完整示例 Demo
以下是一个完整的 Holochain Zome 开发示例,包含了 Entry 定义、Zome 函数、链接操作和信号发送:
use holochain_zome_types::prelude::*;
// 1. 定义自定义 Entry 类型
#[derive(Serialize, Deserialize, Debug, SerializedBytes, Clone)]
pub struct BlogPost {
pub title: String,
pub content: String,
pub author: AgentPubKey,
pub timestamp: Timestamp,
}
// 2. 注册 Entry 类型
#[hdk_entry_defs]
#[unit_enum(UnitEntryTypes)]
pub enum EntryTypes {
#[entry_def(required_validations = 5, visibility = "public")]
BlogPost(BlogPost),
}
// 3. 定义 Zome 函数
#[hdk_extern]
pub fn create_blog_post(input: BlogPost) -> ExternResult<HeaderHash> {
// 创建博客文章 Entry
let entry = EntryTypes::BlogPost(input.clone());
let header_hash = create_entry(entry)?;
// 创建作者到文章的链接
let author = input.author;
let post_hash = hash_entry(EntryTypes::BlogPost(input))?;
create_link(author, post_hash, LinkTag::new("authored"))?;
// 发送新文章通知信号
let signal = Signal::App(format!("New post: {}", input.title).into());
emit_signal(&signal)?;
Ok(header_hash)
}
#[hdk_extern]
pub fn get_blog_post(header_hash: HeaderHash) -> ExternResult<Option<BlogPost>> {
match get(header_hash, GetOptions::default())? {
Some(element) => element.entry().to_app_option(),
None => Ok(None),
}
}
#[hdk_extern]
pub fn get_posts_by_author(author: AgentPubKey) -> ExternResult<Vec<BlogPost>> {
// 获取作者的所有文章链接
let links = get_links(author, Some(LinkTag::new("authored")))?;
// 获取所有链接的文章内容
let mut posts = Vec::new();
for link in links {
if let Some(element) = get(link.target, GetOptions::default())? {
if let Some(post) = element.entry().to_app_option()? {
posts.push(post);
}
}
}
Ok(posts)
}
// 4. 错误处理示例
#[hdk_extern]
pub fn validate_blog_post(validation_data: ValidateData) -> ExternResult<ValidateCallbackResult> {
let element = validation_data.element;
let post: BlogPost = match element.entry().to_app_option()? {
Some(post) => post,
None => return Ok(ValidateCallbackResult::Invalid("Invalid entry type".to_string())),
};
if post.title.is_empty() {
return Ok(ValidateCallbackResult::Invalid("Title cannot be empty".to_string()));
}
if post.content.is_empty() {
return Ok(ValidateCallbackResult::Invalid("Content cannot be empty".to_string()));
}
Ok(ValidateCallbackResult::Valid)
}
总结
holochain_zome_types
提供了开发 Holochain 分布式应用所需的核心数据类型和功能接口。通过合理使用这些类型和功能,开发者可以构建复杂的去中心化应用逻辑,同时确保类型安全和数据一致性。
在实际开发中,建议结合 holochain
和 hdk
等相关库一起使用,以获取完整的 Holochain 开发体验。