Building Blockchain Applications with Solidity, React, Next.js and Rust

Search for a command to run...

No comments yet. Be the first to comment.
There's a question that most people feel but almost nobody says out loud. Not because it's complicated. Because saying it threatens everything built on top of not saying it. The question is simple. Wh

Public discourse around personal finance in India increasingly relies on lifestyle narratives, absolute numbers, and loosely imported benchmarks. Concepts such as middle class, financial security, high income, or wealthy are often used without refere...

By Ahmad W Khan (interactive at https://ahmadwkhan.com/india-work-landscape) Summary (TL;DR): India’s labour market is vast, diversified, and uneven. Government roles remain tenure‑rich but hard to enter; healthcare and licensed professional practice...

Audience: Intermediate PHP devs (comfortable with OOP, Composer, basic MVC) who are new/rusty with SymfonyOS Assumptions: macOS/Linux primary; Windows notes included (PowerShell + WSL2)Target PHP & Symfony: PHP 8.2+ and Symfony 7.3.x (current stable ...

Money, unlike geography, is invisible.We know where a country starts and ends on a map. But wealth and income? They’re like air currents, everywhere, yet hard to see. Percentiles help make them visible: where do you sit compared to your neighbors, yo...

Blockchain technology is revolutionizing various industries by providing decentralized and transparent solutions. Developing applications on the blockchain can seem daunting, but with the right tools and guidance, it becomes a manageable and rewarding endeavor. In this guide, we will walk you through building a blockchain application using Solidity for smart contracts, React for the user interface, and Next.js for server-side rendering and routing.
To follow along with this tutorial, you should have a basic understanding of JavaScript and React. Familiarity with blockchain concepts and Solidity will be helpful but not required. By the end of this tutorial, you will have a working blockchain application and a good grasp of how to develop and deploy decentralized applications (dApps).
Introduction to Blockchain Technology
Understanding the basics of blockchain and its applications.
Overview of Ethereum and smart contracts.
Setting Up the Development Environment
Installing Node.js and npm.
Installing Truffle or Hardhat for smart contract development.
Setting up a local Ethereum network using Ganache.
Installing Metamask for managing Ethereum accounts and transactions.
Writing Smart Contracts in Solidity
Basic syntax and structure of a Solidity contract.
Writing a simple smart contract (e.g., a token contract or a voting contract).
Compiling and deploying the contract to the local Ethereum network.
Interacting with Smart Contracts using Web3.js or Ethers.js
Setting up a React application with Next.js.
Installing Web3.js or Ethers.js for interacting with the blockchain.
Connecting the React app to the Ethereum network using Metamask.
Reading from and writing to the smart contract.
Building the Frontend with React and Next.js
Creating components for the user interface.
Displaying data from the blockchain in the UI.
Handling user inputs and transactions.
Creating Your Own Coin
Writing a token contract in Solidity.
Deploying the token contract.
Integrating the token with the frontend.
Testing and Deployment
Writing tests for smart contracts.
Deploying the smart contract to a testnet (e.g., Ropsten or Rinkeby).
Deploying the React application to a hosting service (e.g., Vercel).
Advanced Topics
Conclusion
Recap of what was covered.
Additional resources for further learning.
Encouragement to build and share blockchain applications.
Let's dive into each section in detail.
Blockchain is a distributed ledger technology that enables secure and transparent record-keeping. Unlike traditional databases, a blockchain stores data in a decentralized manner, meaning that no single entity has control over the entire network. This decentralized nature makes blockchain inherently secure and resistant to tampering.
Blocks: A blockchain is composed of a series of blocks, each containing a list of transactions. Blocks are linked together in chronological order, forming a chain.
Nodes: Nodes are computers that participate in the blockchain network. Each node maintains a copy of the entire blockchain and validates transactions.
Consensus Mechanisms: Consensus mechanisms, such as Proof of Work (PoW) and Proof of Stake (PoS), are used to achieve agreement among nodes on the state of the blockchain.
Smart Contracts: Smart contracts are self-executing contracts with the terms of the agreement directly written into code. They run on the blockchain and can automate complex processes.
Blockchain has a wide range of applications, from financial services and supply chain management to voting systems and healthcare. By providing a transparent and immutable record of transactions, blockchain technology can increase trust and efficiency in various industries.
Ethereum is a decentralized platform that enables developers to build and deploy smart contracts. A smart contract is a self-executing contract with the terms of the agreement directly written into code. Smart contracts run on the Ethereum Virtual Machine (EVM) and can be used to automate and enforce agreements without the need for intermediaries.
Decentralization: Ethereum is a decentralized platform, meaning no single entity controls it. This ensures transparency and security.
Smart Contract Support: Ethereum was the first blockchain to introduce smart contracts, allowing developers to create decentralized applications (dApps).
Active Development Community: Ethereum has a large and active development community, providing extensive resources and support for developers.
Solidity is the most widely used programming language for writing smart contracts on the Ethereum platform. It is a statically-typed language with syntax similar to JavaScript, making it relatively easy for developers to learn and use.
To develop blockchain applications, we need to set up a development environment that includes tools for writing, testing, and deploying smart contracts, as well as for building the frontend of our application.
Node.js is a JavaScript runtime that allows us to run JavaScript code on the server side. npm (Node Package Manager) is a package manager for Node.js that helps us install and manage dependencies for our project.
To check if Node.js and npm are already installed on your machine, open a terminal and run the following commands:
node -v
npm -v
If Node.js and npm are not installed, download and install them from the official Node.js website.
Truffle and Hardhat are popular frameworks for developing, testing, and deploying smart contracts. Both tools provide a suite of features that make it easier to manage the lifecycle of a smart contract project.
Truffle is a development framework for Ethereum that provides a suite of tools for smart contract development. It includes a built-in testing framework, a deployment pipeline, and a console for interacting with contracts.
To install Truffle globally, run the following command:
npm install -g truffle
Hardhat is a development environment for Ethereum that provides a flexible and extensible toolset for smart contract development. It includes a task runner, a testing framework, and a local blockchain network for testing.
To install Hardhat as a development dependency in your project, run the following command:
npm install --save-dev hardhat
Ganache is a personal blockchain for Ethereum development that you can use to deploy contracts, develop applications, and run tests. It provides a local blockchain network with pre-funded accounts, making it easy to test and debug smart contracts.
To install Ganache CLI, run the following command:
npm install -g ganache-cli
To start a local Ethereum network with Ganache, run the following command:
ganache-cli
This will start a local blockchain network on http://127.0.0.1:8545 with 10 pre-funded accounts.
Metamask is a browser extension that allows you to manage Ethereum accounts and interact with the blockchain. It acts as a bridge between your browser and the Ethereum network, enabling you to send transactions and interact with smart contracts directly from your browser.
To install Metamask, visit the Metamask website and follow the instructions to add the extension to your browser.
Smart contracts are the backbone of blockchain applications. In this section, we will learn the basics of Solidity and write a simple smart contract.
A Solidity contract is a collection of code (functions) and data (state variables) that resides at a specific address on the Ethereum blockchain. Here is a simple example of a Solidity contract:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract SimpleStorage {
uint256 public storedData;
function set(uint256 x) public {
storedData = x;
}
function get() public view returns (uint256) {
return storedData;
}
}
In this contract, we define a state variable storedData to store a value, and two functions set and get to update and retrieve the value, respectively.
Let's write a simple smart contract for storing and retrieving a value.
Create a new directory for your project and navigate into it:
mkdir my-blockchain-app
cd my-blockchain-app
Initialize a new Truffle or Hardhat project:
# Using Truffle
truffle init
# Using Hardhat
npx hardhat
Create a new file SimpleStorage.sol in the contracts directory and add the following code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract SimpleStorage {
uint256 public storedData;
function set(uint256 x) public {
storedData = x;
}
function get() public view returns (uint256) {
return storedData;
}
}
Next, we need to compile and deploy the smart contract to the local Ethereum network.
Compile the contract:
truffle compile
Deploy the contract:
Create a new file 2_deploy_contracts.js in the migrations directory and add the following code:
const SimpleStorage = artifacts.require("SimpleStorage");
module.exports = function (deployer) {
deployer.deploy(SimpleStorage);
};
Run the deployment script:
truffle migrate
Compile the contract:
npx hardhat compile
Deploy the contract:
Create a new file deploy.js in the scripts directory and add the following code:
async function main() {
const SimpleStorage = await ethers.getContractFactory("SimpleStorage");
const simpleStorage = await SimpleStorage.deploy();
console.log("SimpleStorage deployed to:", simpleStorage.address);
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
Run the deployment script:
npx hardhat run scripts/deploy.js
Now that we have deployed our smart contract, we need to interact with it from our frontend application. We will use Web3.js or Ethers.js to connect our React application to the Ethereum network and interact with the smart contract.
Next.js is a popular framework for building React applications with server-side rendering and routing capabilities. Let's set up a new Next.js application.
Create a new Next.js application:
npx create-next-app my-blockchain-app
cd my-blockchain-app
Web3.js and Ethers.js are JavaScript libraries that allow you to interact with the Ethereum blockchain from your frontend application.
Install Web3.js or Ethers.js:
# Install Web3.js
npm install web3
# Or install Ethers.js
npm install ethers
To interact with the Ethereum network from our React application, we need to connect to Metamask. Here is an example of how to do this using Web3.js:
import Web3 from 'web3';
if (typeof window.ethereum !== 'undefined') {
const web3 = new Web3(window.ethereum);
try {
// Request account access
await window.ethereum.enable();
// Accounts now exposed
} catch (error) {
console.error("User denied account access...");
}
}
Let's create a React component to interact with our smart contract.
Create a new file SimpleStorage.js in the components directory and add the following code:
import React, { useEffect, useState } from 'react';
import Web3 from 'web3';
const SimpleStorage = ({ contract }) => {
const [storedValue, setStoredValue] = useState(0);
const [inputValue, setInputValue] = useState('');
useEffect(() => {
const getStoredValue = async () => {
const value = await contract.methods.get().call();
setStoredValue(value);
};
getStoredValue();
}, [contract]);
const handleSet = async () => {
const accounts = await web3.eth.getAccounts();
await contract.methods.set(inputValue).send({ from: accounts[0] });
setInputValue('');
};
return (
<div>
<h1>Stored Value: {storedValue}</h1>
<input
type="number"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
/>
<button onClick={handleSet}>Set Value</button>
</div>
);
};
export default SimpleStorage;
Update the index.js file to use the SimpleStorage component:
import React, { useEffect, useState } from 'react';
import Web3 from 'web3';
import SimpleStorage from '../components/SimpleStorage';
import SimpleStorageContract from '../build/contracts/SimpleStorage.json';
const Home = () => {
const [web3, setWeb3] = useState(null);
const [contract, setContract] = useState(null);
useEffect(() => {
const initWeb3 = async () => {
if (typeof window.ethereum !== 'undefined') {
const web3Instance = new Web3(window.ethereum);
try {
await window.ethereum.enable();
setWeb3(web3Instance);
const networkId = await web3Instance.eth.net.getId();
const deployedNetwork = SimpleStorageContract.networks[networkId];
const contractInstance = new web3Instance.eth.Contract(
SimpleStorageContract.abi,
deployedNetwork && deployedNetwork.address
);
setContract(contractInstance);
} catch (error) {
console.error("User denied account access...");
}
}
};
initWeb3();
}, []);
return (
<div>
<h1>Blockchain Application</h1>
{web3 && contract ? <SimpleStorage contract={contract} /> : <p>Loading...</p>}
</div>
);
};
export default Home;
Let's build a user-friendly interface to interact with our smart contract. We will create components to display data from the blockchain and handle user inputs and transactions.
Create a new file SimpleStorage.js in the components directory and add the following code:
import React, { useEffect, useState } from 'react';
const SimpleStorage = ({ contract }) => {
const [storedValue, setStoredValue] = useState(0);
const [inputValue, setInputValue] = useState('');
useEffect(() => {
const getStoredValue = async () => {
const value = await contract.methods.get().call();
setStoredValue(value);
};
getStoredValue();
}, [contract]);
const handleSet = async () => {
const accounts = await web3.eth.getAccounts();
await contract.methods.set(inputValue).send({ from: accounts[0] });
setInputValue('');
};
return (
<div>
<h1>Stored Value: {storedValue}</h1>
<input
type="number"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
/>
<button onClick={handleSet}>Set Value</button>
</div>
);
};
export default SimpleStorage;
The SimpleStorage component retrieves the stored value from the blockchain and displays it in the UI. It also provides an input field and a button to update the stored value.
The handleSet function retrieves the user's account from Metamask and sends a transaction to update the stored value in the smart contract.
In this section, we will create our own coin (ERC-20 token) and integrate it with our platform. ERC-20 is a standard interface for tokens, providing basic functionalities to transfer tokens and allow them to be approved to be spent by another on-chain third party.
We will write a simple ERC-20 token contract using OpenZeppelin, a library for secure smart contract development.
Install OpenZeppelin:
npm install @openzeppelin/contracts
Create a new file MyToken.sol in the contracts directory and add the following code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract MyToken is ERC20, Ownable {
constructor(uint256 initialSupply) ERC20("MyToken", "MTK") {
_mint(msg.sender, initialSupply);
}
function mint(address to, uint256 amount) public onlyOwner {
_mint(to, amount);
}
}
Next, we need to compile and deploy the token contract.
Compile the contract:
truffle compile
Deploy the contract:
Create a new file 3_deploy_token.js in the migrations directory and add the following code:
const MyToken = artifacts.require("MyToken");
module.exports = function (deployer) {
deployer.deploy(MyToken, 1000000);
};
Run the deployment script:
truffle migrate
Compile the contract:
npx hardhat compile
Deploy the contract:
Create a new file deploy_token.js in the scripts directory and add the following code:
async function main() {
const MyToken = await ethers.getContractFactory("MyToken");
const myToken = await MyToken.deploy(1000000);
console.log("MyToken deployed to:", myToken.address);
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
Run the deployment script:
npx hardhat run scripts/deploy_token.js
We will create a React component to interact with our token contract.
Create a new file Token.js in the components directory and add the following code:
import React, { useEffect, useState } from 'react';
import Web3 from 'web3';
const Token = ({ contract }) => {
const [balance, setBalance] = useState(0);
const [recipient, setRecipient] = useState('');
const [amount, setAmount] = useState('');
useEffect(() => {
const getBalance = async () => {
const accounts = await web3.eth.getAccounts();
const balance = await contract.methods.balanceOf(accounts[0]).call();
setBalance(balance);
};
getBalance();
}, [contract]);
const handleTransfer = async () => {
const accounts = await web3.eth.getAccounts();
await contract.methods.transfer(recipient, amount).send({ from: accounts[0] });
setRecipient('');
setAmount('');
};
return (
<div>
<h1>Token Balance: {balance}</h1>
<input
type="text"
value={recipient}
onChange={(e) => setRecipient(e.target.value)}
placeholder="Recipient Address"
/>
<input
type="number"
value={amount}
onChange={(e) => setAmount(e.target.value)}
placeholder="Amount"
/>
<button onClick={handleTransfer}>Transfer Tokens</button>
</div>
);
};
export default Token;
Update the index.js file to use the Token component:
import React, { useEffect, useState } from 'react';
import Web3 from 'web3';
import SimpleStorage from '../components/SimpleStorage';
import Token from '../components/Token';
import SimpleStorageContract from '../build/contracts/SimpleStorage.json';
import TokenContract from '../build/contracts/MyToken.json';
const Home = () => {
const [web3, setWeb3] = useState(null);
const [storageContract, setStorageContract] = useState(null);
const [tokenContract, setTokenContract] = useState(null);
useEffect(() => {
const initWeb3 = async () => {
if (typeof window.ethereum !== 'undefined') {
const web3Instance = new Web3(window.ethereum);
try {
await window.ethereum.enable();
setWeb3(web3Instance);
const networkId = await web3Instance.eth.net.getId();
// Initialize SimpleStorage contract
const storageDeployedNetwork = SimpleStorageContract.networks[networkId];
const storageInstance = new web3Instance.eth.Contract(
SimpleStorageContract.abi,
storageDeployedNetwork && storageDeployedNetwork.address
);
setStorageContract(storageInstance);
// Initialize Token contract
const tokenDeployedNetwork = TokenContract.networks[networkId];
const tokenInstance = new web3Instance.eth.Contract(
TokenContract.abi,
tokenDeployedNetwork && tokenDeployedNetwork.address
);
setTokenContract(tokenInstance);
} catch (error) {
console.error("User denied account access...");
}
}
};
initWeb3();
}, []);
return (
<div>
<h1>Blockchain Application</h1>
{web3 && storageContract ? <SimpleStorage contract={storageContract} /> : <p>Loading...</p>}
{web3 && tokenContract ? <Token contract={tokenContract} /> : <p>Loading...</p>}
</div>
);
};
export default Home;
Testing is an essential part of the development process. We need to ensure that our smart contracts work as expected before deploying them to a live network.
Let's write tests for our SimpleStorage and MyToken contracts.
Create a new file test/SimpleStorage.test.js and add the following code:
const SimpleStorage = artifacts.require("SimpleStorage");
contract("SimpleStorage", (accounts) => {
it("should store the value 89.", async () => {
const simpleStorageInstance = await SimpleStorage.deployed();
// Set value of 89
await simpleStorageInstance.set(89, { from: accounts[0] });
// Get stored value
const storedData = await simpleStorageInstance.get.call();
assert.equal(storedData, 89, "The value 89 was not stored.");
});
});
Create a new file test/MyToken.test.js and add the following code:
const MyToken = artifacts.require("MyToken");
contract("MyToken", (accounts) => {
it("should mint tokens", async () => {
const myTokenInstance = await MyToken.deployed();
const balance = await myTokenInstance.balanceOf(accounts[0]);
assert.equal(balance.toNumber(), 1000000, "Initial balance is not correct.");
});
it("should transfer tokens", async () => {
const myTokenInstance = await MyToken.deployed();
await myTokenInstance.transfer(accounts[1], 1000, { from: accounts[0] });
const balance1 = await myTokenInstance.balanceOf(accounts[1]);
assert.equal(balance1.toNumber(), 1000, "Balance of account 1 is not correct.");
});
});
Run the tests:
# Using Truffle
truffle test
# Using Hardhat
npx hardhat test
Before deploying the smart contract to the mainnet, it's a good practice to deploy it to a testnet for further testing.
Update the truffle-config.js file to include the configuration for a testnet (e.g., Ropsten):
networks: {
ropsten: {
provider: () =>
new HDWalletProvider(
process.env.MNEMONIC,
`https://ropsten.infura.io/v3/${process.env.INFURA_PROJECT_ID}`
),
network_id: 3, // Ropsten's id
gas: 5500000, // Ropsten has a lower block limit than mainnet
confirmations: 2, // # of confs to wait between deployments. (default: 0)
timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50)
skipDryRun: true // Skip dry run before migrations? (default: false for public nets )
},
},
Deploy the contract to the testnet:
truffle migrate --network ropsten
Once our smart contract is deployed, we can deploy our React application to a hosting service like Vercel.
Install the Vercel CLI:
npm install -g vercel
Deploy the application:
vercel
Follow the prompts to configure and deploy your application to Vercel.
In this section, we will explore advanced topics, including integrating Solana and Rust for high-performance blockchain applications.
Solana is a high-performance blockchain that supports fast and scalable applications. Rust is a systems programming language that is used for writing Solana programs. Here’s how you can integrate Solana and Rust into your blockchain application.
Install Rust:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
Install Solana CLI:
sh -c "$(curl -sSfL https://release.solana.com/v1.8.2/install)"
export PATH="/Users/your-user-name/.local/share/solana/install/active_release/bin:$PATH"
Create a New Solana Project:
cargo new --bin solana-hello-world
cd solana-hello-world
Write a Simple Solana Program:
Create a new file src/main.rs and add the following code:
use solana_program::{
account_info::AccountInfo,
entrypoint,
entrypoint::ProgramResult,
msg,
pubkey::Pubkey,
};
entrypoint!(process_instruction);
pub fn process_instruction(
_program_id: &Pubkey,
_accounts: &[AccountInfo],
_instruction_data: &[u8],
) -> ProgramResult {
msg!("Hello, world!");
Ok(())
}
Build and Deploy the Solana Program:
cargo build-bpf
solana program deploy /path/to/solana-hello-world/target/deploy/solana_hello_world.so
Interact with the Solana Program from Your React App:
import { Connection, PublicKey, clusterApiUrl } from '@solana/web3.js';
const connection = new Connection(clusterApiUrl('devnet'), 'confirmed');
const programId = new PublicKey('your-program-id');
const interactWithSolanaProgram = async () => {
// Implement your interaction logic here
};
interactWithSolanaProgram();
In this comprehensive guide, we have walked through the process of setting up a development environment, writing and deploying smart contracts in Solidity, building a frontend with React and Next.js, creating our own coin, and exploring advanced topics like integrating Solana and Rust. Blockchain development is a vast and evolving field, and there is always more to learn.
Happy coding!