DEV Community

sasi
sasi

Posted on

VeriAid — AI-Audited Micro-Philanthropy on Solana

DEV Weekend Challenge: Generosity Edition Submission 💜

This is a submission for Weekend Challenge: Generosity Edition

What I Built

VeriAid is a micro-philanthropy platform where Google Gemini audits every campaign and Solana settles every donation — built for the International Day of Charity.

Two things stop people from giving small amounts to grassroots causes:

  1. You can't tell if it's real. Grassroots campaigns have no audit trail. Donors either give blindly or don't give at all.
  2. Small gifts don't survive the fees. At 2.9% + $0.30, a $2 donation loses 17% before it lands. Micro-giving is economically impossible on card rails.

VeriAid attacks both:

  • Gemini campaign intake audit — every submitted aid request is scored 0–99 for credibility by gemini-2.5-flash, with an urgency classification, a budget-plausibility check against regional market prices, itemized findings, and named risk factors. The prompt is deliberately harsh: vague campaigns with no verifiable location or organizer land in the 30–49 band, and the score is shown to donors before they give.
  • Milestone-gated funds, not lump sums — a campaign is split into milestones (pending → funded → audited). To unlock the next one, the organizer submits a vendor receipt and deliverable notes, and Gemini audits the claimed expense against that milestone's stated scope before approving disbursement.
  • Solana micro-settlement — donations go peer-to-peer from donor to organizer wallet on Devnet with a Memo Program instruction carrying the campaign ID and the donor's message. Fees are ~0.000005 SOL, so a 0.05 SOL gift arrives essentially whole.
  • Zero-install evaluator wallet — the app generates a persistent keypair in localStorage and airdrops Devnet SOL on one click, so you can sign a real transaction without a browser extension.
  • Generosity Copilot — ask "I have 0.2 SOL and want to fund clean water" and Gemini reads the live campaign registry and returns matched campaigns with their trust scores and one-click donate buttons.

Demo

🔗 Live app: https://dev-to-weekend-challenge-generosity-edition-ballsh20t-koodam.vercel.app/

60-second tour:

  1. Look at the top bar — your Devnet evaluator wallet is already provisioned. Hit +Faucet for 1 SOL.
  2. Click "AI Audit" on Maya's Urgent Pediatric Cardiac Surgery (99% trust) or Kerala Monsoon Relief (96%) — you get the full Gemini report: trust score, urgency, budget sanity check, key findings, risk factors.
  3. Click "Request Aid" and submit a deliberately vague campaign ("need money for stuff"). Gemini will score it in the 30s and tell you exactly why. This is the fun part — the auditor actually pushes back.
  4. Donate 0.05 SOL with a message of hope → transaction signs, confetti fires, and you get an explorer link.
  5. Submit a receipt inside a campaign's milestone and watch Gemini audit the expense against the deliverable.
  6. Ask the Copilot for causes matching your budget.

The flow:

       [ Grassroots Aid Request ]
                   │
                   ▼
     ┌────────────────────────────┐
     │  Google Gemini 2.5 Flash   │ ──► Trust Score (0-99)
     │  Intake Verification Agent │ ──► Budget Sanity Check
     └────────────────────────────┘ ──► Urgency Classification
                   │
                   ▼ (Verified)
     ┌────────────────────────────┐
     │   VeriAid Registry Feed    │
     └────────────────────────────┘
                   │
                   ▼ (Donor Micro-Contribution)
     ┌────────────────────────────┐
     │       Solana Devnet        │ ──► Sub-second finality
     │   Peer-to-Peer + Memo      │ ──► Fees < $0.001
     └────────────────────────────┘ ──► On-chain donor message
                   │
                   ▼ (Milestone Completion)
     ┌────────────────────────────┐
     │  Gemini AI Receipt Auditor │ ──► Vendor & deliverable audit
     └────────────────────────────┘ ──► Disbursement authorization
Enter fullscreen mode Exit fullscreen mode

Code

https://github.com/voiddata/dev-to-challenges/tree/main/weekend_challenge_generosity_edition

src/lib/gemini.ts            # 3 Gemini agents: intake audit, receipt audit, donor copilot
src/lib/solana.ts            # Devnet connection, sandbox keypair, airdrop, transfer + memo
src/lib/campaign-store.ts    # Campaign registry, donation recording, milestone state machine
src/lib/sample-data.ts       # 5 seeded campaigns across 5 aid categories
src/app/api/
  gemini/verify              # POST — audit a new campaign
  gemini/copilot             # POST — conversational campaign matching
  campaigns/[id]/donate      # POST — record an on-chain donation
  campaigns/[id]/audit-receipt  # POST — audit a milestone receipt
