Skip to content

Commit 291c487

Browse files
author
jpcaulfi
committed
cpi
1 parent d391241 commit 291c487

File tree

14 files changed

+299
-54
lines changed

14 files changed

+299
-54
lines changed

basics/cross-program-invocation/README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,28 @@ In the above steps, we can't create a metadata account without first creating a
1616

1717
Let's say we decided it was essential to have our mint (operation 1) and our "mint to user" (operation 4) tasks on-chain. We would have no choice but to also include the other two operations, since we can't do operation #1, pause the program while we do #2 & #3 from the client, and then resume the program for #4.
1818

19+
#### Notes on Native setup:
20+
21+
With the `native` implementation, you have to do a little bit of lifting to import one crate into another within your Cargo workspace.
22+
23+
Add the `no-entrypoint` feature to Cargo.toml:
24+
```toml
25+
[features]
26+
no-entrypoint = []
27+
cpi = ["no-entrypoint"]
28+
```
29+
Then use the import just like we did in the `anchor` example:
30+
```toml
31+
[dependencies]
32+
...
33+
lever = { path = "../lever", features = [ "cpi" ] }
34+
```
35+
Lastly, add this annotation over the `entrypoint!` macro that you wish to disable on import (the child program):
36+
```rust
37+
#[cfg(not(feature = "no-entrypoint"))]
38+
entrypoint!(process_instruction);
39+
```
40+
1941
### Let's switch the power on and off using a CPI!
2042

2143
<img src="istockphoto-1303616086-612x612.jpeg" alt="lever" width="128" align="center"/>

basics/cross-program-invocation/anchor/programs/hand/src/lib.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,22 @@ declare_id!("ABoYG2GWbzLgnnGhK2pUGNupzKoYe7UGk2idrAXbstAS");
1111
mod hand {
1212
use super::*;
1313
pub fn pull_lever(ctx: Context<PullLever>, name: String) -> anchor_lang::Result<()> {
14-
let cpi_program = ctx.accounts.lever_program.to_account_info();
15-
let cpi_accounts = SetPowerStatus {
16-
power: ctx.accounts.power.to_account_info(),
17-
};
18-
let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts);
19-
lever::cpi::switch_power(cpi_ctx, name)
14+
15+
// Hitting the switch_power method on the lever program
16+
//
17+
lever::cpi::switch_power(
18+
CpiContext::new(
19+
20+
ctx.accounts.lever_program.to_account_info(),
21+
22+
// Using the accounts context struct from the lever program
23+
//
24+
let cpi_accounts = SetPowerStatus {
25+
power: ctx.accounts.power.to_account_info(),
26+
};
27+
),
28+
name
29+
)
2030
}
2131
}
2232

basics/cross-program-invocation/anchor/tests/test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as anchor from "@project-serum/anchor";
22
import { Hand } from "../target/types/hand";
33
import { Lever } from "../target/types/lever";
44

5-
describe("hello-solana", () => {
5+
describe("CPI Example", () => {
66

77
const provider = anchor.AnchorProvider.env();
88
anchor.setProvider(provider);
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[workspace]
2+
members = [
3+
"programs/*"
4+
]

basics/cross-program-invocation/native/cicd.sh

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,11 @@
44
# It also serves as a reference for the commands used for building & deploying Solana programs.
55
# Run this bad boy with "bash cicd.sh" or "./cicd.sh"
66

7-
cargo build-bpf --manifest-path=./program/Cargo.toml --bpf-out-dir=./program/target/so
8-
solana program deploy ./program/target/so/program.so
7+
cargo build-bpf --bpf-out-dir=./target/so
8+
echo "Hand:"
9+
solana program deploy ./target/so/hand.so | grep "Program Id:"
10+
echo "Lever:"
11+
solana program deploy ./target/so/lever.so | grep "Program Id:"
12+
13+
# D2E39tDWxnndmW3QvYVzmm2gU2kvr9Zv2ywBLAmq8Fw3
14+
# 9qprjFZKZbBeRGNT3vgPW5xpPFqXjNxKZWybUy7mYNBw

basics/cross-program-invocation/native/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
},
55
"dependencies": {
66
"@solana/web3.js": "^1.47.3",
7+
"borsh": "^0.7.0",
8+
"buffer": "^6.0.3",
79
"fs": "^0.0.1-security"
810
},
911
"devDependencies": {

basics/cross-program-invocation/native/program/src/lib.rs

Lines changed: 0 additions & 29 deletions
This file was deleted.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[package]
2+
name = "hand"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[features]
7+
no-entrypoint = []
8+
cpi = ["no-entrypoint"]
9+
10+
[dependencies]
11+
borsh = "0.9.3"
12+
borsh-derive = "0.9.1"
13+
solana-program = "1.10.12"
14+
lever = { path = "../lever", features = [ "cpi" ] }
15+
16+
[lib]
17+
crate-type = ["cdylib", "lib"]
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[target.bpfel-unknown-unknown.dependencies.std]
2+
features = []
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
use borsh::BorshDeserialize;
2+
use lever::SetPowerStatus;
3+
use solana_program::{
4+
account_info::{
5+
next_account_info, AccountInfo
6+
},
7+
entrypoint,
8+
entrypoint::ProgramResult,
9+
instruction::{ AccountMeta, Instruction },
10+
pubkey::Pubkey,
11+
program::invoke,
12+
};
13+
14+
15+
entrypoint!(pull_lever);
16+
17+
18+
fn pull_lever(
19+
_program_id: &Pubkey,
20+
accounts: &[AccountInfo],
21+
instruction_data: &[u8],
22+
) -> ProgramResult {
23+
24+
let accounts_iter = &mut accounts.iter();
25+
let power = next_account_info(accounts_iter)?;
26+
let lever_program = next_account_info(accounts_iter)?;
27+
28+
let set_power_status_instruction = SetPowerStatus::try_from_slice(instruction_data)?;
29+
30+
let ix = Instruction::new_with_borsh(
31+
lever_program.key.clone(), // Our lever program's ID
32+
&set_power_status_instruction, // Passing same instructions through
33+
vec![AccountMeta::new(power.key.clone(), false)], // Passing same accounts through
34+
);
35+
36+
invoke(&ix, &[power.clone()])
37+
}

0 commit comments

Comments
 (0)