@@ -114,21 +114,20 @@ pub fn new_with_signer(
114
114
115
115
#### CPI accounts
116
116
117
- One of the main things about ` CpiContext ` that simplifies cross-program
118
- invocations is that the ` accounts ` argument is a generic type that lets you pass
119
- in any object that adopts the ` ToAccountMetas ` and ` ToAccountInfos<'info> `
120
- traits.
117
+ One of the key features of ` CpiContext ` is that the ` accounts ` argument is
118
+ generic, allowing you to pass in any object that implements the ` ToAccountMetas `
119
+ and ` ToAccountInfos<'info> ` traits.
121
120
122
- These traits are added by the ` #[derive(Accounts)] ` attribute macro that you've
123
- used before when creating structs to represent instruction accounts. That means
124
- you can use similar structs with ` CpiContext ` .
121
+ These traits are added by the ` #[derive(Accounts)] ` attribute macro you've used
122
+ before, to specify the accounts required by your instruction handlers. You can
123
+ use also use ` #[derive(Accounts)] ` structs with ` CpiContext ` .
125
124
126
125
This helps with code organization and type safety.
127
126
128
- #### Invoke an instruction on another Anchor program
127
+ #### Invoke an instruction handler on another Anchor program
129
128
130
- When the program you're calling is an Anchor program with a published crate,
131
- Anchor can generate instruction builders and CPI helper functions for you.
129
+ When calling another Anchor program with a published crate, Anchor can generate
130
+ instruction builders and CPI helper functions for you.
132
131
133
132
Simply declare your program's dependency on the program you're calling in your
134
133
program's ` Cargo.toml ` file as follows:
@@ -141,11 +140,11 @@ callee = { path = "../callee", features = ["cpi"]}
141
140
By adding ` features = ["cpi"] ` , you enable the ` cpi ` feature and your program
142
141
gains access to the ` callee::cpi ` module.
143
142
144
- The ` cpi ` module exposes ` callee ` 's instructions as a Rust function that takes
145
- as arguments a ` CpiContext ` and any additional instruction data. These functions
146
- use the same format as the instruction functions in your Anchor programs, only
147
- with ` CpiContext ` instead of ` Context ` . The ` cpi ` module also exposes the
148
- accounts structs required for calling the instructions .
143
+ The ` cpi ` module turns ` callee ` 's instructions into Rust functions. These
144
+ functions take a ` CpiContext ` and any extra data needed for the instruction.
145
+ They work just like the instruction functions in your Anchor programs, but use
146
+ ` CpiContext ` instead of ` Context ` . The ` cpi ` module also provides the account
147
+ structs needed for these instruction handler .
149
148
150
149
For example, if ` callee ` has the instruction ` do_something ` that requires the
151
150
accounts defined in the ` DoSomething ` struct, you could invoke ` do_something ` as
@@ -212,24 +211,24 @@ possible options:
212
211
similar pattern if you decide to use an accounts struct and ` CpiContext ` to
213
212
organize and prepare your CPI.
214
213
``` rust
215
- pub fn mint_to <'a , ' b , ' c , ' info >(
216
- ctx : CpiContext <'a , 'b , 'c , 'info , MintTo <'info >>,
214
+ pub fn mint_to <'info >(
215
+ ctx : CpiContext <'_foo , '_bar , '_baz , 'info , MintTo <'info >>,
217
216
amount : u64 ,
218
217
) -> Result <()> {
219
- let ix = spl_token :: instruction :: mint_to (
218
+ let instruction_handler = spl_token :: instruction :: mint_to (
220
219
& spl_token :: ID ,
221
220
ctx . accounts. mint. key,
222
221
ctx . accounts. to. key,
223
222
ctx . accounts. authority. key,
224
223
& [],
225
224
amount ,
226
225
)? ;
227
- solana_program :: program :: invoke_signed (
228
- & ix ,
226
+ anchor_lang :: solana_program :: program :: invoke_signed (
227
+ & instruction_handler ,
229
228
& [
230
- ctx . accounts. to. clone () ,
231
- ctx . accounts. mint. clone () ,
232
- ctx . accounts. authority. clone (),
229
+ ctx . accounts. to,
230
+ ctx . accounts. mint,
231
+ ctx . accounts. authority
233
232
],
234
233
ctx . signer_seeds,
235
234
)
@@ -242,8 +241,8 @@ possible options:
242
241
We're deep enough into Anchor at this point that it's important to know how to
243
242
create custom errors.
244
243
245
- Ultimately, all programs return the same error
246
- type: [ ` ProgramError ` ] ( https://docs.rs/solana-program/latest/solana_program/program_error/enum.ProgramError.html ) .
244
+ Ultimately, all programs return the same error type:
245
+ [ ` ProgramError ` ] ( https://docs.rs/solana-program/latest/solana_program/program_error/enum.ProgramError.html ) .
247
246
However, when writing a program using Anchor you can use ` AnchorError ` as an
248
247
abstraction on top of ` ProgramError ` . This abstraction provides additional
249
248
information when a program fails, including:
@@ -381,14 +380,14 @@ pub struct InitializeMint<'info> {
381
380
bump ,
382
381
payer = user ,
383
382
mint :: decimals = 6 ,
384
- mint :: authority = mint ,
383
+ mint :: authority = user ,
385
384
)]
386
385
pub mint : Account <'info , Mint >,
387
386
#[account(mut )]
388
387
pub user : Signer <'info >,
389
388
pub token_program : Program <'info , Token >,
390
389
pub rent : Sysvar <'info , Rent >,
391
- pub system_program : Program <'info , System >
390
+ pub system_program : Program <'info , System >,
392
391
}
393
392
```
394
393
@@ -455,7 +454,7 @@ pub struct AddMovieReview<'info> {
455
454
seeds= [title. as_bytes(), initializer. key(). as_ref()],
456
455
bump ,
457
456
payer = initializer ,
458
- space = MovieAccountState :: INIT_SPACE + title . len () + description . len ()
457
+ space = DISCRIMINATOR + MovieAccountState :: INIT_SPACE
459
458
)]
460
459
pub movie_review : Account <'info , MovieAccountState >,
461
460
#[account(mut )]
@@ -486,12 +485,6 @@ been initialized, it will be initialized as an associated token account for the
486
485
specified mint and authority. Also, the payer for the costs related with the
487
486
account initialization will be set under the constraint ` payer ` .
488
487
489
- If you're unfamiliar with the ` INIT_SPACE ` constant used for the ` movie_review `
490
- account space allocation, please refer to the
491
- [ ` solution-pdas ` ] ( https://github.com/solana-foundation/developer-content/blob/4c8eada3053061e66b907c9b49701b064544681d/content/courses/onchain-development/anchor-pdas.md?plain=1#L467 )
492
- branch that is being used as our starting point. In there, we discuss the
493
- implementation of the ` Space ` trait and the ` INIT_SPACE ` constant.
494
-
495
488
Next, let’s update the ` add_movie_review ` instruction to do the following:
496
489
497
490
- Check that ` rating ` is valid. If it is not a valid rating, return the
@@ -520,15 +513,29 @@ use anchor_spl::associated_token::AssociatedToken;
520
513
Next, update the ` add_movie_review ` function to:
521
514
522
515
``` rust
523
- pub fn add_movie_review (ctx : Context <AddMovieReview >, title : String , description : String , rating : u8 ) -> Result <()> {
516
+ pub fn add_movie_review (
517
+ ctx : Context <AddMovieReview >,
518
+ title : String ,
519
+ description : String ,
520
+ rating : u8
521
+ ) -> Result <()> {
524
522
// We require that the rating is between 1 and 5
525
- require! (rating >= MIN_RATING && rating <= MAX_RATING , MovieReviewError :: InvalidRating );
523
+ require! (
524
+ rating >= MIN_RATING && rating <= MAX_RATING ,
525
+ MovieReviewError :: InvalidRating
526
+ );
526
527
527
528
// We require that the title is not longer than 20 characters
528
- require! (title . len () <= MAX_TITLE_LENGTH , MovieReviewError :: TitleTooLong );
529
+ require! (
530
+ title . len () <= MAX_TITLE_LENGTH ,
531
+ MovieReviewError :: TitleTooLong
532
+ );
529
533
530
534
// We require that the description is not longer than 50 characters
531
- require! (description . len () <= MAX_DESCRIPTION_LENGTH , MovieReviewError :: DescriptionTooLong );
535
+ require! (
536
+ description . len () <= MAX_DESCRIPTION_LENGTH ,
537
+ MovieReviewError :: DescriptionTooLong
538
+ );
532
539
533
540
msg! (" Movie review account created" );
534
541
msg! (" Title: {}" , title );
@@ -568,12 +575,23 @@ pub fn add_movie_review(ctx: Context<AddMovieReview>, title: String, description
568
575
Here we are only adding the check that ` rating ` and ` description ` are valid.
569
576
570
577
``` rust
571
- pub fn update_movie_review (ctx : Context <UpdateMovieReview >, title : String , description : String , rating : u8 ) -> Result <()> {
578
+ pub fn update_movie_review (
579
+ ctx : Context <UpdateMovieReview >,
580
+ title : String ,
581
+ description : String ,
582
+ rating : u8
583
+ ) -> Result <()> {
572
584
// We require that the rating is between 1 and 5
573
- require! (rating >= MIN_RATING && rating <= MAX_RATING , MovieReviewError :: InvalidRating );
585
+ require! (
586
+ rating >= MIN_RATING && rating <= MAX_RATING ,
587
+ MovieReviewError :: InvalidRating
588
+ );
574
589
575
590
// We require that the description is not longer than 50 characters
576
- require! (description . len () <= MAX_DESCRIPTION_LENGTH , MovieReviewError :: DescriptionTooLong );
591
+ require! (
592
+ description . len () <= MAX_DESCRIPTION_LENGTH ,
593
+ MovieReviewError :: DescriptionTooLong
594
+ );
577
595
578
596
msg! (" Movie review account space reallocated" );
579
597
msg! (" Title: {}" , title );
@@ -682,7 +700,7 @@ After that, neither the test for `updateMovieReview` nor the test for
682
700
683
701
At this point, run ` anchor test ` and you should see the following output
684
702
685
- ` ` ` shell
703
+ ` ` ` bash
686
704
anchor - movie - review - program
687
705
✔ Initializes the reward token (458ms )
688
706
✔ Movie review is added (410ms )
0 commit comments