Rust分布式应用开发库holochain_zome_types的使用,构建去中心化应用的数据类型与Zome功能支持

holochain_zome_types

Project Forum Chat License

这个crate提供了Holochain应用开发者在zome代码中所需的基本类型,除此之外没有其他内容。

这个crate特意保持最小化,因为它通常作为依赖项包含在Holochain Zomes中,而Zomes是作为Wasm块进行分发的。相比之下,holochain_types crate包含了更多由Holochain本身使用的类型。

贡献

Holochain是一个开源项目。我们欢迎各种形式的参与,并正在积极扩大接受参与的范围。请参阅我们的贡献指南,了解我们在社区参与方面的一般实践和协议,以及关于代码格式化、测试实践、持续集成等方面的具体期望。

许可证

License

版权所有 © 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中的关键类型来构建一个简单的博客应用,包括:

  1. 定义自定义数据类型(Post)
  2. 创建Zome函数来处理数据
  3. 使用Entry、Header、Element等核心类型
  4. 创建和查询链接关系
  5. 处理时间戳和签名

每个函数都展示了如何使用holochain_zome_types中的不同类型来实现去中心化应用的基本功能。


1 回复

holochain_zome_types:Rust分布式应用开发的核心数据类型库

概述

holochain_zome_types 是 Holochain 生态系统的核心库之一,为开发去中心化应用(DApp)提供了基础数据类型和 Zome 功能支持。它定义了在 Holochain 应用中使用的各种数据结构、序列化格式和功能接口。

主要功能

  1. 基础数据类型:定义 Holochain 应用中使用的核心数据结构
  2. Zome 功能支持:提供开发 Zome(Holochain 的智能合约模块)所需的类型和工具
  3. 序列化/反序列化:支持 Holochain 数据的跨网络传输
  4. 错误处理:标准化的错误类型和结果处理

安装

在 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 分布式应用所需的核心数据类型和功能接口。通过合理使用这些类型和功能,开发者可以构建复杂的去中心化应用逻辑,同时确保类型安全和数据一致性。

在实际开发中,建议结合 holochainhdk 等相关库一起使用,以获取完整的 Holochain 开发体验。

回到顶部