The Transition
I started with ordinary web development: React, Node.js and PostgreSQL. Then I began writing smart contracts, and a few of my habits stopped working.
What Is Different
Deployed code cannot be edited
On a normal web app, a bug gets fixed and redeployed. A deployed contract cannot be changed. That makes tests the main tool you have, because they are the only place a mistake is cheap. It is also why I wrote 62 of them for my NFT marketplace.
Gas shapes the design
Every operation costs the user money, so a loop over an unbounded list is a design problem and not only a performance one. My batch minting function accepts at most 20 tokens in one call.
Users hold their own keys
There are no passwords to reset. A user connects a wallet such as MetaMask and signs each transaction, so the front end has to deal with a confirmation step that ordinary web users are not used to.
Chain data is slow to query
Reading history straight from the chain is slow, so my marketplace listens to contract events and stores them in PostgreSQL. The contracts hold the ownership and the database serves the queries.
How I Learned
I wrote small contracts first, then built three projects: an NFT Trading Platform with ERC-721 and marketplace contracts, an event indexer with an analytics dashboard, and MiniWorld, a grid game whose state lives in a contract. All three run on a local Hardhat chain. The tools I used were Hardhat for development and tests, ethers.js to talk to the contracts, OpenZeppelin for the standard contract code, and IPFS through Pinata for metadata.
What I Would Tell Someone Starting
- Read OpenZeppelin's contracts. They show how experienced developers handle edge cases.
- Write the tests that try to break your own contract, not only the ones that pass.
- Keep as much as you can off-chain. Storage on-chain is expensive, so I used IPFS for images and metadata and PostgreSQL for queries.
The code for all three projects is on GitHub.