Metapunk Community


Posted on • Originally published at

Build a dApp Smart Contract on Solana using the Anchor framework

How to Create Smart Contracts in Solana and Anchor

Deploy your contracts on Anchor

How to Create Smart Contracts in Solana and Anchor

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 trustless 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 timestamps 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 that contains several developer tools. So basically, the Anchor is a lifesaver and makes it really easy to develop smart contracts.

In this guide, we’ll be focusing on project setup, basic operation, and testing.

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.

The code for this project can be found here.

To get started, create a new anchor project:

anchor init counterapp
Enter fullscreen mode Exit fullscreen mode

In the project structure, you will see the following files and folders.

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 file in the program directory.

use anchor\_lang::prelude::\*;  
pub mod counterapp {  
    use super::\*;  
    pub fn initialize(ctx: Context<Initialize>) -> ProgramResult {               Ok(())  
pub struct Initialize {}
Enter fullscreen mode Exit fullscreen mode

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 set up our project let’s build our counter 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 code we have defined two structs, the CounterAccount struct is our Account contains a count variable that is going to store our count.

pub struct Create<'info> {

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

    pub user: Signer<'info>,

        pub system\_program: Program<'info, System>,  

pub struct CounterAccount {  
    pub count: u64,  
Enter fullscreen mode Exit fullscreen mode

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;  
Enter fullscreen mode Exit fullscreen mode

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  
Enter fullscreen mode Exit fullscreen mode

Now, run the test.

anchor test
Enter fullscreen mode Exit fullscreen mode

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

anchor deploy
Enter fullscreen mode Exit fullscreen mode

Thanks for reading.

Top comments (0)