Building with Solana: Smart Contract Integration
Solana is one of the fastest blockchains, making it ideal for decentralized applications (dApps). If you're looking to integrate Solana program with a React app, this guide will walk you through the key concepts using a simple example.
1. Connecting Your React App to Solana
Before interacting with a Solana program, we need to establish a connection using the solana/web3.js
and anchor
frameworks.
import { useConnection, useWallet } from "@solana/wallet-adapter-react";
import { Program, AnchorProvider } from "@project-serum/anchor";
import { PublicKey } from "@solana/web3.js";
const PROGRAM_ID = new PublicKey("your_program_id_here");
export const useProgram = () => {
const { connection } = useConnection();
const wallet = useWallet();
const provider = new AnchorProvider(
connection,
wallet as any,
{ commitment: 'confirmed' }
);
const program = new Program(IDL, PROGRAM_ID, provider);
return { program };
};
How It Works:
Establishes a connection to the Solana network using useConnection
. Accesses the connected wallet via useWallet
. Creates an AnchorProvider
to bundle the connection and wallet. Initializes a program instance, allowing us to interact with our Solana smart contract. Returns a reusable useProgram
hook for easy access across components.
2. Working with Program Derived Addresses (PDAs)
PDAs are special accounts controlled by a Solana program instead of a private key. These accounts store program-specific data like staking balances.
export const findStakeAccountPDA = (program: Program, userPubkey: PublicKey) => {
return PublicKey.findProgramAddressSync(
[Buffer.from("stake"), userPubkey.toBuffer()],
program.programId
);
};
export const findVaultPDA = (program: Program) => {
return PublicKey.findProgramAddressSync(
[Buffer.from("vault")],
program.programId
);
};
How It Works:
findStakeAccountPDA
: Generates a unique PDA for each user's stake account. findVaultPDA
: Generates a fixed PDA for the staking vault. The seeds ("stake"
, "vault"
, and user's public key) ensure predictable addresses. These addresses match what is defined in the Solana smart contract.
3. Fetching Data Using Getter Functions
Now that we can derive account addresses, we need functions to retrieve on-chain data.
export const useStakeAccount = () => {
const { program } = useProgram();
const getStakeAccount = async (userPubkey: PublicKey) => {
const [stakeAccountPDA] = findStakeAccountPDA(program, userPubkey);
const account = await program.account.stakeAccount.fetch(stakeAccountPDA);
return {
amount: account.amount,
lastStakeTime: account.lastStakeTime
};
};
const getVaultBalance = async () => {
const [vaultPDA] = findVaultPDA(program);
const account = await program.account.vault.fetch(vaultPDA);
return account.totalStaked;
};
return {
getStakeAccount,
getVaultBalance
};
};
How It Works:
getStakeAccount
: Retrieves a user's stake amount and last stake timestamp. getVaultBalance
: Fetches the total amount staked in the vault. Uses the PDA helper functions to find accounts before fetching data. Returns a hook (useStakeAccount
) for easy access in components.
4. Displaying Staking Data in React
With our getter functions ready, let’s display a user's staking details in a React component.
const StakeInfo = () => {
const { publicKey } = useWallet();
const { getStakeAccount } = useStakeAccount();
const [stakeInfo, setStakeInfo] = useState(null);
useEffect(() => {
if (!publicKey) return;
const fetchStakeInfo = async () => {
const info = await getStakeAccount(publicKey);
setStakeInfo(info);
};
fetchStakeInfo();
}, [publicKey]);
if (!stakeInfo) return <div>Connect your wallet</div>;
return (
<div>
<h2>Your Stake</h2>
<p>Amount: {stakeInfo.amount.toString()}</p>
<p>Last Stake Time: {new Date(stakeInfo.lastStakeTime).toLocaleString()}</p>
</div>
);
};
How It Works:
Uses useWallet
to get the connected user's public key. Calls getStakeAccount
when the wallet connects. Stores stake info in local state and updates it dynamically. Displays stake amount and last stake time. Shows a connection prompt if no wallet is connected.
Conclusion
By following this guide, you now have a working integration between a Solana smart contract and a React application. We covered: Connecting to a Solana program. Deriving PDAs for program accounts. Fetching and displaying staking data.