Browse Source

Merge pull request #13 from dadepo/add-direct-call-to-system-program-for-creating-accounts

Add direct call to system program for creating accounts
Joe Caulfield 2 years ago
parent
commit
c006e7e8ba

+ 6 - 0
basics/create-account/README.md

@@ -4,6 +4,12 @@
    
 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.
 
 ### Links:

+ 24 - 5
basics/create-account/native/tests/test.ts

@@ -1,6 +1,7 @@
 import {
     Connection,
     Keypair,
+    LAMPORTS_PER_SOL,
     PublicKey,
     sendAndConfirmTransaction,
     SystemProgram,
@@ -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();
 
@@ -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`);
+    });
   });
   

+ 15 - 4
basics/cross-program-invocation/README.md

@@ -20,17 +20,19 @@ 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
@@ -38,6 +40,15 @@ Lastly, add this annotation over the `entrypoint!` macro that you wish to disabl
 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"/>