How to Create Smart Contracts in Solana and Anchor | by Anmol Dhiman | Jan, 2022

Deploy your contracts on Anchor

Anmol Dhiman

Solana is a decentralized blockchain platform created by Anatoly Yakavenko. Solana has a block time of 400 ms which is freakingly fast. This is because of their proof of history consensus mechanism, which is actually a proof of stake but added extra variable time. PoH is used to encode trust less passage of time into a ledger in an append only data structure.

Blockchains have to agree on time before submitting a block, Nodes have to chat back and forth to determine time until they agree on it and this can take a lot of time. Solana came up with a solution with proof of history to save timestamp so nodes don’t have to wait to agree on time and they also have a cryptographic proof for that.

For more information on proof of history I recommend you to go through whitepaper of solana.

Anchor is a framework for developing solana smart contract contains several developer tools. So basically, the anchor is a life saver and makes it really easy to develop smart contracts.

In this guide we’ll be focusing on project setup, basic operation and testing. For this we will be needing. We will create a counter app that increments the counter by one every time we call the rpc.

Rust — Rust is a very powerful general purpose programming language. We are going to use this for smart contract development.There is a very good book available to learn Rust.

Solana Tool Suit — This includes the solana cli.

Code for this project can be found here.

To get started, create a new anchor project:

anchor init counterapp

In the project srructure you will see the following files and folder.

program — This is the directory of solana programs (Smart contracts)

test — This is where javascript test code lives

migrations — This is the deploy script

app — This is where frontend is going to be built

Let’s look at our lib.rs file in program directory.

use anchor_lang::prelude::*;
declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");

#[program]
pub mod counterapp {
use super::*;
pub fn initialize(ctx: Context<Initialize>) -> ProgramResult {
Ok(())
}
}
#[derive(Accounts)]
pub struct Initialize {}

This is the most basic program written by cli. There is a function initialize when invoked do nothing just execute successfully, the initialize struct defines the context of the initialize function.

Now that we have setup our project let’s build our couter app.

To do that we need to create an account to store our data. You must be thinking what the heck is this account. Accounts are just the way of storing and accessing the data in solana sealevel. For more information I recommend reading this.

In the above core we have defined two structs, the CounterAccount struct is our Account contains a count variable that are going to store our count.

#[derive(Accounts)]
pub struct Create<'info> {

#[account(init, payer=user, space = 16+16)]
pub counter_account: Account<'info, CounterAccount>,

#[account(mut)]
pub user: Signer<'info>,

pub system_program: Program<'info, System>,
}

#[account]
pub struct CounterAccount {
pub count: u64,
}

The Create struct is our instruction struct that defines our context for creating an account, that is saying, Hey I want to create an account counter_account with the space 32 byte. The #[account(…)] attributes define constraints and instructions in preprocessing done by anchor to create context. Now let’s create our function.

pub fn create(ctx: Context<Create>) -> ProgramResult {
let counter_account = &mut ctx.accounts.counter_account;
counter_account.count = 0;
Ok(())
}

create function is our handler for rpc request which takes the context created with Create struct.

Cool. We are done with this amazing program. Now let’s create the test function and deploy our masterpiece.

import * as anchor from '@project-serum/anchor';
import { Program } from '@project-serum/anchor';
import { Counterapp } from '../target/types/counterapp';
describe('counterapp', () => { const provider = anchor.Provider.env()
anchor.setProvider(provider);
const program = anchor.workspace.Counterapp as Program<Counterapp>; const counterAccount = anchor.web3.Keypair.generate(); it('Is initialized!', async () => {
await program.rpc.create({
accounts: {
counterAccount: counterAccount.publicKey,
user: provider.wallet.publicKey,
systemProgram: anchor.web3.SystemProgram.programId,
},
signers: [counterAccount]
} as any)
});
it("Increment counter", async () => {
await program.rpc.increment({
accounts: {
counterAccount: counterAccount.publicKey
}
} as any)
})
it("Fetch account", async () => {
const account: any = await
program.account.counterAccount.fetch(counterAccount.publicKey)
console.log(account.count)
})
});

Now, run the test.

anchor test

After test passes we can now deploy the program. Be sure that solana-test-validator is running.

anchor deploy

Thanks for reading.

Leave a Comment