<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Alena</title>
    <description>The latest articles on Forem by Alena (@alenadevsoft).</description>
    <link>https://forem.com/alenadevsoft</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3908355%2F2225cc41-06f2-4371-a91e-fc6292a4bc7b.jpeg</url>
      <title>Forem: Alena</title>
      <link>https://forem.com/alenadevsoft</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/alenadevsoft"/>
    <language>en</language>
    <item>
      <title>A .NET Dinosaur in Web3. Day 9–10 — MVP of WishList Chain</title>
      <dc:creator>Alena</dc:creator>
      <pubDate>Sat, 23 May 2026 18:00:00 +0000</pubDate>
      <link>https://forem.com/alenadevsoft/a-net-dinosaur-in-web3-day-9-10-mvp-of-wishlist-chain-4fpl</link>
      <guid>https://forem.com/alenadevsoft/a-net-dinosaur-in-web3-day-9-10-mvp-of-wishlist-chain-4fpl</guid>
      <description>&lt;p&gt;&lt;em&gt;"It's alive!!! It's alive!!!"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Days 9 and 10 were about infrastructure — building the bridge between the smart contract and the real world. Supabase, Drizzle, Claude API, a Telegram bot, and a Vercel deploy are classic Web2 tools. But the magic ingredient was &lt;strong&gt;Alchemy webhooks — the definitive Web3 piece&lt;/strong&gt; that connected the blockchain straight into my traditional stack. All of it was new to me.&lt;/p&gt;

&lt;p&gt;And honestly… that was the most interesting part.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Got Built
&lt;/h2&gt;

&lt;p&gt;The full pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Donation → Sepolia → Alchemy webhook →
Next.js API → Claude AI → Supabase →
Telegram Bot → notification to owner
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Live at &lt;a href="https://wish-list-chain.vercel.app" rel="noopener noreferrer"&gt;wish-list-chain.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The app is running on Sepolia (testnet). To try it, make sure your wallet is connected to Sepolia and use test ETH only.&lt;/p&gt;

&lt;p&gt;How to set up Sepolia correctly and get test funds: &lt;a href="https://github.com/alena-dev-soft/wish-list-chain/blob/main/GETTING_STARTED.md" rel="noopener noreferrer"&gt;github.com/alena-dev-soft/wish-list-chain/blob/main/GETTING_STARTED.md&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Supabase + Drizzle
&lt;/h2&gt;

&lt;p&gt;I've worked with .NET EF (Core and Framework) for years. Drizzle is the closest thing to it in the TypeScript ecosystem — and I got familiar with it much faster than I expected.&lt;/p&gt;

&lt;p&gt;The schema is just TypeScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;donations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pgTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;donations&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;defaultRandom&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;primaryKey&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;goalId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;goal_id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;references&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;goals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;notNull&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;donorAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;donor_address&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;notNull&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;numeric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;amount&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;notNull&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;txHash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tx_hash&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;notNull&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;aiComment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ai_comment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;created_at&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;defaultNow&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;notNull&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then &lt;code&gt;npx drizzle-kit generate&lt;/code&gt; produces a SQL migration file. &lt;code&gt;npx drizzle-kit migrate&lt;/code&gt; runs it against the database. That's it. Very simple.&lt;/p&gt;

&lt;p&gt;The .NET analogy is exact: &lt;code&gt;dotnet ef migrations add&lt;/code&gt; followed by &lt;code&gt;dotnet ef database update&lt;/code&gt;. Same mental model, different syntax.&lt;/p&gt;

&lt;p&gt;Supabase also has a Schema Visualizer that automatically draws relationships between tables after migration. Small thing — but satisfying.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alchemy Webhooks — The Blockchain Calls You
&lt;/h2&gt;

&lt;p&gt;This was the conceptual shift of the sprint.&lt;/p&gt;

&lt;p&gt;Instead of polling for changes — asking "did something happen?" on a schedule — the system becomes event-driven. With Alchemy webhooks, the blockchain effectively calls you.&lt;/p&gt;

&lt;p&gt;Every time a &lt;code&gt;DreamPowerIncreased&lt;/code&gt; event fires on the contract, Alchemy sends a POST request to our API route with the raw log data. We decode it with viem's &lt;code&gt;decodeEventLog&lt;/code&gt;, extract the donor address, goal index, and amount, and write it to Supabase.&lt;/p&gt;

&lt;p&gt;The GraphQL filter in Alchemy is precise — we only listen for logs from our specific contract address. Everything else on Sepolia is ignored.&lt;/p&gt;

&lt;p&gt;Testing locally required ngrok. This is a pattern that comes up in any webhook development — your localhost is not publicly accessible. ngrok solves it by giving you a public HTTPS URL that forwards to your local port. One command, done.&lt;/p&gt;

&lt;p&gt;One thing worth noting: if the webhook fires and the handler throws an error, the transaction still happened. The ETH moved. The event was emitted. The blockchain doesn't care that your API crashed. Your handler needs to be idempotent — &lt;code&gt;onConflictDoNothing()&lt;/code&gt; on the donations insert handles duplicate deliveries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Claude API — AI Comments on Donations
&lt;/h2&gt;

&lt;p&gt;Each donation triggers a call to Claude with the goal name and amount. It returns a short encouraging comment, which gets saved and later included in the Telegram notification.&lt;/p&gt;

&lt;p&gt;The integration itself is straightforward — one API call, structured prompt, short response. At this scale, cost is negligible (around $0.002 per comment), so it's not a concern for MVP.&lt;/p&gt;

&lt;h2&gt;
  
  
  Telegram Bot — grammY
&lt;/h2&gt;

&lt;p&gt;The bot is intentionally minimal — just outbound notifications for now. When a donation happens, it sends a message with the goal, amount, sender, and the AI-generated comment. grammY is clean and easy to work with.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpdrn1yssx2i7jakxv6xb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpdrn1yssx2i7jakxv6xb.png" alt="Tg bot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Vercel — Not Just Hosting
&lt;/h2&gt;

&lt;p&gt;I didn't have much experience with Vercel before this. Coming from an Azure background, I expected another cloud platform with configuration overhead.&lt;/p&gt;

&lt;p&gt;It turned out to be much simpler. Connect a GitHub repo, set environment variables, deploy. Vercel detects Next.js automatically, builds it, and gives you a working URL. The whole process took just a few minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One thing that came up during deployment:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Direct Postgres connections can behave unexpectedly in a serverless environment. It's not that they don't work — but they're not designed for short-lived execution. Each function invocation may try to establish a new connection, which doesn't always play well with how serverless functions scale. Using Supabase's transaction pooler solved the issue immediately.&lt;/p&gt;

