Role: Main developer — owned it end-to-end: the seven Solidity contracts, the Ponder indexer, the Hono API and WS fanout, the auto-graduation keeper, the Next.js frontend, and the Docker/Cloudflare deployment.
Next.js 16 + React 19 App Router on Bun, deliberately scoped to four pages — Discover, Token Detail, Create, and Portfolio. wagmi v2 + viem + RainbowKit for wallet and chain access, TanStack Query patched by a single multiplexed WebSocket instead of polling, and `lightweight-charts` rendering one venue-continuous series that crosses graduation without a visual seam. The trade lifecycle renders optimistically at tx-send and reconciles to indexed truth by transaction hash — values are replaced, never dropped — and the UI makes no finality claim on a fresh trade, escalating confirmation tiers only as the L1 watermarks advance.
Key Features
- Next.js 16 + React 19 App Router on Bun, scoped to four pages: Discover, Token Detail, Create, Portfolio
- wagmi v2 + viem + RainbowKit wallet integration against chain 4663, including mobile wallet connect
- TanStack Query patched by one multiplexed WebSocket — no polling layer anywhere between chain and browser
- `lightweight-charts` price series that crosses curve → Uniswap V3 as one continuous chart with no economic or visual seam
- Optimistic trade lifecycle reconciled to indexed truth by tx hash, with confirmation tiers escalated for trades ≥1 ETH
- Top Holders table and on-chain metadata commitment surfaced as first-class anti-rug transparency
Tech Stack
Frontend
API & Services
Smart Contracts
Infra & Testing
Indexer & Data
Challenges & Solutions
Sub-Second UX Without Lying About Finality
An Orbit L2 reflects trades at sequencer speed in about 100ms, but that is not settlement — showing an instant green check would be a finality claim the chain has not made, while waiting for L1 finality would throw away the entire speed advantage.
Made confirmation an explicit three-tier vocabulary — soft-confirmed, posted-to-L1, finalized — tracked by an indexer watermark poller and read-derived at query time from a row's block number, so tiers are monotonic by construction with no per-row write-back. Propagation is O(1): one broadcast per watermark advance upgrades every held event in every client. The UI renders optimistically and makes no finality claim on a fresh trade, and discloses the tier more prominently once a trade crosses 1 ETH.
Graduating Into a Pool Someone Can Pre-Seed
Graduation mints liquidity into a Uniswap V3 pool that anyone can create and push to an arbitrary price first, turning the migration into a hostile-ratio mint that hands the attacker most of the raised ETH.
Created and initialized the V3 pool at token creation, at the deterministic graduation price, so there is no unclaimed pool to pre-seed. If the price is polluted anyway, the migrator arbs it back to the target tick from curve inventory within bounds and reverts rather than minting at a hostile ratio — leaving the curve retriable instead of drained. Because the pool starts at the curve's terminal price, the chart also continues as one series with no seam.
Anti-Snipe Where Gas Auctions Don't Exist
The chain runs a single first-come-first-served sequencer, so priority fees cannot jump the queue — sniping is a pure latency race, and the usual gas-based mitigations are meaningless. Compounding it, `block.number` returns an L1 estimate on Orbit, so the obvious block-window guard silently misbehaves.
Capped per-transaction buys during an 8-second early window at 2.5% of the graduation target, making a latency win worth only a bounded slice instead of the whole curve, and made the creator's own initial buy atomic with creation so the launcher cannot self-snipe ahead of it. Banned `block.number` in contract logic outright — time-based logic uses `block.timestamp` or `ArbSys.arbBlockNumber()`.
Making Rug-Pulls Structurally Impossible
Launchpad users have no reason to trust an operator's promise not to freeze withdrawals or drain liquidity, and any pause switch or push-payment fee path is a lever someone can eventually pull against them.
Removed the levers instead of promising not to use them: the only pause switches are on creates and buys — no code path can block a curve sell — and every fee leg accrues in-contract as a pull payment swept by permissionless functions, so a hostile treasury or a reverting creator address can at worst break its own claim. The graduated LP NFT goes into an immutable, ownerless vault whose sole external function is `collect()`, and no pause authority of any kind exists after graduation.