Back to projects

Personal project · 2026

DeFi Lens

Senior frontend engineer with end-to-end Web3 architecture ownership

A production-grade Web3 DeFi portfolio dashboard for tracking on-chain holdings, executing safe token transfers, and visualizing DeFi protocol analytics across chains.

The problem

Tracking a DeFi portfolio means reconciling data from disconnected sources — wallet balances, live prices, DEX trade history, protocol TVL — and most tools either oversimplify the transaction lifecycle or expose enough raw complexity that costly mistakes (bad approvals, stuck transactions, phishing) become easy to make.

The solution

DeFi Lens is built around transaction safety and data reconciliation rather than just balance display: every contract write is simulated before it's signed, tracked through an explicit state machine, and confirmed against the chain — not against wallet UI, which can lag or mislead.

Architecture decisions

  • Multi-chain wagmi/viem setup (Base primary, Ethereum mainnet read-only, Base Sepolia for writes) with RainbowKit wallet UI and SIWE + iron-session for encrypted, HttpOnly-cookie authentication.
  • An on-chain data layer combining Alchemy token discovery, viem Multicall batching, and CoinGecko pricing, all proxied server-side through Route Handlers so no API key ever reaches the browser.
  • A transaction safety layer: simulateContract before every write, a Zustand-driven state machine (idle → simulating → broadcasting → pending → confirmed/failed), and human-readable revert-reason parsing instead of raw viem errors.

Trade-offs

  • wagmi's client-only wallet hooks pushed most portfolio components to the client boundary, trading some SSR benefits for direct wallet access.
  • Persisting swap history and portfolio snapshots in IndexedDB (rather than relying solely on TanStack Query's cache) added complexity but was necessary for fast cross-session reloads without a backend database.

Impact

  • Sharpened a concrete state-management discipline — server state in TanStack Query, UI/transaction state in Zustand, with Zustand treated as a last resort rather than a default — which kept the codebase from developing duplicate sources of truth.
  • Turned abstract Web3 concepts (nonce-based replay protection, ECDSA signature recovery, EIP-1559 gas mechanics, approval phishing) into concrete engineering decisions rather than just interview talking points.

What I learned

  • Wallet UI can't always be trusted at face value: a successfully confirmed transfer can look 'missing' in MetaMask's activity feed until the token is manually imported — the block explorer is the real source of truth.
  • Treating a signed transaction hash as 'done' is a common but serious mistake; real confirmation only happens once the receipt is mined, and the UI has to reflect that gap explicitly.

Stack

Next.jsReactTypeScriptwagmiviemRainbowKitTanStack QueryZustandWeb3