&lt;p&gt;This is less about Vercel specifically and more about the execution model. Instead of a long-running process managing connections, you have short-lived functions that start, execute, and stop. It's a small detail — but one that can be confusing if you approach it with a traditional backend mindset.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Moment It All Connected
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F595ry43gidiehp37fqfu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F595ry43gidiehp37fqfu.png" alt="Final resul"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's a point where things stop feeling like separate pieces and start behaving like a system.&lt;/p&gt;

&lt;p&gt;For me, it was surprisingly simple.&lt;/p&gt;

&lt;p&gt;Open the app. Connect MetaMask. Click "Donate". Confirm the transaction. Wait a bit.&lt;/p&gt;

&lt;p&gt;And then — a Telegram notification arrives.&lt;/p&gt;

&lt;p&gt;Just because everything is connected.&lt;/p&gt;

&lt;p&gt;It's a strange feeling to see even a small project come alive in the cloud. You can open it, connect your wallet, send a donation to a goal — and it just works. The contract, the frontend, the notifications — all reacting to each other.&lt;/p&gt;

&lt;p&gt;Right now everything is still pretty raw. Over the next few days I want to add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a proper donations list&lt;/li&gt;
&lt;li&gt;maybe some simple dashboards&lt;/li&gt;
&lt;li&gt;and rethink how DreamPower actually grows as more donations come in&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because if the chain is supposed to reflect collective support, then the way this "power" is calculated should probably evolve as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Sprint Taught Me
&lt;/h2&gt;

&lt;p&gt;The Web3 part of this project — the contract, wallet connection, on-chain reads and writes — was actually done a few days ago. What followed was everything around it. Infrastructure. Integrations. Small details that make the system usable.&lt;/p&gt;

&lt;p&gt;And that's probably the most honest picture of what building a dApp looks like. The contract handles trust and transparency. Everything else — storage, notifications, AI, hosting — is still very much traditional engineering.&lt;/p&gt;

&lt;p&gt;The .NET dinosaur is still needed. Just… in a slightly different ecosystem.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Repo:&lt;/strong&gt; &lt;a href="https://github.com/alena-dev-soft/wish-list-chain" rel="noopener noreferrer"&gt;github.com/alena-dev-soft/wish-list-chain&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Follow the journey on Telegram:&lt;/strong&gt; &lt;a href="https://t.me/dotnetToWeb3" rel="noopener noreferrer"&gt;t.me/dotnetToWeb3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Stage: Dinosaur 🦕 — MVP shipped. Testnet live. The system works.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devjournal</category>
      <category>nextjs</category>
      <category>showdev</category>
      <category>web3</category>
    </item>
    <item>
      <title>A .NET Dinosaur in Web3. Day 8 — Reading &amp; Writing — WishList Chain</title>
      <dc:creator>Alena</dc:creator>
      <pubDate>Thu, 21 May 2026 16:30:00 +0000</pubDate>
      <link>https://forem.com/alenadevsoft/a-net-dinosaur-in-web3-day-8-reading-writing-wishlist-chain-4c4o</link>
      <guid>https://forem.com/alenadevsoft/a-net-dinosaur-in-web3-day-8-reading-writing-wishlist-chain-4c4o</guid>
      <description>&lt;p&gt;Long time no see.&lt;/p&gt;

&lt;p&gt;The dinosaur was a bit busy finishing a module on .NET Windows Forms. To be honest, it's not my favourite stack — I'm much more into web development — but it's part of the job.&lt;/p&gt;

&lt;p&gt;Now that I'm done with those tasks, I can finally get back to my favourite projects and the whole learn-in-public vibe.&lt;/p&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Day 8 of trying to get into Web3 turned out to be an amazing experience.&lt;/p&gt;

&lt;p&gt;It didn't feel like just another step where you "add a feature and move on." It felt more like a point where the system actually starts behaving like a system.&lt;/p&gt;

&lt;h2&gt;
  
  
  From Reading to Writing
&lt;/h2&gt;

&lt;p&gt;Reading from the blockchain feels almost like calling a regular API. You ask for data, you get data, you render it.&lt;/p&gt;

&lt;p&gt;Writing introduces a completely different flow.&lt;/p&gt;

&lt;p&gt;Now there's a wallet involved. The user has to confirm the action. The transaction is sent to the network, included in a block, and only then reflected in the UI — and you don't control that timeline anymore.&lt;/p&gt;

&lt;p&gt;At that point it became obvious that building a UI for Web3 is not just about displaying data. It's about handling uncertainty, delays, and state that lives somewhere outside of your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Weird Environment Reality
&lt;/h2&gt;

&lt;p&gt;It seems I might need a more modern laptop — my MacBook almost gave up because of Turbopack. I used it initially, but it was consuming far more resources than expected.&lt;/p&gt;

&lt;p&gt;Nothing critical — I switched back to good old webpack.&lt;/p&gt;

&lt;p&gt;But if you're working on an older machine, it's definitely something to be aware of.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reality of Building UI
&lt;/h2&gt;

&lt;p&gt;The UI is no longer just reactive — it becomes dependent on external events:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the user confirms the transaction (or not)&lt;/li&gt;
&lt;li&gt;the network processes it&lt;/li&gt;
&lt;li&gt;the block is mined&lt;/li&gt;
&lt;li&gt;the state becomes available
And only then can your UI reflect what actually happened.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This introduces a different kind of thinking. You're not just updating state — you're waiting for the system to converge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Things That Actually Matter
&lt;/h2&gt;

&lt;p&gt;There was a moment where the transaction clearly went through — MetaMask confirmed it — but the UI still showed "No goals yet."&lt;/p&gt;

&lt;p&gt;The contract state had changed, but nothing triggered a refetch on the frontend. From the UI perspective, nothing happened.&lt;/p&gt;

&lt;p&gt;And then there was the more serious one.&lt;/p&gt;

&lt;p&gt;At some point I realised I was sending transactions to the wrong contract address.&lt;/p&gt;

&lt;p&gt;Everything looked correct. MetaMask confirmed the transaction. No errors. No warnings.&lt;/p&gt;

&lt;p&gt;And that's exactly the problem.&lt;/p&gt;

&lt;p&gt;In Web3, if you send a transaction to the wrong address — it doesn't fail in a helpful way. It just… succeeds somewhere else.&lt;/p&gt;

&lt;p&gt;There's no backend validation, no "wrong destination" error. The transaction goes through, and from the system's perspective — everything is fine.&lt;/p&gt;

&lt;p&gt;But your funds are gone.&lt;/p&gt;

&lt;p&gt;In my case it was just a test transaction — nothing critical — but it was a very clear reminder: double-check addresses. Every time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Moment
&lt;/h2&gt;

&lt;p&gt;And then it all came together.&lt;/p&gt;

&lt;p&gt;First goal created. First donation sent. DreamPower increased.&lt;/p&gt;

