Start now →

A .NET Dinosaur in Web3 — Day 5: First dApp. Real UI. Real Blockchain

By Alena .NET Dinosaur · Published May 12, 2026 · 3 min read · Source: Web3 Tag
EthereumWeb3BlockchainAI & Crypto
A .NET Dinosaur in Web3 — Day 5: First dApp. Real UI. Real Blockchain

A .NET Dinosaur in Web3 — Day 5: First dApp. Real UI. Real Blockchain

Alena .NET DinosaurAlena .NET Dinosaur3 min read·Just now

--

Press enter or click to view image in full size
AI Dino — KL amazing place

Honest disclaimer ⚠️Yes, this one is late. The dinosaur went travelling, then came back and started building something. Both count.

Day 5 was about wiring the WishList contract to a real frontend — React, TypeScript, ethers.js, MetaMask. But somewhere between the travel and the code, a project idea formed. Two-week sprint, MVP target. It stays under wraps for now — but the daily insights don’t stop.

Today: the dApp. Soon: something real.

The Goal

Take the WishList contract from Day 4 and make it usable in the real world. (If someone feels like fulfilling one of my wishes — I’m not stopping you).

The code is below:
Solidity: github.com/alena-dev-soft/solidity-learn/contracts/05day/
UI: https://github.com/alena-dev-soft/wishlist-dapp.git

What I Built

WishlistV2 — an upgraded contract plus a React dApp on top of it.

Contract additions:

The frontend stack: Vite + React + TypeScript + ethers.js.

What Actually Clicked

ABI is just an interface.

To call a smart contract from JavaScript, you need its ABI — the list of function signatures. The mental model for .NET developers:

ABI = interface IWishlist in C#

It describes what exists. Not how it works. The frontend doesn’t need the implementation — just the signatures.

provider vs signer — the key distinction.

provider reads from the blockchain — no permissions needed, no gas.
signer represents an account that can authorize transactions. If something changes state, it must be signed.

Blockchain is not a REST API.

In a normal React app — button click, data saves in 50ms, UI updates instantly. In Web3 — the transaction goes to network nodes, gets included in a block, block gets confirmed. On Sepolia that takes 10–15 seconds. await tx.wait() literally waits for the block. This is not a bug. This is the execution model.

isOwner flag — access control in the UI.

The contract enforces owner-only rules on-chain. But the UI should also reflect them — no point showing “Delete” to someone who can’t delete. Solution: load owner() from the contract, compare with the connected wallet, set an isOwner flag. Owner sees all controls. Everyone else sees a read-only list.

A Few Things That Can Waste Your Time

TypeScript doesn’t know about MetaMask out of the box.
window.ethereum isn’t part of the default typings. Quick fix: declare it as any. Good enough for now.

Vite creates a nested folder structure by default. If you run it inside an existing project directory, you end up one level too deep. Easy to miss, costs a few minutes.

Testnet latency is real. Sepolia blocks roughly every ~12 seconds. Even after tx.wait() resolves, the updated state might not be immediately visible.
A small delay or refetch avoids reading stale data.

The Project

The days off weren’t wasted. An idea formed — something that combines what I’m learning with a real use case. Two-week sprint, MVP target. The project stays under wraps for now, but the daily learning logs continue. The insights will keep coming. Just with a different backdrop.

Stage: Dinosaur 🦕 — first dApp live. Backend meets frontend. Something is forming.

This article was originally published on Web3 Tag and is republished here under RSS syndication for informational purposes. All rights and intellectual property remain with the original author. If you are the author and wish to have this article removed, please contact us at [email protected].

NexaPay — Accept Card Payments, Receive Crypto

No KYC · Instant Settlement · Visa, Mastercard, Apple Pay, Google Pay

Get Started →