Solana[part7]_社交项目2-客户端文档

Solana[part7]_社交项目2—客户端文档

社交项目地址链接

🔗 合约地址:https://github.com/SoniaChan33/sol-friend

🔗 客户端地址: https://github.com/SoniaChan33/solana-friend-cli

一、概述

本文档介绍基于Solana区块链的社交应用客户端代码的核心功能、数据结构及使用方法。该客户端通过RPC与Solana网络交互,实现用户资料管理、关注/取消关注、内容发布与查询等社交功能,依赖链上程序处理核心业务逻辑。

二、依赖说明

客户端代码依赖以下Rust crate:

  • solana-client:提供Solana RPC客户端功能,用于与节点交互
  • solana-sdk:Solana核心SDK,包含账户、交易、签名等基础类型
  • borsh:用于链上数据的序列化/反序列化(Solana生态常用)
  • std::str::FromStr:用于Pubkey字符串解析

三、核心数据结构

1. 账户数据结构

用于在链上存储用户相关数据,需实现BorshDeserializeBorshSerialize以支持链上传输。

UserProfile

  • 功能:存储用户的关注者列表信息
  • 字段:
    • data_len: u16:关注者数量(与followers长度一致)
    • followers: Vec<Pubkey>:关注当前用户的用户公钥列表
  • 方法:
    • new():创建空的用户资料实例
    • follow(&mut self, user: Pubkey):添加新关注者(去重处理)

UserPost

  • 功能:记录用户的发帖数量
  • 字段:
    • post_count: u16:用户发布的内容总数

Post

  • 功能:存储单条帖子内容
  • 字段:
    • content: String:帖子文本内容
    • timestamp: u64:发帖时间戳(通常为区块时间)

2. 客户端核心结构

SocialClient

  • 功能:封装与Solana链上社交程序交互的所有方法
  • 字段:
    • rpc_client: RpcClient:Solana RPC客户端实例
    • program_id: Pubkey:链上社交程序的公钥
  • 构造方法:
    pub fn new(rpc_url: &str, program_id: Pubkey) -> Self
    • 参数:rpc_url(Solana节点RPC地址)、program_id(链上程序公钥)
    • 返回:SocialClient实例

3. 指令枚举 SocialInstruction

定义客户端向链上程序发送的指令类型,需实现BorshDeserializeBorshSerialize

  • InitializeUser { seed_type: String }:初始化用户账户(资料/帖子账户)
  • FollowUser { user_to_follow: Pubkey }:关注指定用户
  • UnfollowUser { user_to_unfollow: Pubkey }:取消关注指定用户
  • QueryFollowers:查询当前用户的关注者列表
  • PostContent { content: String }:发布新内容
  • QueryPosts:查询指定帖子内容

四、核心功能说明

1. PDA生成(get_pda函数)

  • 功能:基于程序ID和种子(seed)生成Program Derived Address(PDA),用于唯一标识链上账户
  • 参数:program_id(程序公钥)、seed(种子数组,用于区分不同账户)
  • 种子作用:通过不同种子生成唯一PDA,避免账户地址冲突(例如:USER_PROFILE_SEED用于用户资料账户,USER_POST_SEED用于帖子相关账户)
  • 代码:
    fn get_pda(program_id: &Pubkey, seed: &[&[u8]]) -> Pubkey {
        let (pda, _bump) = Pubkey::find_program_address(seed, &program_id);
        pda
    }