&lt;p&gt;Balance changed. Progress updated. State reflected in the UI.&lt;/p&gt;

&lt;p&gt;End-to-end:&lt;/p&gt;

&lt;p&gt;MetaMask → smart contract → Sepolia → frontend&lt;/p&gt;

&lt;p&gt;At that point it stopped feeling like a collection of separate parts and started feeling like a real system.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Clicked
&lt;/h2&gt;

&lt;p&gt;The biggest shift for me was understanding that in this setup, the blockchain is not just another service.&lt;/p&gt;

&lt;p&gt;It is the backend.&lt;/p&gt;

&lt;p&gt;There's no API layer translating requests. The frontend talks directly to the contract, and that removes an entire layer of abstraction I'm used to in .NET systems.&lt;/p&gt;

&lt;p&gt;It also means that things like latency, consistency, and state management behave differently — and you have to design with that in mind.&lt;/p&gt;

&lt;h2&gt;
  
  
  One More Question
&lt;/h2&gt;

&lt;p&gt;At some point I also started thinking about limits.&lt;/p&gt;

&lt;p&gt;How many users can this support? How many goals can a contract realistically store?&lt;/p&gt;

&lt;p&gt;Technically — a lot. Practically — every write costs gas, and large reads eventually hit limits. It's not something that matters right now, but it's definitely something that will matter later.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Stage: Dinosaur 🦕 — first full interaction. Not just reading. Not just UI. A system that reads, writes, and reacts.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Repo:&lt;/strong&gt; &lt;a href="https://github.com/alena-dev-soft/wish-list-chain" rel="noopener noreferrer"&gt;github.com/alena-dev-soft/wish-list-chain&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Follow the journey on Telegram:&lt;/strong&gt; &lt;a href="https://t.me/dotnetToWeb3" rel="noopener noreferrer"&gt;t.me/dotnetToWeb3&lt;/a&gt;&lt;/p&gt;

</description>
      <category>web3</category>
      <category>dotnet</category>
      <category>beginners</category>
      <category>ethereum</category>
    </item>
    <item>
      <title>A .NET Dinosaur in Web3. Day 7 — First connect</title>
      <dc:creator>Alena</dc:creator>
      <pubDate>Sat, 16 May 2026 18:00:00 +0000</pubDate>
      <link>https://forem.com/alenadevsoft/a-net-dinosaur-in-web3-day-7-first-connect-2ajp</link>
      <guid>https://forem.com/alenadevsoft/a-net-dinosaur-in-web3-day-7-first-connect-2ajp</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;This day is a bit different from the previous ones. Initially, the idea was simple — one contract per day. But Web3 is not just about contracts and blockchain. There are other layers — UI, integration, the way everything connects together. At some point it became obvious: it makes more sense to start structuring the project early, instead of treating each part in isolation. As a developer who is getting close to an architect level — and someone who enjoys microservice architecture — I got curious: how are these projects actually structured?&lt;/p&gt;

&lt;p&gt;A contract is just one piece. A dApp is a system. I assume the same principles apply here — some form of clean architecture, separation of concerns, clear boundaries. And for something like WishList Chain, it felt important to start thinking about the structure from the beginning.&lt;/p&gt;

&lt;p&gt;At that point, I started thinking not just about the contract itself, but about the structure of the whole project. Because Web3 is clearly not only about writing smart contracts. There is always a frontend, some kind of interaction layer, maybe scripts or bots, and potentially even a backend later on. All of these parts are connected, whether you plan for it or not.&lt;/p&gt;

&lt;p&gt;So the question became less about "what to build next" and more about "how to structure it properly from the beginning."&lt;/p&gt;

&lt;p&gt;That's where the idea of using a monorepo came in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Monorepo?
&lt;/h2&gt;

&lt;p&gt;I decided to approach this a bit differently. Usually, I create separate repositories by responsibility (the "S" in SOLID), but not this time.&lt;/p&gt;

&lt;p&gt;Here the picture is clearer. The contract and the frontend are tightly connected. Any change in the contract — new fields, updated logic, even a different address — will require changes in multiple places. That means more manual work, more context switching, and more chances to break something.&lt;/p&gt;

&lt;p&gt;Better to keep things as simple as possible.&lt;/p&gt;

&lt;p&gt;So instead of splitting things too early, I decided to keep everything in one place. A single repository, but clearly separated layers inside it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wish-list-chain/
├── apps/
│   └── web/       ← Next.js 15
├── contracts/     ← Hardhat
├── package.json
└── .env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From a structural point of view, it already feels closer to a real system rather than a set of experiments.&lt;/p&gt;

&lt;p&gt;I know this goes a bit against how I usually structure things. Normally, I prefer to separate repositories by responsibility — the "S" in SOLID. It keeps boundaries clear and makes scaling easier later. But in this case, it felt like the separation would introduce more friction than value. The responsibilities are still separated — just not at the repository level.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Stack
&lt;/h2&gt;

&lt;p&gt;Before the code — a quick map of what we're working with and why.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;.NET analogy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Next.js 15 (App Router)&lt;/td&gt;
&lt;td&gt;Frontend framework&lt;/td&gt;
&lt;td&gt;ASP.NET Core MVC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;wagmi 2&lt;/td&gt;
&lt;td&gt;React hooks for blockchain&lt;/td&gt;
&lt;td&gt;SDK wrapper for Web3 calls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;viem 2&lt;/td&gt;
&lt;td&gt;Low-level Ethereum client&lt;/td&gt;
&lt;td&gt;HttpClient for the blockchain&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RainbowKit&lt;/td&gt;
&lt;td&gt;Wallet connection UI&lt;/td&gt;
&lt;td&gt;OAuth login button&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;@tanstack/react-query&lt;/td&gt;
&lt;td&gt;Async state management&lt;/td&gt;
&lt;td&gt;No direct equivalent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WalletConnect / Reown&lt;/td&gt;
&lt;td&gt;Multi-wallet protocol&lt;/td&gt;
&lt;td&gt;OAuth provider&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Theory — A Little Bit
&lt;/h2&gt;

&lt;p&gt;wagmi sits on top of viem. viem handles the low-level blockchain calls. wagmi provides React hooks like &lt;code&gt;useAccount&lt;/code&gt;, &lt;code&gt;useReadContract&lt;/code&gt;, &lt;code&gt;useWriteContract&lt;/code&gt;. You can drop down to viem when you need more control, but most of the time wagmi is enough.&lt;/p&gt;

&lt;p&gt;RainbowKit is just a UI layer on top of wagmi — the modal, the button, the wallet list. It doesn't do any blockchain work itself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fodo3o96walie4quz7vlg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fodo3o96walie4quz7vlg.png" alt=" " width="800" height="599"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Clicked
&lt;/h2&gt;

