Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions basics/create-account/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
:wrench: We're going to create a Solana account. :wrench:

This account is going to be a **system account** - meaning it will be owned by the System Program. In short, this means only the System Program will be allowed to modify it's data.

In the test, we use two methods for creating the accounts. One of the methods uses Cross program invocation and the other calls the System Program directly.

Cross program invocation means that we send the transaction to create the account first to our deployed Solana Program, which then calls the System Program. See [here](https://github.com/solana-developers/program-examples/tree/main/basics/cross-program-invocation) for more Cross Program Invocation examples.

Calling the System Program directly means that the client sends the transaction to create the account directly to the Solana Program

In this example, this account will simply hold some SOL.

Expand Down
29 changes: 24 additions & 5 deletions basics/create-account/native/tests/test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
Connection,
Keypair,
LAMPORTS_PER_SOL,
PublicKey,
sendAndConfirmTransaction,
SystemProgram,
Expand All @@ -20,12 +21,11 @@ describe("Create a system account", async () => {

const connection = new Connection(`http://localhost:8899`, 'confirmed');
const payer = createKeypairFromFile(require('os').homedir() + '/.config/solana/id.json');

const PROGRAM_ID: PublicKey = new PublicKey(
"Au21huMZuDQrbzu2Ec5ohpW5CKRqhcGV6qLawfydStGs"
);
const program = createKeypairFromFile('./program/target/so/program-keypair.json')

const PROGRAM_ID: PublicKey = program.publicKey;

it("Create the account", async () => {
it("Create the account via a cross program invocation", async () => {

const newKeypair = Keypair.generate();

Expand All @@ -45,5 +45,24 @@ describe("Create a system account", async () => {
[payer, newKeypair]
);
});

it("Create the account via direct call to system program", async () => {

const newKeypair = Keypair.generate();

const ix = SystemProgram.createAccount({
fromPubkey: payer.publicKey,
newAccountPubkey: newKeypair.publicKey,
lamports: LAMPORTS_PER_SOL,
space: 0,
programId: SystemProgram.programId
})

await sendAndConfirmTransaction(connection,
new Transaction().add(ix),
[payer, newKeypair]);

console.log(`Account with public key ${newKeypair.publicKey} successfully created`);
});
});

19 changes: 15 additions & 4 deletions basics/cross-program-invocation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,35 @@ Let's say we decided it was essential to have our mint (operation 1) and our "mi

With the `native` implementation, you have to do a little bit of lifting to import one crate into another within your Cargo workspace.

Add the `no-entrypoint` feature to Cargo.toml:
This is because a Solana Program needs to have a single entry point. This means a Solana Program that depends on
other Solana Programs needs a way to disable the other entry points. This is done using `[features]` in Cargo.

Add the `no-entrypoint` feature to Cargo.toml of the `lever` crate:
```toml
[features]
no-entrypoint = []
cpi = ["no-entrypoint"]
```
Then use the import just like we did in the `anchor` example:
Then, in the `hand` crate, use the import just like we did in the `anchor` example:
```toml
[dependencies]
...
lever = { path = "../lever", features = [ "cpi" ] }
lever = { path = "../lever", features = [ "no-entrypoint" ] }
```
Lastly, add this annotation over the `entrypoint!` macro that you wish to disable on import (the child program):
```rust
#[cfg(not(feature = "no-entrypoint"))]
entrypoint!(process_instruction);
```

The above configuration defines `no-entrypoint` as a _feature_ in the `lever` crate. This controls whether the line
`entrypoint!(process_instruction)` gets compiled or not depending on how the `lever` crate is included as a dependency.

When adding `lever` as a dependency in the Cargo.tml of `hand` crate, we configure it with `features = [ "no-entrypoint" ]`
this makes sure that the `entrypoint!(process_instruction)` line is not part of the compilation. This ensures that only
the `entrypoint!(process_instruction)` from the `hand` crate is part of the compilation.

For more about how `[features]` see [Features chapter in the Rust Book](https://doc.rust-lang.org/cargo/reference/features.html)

### Let's switch the power on and off using a CPI!

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