src/components/              # 13 components: cards, detail modal, donate, receipt audit, copilot, ledger
scripts/test-engine.ts       # End-to-end suite across store, Gemini, and Solana layers
Enter fullscreen mode Exit fullscreen mode

Next.js 14 App Router + TypeScript, Tailwind, @google/genai, @solana/web3.js. No database, no external backend — clone, npm install, npm run dev.

How I Built It

Gemini as an auditor, not a chatbot

The interesting design decision was making Gemini adversarial toward its own users. A trust score is worthless if everything scores 95%, so the intake prompt hands Gemini an explicit scoring rubric with anchored bands:

const response = await ai.models.generateContent({
  model: 'gemini-2.5-flash',
  contents: prompt,
  config: {
    responseMimeType: 'application/json',
    temperature: 0.2,
  },
});
Enter fullscreen mode Exit fullscreen mode

responseMimeType: 'application/json' is what makes this production-viable — Gemini returns parseable structured output directly, no regex-scraping fenced code blocks. temperature: 0.2 keeps scores stable across identical submissions, which matters when a number is a trust signal to a donor.

The rubric bands (0–29 fake, 30–49 vague, 50–64 gaps, 65–79 credible, 80–94 strong, 95–99 exceptional) were the fix for a real problem: with an unanchored "score 0–100" prompt, Gemini clustered everything at 85+ and flattered every campaign. Anchoring the bands with concrete failure criteria made it genuinely willing to fail a submission.

Every parsed field is then clamped and defaulted server-side, so a malformed model response degrades into a low-confidence report instead of a crash:

trustScore: Math.min(99, Math.max(0, parsed.trustScore ?? 50)),
Enter fullscreen mode Exit fullscreen mode

The receipt auditor is the same pattern pointed at a narrower question: does this vendor, amount, and description actually match the milestone's stated deliverable? It returns a confidence score plus a flaggedDiscrepancies array, and disbursementApproved gates the milestone transition.

Solana as the reason micro-giving works at all

Solana isn't decoration here — it's the enabling constraint. The entire product premise (fund one water filter for 0.05 SOL) only exists on a chain where fees round to zero.

Donations carry a Memo Program v2 instruction, so the donor's message and campaign reference live on-chain alongside the transfer rather than in my database:

const transaction = new Transaction().add(
  SystemProgram.transfer({
    fromPubkey: fromKeypair.publicKey,
    toPubkey: recipientPubkey,
    lamports: Math.round(amountSol * LAMPORTS_PER_SOL),
  })
);

transaction.add({
  keys: [{ pubkey: fromKeypair.publicKey, isSigner: true, isWritable: true }],
  programId: new PublicKey('MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr'),
  data: Buffer.from(`VeriAid Giving: ${memoText}`, 'utf-8'),
});
Enter fullscreen mode Exit fullscreen mode

The friction I actually spent the most time on

Wallet onboarding kills demos. Asking a judge to install Phantom, switch to Devnet, and find a faucet is three chances to lose them before they see anything.

So the app provisions its own keypair in localStorage on first load and wires a one-click faucet button next to the balance. Before every transfer it checks the on-chain balance and auto-airdrops if you're short. When the public Devnet faucet rate-limits (429s are common on hackathon weekends), the donation completes in a Sandbox Relayer mode that records the gift locally and labels the receipt accordingly, so a rate-limited faucet doesn't dead-end the walkthrough. With a funded wallet, transfers are fully on-chain and explorer-verifiable.

There's also a settings modal for bringing your own Gemini key at runtime, and every Gemini call falls back to a deterministic heuristic audit if no key is configured — so a fresh clone with an empty .env still demos end to end.

Prize Categories

🌟 Best Use of Google AI

Gemini is the product's trust layer, not a feature bolted on. Three distinct agents on gemini-2.5-flash via @google/genai, all using structured JSON output: an adversarial intake auditor with an anchored scoring rubric that will fail a weak campaign, a receipt auditor that gates real fund disbursement on expense-to-deliverable matching, and a donor copilot that reasons over the live campaign registry. Remove Gemini and VeriAid is just another donation form.

⚡ Best Use of Solana

Solana is the precondition for the whole idea. Sub-penny fees are what make a 0.05 SOL gift viable when card rails would eat 17% of it, and sub-second finality is what makes the donate-and-see-it-land moment feel instant. Donations are non-custodial peer-to-peer transfers with on-chain memos, paired with a zero-install sandbox wallet that generates, funds, and signs in the browser in seconds.


Generosity scales when it's verifiable. VeriAid makes small giving both provable and worth doing.

Top comments (0)