&lt;p&gt;Next.js 15 App Router makes everything a Server Component by default. wagmi hooks rely on React state and browser APIs — they can't run on the server. Any component that calls &lt;code&gt;useAccount&lt;/code&gt;, &lt;code&gt;useReadContract&lt;/code&gt;, or renders &lt;code&gt;&amp;lt;ConnectButton /&amp;gt;&lt;/code&gt; needs &lt;code&gt;'use client'&lt;/code&gt; at the top. Otherwise, the code looks correct — but simply doesn't work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ConnectKit doesn't support React 19 yet.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I actually started with ConnectKit — clean UI, good docs, everything looked straightforward. It failed immediately. Peer dependency error: it requires React 17 or 18, while Next.js 15 already ships with React 19. So that path just… stopped there.&lt;/p&gt;

&lt;p&gt;This is the current state of the Web3 frontend ecosystem: some libraries are ahead, some are behind. Check React version compatibility before installing anything.&lt;/p&gt;

&lt;p&gt;Downgrading React didn't feel right. So I kept React 19 and aligned the rest of the stack around it — wagmi 2.x ended up being the stable choice.&lt;/p&gt;

&lt;p&gt;RainbowKit requires wagmi 2. wagmi 3 is out but RainbowKit hasn't released a compatible version yet. Pinning wagmi to version 2 for now. This will resolve eventually — until then, mixing versions breaks the dependency tree.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Result
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;ConnectButton /&amp;gt;&lt;/code&gt; renders. Click it — RainbowKit modal opens with MetaMask, WalletConnect, and others. Connect MetaMask — wallet address and balance appear.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi8ed6ok7xfc7z8lttt3c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi8ed6ok7xfc7z8lttt3c.png" alt=" " width="461" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's a Next.js 15 app reading live data from the Sepolia blockchain through a connected wallet. No backend. No API. The blockchain is the data source.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fivasohu01bvq9gwmyxtb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fivasohu01bvq9gwmyxtb.png" alt=" " width="551" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next: read &lt;code&gt;totalDreamPower&lt;/code&gt; directly from the WishlistV3 contract using &lt;code&gt;useReadContract&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/alena-dev-soft/wish-list-chain" rel="noopener noreferrer"&gt;github.com/alena-dev-soft/wish-list-chain&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Stage: Dinosaur 🦕 — frontend connected. Blockchain is the backend.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>web3</category>
      <category>ethereum</category>
      <category>beginners</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>A .NET Dinosaur in Web3. Day 6 - Wishlist or… “Dream Coins True”?</title>
      <dc:creator>Alena</dc:creator>
      <pubDate>Fri, 15 May 2026 15:07:18 +0000</pubDate>
      <link>https://forem.com/alenadevsoft/a-net-dinosaur-in-web3-day-6-wishlist-or-dream-coins-true-1kb9</link>
      <guid>https://forem.com/alenadevsoft/a-net-dinosaur-in-web3-day-6-wishlist-or-dream-coins-true-1kb9</guid>
      <description>&lt;p&gt;There's something that happened between Day 5 and Day 6 during brainstorming about project ideas. Day 6 wasn't just a deploy session — it was the first day of building something real.&lt;/p&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Brainstorming started as a strategy question — I needed a practice project. Something to learn the full modern Web3 stack and something I could build in public.&lt;/p&gt;

&lt;p&gt;I already have another idea that I've started building, but until the MVP is ready — I decided to keep it under wraps.&lt;/p&gt;

&lt;p&gt;The idea was simple: pick something "common", but complex enough to cover real technical ground.&lt;/p&gt;

&lt;p&gt;Well… I'm a dreamer. So the wishlist idea just felt right.&lt;/p&gt;

&lt;p&gt;I started thinking — is it possible to build something interesting around it? Maybe the idea isn't new. It doesn't really matter… I just like it.&lt;/p&gt;

&lt;p&gt;Take a wishlist, let people make each other's dreams come true and… maybe build something on-chain around it.&lt;/p&gt;

&lt;p&gt;The base Wishlist contract was already written. It was already there — a working smart contract with a React frontend deployed on Sepolia.&lt;/p&gt;

&lt;p&gt;So why not just build something on top of it?&lt;/p&gt;

&lt;p&gt;Multi-user goals, ETH donations for specific goals, a Telegram bot for notifications. A proper monorepo with contract, Supabase, Drizzle, Next.js, and more.&lt;/p&gt;

&lt;p&gt;And then the idea shifted.&lt;/p&gt;

&lt;p&gt;What if every donation increases the "strength" of something?&lt;/p&gt;

&lt;p&gt;A global counter. An on-chain kind of energy. A number that grows every time someone believes in someone else's dream enough to send ETH.&lt;/p&gt;

&lt;p&gt;The working name became WishList Chain (WSHL) — not a token, at least not yet. An on-chain power score. &lt;code&gt;totalDreamPower&lt;/code&gt; in the contract. Every donation adds to it. Every goal has its own dream power.&lt;/p&gt;

&lt;p&gt;(DreamCoin, the name I originally wanted, is apparently already taken — so I had to rethink pretty quickly.)&lt;/p&gt;

&lt;p&gt;Is it a real product? Possibly. Is it a learning project? Definitely. Is the idea somewhat ridiculous? Yes, and that's exactly why it might work in crypto.&lt;/p&gt;

&lt;p&gt;The project is at &lt;a href="https://github.com/alena-dev-soft/wish-list-chain" rel="noopener noreferrer"&gt;github.com/alena-dev-soft/wish-list-chain&lt;/a&gt; — open source.&lt;/p&gt;

&lt;p&gt;Day 6 was about laying the foundation for all of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Goal
&lt;/h2&gt;

&lt;p&gt;Write the core contract for WishList Chain — version 3 of the original Wishlist.sol.&lt;/p&gt;

&lt;p&gt;Multi-user goals, ETH donations, &lt;code&gt;dreamPower&lt;/code&gt; accumulation per goal, &lt;code&gt;totalDreamPower&lt;/code&gt; globally, and a &lt;code&gt;DreamPowerIncreased&lt;/code&gt; event for future Alchemy webhooks. Deploy with Hardhat. Verify on Etherscan.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Contract
&lt;/h2&gt;

&lt;p&gt;WishlistV3 is a different architecture from V2. V2 was one owner, one wishlist. V3 is a shared contract where every wallet has its own goals.&lt;/p&gt;

&lt;p&gt;The .NET analogy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// V2&lt;/span&gt;
&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;WishItem&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;wishes&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// V3&lt;/span&gt;
&lt;span class="nc"&gt;Dictionary&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Goal&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;goals&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Solidity: &lt;code&gt;mapping(address =&amp;gt; Goal[]) public goals&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;struct Goal&lt;/code&gt; gained financial fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Goal&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;targetAmount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;currentAmount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;dreamPower&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;isFulfilled&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;donate()&lt;/code&gt; is the core function. Two things worth noting:&lt;/p&gt;

