Pārlūkot izejas kodu

update anchor basics examples

John 2 gadi atpakaļ
vecāks
revīzija
1f38abb062

+ 1 - 0
.github/workflows/anchor.yml

@@ -30,6 +30,7 @@ jobs:
             "basics/pda-rent-payer/anchor"
             "basics/processing-instructions/anchor"
             "basics/program-derived-addresses/anchor"
+            "basics/realloc/anchor"
             "basics/rent/anchor"
             "basics/repository-layout/anchor"
             "basics/transfer-sol/anchor"

+ 1 - 2
basics/account-data/anchor/tests/test.ts

@@ -1,6 +1,6 @@
 import * as anchor from "@coral-xyz/anchor"
 import { AnchorProgramExample } from "../target/types/anchor_program_example"
-import { Keypair, SystemProgram } from "@solana/web3.js"
+import { Keypair } from "@solana/web3.js"
 
 describe("Account Data!", () => {
   const provider = anchor.AnchorProvider.env()
@@ -34,7 +34,6 @@ describe("Account Data!", () => {
       .accounts({
         addressInfo: addressInfoAccount.publicKey,
         payer: payer.publicKey,
-        systemProgram: SystemProgram.programId,
       })
       .signers([addressInfoAccount])
       .rpc()

+ 13 - 8
basics/checking-accounts/anchor/programs/anchor-program-example/src/lib.rs

@@ -8,20 +8,25 @@ declare_id!("ECWPhR3rJbaPfyNFgphnjxSEexbTArc7vxD8fnW6tgKw");
 pub mod anchor_program_example {
     use super::*;
 
-    #[allow(clippy::result_large_err)]
     pub fn check_accounts(_ctx: Context<CheckingAccounts>) -> Result<()> {
         Ok(())
     }
 }
 
+// Account validation in Anchor is done using the types and constraints specified in the #[derive(Accounts)] structs
+// This is a simple example and does not include all possible constraints and types
 #[derive(Accounts)]
 pub struct CheckingAccounts<'info> {
-    payer: Signer<'info>,
-    #[account(mut)]
-    /// CHECK: This account's data is empty
-    account_to_create: AccountInfo<'info>,
+    payer: Signer<'info>, // checks account is signer
+
+    /// CHECK: No checks performed, example of an unchecked account
     #[account(mut)]
-    /// CHECK: This account's data is empty
-    account_to_change: AccountInfo<'info>,
-    system_program: Program<'info, System>,
+    account_to_create: UncheckedAccount<'info>,
+    /// CHECK: Perform owner check using constraint
+    #[account(
+        mut,
+        owner = id()
+    )]
+    account_to_change: UncheckedAccount<'info>,
+    system_program: Program<'info, System>, // checks account is executable, and is the system program
 }

+ 27 - 22
basics/checking-accounts/anchor/tests/test.ts

@@ -1,45 +1,50 @@
-import * as anchor from "@coral-xyz/anchor";
-import { AnchorProgramExample } from "../target/types/anchor_program_example";
+import * as anchor from "@coral-xyz/anchor"
+import { AnchorProgramExample } from "../target/types/anchor_program_example"
+import {
+  Keypair,
+  SystemProgram,
+  Transaction,
+  sendAndConfirmTransaction,
+} from "@solana/web3.js"
 
 describe("Anchor example", () => {
-  const provider = anchor.AnchorProvider.env();
-  anchor.setProvider(provider);
+  const provider = anchor.AnchorProvider.env()
+  anchor.setProvider(provider)
   const program = anchor.workspace
-    .AnchorProgramExample as anchor.Program<AnchorProgramExample>;
-  const payer = provider.wallet as anchor.Wallet;
+    .AnchorProgramExample as anchor.Program<AnchorProgramExample>
+  const wallet = provider.wallet as anchor.Wallet
 
   // We'll create this ahead of time.
   // Our program will try to modify it.
-  const accountToChange = anchor.web3.Keypair.generate();
+  const accountToChange = new Keypair()
   // Our program will create this.
-  const accountToCreate = anchor.web3.Keypair.generate();
+  const accountToCreate = new Keypair()
 
   it("Create an account owned by our program", async () => {
-    let ix = anchor.web3.SystemProgram.createAccount({
+    let instruction = SystemProgram.createAccount({
       fromPubkey: provider.wallet.publicKey,
       newAccountPubkey: accountToChange.publicKey,
       lamports: await provider.connection.getMinimumBalanceForRentExemption(0),
       space: 0,
       programId: program.programId, // Our program
-    });
+    })
 
-    await anchor.web3.sendAndConfirmTransaction(
-      provider.connection,
-      new anchor.web3.Transaction().add(ix),
-      [payer.payer, accountToChange]
-    );
-  });
+    const transaction = new Transaction().add(instruction)
+
+    await sendAndConfirmTransaction(provider.connection, transaction, [
+      wallet.payer,
+      accountToChange,
+    ])
+  })
 
   it("Check accounts", async () => {
     await program.methods
       .checkAccounts()
       .accounts({
-        payer: provider.wallet.publicKey,
+        payer: wallet.publicKey,
         accountToCreate: accountToCreate.publicKey,
         accountToChange: accountToChange.publicKey,
-        systemProgram: anchor.web3.SystemProgram.programId,
       })
-      .signers([payer.payer])
-      .rpc();
-  });
-});
+      .rpc()
+  })
+})

