Solana Playground | 18 小时最全 Solana 教程 - 2024 训练营
学习Solana,https://github.com/solana-developers/developer-bootcamp-2024 https://space.bilibili.com/581611011/channel/collectiondetail?sid=4304339
// Our program's address!
// This matches the key in the target/deploy directory
declare_id!("ww9C83noARSQVBnqmCUmaVdbJjmiwcV9j2LkXYMoUCV");
// Anchor programs always use 8 bits for the discriminator
pub const ANCHOR_DISCRIMINATOR_SIZE: usize = 8;
// Our Solana program!
#[program]
pub mod favorites {
use super::*;
// Our instruction handler! It sets the user's favorite number and color
pub fn set_favorites(context: Context<SetFavorites>, number: u64, color: String, hobbies: Vec<String>) -> Result<()> {
let user_public_key = context.accounts.user.key();
msg!("Greetings from {}", context.program_id);
msg!(
"User {user_public_key}'s favorite number is {number}, favorite color is: {color}",
);
msg!(
"User's hobbies are: {:?}",
hobbies
);
context.accounts.favorites.set_inner(Favorites {
number,
color,
hobbies
});
Ok(())
}
// We can also add a get_favorites instruction handler to return the user's favorite number and color
}
// What we will put inside the Favorites PDA
#[account]
#[derive(InitSpace)]
pub struct Favorites {
pub number: u64,
#[max_len(50)]
pub color: String,
#[max_len(5, 50)]
pub hobbies: Vec<String>
}
// When people call the set_favorites instruction, they will need to provide the accounts that will be modifed. This keeps Solana fast!
#[derive(Accounts)]
pub struct SetFavorites<'info> {
#[account(mut)]
pub user: Signer<'info>,
#[account(
init_if_needed,
payer = user,
space = ANCHOR_DISCRIMINATOR_SIZE + Favorites::INIT_SPACE,
seeds=[b"favorites", user.key().as_ref()],
bump)]
pub favorites: Account<'info, Favorites>,
pub system_program: Program<'info, System>,
}
<!--StartFragment-->
1. 程序定义和程序 ID
declare_id!("ww9C83noARSQVBnqmCUmaVdbJjmiwcV9j2LkXYMoUCV");
- 这一行声明了 Solana 程序的唯一标识符(程序 ID)。该程序 ID 应该匹配部署时生成的公钥。
- 该 ID 用于区分不同的智能合约和确保与其他程序的交互。
2. 常量定义:ANCHOR_DISCRIMINATOR_SIZE
pub const ANCHOR_DISCRIMINATOR_SIZE: usize = 8;
- ANCHOR_DISCRIMINATOR_SIZE 定义了 Anchor 框架所使用的区分符(discriminator)的大小。在 Solana 中,所有账户都有一个区分符,用于确保账户类型的一致性。Anchor 使用 8 字节的区分符来区分不同类型的账户。
3. 主程序结构:#[program]
#[program]
pub mod favorites {
use super::*;
pub fn set_favorites(context: Context<SetFavorites>, number: u64, color: String, hobbies: Vec<String>) -> Result<()> {
let user_public_key = context.accounts.user.key();
msg!("Greetings from {}", context.program_id);
msg!(
"User {user_public_key}'s favorite number is {number}, favorite color is: {color}",
);
msg!(
"User's hobbies are: {:?}",
hobbies
);
context.accounts.favorites.set_inner(Favorites {
number,
color,
hobbies
});
Ok(())
}
}
学习重点:
#[program]
宏标记了一个 Solana 程序。set_favorites
函数是主处理逻辑,接收三个参数:用户的数字、颜色和爱好。该函数会将这些信息存储在一个名为favorites
的账户中。msg!
用于输出日志信息,这在调试时非常有用,可以显示交易的相关信息。context.accounts.favorites.set_inner()
是一个 Anchor 提供的功能,用于将数据写入指定的账户,确保这些账户的状态得到更新。
4. 账户定义:#[account]
#[account]
#[derive(InitSpace)]
pub struct Favorites {
pub number: u64,
#[max_len(50)]
pub color: String,
#[max_len(5, 50)]
pub hobbies: Vec<String>
}
学习重点:
#[account]
宏标记了一个账户结构体,定义了程序需要用到的账户类型。Favorites
结构体包含三个字段:number
、color
和hobbies
。这些字段代表用户的最爱信息。#[max_len]
宏限制了color
字符串的最大长度为 50,hobbies
向量的每个元素的最大长度为 50,并且最多包含 5 个元素。这些限制用于优化存储,避免不必要的数据浪费。#[derive(InitSpace)]
用于为该账户提供空间计算功能,确保初始化时分配足够的空间。
5. 账户处理:SetFavorites
#[derive(Accounts)]
pub struct SetFavorites<'info> {
#[account(mut)]
pub user: Signer<'info>,
#[account(
init_if_needed,
payer = user,
space = ANCHOR_DISCRIMINATOR_SIZE + Favorites::INIT_SPACE,
seeds=[b"favorites", user.key().as_ref()],
bump
)]
pub favorites: Account<'info, Favorites>,
pub system_program: Program<'info, System>,
}
学习重点:
-
#[derive(Accounts)]
宏用来定义与该指令相关的账户结构体。 -
user
是一个签名账户,表示执行该操作的用户。Signer
类型的账户代表一个可以签署交易的用户。 -
favorites
是存储用户最爱信息的账户。如果该账户还不存在,程序会通过init_if_needed
创建它。这里使用了 PDA(Program Derived Address) 作为账户的地址,seeds
和bump
用于计算 PDA。seeds=[b"favorites", user.key().as_ref()]
生成一个基于user
公钥的派生地址,用作存储最爱信息的账户地址。bump
是一种确保 PDA 地址唯一的机制,避免发生冲突。
-
system_program
是系统程序,用于处理基本的账户操作,如创建和初始化账户。
6. 总结与学习重点
- Anchor框架的结构与功能: 通过
#[program]
、#[account]
和#[derive(Accounts)]
宏,Anchor 框架简化了 Solana 程序的开发,使账户和指令处理变得更易于理解和实现。 - 账户与数据存储: 在 Solana 上存储数据通常使用账户,本例中的
Favorites
账户存储用户的最爱信息。#[account]
宏使得账户结构体可以直接用于程序中,并自动处理数据存储。 - PDA(Program Derived Address): 使用
seeds
和bump
来生成派生地址,可以确保每个用户的数据存储在唯一的账户中。PDA 是 Solana 程序中一个重要的概念,通常用于创建无权签署的账户。 - 程序日志与调试:
msg!
宏可以在调试时输出程序的状态信息,这有助于理解程序执行的过程和验证数据是否正确。 - 初始化空间: 使用
Favorites::INIT_SPACE
和ANCHOR_DISCRIMINATOR_SIZE
来计算所需的空间大小,这是 Solana 中一个重要的概念,用于确保程序分配足够的空间来存储账户数据。
<!--EndFragment-->
版权声明
本文仅代表作者观点,不代表区块链技术网立场。
本文系作者授权本站发表,未经许可,不得转载。
上一篇:下一个 700 种 EVM 语言 下一篇:Protokit 是什么?
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。