&lt;p&gt;It must be &lt;code&gt;payable&lt;/code&gt; — without that modifier, Solidity won't accept ETH. The keyword is required, not optional.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Goal storage goal = goals[_owner][_goalIndex]&lt;/code&gt; — &lt;code&gt;storage&lt;/code&gt; means you're working with the actual on-chain data, not a copy. Change it, and the state changes. Use &lt;code&gt;memory&lt;/code&gt; instead, and you're editing a local copy that disappears after the function returns. This distinction doesn't exist in .NET — it's specific to the EVM execution model.&lt;/p&gt;

&lt;p&gt;The event:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="nf"&gt;DreamPowerIncreased&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;indexed&lt;/span&gt; &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;indexed&lt;/span&gt; &lt;span class="n"&gt;goalIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;addedPower&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;newTotalPower&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;indexed&lt;/code&gt; parameters are searchable in logs. They become filter keys — Alchemy webhooks can listen for specific owners or goal indices without scanning every event. The non-indexed parameters are just data payload.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hardhat
&lt;/h2&gt;

&lt;p&gt;Moving from Remix to Hardhat is the next step in my Web3 journey. Remix is a great tool for exploration. Hardhat provides everything needed out of the box, including a proper build pipeline.&lt;/p&gt;

&lt;p&gt;The setup that actually works with Hardhat 3 + viem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; hardhat@latest @nomicfoundation/hardhat-toolbox-viem@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I really like this part — deploy and verify in one command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx hardhat ignition deploy ignition/modules/WishlistV3.ts &lt;span class="nt"&gt;--network&lt;/span&gt; sepolia &lt;span class="nt"&gt;--verify&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fair warning: getting there involved the usual package dependency hell — wrong versions, renamed config keys, cached artifacts. Nothing mysterious, just the standard tax you pay any time you touch a stack that lives and dies by npm. Read the error codes, fix one thing at a time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Project
&lt;/h2&gt;

&lt;p&gt;WishlistV3 is not just a learning exercise. It's the core contract for something that's being built. The &lt;code&gt;donate()&lt;/code&gt; function, the &lt;code&gt;DreamPowerIncreased&lt;/code&gt; event, the multi-user architecture — all of it is designed for a real use case that will be revealed when the MVP is ready.&lt;/p&gt;

&lt;p&gt;Two-week sprint. This was the foundation.&lt;/p&gt;

&lt;p&gt;Contract address: &lt;code&gt;0x90de4a1934d0B062423adAEeDEe37Bb6fD12D0Ca&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Verified: &lt;a href="https://sepolia.etherscan.io/address/0x90de4a1934d0B062423adAEeDEe37Bb6fD12D0Ca" rel="noopener noreferrer"&gt;sepolia.etherscan.io/address/0x90de4a1934d0B062423adAEeDEe37Bb6fD12D0Ca&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Stage: Dinosaur 🦕 — dependency hell survived. Foundation is live.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>web3</category>
      <category>dotnet</category>
      <category>beginners</category>
      <category>ethereum</category>
    </item>
    <item>
      <title>A .NET Dinosaur in Web3. Day 5 - First dApp.</title>
      <dc:creator>Alena</dc:creator>
      <pubDate>Tue, 12 May 2026 07:24:31 +0000</pubDate>
      <link>https://forem.com/alenadevsoft/a-net-dinosaur-in-web3-day-5-first-dapp-1hf3</link>
      <guid>https://forem.com/alenadevsoft/a-net-dinosaur-in-web3-day-5-first-dapp-1hf3</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;⚠️ Honest disclaimer: Yes, this one is late. The dinosaur went travelling, then came back and started building something. Both count.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Today: the dApp. Soon: something real.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Goal
&lt;/h2&gt;

&lt;p&gt;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.)&lt;/p&gt;

&lt;p&gt;Solidity: &lt;a href="http://github.com/alena-dev-soft/solidity-learn/contracts/05day/" rel="noopener noreferrer"&gt;github.com/alena-dev-soft/solidity-learn/contracts/05day/&lt;/a&gt;&lt;br&gt;
UI: &lt;a href="https://github.com/alena-dev-soft/wishlist-dapp.git" rel="noopener noreferrer"&gt;github.com/alena-dev-soft/wishlist-dapp&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;WishlistV2 — an upgraded contract plus a React dApp on top of it.&lt;/p&gt;

&lt;p&gt;Contract additions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;createdAt: block.timestamp&lt;/code&gt; — creation timestamp. Like &lt;code&gt;DateTime.UtcNow&lt;/code&gt; in C# but in Unix seconds, written permanently on-chain.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;deleteWish(uint _index)&lt;/code&gt; — removes a wish. The trick: swap the target with the last element, then &lt;code&gt;pop()&lt;/code&gt;. Cheaper than shifting the entire array. This breaks the original order — acceptable here, but something to be aware of.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The frontend stack: Vite + React + TypeScript + ethers.js.&lt;/p&gt;
&lt;h2&gt;
  
  
  What Actually Clicked
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;ABI is just an interface.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To call a smart contract from JavaScript, you need its ABI — the list of function signatures. The mental model for .NET developers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;ABI&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IWishlist&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It describes what exists. Not how it works. The frontend doesn't need the implementation — just the signatures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;provider vs signer — the key distinction.&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Blockchain is not a REST API.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;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. &lt;code&gt;await tx.wait()&lt;/code&gt; literally waits for the block. This is not a bug. This is the execution model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;isOwner flag — access control in the UI.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;owner()&lt;/code&gt; from the contract, compare with the connected wallet, set an &lt;code&gt;isOwner&lt;/code&gt; flag. Owner sees all controls. Everyone else sees a read-only list.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Few Things That Can Waste Your Time
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;TypeScript doesn't know about MetaMask out of the box.&lt;/strong&gt; &lt;code&gt;window.ethereum&lt;/code&gt; isn't part of the default typings. Quick fix: declare it as &lt;code&gt;any&lt;/code&gt;. Good enough for now.&lt;/p&gt;

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

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

&lt;h2&gt;
  
  
  The Project
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Stage: Dinosaur 🦕 — first dApp live. Backend meets frontend. Something is forming.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>web3</category>
      <category>dotnet</category>
      <category>beginners</category>
      <category>ethereum</category>
    </item>
    <item>
      <title>A .NET Dinosaur in Web3. Day 4 - Writing My First Contract From Scratch</title>
      <dc:creator>Alena</dc:creator>
      <pubDate>Sun, 03 May 2026 15:58:16 +0000</pubDate>
      <link>https://forem.com/alenadevsoft/a-net-dinosaur-in-web3-4-2llg</link>
      <guid>https://forem.com/alenadevsoft/a-net-dinosaur-in-web3-4-2llg</guid>
      <description>&lt;p&gt;Three days of guided exercises. Today — no template, no "here's the complete code, just copy and paste." Just a brief: based on what you know — build your WishList contract.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Task
