Introduction
Building and deploying a decentralized application (dApp) on the Solana blockchain can seem daunting, but with the right guidance, it’s a manageable and rewarding process. This guide will walk you through the steps to set up your Solana development environment, deploy a program to the devnet, and create a React front-end for your dApp.
Prerequisites
Before moving further, explore the following article if you have not read it yet.
Setting Up Your Environment
Install Prerequisites
Ensure you have the necessary tools installed on your machine:
- Node.js and npm: For managing packages and running scripts.
- Solana CLI: For interacting with the Solana blockchain.
- Anchor: A framework for Solana dApp development.
Install the Solana CLI
sh -c "$(curl -sSfL https://release.solana.com/v1.8.5/install)"
Install Anchor
cargo install --git https://github.com/project-serum/anchor anchor-cli --locked
Configure Your Solana CLI Wallet
Set up and configure your Solana CLI wallet.
solana-keygen new
solana config set --url devnet
Airdrop some tokens to your Devnet wallet.
solana airdrop 2
Develop Your Solana Program
Create a New Anchor Project
Initialize a new Anchor project.
anchor init my_solana_dapp
cd my_solana_dapp
Update the Program Code
Modify the program code in the 'programs/my_solana_dapp/src/lib.rs' file to implement your desired functionality. Here’s a simple example of a counter program.
use anchor_lang::prelude::*;
declare_id!("F7nbbscQpQucypsjzJccBDLBSVAVKBHumNLpxqHXym4U");
#[program]
pub mod my_solana_dapp {
use super::*;
pub fn initialize(ctx: Context<Initialize>) -> ProgramResult {
let counter = &mut ctx.accounts.counter;
counter.count = 0;
Ok(())
}
pub fn increment(ctx: Context<Increment>) -> ProgramResult {
let counter = &mut ctx.accounts.counter;
counter.count += 1;
Ok(())
}
}
#[derive(Accounts)]
pub struct Initialize<'info> {
#[account(init, payer = user, space = 8 + 8)]
pub counter: Account<'info, Counter>,
#[account(mut)]
pub user: Signer<'info>,
pub system_program: Program<'info, System>,
}
#[derive(Accounts)]
pub struct Increment<'info> {
#[account(mut)]
pub counter: Account<'info, Counter>,
}
#[account]
pub struct Counter {
pub count: u64,
}
Build and Test Your Program
Build the program.
anchor build
Test the program locally.
anchor test
Deploy to Solana Devnet
Update Anchor Configuration
Update the 'Anchor.toml' file to use the devnet.
[provider]
cluster = "devnet"
wallet = "/path/to/your/solana/id.json"
[programs.devnet]
my_solana_dapp = "F7nbbscQpQucypsjzJccBDLBSVAVKBHumNLpxqHXym4U"
Deploy the Program
Deploy your program to the devnet.
anchor deploy
Build a React Front-End
Set Up Your React Project
Create a new React project using Vite.
npm create vite@latest my_solana_frontend -- --template react-ts
cd my_solana_frontend
yarn
Install Solana and Wallet Adapter Dependencies
Install the necessary dependencies.
yarn add @solana/web3.js @solana/wallet-adapter-base @solana/wallet-adapter-react @solana/wallet-adapter-react-ui @solana/wallet-adapter-wallets @coral-xyz/anchor
Create a Connect Wallet Button
Create a 'ConnectWalletButton' component in 'src/components/ConnectWalletButton.tsx.
import { WalletMultiButton } from '@solana/wallet-adapter-react-ui';
import '@solana/wallet-adapter-react-ui/styles.css';
const ConnectWalletButton = () => {
return <WalletMultiButton />;
};
export default ConnectWalletButton;
Fetch and Display Data from the Blockchain
Create a 'CounterState' component in 'src/components/CounterState.tsx'.
import { useEffect, useState } from 'react';
import { useConnection } from '@solana/wallet-adapter-react';
import { program, counterPDA, CounterData } from '../anchor/setup';
const CounterState = () => {
const { connection } = useConnection();
const [counterData, setCounterData] = useState<CounterData | null>(null);
useEffect(() => {
program.account.counter.fetch(counterPDA).then(data => {
setCounterData(data);
});
const subscriptionId = connection.onAccountChange(
counterPDA,
accountInfo => {
setCounterData(program.coder.accounts.decode('counter', accountInfo.data));
}
);
return () => {
connection.removeAccountChangeListener(subscriptionId);
};
}, [connection]);
return <p className="text-lg">Count: {counterData?.count?.toString()}</p>;
};
export default CounterState;
Increment the Counter
Create an 'IncrementButton' component in 'src/components/IncrementButton.tsx'.
import { useState } from 'react';
import { useConnection, useWallet } from '@solana/wallet-adapter-react';
import { program } from '../anchor/setup';
const IncrementButton = () => {
const { publicKey, sendTransaction } = useWallet();
const { connection } = useConnection();
const [isLoading, setIsLoading] = useState(false);
const onClick = async () => {
if (!publicKey) return;
setIsLoading(true);
try {
const transaction = await program.methods.increment().transaction();
const transactionSignature = await sendTransaction(transaction, connection);
console.log(`Transaction: ${transactionSignature}`);
} catch (error) {
console.error(error);
} finally {
setIsLoading(false);
}
};
return (
<button className="w-24" onClick={onClick} disabled={!publicKey}>
{isLoading ? 'Loading' : 'Increment'}
</button>
);
};
export default IncrementButton;
Integrate Components into App
Update 'src/App.tsx' to use the components.
import { useMemo } from 'react';
import { ConnectionProvider, WalletProvider } from '@solana/wallet-adapter-react';
import { WalletAdapterNetwork } from '@solana/wallet-adapter-base';
import { WalletModalProvider } from '@solana/wallet-adapter-react-ui';
import { clusterApiUrl } from '@solana/web3.js';
import ConnectWalletButton from './components/ConnectWalletButton';
import CounterState from './components/CounterState';
import IncrementButton from './components/IncrementButton';
import './App.css';
const App = () => {
const network = WalletAdapterNetwork.Devnet;
const endpoint = useMemo(() => clusterApiUrl(network), [network]);
return (
<ConnectionProvider endpoint={endpoint}>
<WalletProvider wallets={[]} autoConnect>
<WalletModalProvider>
<ConnectWalletButton />
<h1>Hello Solana</h1>
<CounterState />
<IncrementButton />
</WalletModalProvider>
</WalletProvider>
</ConnectionProvider>
);
};
export default App;
Run Your Application
Run the React application.
yarn dev
Visit http://localhost:5173 to interact with your deployed Solana program.
Conclusion
Congratulations! You've successfully built and deployed your decentralized application (dApp) on the Solana blockchain. By setting up your Solana development environment, deploying a program to the devnet, and creating a React front-end, you have laid a strong foundation for further development. You can expand your dApp's functionality, integrate more complex features, and even deploy to the Solana mainnet.