Odak modu
Back to the future. We're gonna come full circle and finish out or movie review program with CPIs.
This time, let’s:
Starter code
The first thing we wanna do is define the create_reward_mint instruction:
pub fn create_reward_mint(
ctx: Context<CreateTokenReward>,
uri: String,
name: String,
symbol: String,
) -> Result<()> {
msg!("Create Reward Token");
let seeds = &["mint".as_bytes(), &[*ctx.bumps.get("reward_mint").unwrap()]];
let signer = [&seeds[..]];
let account_info = vec![
ctx.accounts.metadata.to_account_info(),
ctx.accounts.reward_mint.to_account_info(),
ctx.accounts.reward_mint.to_account_info(),
ctx.accounts.user.to_account_info(),
ctx.accounts.token_metadata_program.to_account_info(),
ctx.accounts.token_program.to_account_info(),
ctx.accounts.system_program.to_account_info(),
ctx.accounts.rent.to_account_info(),
];
invoke_signed(
&create_metadata_accounts_v2(
ctx.accounts.token_metadata_program.key(),
ctx.accounts.metadata.key(),
ctx.accounts.reward_mint.key(),
ctx.accounts.reward_mint.key(),
ctx.accounts.user.key(),
ctx.accounts.user.key(),
name,
symbol,
uri,
None,
0,
true,
true,
None,
None,
),
account_info.as_slice(),
&signer,
)?;
Ok(())
}
This is long but dead simple! We're making a CPI to create_metadata_account_v2 instruction on Token Metadata program.
Next, we see the CreateTokenReward context type.
#[derive(Accounts)]
pub struct CreateTokenReward<'info> {
#[account(
init,
seeds = ["mint".as_bytes().as_ref()],
bump,
payer = user,
mint::decimals = 6,
mint::authority = reward_mint,
)]
pub reward_mint: Account<'info, Mint>,
#[account(mut)]
pub user: Signer<'info>,
pub system_program: Program<'info, System>,
pub rent: Sysvar<'info, Rent>,
pub token_program: Program<'info, Token>,
/// CHECK:
#[account(mut)]
pub metadata: AccountInfo<'info>,
/// CHECK:
pub token_metadata_program: AccountInfo<'info>,
}
ErrorCode#[error_code]
pub enum ErrorCode {
#[msg("Rating greater than 5 or less than 1")]
InvalidRating,
}
add_movie_reviewErrorCode checkcounter on Comment Counter AccountmintTo instruction to mint tokens to reviewerpub fn add_movie_review(
ctx: Context<AddMovieReview>,
title: String,
description: String,
rating: u8,
) -> Result<()> {
msg!("Movie Review Account Created");
msg!("Title: {}", title);
msg!("Description: {}", description);
msg!("Rating: {}", rating);
if rating > 5 || rating < 1 {
msg!("Rating cannot be higher than 5");
return err!(ErrorCode::InvalidRating);
}
let movie_review = &mut ctx.accounts.movie_review;
movie_review.reviewer = ctx.accounts.initializer.key();
movie_review.title = title;
movie_review.rating = rating;
movie_review.description = description;
msg!("Movie Comment Counter Account Created");
let movie_comment_counter = &mut ctx.accounts.movie_comment_counter;
movie_comment_counter.counter = 0;
msg!("Counter: {}", movie_comment_counter.counter);
let seeds = &["mint".as_bytes(), &[*ctx.bumps.get("reward_mint").unwrap()]];
let signer = [&seeds[..]];
let cpi_ctx = CpiContext::new_with_signer(
ctx.accounts.token_program.to_account_info(),
token::MintTo {
mint: ctx.accounts.reward_mint.to_account_info(),
to: ctx.accounts.token_account.to_account_info(),
authority: ctx.accounts.reward_mint.to_account_info(),
},
&signer,
);
token::mint_to(cpi_ctx, 10000000)?;
msg!("Minted Tokens");
Ok(())
}
AddMovieReview contextmovie_reviewmovie_comment_counterinit_if_needed to initialize token account#[derive(Accounts)]
#[instruction(title:String, description:String)]
pub struct AddMovieReview<'info> {
#[account(
init,
seeds = [title.as_bytes(), initializer.key().as_ref()],
bump,
payer = initializer,
space = 8 + 32 + 1 + 4 + title.len() + 4 + description.len()
)]
pub movie_review: Account<'info, MovieAccountState>,
#[account(
init,
seeds = ["counter".as_bytes(), movie_review.key().as_ref()],
bump,
payer = initializer,
space = 8 + 8
)]
pub movie_comment_counter: Account<'info, MovieCommentCounter>,
#[account(mut,
seeds = ["mint".as_bytes().as_ref()],
bump
)]
pub reward_mint: Account<'info, Mint>,
#[account(
init_if_needed,
payer = initializer,
associated_token::mint = reward_mint,
associated_token::authority = initializer
)]
pub token_account: Account<'info, TokenAccount>,
#[account(mut)]
pub initializer: Signer<'info>,
pub token_program: Program<'info, Token>,
pub associated_token_program: Program<'info, AssociatedToken>,
pub rent: Sysvar<'info, Rent>,
pub system_program: Program<'info, System>,
}
ErrorCode to update_movie_reviewErrorCode check to update_movie_review instructionpub fn update_movie_review(
ctx: Context<UpdateMovieReview>,
title: String,
description: String,
rating: u8,
) -> Result<()> {
msg!("Updating Movie Review Account");
msg!("Title: {}", title);
msg!("Description: {}", description);
msg!("Rating: {}", rating);
if rating > 5 || rating < 1 {
msg!("Rating cannot be higher than 5");
return err!(ErrorCode::InvalidRating);
}
let movie_review = &mut ctx.accounts.movie_review;
movie_review.rating = rating;
movie_review.description = description;
Ok(())
}
add_commentadd_comment instructionmovie_comment datamovie_comment_countermintTo instruction to mint tokens to reviewerpub fn add_comment(ctx: Context<AddComment>, comment: String) -> Result<()> {
msg!("Comment Account Created");
msg!("Comment: {}", comment);
let movie_comment = &mut ctx.accounts.movie_comment;
let movie_comment_counter = &mut ctx.accounts.movie_comment_counter;
movie_comment.review = ctx.accounts.movie_review.key();
movie_comment.commenter = ctx.accounts.initializer.key();
movie_comment.comment = comment;
movie_comment.count = movie_comment_counter.counter;
movie_comment_counter.counter += 1;
let seeds = &["mint".as_bytes(), &[*ctx.bumps.get("reward_mint").unwrap()]];
let signer = [&seeds[..]];
let cpi_ctx = CpiContext::new_with_signer(
ctx.accounts.token_program.to_account_info(),
token::MintTo {
mint: ctx.accounts.reward_mint.to_account_info(),
to: ctx.accounts.token_account.to_account_info(),
authority: ctx.accounts.reward_mint.to_account_info(),
},
&signer,
);
token::mint_to(cpi_ctx, 5000000)?;
msg!("Minted Tokens");
Ok(())
}
AddComment contextmovie_commentinit_if_needed to initialize token account#[derive(Accounts)]
#[instruction(comment:String)]
pub struct AddComment<'info> {
#[account(
init,
seeds = [movie_review.key().as_ref(), &movie_comment_counter.counter.to_le_bytes()],
bump,
payer = initializer,
space = 8 + 32 + 32 + 4 + comment.len() + 8
)]
pub movie_comment: Account<'info, MovieComment>,
pub movie_review: Account<'info, MovieAccountState>,
#[account(
mut,
seeds = ["counter".as_bytes(), movie_review.key().as_ref()],
bump,
)]
pub movie_comment_counter: Account<'info, MovieCommentCounter>,
#[account(mut,
seeds = ["mint".as_bytes().as_ref()],
bump
)]
pub reward_mint: Account<'info, Mint>,
#[account(
init_if_needed,
payer = initializer,
associated_token::mint = reward_mint,
associated_token::authority = initializer
)]
pub token_account: Account<'info, TokenAccount>,
#[account(mut)]
pub initializer: Signer<'info>,
pub token_program: Program<'info, Token>,
pub associated_token_program: Program<'info, AssociatedToken>,
pub rent: Sysvar<'info, Rent>,
pub system_program: Program<'info, System>,
}
Solution: [https://beta.solpg.io/6319c7bf77ea7f12846aee87](https://beta.solpg.io/6319c7bf77ea7f12846aee87)
Yorum yapabilmek için derse kayıt olmalısın!