&lt;/h2&gt;

&lt;p&gt;A personal WishList where only the owner can fulfill a wish. Small enough to finish in one session. Not so small that the decisions made themselves.&lt;/p&gt;

&lt;p&gt;Code: &lt;a href="http://github.com/alena-dev-soft/solidity-learn/contracts/04day/" rel="noopener noreferrer"&gt;github.com/alena-dev-soft/solidity-learn/contracts/04day/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Clicked
&lt;/h2&gt;

&lt;p&gt;The first thing I got tripped up on wasn't syntax — it was initialization. In .NET, almost everything needs to be explicitly initialized, especially array-related types. In Solidity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WishItem[] public wishes;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. The array exists, it's empty, &lt;code&gt;push()&lt;/code&gt; works immediately. The EVM assigns default values at deployment — &lt;code&gt;uint256&lt;/code&gt; is &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;bool&lt;/code&gt; is &lt;code&gt;false&lt;/code&gt;, &lt;code&gt;address&lt;/code&gt; is the zero address.&lt;/p&gt;

&lt;p&gt;Worth noting though: arrays in Solidity aren't free the way they are in .NET. Every &lt;code&gt;push()&lt;/code&gt; is a state change with a gas cost. And "EVM handles defaults" is not the same as "no initialization needed" — that distinction matters once you're working with memory arrays, nested structs, or upgradeable contracts.&lt;/p&gt;

&lt;p&gt;The next decision was identification. Every wish needs some kind of handle — otherwise how do you reference the one you want to fulfill? My instinct was to reach for something explicit, maybe even overcomplicate it. The options in Solidity are straightforward:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Array index — simplest, no overhead&lt;/li&gt;
&lt;li&gt;Manual counter — more control, slightly more code&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mapping(uint256 =&amp;gt; WishItem)&lt;/code&gt; — keyed table, most flexible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Went with array index. &lt;code&gt;fulfillWish(uint _index)&lt;/code&gt; takes the position. For a contract this size, there's no reason to reach for more than you need.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ Fair warning: array index works as an identifier only as long as the array is append-only and items are never removed or reordered.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  On Validation — Index Safety
&lt;/h2&gt;

&lt;p&gt;Nothing in Solidity protects you unless you do it explicitly. Using an array index as an identifier is clean and simple — but only if you validate it first.&lt;/p&gt;

&lt;p&gt;Calling &lt;code&gt;fulfillWish(uint _index)&lt;/code&gt; without a boundary check is asking for trouble. At minimum:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;require(_index &amp;lt; wishes.length, "Invalid index");

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without this, you're relying on implicit behavior and risking unexpected reverts. In .NET you often get guardrails for free. In Solidity — you build them yourself, or they don't exist.&lt;/p&gt;

&lt;h2&gt;
  
  
  On Access Control — There Is No Default Security
&lt;/h2&gt;

&lt;p&gt;The requirement was simple: only the owner can fulfill a wish. What clicked is that in Solidity this isn't a built-in rule — it's just code you have to write.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;require(msg.sender == owner, "Not the owner");

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without this line, anyone can call your function. Solidity doesn't assume intent. It executes what's written — nothing more, nothing less.&lt;/p&gt;

&lt;h2&gt;
  
  
  One Tooling Trap Worth Knowing
&lt;/h2&gt;

&lt;p&gt;I use Edge, and I tend to keep tabs open for days. After a two-day gap — life happens — I came back to Remix with MetaMask still connected from before.&lt;/p&gt;

&lt;p&gt;Here's the gotcha: switching to Sepolia in the top network dropdown isn't enough. The wallet panel at the bottom has its own network selector, and it needs to match. If they silently disagree, you get a gas estimation error with null revert data. Looks exactly like a contract bug. Isn't one.&lt;/p&gt;

&lt;p&gt;Web3 tooling fails loudly and explains itself poorly. File that under "features, probably."&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;Solidity alone is a backend with no front door. The next step is wiring this contract to something a human can actually use — ethers.js, React, TypeScript. The blockchain as a data layer, with a real interface on top.&lt;/p&gt;

&lt;p&gt;That's Day 5.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Stage: Dinosaur 🦕 — first contract, no scaffolding.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>web3</category>
      <category>dotnet</category>
      <category>beginners</category>
      <category>ethereum</category>
    </item>
    <item>
      <title>A .NET Dinosaur in Web3. Day 3 - Voting, Sybil Attacks and Identity</title>
      <dc:creator>Alena</dc:creator>
      <pubDate>Sun, 03 May 2026 09:51:21 +0000</pubDate>
      <link>https://forem.com/alenadevsoft/a-net-dinosaur-in-web3-3-7j9</link>
      <guid>https://forem.com/alenadevsoft/a-net-dinosaur-in-web3-3-7j9</guid>
      <description>&lt;p&gt;Day 3 was the first day that felt like actual software engineering rather than syntax tourism. The task: write a voting contract. Simple enough on the surface - until you start poking at the security model and realize the whole thing has serious gaps in its logic.&lt;/p&gt;

&lt;p&gt;What looked like a toy example turned out to be a good proxy for real system design problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Contract
&lt;/h2&gt;

&lt;p&gt;Instead of dumping a wall of code here, I moved the full contract and instructions to GitHub. This post is about what actually matters - how it works.&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/alena-dev-soft/solidity-learn/tree/main/contracts/03day" rel="noopener noreferrer"&gt;github.com/alena-dev-soft/solidity-learn/contracts/03day/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Clicked
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;struct&lt;/code&gt; → &lt;code&gt;record&lt;/code&gt; in C#&lt;/strong&gt;&lt;br&gt;
Not a class. No methods, no behavior - pure data container. Closer to &lt;code&gt;record&lt;/code&gt;&lt;br&gt;
in C# than anything else.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;mapping(address =&amp;gt; bool)&lt;/code&gt; → &lt;code&gt;Dictionary&amp;lt;address, bool&amp;gt;&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
Exact mental model. The key is a wallet address, the value is whether they've&lt;br&gt;
voted. Lookup is O(1), there's no iteration - same tradeoffs as &lt;code&gt;Dictionary&lt;/code&gt;&lt;br&gt;
in .NET.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;view&lt;/code&gt; modifier → read-only, free to call&lt;/strong&gt;&lt;br&gt;
Methods marked &lt;code&gt;view&lt;/code&gt; don't write to state, so they don't cost gas. The EVM&lt;br&gt;
equivalent of a GET endpoint versus a POST. This clicked immediately because&lt;br&gt;
the cost model maps directly to why you'd separate reads from writes in&lt;br&gt;
any system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;require()&lt;/code&gt; → guard clauses + exception in one&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;require(condition, "message")&lt;/code&gt; is exactly &lt;code&gt;if (!condition) throw new Exception("message")&lt;/code&gt; - except when it reverts, the entire transaction is reverted. No state is changed, but gas is still spent. Closer to a database transaction abort than a simple exception.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Insight
&lt;/h2&gt;

