I Built a Solana Tip Jar

Published: (March 7, 2026 at 03:57 AM EST)
5 min read
Source: Dev.to

Source: Dev.to

Kingfaitho

I’ll be honest. When I started this I had no idea what I was doing.

I knew some Solana basics. I’d read the docs, watched a few YouTube videos, nodded along like I understood everything. But actually building something? That was a different story.

So I set myself a challenge: build a real dApp, deploy it, and make it work—no tutorials holding my hand the whole way.

I chose a tip jar. Simple concept: connect your wallet, enter an amount, send SOL to someone. How hard could it be?

Very hard, as it turns out. But I got there.

Why a Tip Jar?

Because I wanted to build something real but not overwhelming.

A lot of beginner Solana tutorials have you building things that are either too simple to be impressive or too complex to actually finish. A tip jar sits right in the middle. It involves:

  • Real wallet connections
  • Real transactions
  • Real money moving on a real blockchain

…but the logic is simple enough that you can understand every line of code you write.

Rule: If you can’t explain what your code does, you don’t really know it.

The Stack I Used

  • Solana + Anchor – for the smart contract
  • React + Vite – for the frontend
  • Phantom wallet – for connecting and signing
  • Vercel – for deployment

I picked Vite over Create React App because CRA feels ancient at this point. Vite is fast, modern, and the developer experience is just better.

How the App Actually Works

  1. Open the app → see a Connect Wallet button.
  2. Click it → Phantom pops up, you approve the connection.
  3. The app now knows your public key, balance, etc.
  4. Type in how much SOL you want to send and hit Send.

Behind the scenes (≈2 seconds):

  • The frontend builds a transaction – think of it as a signed cheque that says who is sending, who is receiving, how much, and includes your signature.
  • The transaction is sent to Solana devnet. Validators check it, confirm it’s legitimate, and execute it.
  • The SOL moves, the blockchain records it permanently.

Done. Nobody can reverse it or lie about it. That permanence is what makes blockchain interesting to me—not the hype, not the price, just the fact that code can enforce rules without a middle‑man.

The Part That Almost Broke Me

Vite and Solana don’t like each other out of the box. Solana’s @solana/web3.js library was built when Webpack ruled everything; it relies on Node.js built‑ins like buffer that Vite deliberately excludes from browser bundles.

I kept getting this error:

Module "buffer" has been externalized for browser compatibility

The fix was two lines:

npm install buffer
// main.tsx
import { Buffer } from "buffer";

window.Buffer = Buffer;

Two lines. That’s it. Sometimes the most painful bugs have the most anticlimactic solutions.

What Anchor Actually Does

Before this project I thought Anchor was optional—a nice‑to‑have. It is not optional.

Writing a Solana program in pure Rust without Anchor is like building furniture with no tools: technically possible, but why would you do that to yourself?

Anchor handles all the boilerplate that would otherwise make you want to quit: account validation, error handling, serialization, etc. It lets you focus on what your program actually does.

Core program logic

pub fn send_tip(ctx: Context, amount: u64) -> Result {
    anchor_lang::system_program::transfer(
        CpiContext::new(
            ctx.accounts.system_program.to_account_info(),
            anchor_lang::system_program::Transfer {
                from: ctx.accounts.sender.to_account_info(),
                to:   ctx.accounts.receiver.to_account_info(),
            },
        ),
        amount,
    )?;

    msg!("Tip sent! 💰");
    Ok(())
}

That CPI (Cross‑Program Invocation) call at the end is basically my program saying, “Hey Solana’s System Program, please move this SOL for me.” Programs on Solana don’t move SOL directly; they ask the System Program to do it. Once that clicked, everything made more sense.

Devnet vs. Mainnet

Everything I built runs on devnet – Solana’s testing environment. Same technology, same speed, but the SOL is fake and free.

Why does that matter? Mistakes on mainnet cost real money. On devnet you can break things, fix them, break them again, and it costs you nothing.

When I was ready to test I airdropped myself some devnet SOL:

solana airdrop 2

Free money. Only on devnet. Enjoy it while you can.

Deploying It

I used Vercel and it took about 3 minutes.

  1. Connect GitHub, import the repo.
  2. Set the root directory to app.
  3. Click Deploy.

That’s genuinely it. Vercel detected the Vite project and handled the rest.

Live app:
Source code:

What I Would Do Differently

A few things I’d change if I started over:

  1. Set up the buffer polyfill first. Don’t discover that error halfway through.
  2. Use devnet from day 1 and make sure Phantom is set to devnet before connecting. Mismatched networks cause confusing errors.
  3. Write tests earlier. Anchor’s TypeScript testing setup is great. I skipped it to move fast and paid for it in debugging time.

What’s Next

This was version one. Here’s what I want to add:

  • A transa… (the post cuts off here)

Transaction History

  • A history view so you can see every tip that was ever sent.
  • A message field so senders can leave a note with their tip.
  • Eventually a mainnet deployment when I’m confident enough to use real SOL.

If You’re Just Starting Out

Build something. Anything.

The docs are good. The tutorials are helpful. But nothing teaches you like staring at an error message at midnight and figuring it out anyway.

  1. Start small.
  2. Finish it.
  3. Deploy it.

Then build the next thing.

That’s the whole strategy.

0 views
Back to Blog

Related posts

Read more »