2. 账户初始化(initialize_user

  • 功能:创建用户的PDA账户(支持资料账户或帖子账户,通过seed_type区分)
  • 参数:
    • user_keypair: &Keypair:用户签名密钥对(交易 payer)
    • seed_type: &str:种子类型(USER_PROFILE_SEEDUSER_POST_SEED
  • 流程:
    1. 基于用户公钥和seed_type生成PDA
    2. 构建InitializeUser指令,包含用户账户、PDA账户和系统程序(用于创建账户)
    3. 发送交易并确认
  • 返回:Result<(), Box<dyn Error>>(成功/错误信息)

3. 关注/取消关注

follow_user

  • 功能:让当前用户关注指定用户
  • 参数:
    • user_keypair: &Keypair:当前用户密钥对
    • follow_user: Pubkey:被关注用户的公钥
  • 流程:生成用户资料PDA,发送FollowUser指令更新关注者列表

unfollow_user

  • 功能:让当前用户取消关注指定用户
  • 参数:
    • user_keypair: &Keypair:当前用户密钥对
    • unfollow_user: Pubkey:被取消关注用户的公钥
  • 流程:生成用户资料PDA,发送UnfollowUser指令从关注者列表移除

4. 关注者查询(query_followers

  • 功能:查询当前用户的关注者列表
  • 参数:user_keypair: &Keypair(当前用户密钥对)
  • 流程:生成用户资料PDA,发送QueryFollowers指令,由链上程序返回关注者数据

5. 内容发布与查询

post_content

  • 功能:发布新帖子
  • 参数:
    • user_keypair: &Keypair:发布者密钥对
    • content: String:帖子内容
    • id: u64:帖子唯一ID(用于生成帖子PDA)
  • 流程:
    1. 生成用户帖子主PDA(记录发帖数量)和当前帖子PDA(存储内容)
    2. 发送PostContent指令,包含内容和时间戳
    3. 链上程序更新UserPostpost_count并存储Post数据

query_posts

  • 功能:查询指定ID的帖子内容
  • 参数:
    • user_keypair: &Keypair:用户密钥对
    • id: u64:帖子ID
  • 流程:生成用户帖子主PDA和目标帖子PDA,发送QueryPosts指令查询内容

6. 交易发送(send_instruction

  • 功能:通用交易发送工具,封装交易签名、发送和确认逻辑
  • 参数:
    • payer: &Keypair:交易付费者密钥对
    • instruction: Vec<Instruction>:待执行的指令列表
  • 流程:
    1. 获取最新区块哈希(用于交易有效性)
    2. 生成并签名交易
    3. 发送交易并等待确认,返回签名信息

五、使用示例

以下示例展示客户端核心功能的调用流程(参考main函数):

// 1. 初始化客户端
let program_id = Pubkey::from_str("9ti8R5H2Ru5553wi419aj2h5cZJbbJEk6zr8insVphJe")?; // 链上程序公钥
let user_keypair = read_keypair_file("/Users/tinachan/.config/solana/id.json")?; // 加载用户密钥对
let client = SocialClient::new("http://127.0.0.1:8899", program_id); // 连接本地测试网

// 2. 初始化用户资料账户
client.initialize_user(&user_keypair, USER_PROFILE_SEED)?;

// 3. 关注指定用户
let follow_user = Pubkey::from_str("2tQibfGH1UX4PEA1dNWJ8zvnpSbKRBr5a5eVhaRxF6EX")?;
client.follow_user(&user_keypair, follow_user)?;

// 4. 查询关注者列表
client.query_followers(&user_keypair)?;

// 5. 取消关注
client.unfollow_user(&user_keypair, follow_user)?;

// 6. 初始化帖子账户
client.initialize_user(&user_keypair, USER_POST_SEED)?;

// 7. 发布帖子
client.post_content(&user_keypair, "Hello, world!".into(), 1)?;

// 8. 查询帖子
client.query_posts(&user_keypair, 1)?;

六、注意事项

  1. 序列化必要性:所有链上数据(如UserProfileSocialInstruction)需通过borsh序列化,因为Solana链上程序仅能处理二进制数据,且borsh是Solana生态的标准序列化方式。
  2. PDA唯一性:种子(seed)需确保唯一,避免不同类型账户地址冲突(例如用户资料和帖子账户需使用不同种子)。
  3. 错误处理:所有方法返回Result类型,需处理可能的错误(如RPC连接失败、交易确认超时、账户未初始化等)。
  4. 测试环境:示例中使用本地测试网(http://127.0.0.1:8899),正式环境需切换为Solana主网或devnet RPC地址。