&lt;p&gt;At some point I stopped and asked myself a simple question.&lt;/p&gt;

&lt;p&gt;How does the contract know that "Alice" is actually Alice?&lt;/p&gt;

&lt;p&gt;The answer was a little unsettling - because I've spent years designing systems where knowing who the user is was fundamental. Authentication, authorization, identity verification. That was always the baseline.&lt;/p&gt;

&lt;p&gt;In Web3 there is no baseline like that.&lt;/p&gt;

&lt;p&gt;The contract sees only an address. Just a string starting with &lt;code&gt;0x&lt;/code&gt;. No name, no history, no face. If the same person creates 10 wallets - congratulations, they now have 10 votes.&lt;/p&gt;

&lt;p&gt;This is just how the system works.&lt;/p&gt;

&lt;p&gt;And once that clicks, it quietly rewires how you think about everything else: access control, fairness, "one person = one vote." All the assumptions we carry from Web2 - where identity is tied to accounts, emails, phone numbers - simply don't apply here.&lt;/p&gt;

&lt;p&gt;Ownership of a wallet is not identity. It's just… ownership of a wallet.&lt;/p&gt;

&lt;p&gt;The fix exists, of course. Several of them, actually.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Whitelist&lt;/strong&gt; - the owner manually approves addresses. Simple, but it requires trusting whoever manages the list. And it scales terribly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NFT / Token gating&lt;/strong&gt; - only wallets holding a specific token can participate. Think of it as a membership card. Still doesn't prove who the person is - just that they own the token.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Proof of Humanity&lt;/strong&gt; - on-chain verification that a real human stands behind the address. Technically elegant. Still a largely unsolved problem at scale.&lt;/p&gt;

&lt;p&gt;And then there's the quiet irony: most production solutions still route back to Web2 identity providers - Google, Binance, Microsoft and others. Web3 solved decentralized execution beautifully - identity remains outsourced to the old world.&lt;/p&gt;

&lt;p&gt;So no, dinosaurs aren't extinct yet. Apparently we're still needed. 🦕 (like me 🙃)&lt;/p&gt;

&lt;h2&gt;
  
  
  Side Observations
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Etherscan shows bytecode by default.&lt;/strong&gt; The contract is there, but unreadable - same as looking at compiled IL instead of C# source. To expose the actual Solidity code, you need to verify the contract: upload the source, match the compiler version exactly. One wrong version number and it fails silently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remix doesn't persist deployed contracts across page reloads.&lt;/strong&gt; After a refresh, the contract still exists on-chain - but Remix has no memory of it. Recovery is straightforward: find the contract address on Etherscan, use "At Address" in Remix to reattach. Good to know before it happens in a less forgiving context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testing multi-wallet scenarios requires either Remix VM or separate wallets with testnet ETH.&lt;/strong&gt; Browser Extension mode only sees what MetaMask sees. Not a problem - just a constraint to know upfront.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Day 3 changed something in how I think about system design in Web3.&lt;/p&gt;

&lt;p&gt;In Web2, identity is assumed. You build on top of it. In Web3, identity is your problem to solve - and every solution is either a tradeoff or a dependency on something outside the chain.&lt;/p&gt;

&lt;p&gt;The contract works. The logic is sound. The gaps are in the model, not the code.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Stage: Dinosaur 🦕 - mapping the terrain. Starting to see where the edges are.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Day 4 incoming. 🚀&lt;/p&gt;

</description>
      <category>web3</category>
      <category>dotnet</category>
      <category>beginners</category>
      <category>ethereum</category>
    </item>
    <item>
      <title>A .NET Dinosaur in Web3. Day 2 - Access Control</title>
      <dc:creator>Alena</dc:creator>
      <pubDate>Sun, 03 May 2026 09:44:52 +0000</pubDate>
      <link>https://forem.com/alenadevsoft/a-net-dinosaur-in-web3-2-4g41</link>
      <guid>https://forem.com/alenadevsoft/a-net-dinosaur-in-web3-2-4g41</guid>
      <description>&lt;p&gt;New day, new challenge...&lt;br&gt;
Counter.sol - a little better than "Hello World", right?&lt;/p&gt;

&lt;p&gt;The goal: write a simple Counter contract - increment, decrement, reset -&lt;br&gt;
with real access rules.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Contract
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// SPDX-License-Identifier: MIT&lt;/span&gt;
&lt;span class="n"&gt;pragma&lt;/span&gt; &lt;span class="n"&gt;solidity&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="mf"&gt;0.8.0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;Counter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;owner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;decrement&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Already zero"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Only owner can reset!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub: &lt;a href="http://github.com/alena-dev-soft/solidity-learn/contracts/02day/" rel="noopener noreferrer"&gt;github.com/alena-dev-soft/solidity-learn/contracts/02day/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Clicked
&lt;/h2&gt;

&lt;p&gt;In the .NET world we use &lt;code&gt;HttpContext.User&lt;/code&gt; to know who's making a request. In Solidity it's &lt;code&gt;msg.sender&lt;/code&gt; - the wallet address of whoever called the method. No login system, no JWT, no sessions. Just a cryptographically verified address. The contract knows exactly who you are. Always.&lt;/p&gt;

&lt;p&gt;The next thing - calling &lt;code&gt;count&lt;/code&gt; to check the current value is free.Simple rule: no transaction, no gas.&lt;/p&gt;

&lt;p&gt;But there's a warning that almost everyone forgets - which makes it kind of dangerous for your budget. If you forget to switch from the real network to the test network, those transactions will cost you actual money. Every single one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The .NET → Solidity Map (So Far)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Solidity&lt;/th&gt;
&lt;th&gt;.NET equivalent&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;msg.sender&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;HttpContext.User&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;require()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Guard clause + exception&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;uint256&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;uint&lt;/code&gt; (unsigned)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;address&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;No direct equivalent — wallet ID&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Day 2 Score: 10/10
&lt;/h2&gt;

&lt;p&gt;Everything is mapping cleanly to .NET concepts. The mental model is familiar, the syntax is new.&lt;/p&gt;

&lt;p&gt;Tomorrow I want something with real-world application - not a toy example, but a contract that actually does something useful.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Stage: Dinosaur 🦕 - mapping the terrain.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Day 3 incoming. 🚀&lt;/em&gt;&lt;/p&gt;

