~/goonerlabs
← All case studies

ViewReward

Live · Algorand
Role
Sole backend developer (~26k LOC)
Timeline
Aug 2023 → present (~2.5 yr)
Chain
Algorand
Scale
1,647 commits · 36 models · 18 controllers · 205 endpoints · 9 crons
Stack
Node · Express · MongoDB (36 models) · Redis (Bull · Redlock) · Algorand SDK · PM2 (cluster)
Advertise → view → earn loopOn-chain transitive Sybil engine3-step on-chain-verified funding4 staking variants + vaultsMulti-type airdrops + NFD targetingAutomated lifecycle + on-chain refunds

ViewReward is advertising with profit-sharing. Projects pay to advertise their products on the platform; a share of that ad revenue is paid back to the viewers who spend their attention on the ads. Users check in, watch the adverts, and claim a reward for their time — and on top of that sits a large airdrop and staking layer. Money moves in both directions on Algorand, which makes the backend's real job being the trustworthy referee between advertisers, viewers, and the ledger.

The problem

The core economic loop is: an advertiser funds an ad campaign → users view it → the platform pays viewers out of the campaign's proceeds → the platform keeps a margin. Every edge of that loop touches money on Algorand, and you cannot trust anything the client tells you about a payment. An advertiser claiming "I funded the campaign" or a user claiming "I'm eligible to claim" has to be proven against the chain. And any pool that pays people for an action is a magnet for Sybil farming — one person running hundreds of wallets to drain a reward.

So the backend has to: verify advertiser funding on-chain before a campaign goes live, meter and pay viewers fairly without being drained, run a sprawling airdrop and staking layer with the same trust guarantees, and reconcile the platform's own take — all while staying adversarial-by-default.

Architecture

Auth is wallet-based: a user logs in with their Algorand address and gets a short-lived JWT access token plus a refresh token in an httpOnly cookie, with silent refresh every few minutes — so the access token stays out of JavaScript's reach while sessions stay seamless.

The hardest decision: prove every payment against the ledger, then defend the pool

Two design choices define this system, and both come from the same principle — never trust a self-reported payment, and never assume a claimer is who they say they are.

A 3-step, on-chain-verified funding flow. Creating a funded campaign or airdrop isn't one request — it's a three-step state machine, each step gated on a transaction the backend independently verifies on-chain:

  1. Create (pending) → the backend returns a dedicated go-between wallet for the advertiser to fund.
  2. Fund + opt-in → the advertiser sends ALGO (to cover transfers, opt-ins, and minimum-balance) and submits the txID; the backend verifies it on-chain before opting the wallet into the asset.
  3. Stock + activate → the advertiser transfers the reward assets and submits that txID; the backend verifies it, then flips the campaign to active.

It's more stateful than a one-click flow and introduces a custodial go-between wallet — I accepted that because it's the only honest way to do it: every value-moving step is confirmed against the ledger before the system commits, so an advertiser can't activate an unfunded campaign and the platform never fronts assets it hasn't received.

An on-chain transitive Sybil-detection engine — the deepest defense. One person spinning up hundreds of wallets to farm a single reward pool is the canonical attack. I built an engine that traces funding graphs across Algorand accounts — following who funded whom, transitively — to cluster wallets that share an origin and exclude the cluster before payout. It reasons about the public ledger, not just per-request rate limits, so it catches coordinated farming that looks innocent one wallet at a time.

What I built around that core

  • A deep airdrop layer. Multiple airdrop types — ASA, ALGO, NFT reserve-claim, video-verified, and sponsor-funded — plus reusable templates, all running through the same on-chain-verified funding and lifecycle machinery, with NFD-segment distribution for targeting holders of a given NFD.
  • Four staking variants. Token staking, NFT staking, VIP-key pools, and APR pools — each with its own accrual and custody rules, backed by vault wallets.
  • Drain-resistant claims. Claims are rate-limited and bounded by per-day user caps and 24-hour cooldowns, so a popular reward can't be emptied by rapid or scripted claiming.
  • Automated financial lifecycle. Cron workers move campaigns through pending → active → inactive → expired and, when one ends, automatically refund the remaining ALGO and tokens to the advertiser (handling opt-in/opt-out and minimum-balance edge cases on-chain).
  • Revenue integrity. Configurable fees, tracked unclaimed balances, and per-ASA revenue accounting, so the platform's take is reconcilable.

Results

  • 1,647 commits, sole author (~26k LOC) — among my largest and longest-running backends — over ~2.5 years, still live, on a PM2 cluster with Redlock concurrency.
  • 36 models · 18 controllers · 205 endpoints · 9 cron workers covering ad campaigns, viewer rewards, airdrops, four staking variants, vaults, fees, and revenue.
  • An on-chain transitive Sybil-detection engine (funding-graph clustering) plus a funding flow where every value-moving step is verified on-chain before the system commits — the properties that make a multi-party reward platform safe to run.

What this demonstrates

Designing for an adversarial environment: a two-sided value loop (advertisers fund, viewers earn) with trustless multi-step settlement verified against the ledger, Sybil-resistant payouts that reason about the public chain, an automated financial lifecycle with on-chain refunds, and secure session handling — the backend discipline that fintech and on-chain-settlement roles screen for.