+ 5 - 6
basics/close-account/anchor/programs/close-account/src/instructions/create_user.rs

@@ -21,11 +21,10 @@ pub struct CreateUserContext<'info> {
 }
 
 pub fn create_user(ctx: Context<CreateUserContext>, name: String) -> Result<()> {
-    let user_account = &mut ctx.accounts.user_account;
-
-    user_account.bump = *ctx.bumps.get("user_account").unwrap();
-    user_account.user = ctx.accounts.user.key();
-    user_account.name = name;
-
+    *ctx.accounts.user_account = UserState {
+        bump: *ctx.bumps.get("user_account").unwrap(),
+        user: ctx.accounts.user.key(),
+        name,
+    };
     Ok(())
 }

+ 0 - 1
basics/create-account/anchor/tests/test.ts

@@ -20,7 +20,6 @@ describe("Create a system account", () => {
       .accounts({
         payer: wallet.publicKey,
         newAccount: newKeypair.publicKey,
-        systemProgram: SystemProgram.programId,
       })
       .signers([newKeypair])
       .rpc()

+ 17 - 16
basics/cross-program-invocation/anchor/tests/test.ts

@@ -1,14 +1,16 @@
-import * as anchor from "@coral-xyz/anchor";
-import { Hand } from "../target/types/hand";
-import { Lever } from "../target/types/lever";
+import * as anchor from "@coral-xyz/anchor"
+import { Hand } from "../target/types/hand"
+import { Lever } from "../target/types/lever"
+import { Keypair } from "@solana/web3.js"
 
 describe("CPI Example", () => {
-  const provider = anchor.AnchorProvider.env();
-  anchor.setProvider(provider);
-  const hand = anchor.workspace.Hand as anchor.Program<Hand>;
-  const lever = anchor.workspace.Lever as anchor.Program<Lever>;
+  const provider = anchor.AnchorProvider.env()
+  anchor.setProvider(provider)
+  const hand = anchor.workspace.Hand as anchor.Program<Hand>
+  const lever = anchor.workspace.Lever as anchor.Program<Lever>
 
-  const powerAccount = anchor.web3.Keypair.generate();
+  // Generate a new keypair for the power account
+  const powerAccount = new Keypair()
 
   it("Initialize the lever!", async () => {
     await lever.methods
@@ -16,11 +18,10 @@ describe("CPI Example", () => {
       .accounts({
         power: powerAccount.publicKey,
         user: provider.wallet.publicKey,
-        systemProgram: anchor.web3.SystemProgram.programId,
       })
       .signers([powerAccount])
-      .rpc();
-  });
+      .rpc()
+  })
 
   it("Pull the lever!", async () => {
     await hand.methods
@@ -29,8 +30,8 @@ describe("CPI Example", () => {
         power: powerAccount.publicKey,
         leverProgram: lever.programId,
       })
-      .rpc();
-  });
+      .rpc()
+  })
 
   it("Pull it again!", async () => {
     await hand.methods
@@ -39,6 +40,6 @@ describe("CPI Example", () => {
         power: powerAccount.publicKey,
         leverProgram: lever.programId,
       })
-      .rpc();
-  });
-});
+      .rpc()
+  })
+})