</description>
      <category>web3</category>
      <category>dotnet</category>
      <category>beginners</category>
      <category>ethereum</category>
    </item>
    <item>
      <title>A .NET Dinosaur in Web3. Day 1 - First Smart Contract</title>
      <dc:creator>Alena</dc:creator>
      <pubDate>Sun, 03 May 2026 09:37:47 +0000</pubDate>
      <link>https://forem.com/alenadevsoft/a-net-dinosaur-in-web3-1-38g7</link>
      <guid>https://forem.com/alenadevsoft/a-net-dinosaur-in-web3-1-38g7</guid>
      <description>&lt;p&gt;I've been writing .NET for many years. Today I deployed my first smart contract.&lt;br&gt;
Here's what actually happened.&lt;/p&gt;

&lt;p&gt;I'd like to share my journey into Web3 — every single day.&lt;br&gt;
Maybe it'll be helpful for someone out there.&lt;/p&gt;

&lt;p&gt;I love what I do — really. I'm a .NET Dinosaur and Azure-passionate developer,&lt;br&gt;
but let's be honest — the .NET niche isn't exactly overflowing with money 💵.&lt;br&gt;
I've been meaning to try something new for a while. Something with a cool and&lt;br&gt;
live market. Something different. So I chose Web3.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Setup: I Built Myself an AI Mentor
&lt;/h2&gt;

&lt;p&gt;Instead of drowning in YouTube tutorials and boring courses, I did something&lt;br&gt;
a little different. Well — I have ADHD. And I know my brain. It needs dopamine&lt;br&gt;
to stay focused (weird combo, ADHD person and software engineer — but for me,&lt;br&gt;
coding is my dopamine). My brain needs a clear win every single day, not a&lt;br&gt;
promise of understanding. So I configured Claude as my personal AI mentor:&lt;br&gt;
one goal per day, theory only when it's actually needed, and an honest debrief&lt;br&gt;
of where I got stuck.&lt;/p&gt;

&lt;p&gt;Think of it as a personal trainer who never judges you for asking "stupid"&lt;br&gt;
questions, and is available 24/7.&lt;/p&gt;

&lt;p&gt;So — today was Day 1.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Goal
&lt;/h2&gt;

&lt;p&gt;Deploy your first smart contract to a test network and see its address&lt;br&gt;
on the blockchain.&lt;/p&gt;

&lt;p&gt;Simple, concrete — and I received detailed instructions, step by step.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Actually Did
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Set up MetaMask.&lt;/strong&gt; "Piece of cake" — really. I already had an account,&lt;br&gt;
but I'd forgotten my keys (things happen). So I had to create a new one.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Switched to the Sepolia test network.&lt;/strong&gt; A staging environment where&lt;br&gt;
everything works exactly like the real Ethereum network — but you're not&lt;br&gt;
using real money.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Got free test ETH.&lt;/strong&gt; ETH is needed for "gas" — the fee you pay for&lt;br&gt;
every piece of code the blockchain executes. It's free, but finding a working&lt;br&gt;
faucet with an empty wallet took 3 attempts.&lt;br&gt;
&lt;em&gt;(I'm a beginner — I don't have funds for that yet 😅)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Wrote my first Solidity contract in Remix IDE.&lt;/strong&gt; Solidity, by the way,&lt;br&gt;
reads really easily — like other typed languages. For a .NET brain, it's&lt;br&gt;
immediately familiar: classes, constructors, typed fields, public methods.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deployed it.&lt;/strong&gt; One click, one MetaMask confirmation, 30 seconds of&lt;br&gt;
waiting — and pure happiness when I received a contract address.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Where I Got Stuck
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;MetaMask's UI has changed.&lt;/strong&gt; Sometimes my AI mentor provided instructions&lt;br&gt;
for the old version, so finding things took a little more time than expected.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Three faucets, one winner.&lt;/strong&gt; Getting free test ETH required more tries&lt;br&gt;
than expected:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Faucet&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="http://sepoliafaucet.com" rel="noopener noreferrer"&gt;sepoliafaucet.com&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;❌ Requires conditions I didn't meet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://faucets.chain.link/sepolia" rel="noopener noreferrer"&gt;faucets.chain.link/sepolia&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;❌ Asks for LINK tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://cloud.google.com/application/web3/faucet/ethereum/sepolia" rel="noopener noreferrer"&gt;Google Web3 Faucet&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;✅ Worked immediately&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Day 1 Score: 9/10
&lt;/h2&gt;

&lt;p&gt;Easier than expected, honestly. The .NET background helps more than I thought —&lt;br&gt;
typed languages, deployment concepts, staging vs production thinking. It all&lt;br&gt;
maps over. I played with the code and the environment.&lt;/p&gt;

&lt;p&gt;Solidity feels like home. A strange, decentralised, immutable home — but home.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Stage: Dinosaur 🦕 — mapping the terrain.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;See you on Day 2. 🚀&lt;/p&gt;

</description>
      <category>web3</category>
      <category>dotnet</category>
      <category>beginners</category>
      <category>ethereum</category>
    </item>
    <item>
      <title>Hello!</title>
      <dc:creator>Alena</dc:creator>
      <pubDate>Sun, 03 May 2026 09:31:21 +0000</pubDate>
      <link>https://forem.com/alenadevsoft/hello-12p9</link>
      <guid>https://forem.com/alenadevsoft/hello-12p9</guid>
      <description>&lt;p&gt;&lt;strong&gt;I'm a .NET dinosaur. And I'm done being one.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Senior .NET and Azure backend developer, also former Tech Lead. Years of enterprise systems, clean architecture, corporate backend at scale. It's a solid career. It's also, if I'm being honest - started to feel like the same hallway walked in circles.&lt;/p&gt;

&lt;p&gt;So I'm changing direction. Slowly and deliberately.&lt;br&gt;
Not because .NET is bad or I don't like it anymore. But the work got repetitive, the market got crowded, and somewhere along the way the technology stopped feeling like a frontier.&lt;br&gt;
My new space is blockchain. The execution model is different. The trust model is different. The economics are different. And unlike most of my .NET career - the output is visible, verifiable, and lives on a public ledger forever.&lt;br&gt;
So I'm learning Solidity from scratch. Publicly.&lt;/p&gt;

&lt;p&gt;The series "A .NET Dinosaur in Web3" will contain real code, real mistakes, real "naive" thoughts, .NET analogies where they help - and honest notes on what it actually takes to make this switch.&lt;/p&gt;

&lt;p&gt;I started writing on another platform - and will gradually move my "historic" articles here.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Stage: Dinosaur 🦕 - mapping the terrain.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>web3</category>
      <category>solidity</category>
      <category>learning</category>
    </item>
  </channel>
</rss>
