I wrote and deployed a demo Web3 store with Solidity and ethers.js.
Users can log in using MetaMask and make purchases.
The store runs without a database; all transaction data is stored on‑chain.
The store was created for learning about solidity and working with smart contracts.
Unfortunately, the book I bought few years ago and the tools it recommends (web3.js, Truffle, Ganache) are now obsolete and no longer maintained, so I had to figure everything out on my own.
First, we needed a tool for building and deploying smart contracts. Modern options are Forge and Hardhat; I chose Forge.
A testnet is required for development. Both Hardhat and Forge provide built‑in local testnets; I used Anvil, Forge’s fast, in‑memory Ethereum node.
Anvil is started from the console. It automatically creates funded accounts and prints the RPC endpoint (e.g., http://127.0.0.1:8545) that MetaMask can connect to.

Connect the MetaMask extension to the RPC URL shown by Anvil, then deploy the compiled contract to that network.
For the contract, we need two functions:
1.Purchase an item. The purchase will transfer funds to the store wallet and record the ID of the purchased item for the buyer.
function purchaseItem(uint8 _itemId) external payable {
uint256 itemCost = 2 gwei; // 0.0012 USD / 0.18 RUB;
// Forward the funds to the seller
(bool success, ) = STORE_ADDRESS.call{value: itemCost}("");
require(success, "Transfer failed");
boughtItems[msg.sender].push(_itemId);
}
2.View purchased items.
function getBoughtItems() external view returns (uint8[] memory) {
return boughtItems[msg.sender];
}
I won't provide tests here. After successful testing and compilation, publish the contract:
forge create ./src/Store.sol:Store \
--private-key <PRIVATE_KEY> \
--rpc-url <RPC_URL> \
--broadcast \
--constructor-args <STORE_PUBLIC_KEY>
After successful publication, we are given the smart contract address.
Next, we'll write the store application. We'll need a library to interact with MetaMask and the blockchain. I used Ethers v6, as I found it to be the most well-documented.
First, connect to the Ethereum wallet through the MetaMask extension.
const provider = new ethers.BrowserProvider(window.ethereum);
Query the balance to ensure it's working correctly.
const signerObj = await provider.getSigner();
const balance = await provider.getBalance(signerObj.address);
const balanceFormatted = ethers.formatEther(balance);
Next, interact with the smart contract.
1.Import abi – a json from the solidity build result.
import ContractArtifact from "***/Store.json";
const abi = ContractArtifact.abi;
2.Create an Contract instance and pass it the smart contract address we received after publish.
const contract = new ethers.Contract(CONTRACT_ADDRESS, abi, signerObj);
3.That's it, you can call the smart contract's functions.
contract.purchaseItem(itemId, {
value: ethers.parseUnits("2", "gwei") // <-- attach the wei
}).then((tx) => {
return tx.wait();
}).then(() => {
const newItems = items.add(itemId);
setItems(newItems);
});
const userItems = await contract.getBoughtItems();
Once the work is complete, you can deploy the store and contract to the live network.
Thanks for reading, any feedback or suggestions are appreciated.



Top comments (0)