+ 1 - 1
basics/pda-rent-payer/anchor/programs/anchor-program-example/src/instructions/create_new_account.rs

@@ -24,7 +24,7 @@ pub fn create_new_account(ctx: Context<CreateNewAccount>) -> Result<()> {
     // The minimum lamports for rent exemption
     let lamports = (Rent::get()?).minimum_balance(0);
 
-    // Create the new account using the PDA signer seeds
+    // Create the new account, transferring lamports from the rent vault to the new account
     create_account(
         CpiContext::new(
             ctx.accounts.system_program.to_account_info(),

+ 2 - 0
basics/pda-rent-payer/anchor/programs/anchor-program-example/src/instructions/init_rent_vault.rs

@@ -17,6 +17,8 @@ pub struct InitRentVault<'info> {
     system_program: Program<'info, System>,
 }
 
+// When lamports are transferred to a new address (without and existing account),
+// An account owned by the system program is created by default
 pub fn init_rent_vault(ctx: Context<InitRentVault>, fund_lamports: u64) -> Result<()> {
     transfer(
         CpiContext::new(

+ 2 - 2
basics/pda-rent-payer/anchor/tests/test.ts

@@ -1,6 +1,6 @@
 import * as anchor from "@coral-xyz/anchor"
 import { PdaRentPayer } from "../target/types/pda_rent_payer"
-import { LAMPORTS_PER_SOL, Keypair } from "@solana/web3.js"
+import { LAMPORTS_PER_SOL, PublicKey, Keypair } from "@solana/web3.js"
 import { assert } from "chai"
 
 describe("PDA Rent-Payer", () => {
@@ -11,7 +11,7 @@ describe("PDA Rent-Payer", () => {
   const program = anchor.workspace.PdaRentPayer as anchor.Program<PdaRentPayer>
 
   // PDA for the Rent Vault
-  const [rentVaultPDA] = anchor.web3.PublicKey.findProgramAddressSync(
+  const [rentVaultPDA] = PublicKey.findProgramAddressSync(
     [Buffer.from("rent_vault")],
     program.programId
   )

+ 8 - 0
basics/realloc/anchor/.gitignore

@@ -0,0 +1,8 @@
+
+.anchor
+.DS_Store
+target
+**/*.rs.bk
+node_modules
+test-ledger
+.yarn

+ 8 - 0
basics/realloc/anchor/.prettierignore

@@ -0,0 +1,8 @@
+
+.anchor
+.DS_Store
+target
+node_modules
+dist
+build
+test-ledger

+ 16 - 0
basics/realloc/anchor/Anchor.toml

@@ -0,0 +1,16 @@
+[features]
+seeds = false
+skip-lint = false
+
+[programs.localnet]
+anchor_realloc = "Fod47xKXjdHVQDzkFPBvfdWLm8gEAV4iMSXkfUzCHiSD"
+
+[registry]
+url = "https://api.apr.dev"
+
+[provider]
+cluster = "Localnet"
+wallet = "~/.config/solana/id.json"
+
+[scripts]
+test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"

+ 13 - 0
basics/realloc/anchor/Cargo.toml

@@ -0,0 +1,13 @@
+[workspace]
+members = [
+    "programs/*"
+]
+
+[profile.release]
+overflow-checks = true
+lto = "fat"
+codegen-units = 1
+[profile.release.build-override]
+opt-level = 3
+incremental = false
+codegen-units = 1

+ 12 - 0
basics/realloc/anchor/migrations/deploy.ts

@@ -0,0 +1,12 @@
+// Migrations are an early feature. Currently, they're nothing more than this
+// single deploy script that's invoked from the CLI, injecting a provider
+// configured from the workspace's Anchor.toml.
+
+const anchor = require("@coral-xyz/anchor");
+
+module.exports = async function (provider) {
+  // Configure client to use the provider.
+  anchor.setProvider(provider);
+
+  // Add your deploy script here.
+};

+ 19 - 0
basics/realloc/anchor/package.json

@@ -0,0 +1,19 @@
+{
+    "scripts": {
+        "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w",
+        "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check"
+    },
+    "dependencies": {
+        "@coral-xyz/anchor": "^0.28.0"
+    },
+    "devDependencies": {
+        "chai": "^4.3.4",
+        "mocha": "^9.0.3",
+        "ts-mocha": "^10.0.0",
+        "@types/bn.js": "^5.1.0",
+        "@types/chai": "^4.3.0",
+        "@types/mocha": "^9.0.0",
+        "typescript": "^4.3.5",
+        "prettier": "^2.6.2"
+    }
+}

+ 19 - 0
basics/realloc/anchor/programs/anchor-realloc/Cargo.toml

@@ -0,0 +1,19 @@
+[package]
+name = "anchor-realloc"
+version = "0.1.0"
+description = "Created with Anchor"
+edition = "2021"
+
+[lib]
+crate-type = ["cdylib", "lib"]
+name = "anchor_realloc"
+
+[features]
+no-entrypoint = []
+no-idl = []
+no-log-ix-name = []
+cpi = ["no-entrypoint"]
+default = []
+
+[dependencies]
+anchor-lang = "0.28.0"

+ 2 - 0
basics/realloc/anchor/programs/anchor-realloc/Xargo.toml

@@ -0,0 +1,2 @@
+[target.bpfel-unknown-unknown.dependencies.std]
+features = []

+ 63 - 0
basics/realloc/anchor/programs/anchor-realloc/src/lib.rs

@@ -0,0 +1,63 @@
+use anchor_lang::prelude::*;
+
+declare_id!("Fod47xKXjdHVQDzkFPBvfdWLm8gEAV4iMSXkfUzCHiSD");
+
+#[program]
+pub mod anchor_realloc {
+    use super::*;
+
+    pub fn initialize(ctx: Context<Initialize>, input: String) -> Result<()> {
+        ctx.accounts.message_account.message = input;
+        Ok(())
+    }
+
+    pub fn update(ctx: Context<Update>, input: String) -> Result<()> {
+        ctx.accounts.message_account.message = input;
+        Ok(())
+    }
+}
+
+#[derive(Accounts)]
+#[instruction(input: String)]
+pub struct Initialize<'info> {
+    #[account(mut)]
+    pub payer: Signer<'info>,
+
+    #[account(
+        init,
+        payer = payer,
+        space = Message::required_space(input.len()),
+    )]
+    pub message_account: Account<'info, Message>,
+    pub system_program: Program<'info, System>,
+}
+
+#[derive(Accounts)]
+#[instruction(input: String)]
+pub struct Update<'info> {
+    #[account(mut)]
+    pub payer: Signer<'info>,
+
+    #[account(
+       mut, 
+       realloc = Message::required_space(input.len()),
+       realloc::payer = payer,
+       realloc::zero = true,
+    )]
+    pub message_account: Account<'info, Message>,
+    pub system_program: Program<'info, System>,
+}
+
+#[account]
+pub struct Message {
+    pub message: String,
+}
+
+impl Message {
+    pub fn required_space(input_len: usize) -> usize {
+        8 + // 8 byte discriminator
+        4 + // 4 byte for length of string
+        input_len
+    }
+}
+

+ 75 - 0
basics/realloc/anchor/tests/anchor-realloc.ts

@@ -0,0 +1,75 @@
+import * as anchor from "@coral-xyz/anchor"
+import { Program } from "@coral-xyz/anchor"
+import { AnchorRealloc } from "../target/types/anchor_realloc"
+import { Keypair } from "@solana/web3.js"
+import { assert } from "chai"
+
+describe("anchor-realloc", () => {
+  // Configure the client to use the local cluster.
+  const provider = anchor.AnchorProvider.env()
+  anchor.setProvider(provider)
+  const payer = provider.wallet as anchor.Wallet
+  const connection = provider.connection
+
+  const program = anchor.workspace.AnchorRealloc as Program<AnchorRealloc>
+
+  const messageAccount = new Keypair()
+
+  // helper function to check the account data and message
+  async function checkAccount(publicKey, expectedMessage) {
+    const accountInfo = await connection.getAccountInfo(publicKey)
+    const accountData = await program.account.message.fetch(publicKey)
+
+    // 8 bytes for the discriminator,
+    // 4 bytes for the length of the message,
+    // and the length of the message
+    assert.equal(accountInfo.data.length, 8 + 4 + expectedMessage.length)
+    assert.equal(accountData.message, expectedMessage)
+
+    console.log(`Account Data Length: ${accountInfo.data.length}`)
+    console.log(`Message: ${accountData.message}`)
+  }
+
+  it("Is initialized!", async () => {
+    const input = "hello"
+
+    await program.methods
+      .initialize(input)
+      .accounts({
+        payer: payer.publicKey,
+        messageAccount: messageAccount.publicKey,
+      })
+      .signers([messageAccount])
+      .rpc()
+
+    await checkAccount(messageAccount.publicKey, input)
+  })
+
+  it("Update", async () => {
+    const input = "hello world"
+
+    await program.methods
+      .update(input)
+      .accounts({
+        payer: payer.publicKey,
+        messageAccount: messageAccount.publicKey,
+      })
+      .rpc()
+
+    await checkAccount(messageAccount.publicKey, input)
+  })
+
+  it("Update", async () => {
+    const input = "hi"
+
+    await program.methods
+      .update(input)
+      .accounts({
+        payer: payer.publicKey,
+        messageAccount: messageAccount.publicKey,
+      })
+      .rpc()
+
+    await checkAccount(messageAccount.publicKey, input)
+  })
+})

+ 11 - 0
basics/realloc/anchor/tsconfig.json

@@ -0,0 +1,11 @@
+{
+            "compilerOptions": {
+              "types": ["mocha", "chai"],
+              "typeRoots": ["./node_modules/@types"],
+              "lib": ["es2015"],
+              "module": "commonjs",
+              "target": "es6",
+              "esModuleInterop": true
+            }
+          }
+          

+ 2 - 3
basics/transfer-sol/anchor/programs/transfer-sol/src/lib.rs

@@ -46,13 +46,12 @@ pub struct TransferSolWithCpi<'info> {
 
 #[derive(Accounts)]
 pub struct TransferSolWithProgram<'info> {
-    /// CHECK: Use owner constraint to check account is owned by the program
+    /// CHECK: Use owner constraint to check account is owned by our program
     #[account(
         mut,
-        owner = id()
+        owner = id() // value of declare_id!()
     )]
     payer: UncheckedAccount<'info>,
     #[account(mut)]
     recipient: SystemAccount<'info>,
-    system_program: Program<'info, System>,
 }

+ 1 - 0
basics/transfer-sol/anchor/tests/test.ts

@@ -14,6 +14,7 @@ describe("transfer-sol", () => {
   const payer = provider.wallet as anchor.Wallet
   const program = anchor.workspace.TransferSol as anchor.Program<TransferSol>
 
+  // 1 SOL
   const transferAmount = 1 * LAMPORTS_PER_SOL
 
   // Generate a new keypair for the recipient