Year
Tech Stack
Description
Versus started as a product bet and a technical bet at the same time: could we turn SaltyBet AI fighter matches into a live Solana betting experience that felt fast enough for real users?
We built it as a multi-service TypeScript system with a Next.js frontend, Fastify backend, PostgreSQL with Drizzle, Twitch scraper, Solana oracle and jackpot worker running in parallel.
My Role
I worked on the product with Frensurfer over roughly 4 months, half time, while owning the oracle, the Twitch scraper and a lot of the repo coordination work across services.
My part sat close to the parts users never see but immediately feel when they break: phase detection, timing between services, payout logic, refunds, Solana transaction handling and keeping the repo runnable while the product kept moving.
Case Study
Summary
A Solana betting product I built with Frensurfer around live AI fighting matches. It reached public testing, handled 100+ testers and around 150 SOL in total volume before we paused it because we couldn’t maintain it properly.
Context
The product follows SaltyBet AI fighting matches: red fighter versus blue fighter, betting opens, bets lock, the match runs, then the result drives payouts.
We ran it on Solana mainnet during public testing. There was no custom smart contract layer in this version; the oracle managed a private wallet and coordinated the money flow from detected match state.
Problem
The hardest problem was avoiding duplicated state and conflicting timings between the website and the oracle. If the frontend thinks betting is open while the oracle has already moved on, users lose trust immediately.
Twitch chat announces phases, the backend stores match and bet state, the frontend needs live updates, and the oracle has to read Solana transactions before computing winners, refunds, referrals and house fees. Getting those pieces to agree was the real work.
Contributions
Built the Twitch scraper that listens for match phases and sends structured updates to the backend instead of relying on manual admin actions.
Owned the Solana oracle flow around phase changes, private wallet operations, transaction fetching, payout computation, refunds, referral deductions and transfer execution.
Handled a lot of the monorepo work: keeping the frontend, backend, scraper, oracle and jackpot services aligned enough to test and deploy together.
Worked through mainnet edge cases during public testing, including late state changes, invalid matches, refunds and payout paths where the product couldn’t afford vague behavior.
Technical Decisions
We used Server-Sent Events instead of a heavier socket layer because the frontend mostly needs one-way live state: phase changes, match data, volume updates and global stats.
We split the system into frontend, backend, scraper, oracle and jackpot packages so each service could fail, restart and deploy with a narrower responsibility.
The oracle treated invalid matches as a normal branch, not an exception. If only one side had bets, or if a match couldn’t settle cleanly, the system needed a refund path instead of pretending every fight was usable.
We stopped the public test even though the product worked, because maintaining five live services plus a mainnet money flow deserved more time than we could give it.
Result
Versus handled 100+ public testers and roughly 100 SOL of total betting volume before we took it down.
It’s the project that best shows how I think under product pressure: I can care about the betting screen, but I’m also watching the service boundary, the timing bug, the failed payout and the user who just wants to know where their SOL went.

