Posted By : Siddharth
This blog gives a comprehensive guide to smart contract development using Anchor for counter dApp development on the Solana blockchain.
Solana is a high-performance blockchain known for its remarkable speed and scalability. It uses proof-of-history (PoH) and proof-of-stake (PoS) to process thousands of transactions per second, offering low fees. Solana's native cryptocurrency is SOL.
It has a growing ecosystem that enables dApps (decentralized applications) to thrive. The network focuses on decentralization and interoperability. While it has faced some challenges, Solana remains a promising platform for blockchain innovation.
Check It Out: What Makes Solana Blockchain Development Stand Out
Install Rust, Solana CLI, and Anchor CLI for development, for more details refer to https://www.anchor-lang.com/docs/installation.
Use Anchor CLI to create a project with smart contract templates.
Write your smart contract logic in Rust within the lib.rs file, specifying state structures and initializing accounts.
Use Anchor CLI to compile your code into a Solana program and deploy it to the network.
Users can interact with your contract by sending transactions to its entry points.
Test your contract and use Anchor for upgrades.
Suggested Read: Exploring the Potential of Solana Smart Contract Development
This is a simple smart contract built using Anchor. This smart contract allows you to initialize a counter account and then increment and decrement it. Only the creator can increment and decrement on the counter account they created and then choose to remove it.
Anchor 0.28.0
Solana CLI 1.16.9
anchor init solana-counter
First of all, we'll create an account struct that will store data.
#[account]
#[derive(Default, InitSpace)]
pub struct Counter {
pub owner: Pubkey,
pub counter: u64,
pub bump: u8,
}
Explanation
Then we'll manage this created account as follows:
1. Initialize: To initialize the counter account which can store the above details, below is the code to initialize a counter account.
Account
#[derive(Accounts)]
pub struct Initialize<'info> {
#[account(
init,
payer = initializer,
seeds = [
COUNTER_SEED.as_bytes(),
initializer.key.as_ref()
],
bump,
space = 8 + Counter::INIT_SPACE
)]
pub counter_account: Account<'info, Counter>,
#[account(mut)]
pub initializer: Signer<'info>,
pub system_program: Program<'info, System>,
}
Function
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
let counter_account = &mut ctx.accounts.counter_account;
counter_account.owner = ctx.accounts.initializer.key();
counter_account.counter = 0;
counter_account.bump = *ctx.bumps.get("counter_account").unwrap();
Ok(())
}
2. Increment Counter: To increment the counter account, below is the code to increment a counter account.
Account
#[derive(Accounts)]
pub struct Update<'info> {
#[account(
mut,
seeds = [
COUNTER_SEED.as_bytes(),
updater.key.as_ref()
],
bump = counter_account.bump,
)]
pub counter_account: Account<'info, Counter>,
#[account(
mut,
constraint = updater.key() == counter_account.owner @ ErrorCode::AccessDenied
)]
pub updater: Signer<'info>,
}
Function
pub fn increment_counter(ctx: Context<Update>) -> Result<()> {
let counter_account = &mut ctx.accounts.counter_account;
counter_account.counter += 1;
Ok(())
}
Explanation
3. Decrement Counter: To decrement the counter account, below is the code to decrement a counter account.
Function
pub fn decrement_counter(ctx: Context<Update>) -> Result<()> {
let counter_account = &mut ctx.accounts.counter_account;
require!(counter_account.counter > 0, ErrorCode::InvalidCount);
counter_account.counter -= 1;
Ok(())
}
Explanation
Note: We can use the same Update Account in Increment for decrement as well.
4. Remove Counter: To remove the counter account, below is the code to remove a counter account.
Account
#[derive(Accounts)]
pub struct Remove<'info> {
#[account(
mut,
seeds = [
COUNTER_SEED.as_bytes(),
remover.key.as_ref()
],
bump = counter_account.bump,
close = remover
)]
pub counter_account: Account<'info, Counter>,
#[account(
mut,
constraint = remover.key() == counter_account.owner @ ErrorCode::AccessDenied
)]
pub remover: Signer<'info>,
}
Function
pub fn remove_counter(_ctx: Context<Remove>) -> Result<()> {
Ok(())
}
Explanation
"solana config get" - Make sure it shows localhost configuration, if not run the command below.
"solana config set -url localhost"
After the instance is set to localhost, run the command below.
"anchor localnet" - This will start a local validator so that you can deploy and run the smart contract.
"anchor build" - This will build the smart contract.
"anchor keys list" - Copy the program ID that is returned and paste it in lib.rs and Anchor.toml also check if the cluster is set to "localnet".
"anchor build" - This will build the smart contract again with the updated program ID.
"anchor deploy" - This will deploy the smart contract on the localhost.
"anchor run test" - This will run the smart contract test cases.
Complete code - https://github.com/siddharth-oodles/solana-counter
Explore More: Why Develop DApps on Solana
Oodles Blockchain offers a wide range of dApp development services for the Solana blockchain. We enable you to develop robust Solana dApps for fintech, non-fungible token marketplaces, gaming, and beyond. Connect with our Solana developers to discuss your project needs.
November 21, 2024 at 11:06 am
Your comment is awaiting moderation.