学习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-->
declare_id!("ww9C83noARSQVBnqmCUmaVdbJjmiwcV9j2LkXYMoUCV");
ANCHOR_DISCRIMINATOR_SIZE
pub const ANCHOR_DISCRIMINATOR_SIZE: usize = 8;
#[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 提供的功能,用于将数据写入指定的账户,确保这些账户的状态得到更新。#[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)]
用于为该账户提供空间计算功能,确保初始化时分配足够的空间。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
是系统程序,用于处理基本的账户操作,如创建和初始化账户。
#[program]
、#[account]
和 #[derive(Accounts)]
宏,Anchor 框架简化了 Solana 程序的开发,使账户和指令处理变得更易于理解和实现。Favorites
账户存储用户的最爱信息。#[account]
宏使得账户结构体可以直接用于程序中,并自动处理数据存储。seeds
和 bump
来生成派生地址,可以确保每个用户的数据存储在唯一的账户中。PDA 是 Solana 程序中一个重要的概念,通常用于创建无权签署的账户。msg!
宏可以在调试时输出程序的状态信息,这有助于理解程序执行的过程和验证数据是否正确。Favorites::INIT_SPACE
和 ANCHOR_DISCRIMINATOR_SIZE
来计算所需的空间大小,这是 Solana 中一个重要的概念,用于确保程序分配足够的空间来存储账户数据。<!--EndFragment-->
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!