Skip to content

About

Frontend for Lendify, an Aave-style lending market on Sepolia. Next.js App Router, wagmi v2, viem, RainbowKit — no backend, reads live from chain.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Lendify

A dense, dark-mode frontend for Lendify, an Aave-style lending protocol deployed on Sepolia. Supply collateral, borrow against it, get liquidated if your health factor drops below 1.00 — all read and written straight from the chain. There's no backend, no database, and no indexer; every number on screen comes from a live contract call.

Built with Next.js 16 (App Router, Turbopack), wagmi v2, viem, and RainbowKit.

Screenshots

Markets

Live reserve data for all four listed assets — price, supply/borrow totals, APYs, utilization, LTV and liquidation threshold shown as separate columns.

Markets page

Dashboard

Your position at a glance: total supplied/borrowed, net APY, health factor (color-coded, with an explainer for what triggers liquidation), and per-asset supply/borrow rows with a collateral toggle.

Dashboard with a healthy, mostly-collateral position

Dashboard after borrowing against WBTC and DAI

Supply flow

Opening the Supply modal for USDC — the amount input reads the wallet's real balance for the Max button, not a cached figure.

Supply USDC modal

Approvals are explicit two-step actions ("1. Approve" → "2. Supply") rather than a single button that silently asks for a second signature:

MetaMask spending-cap approval as step 1 of 2

Dashboard after the supply confirms, with USDC now marked as collateral

Liquidations

Paste a borrower address (or pick one from Borrow event logs) to inspect their health factor and, if it's below 1.00, liquidate part of their debt for a collateral bonus.

Liquidate page

Admin

Owner-gated reserve configuration — freeze/activate/enable-borrowing per asset, adjust LTV and liquidation parameters, pause the whole pool, and (testnet-only) push fresh prices through the mock price feed.

Admin: pool pause, demo price controls, WETH reserve config

Admin: WBTC, USDC, and DAI reserve config

Getting started

pnpm install
pnpm dev

Open http://localhost:3000 and connect a wallet on Sepolia.

WalletConnect project ID

RainbowKit needs a WalletConnect Cloud project ID for the QR/mobile wallet flow. Without one, an injected wallet (e.g. MetaMask's browser extension) still works, but you'll see a console warning. Create a project at cloud.reown.com and set it in .env.local:

NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=your-project-id

YouTube video

Video link: https://www.youtube.com/watch?v=N6pNZwhzdQs&t=6s

Scripts

  • pnpm dev — start the dev server (Turbopack)
  • pnpm build — production build, type-checked
  • pnpm test — unit tests for the decimal/RAY conversion helpers in lib/format.ts and lib/math.ts
  • pnpm dlx @wagmi/cli generate — regenerate lib/generated.ts after editing an ABI or wagmi.config.ts

Contracts (Sepolia, chain ID 11155111)

Contract Address
LendingPool 0x0e45445C291304b0c7bF6343CCfa75228f96dB2D
LendifyDataProvider 0x395Cf49c6e01DD43b89633C0671439BAaA1Cc2c7
PriceOracle 0xff8529Ec32d4040E4AF0132358C1aBa8962289D8
WETHGateway 0x1C67F08F127C96D36C29E33472805feefC997fE8
MockAssetFactory (faucet + demo prices) 0x6F8EDdE53001D82CAEb573E86211beaA3dA1fF33
Token Address Decimals
WETH 0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14 18
USDC 0xF190509003A16265c317A9606699F69558ce36f0 6
DAI 0x3E2b8428f63A26E3e7193Dc541591DCA1be30238 18
WBTC 0x84Cc70BaEA953Fdf772e8d3AfB8914441626E3fE 8

LendingPoolConfigurator isn't in this table because it isn't a fixed address — the pool looks it up dynamically via LendingPool.configurator(), and the Admin page follows that pointer at runtime rather than hardcoding it.

Addresses and token metadata live in lib/addresses.ts. ABIs are hand-written in lib/abis/ from the documented contract surface (no Foundry out/ or Etherscan verification was available when this was built) — regenerate typed hooks after any change with the command above.

Notes

  • The interest rate curve on the markets page is reconstructed from the single live (utilization, borrowRate) point returned by getAllReserves(), anchored at an assumed 80% kink — there's no on-chain InterestRateModel address in this app's contract surface to sample directly. See lib/rateModel.ts.
  • The liquidations page discovers borrower addresses by reading Borrow event logs from block 0, which can be slow or rate-limited on some public RPCs; the manual address input always works regardless.
  • Contract reads are never retried. A reverting call is a deterministic failure — retrying it can't fix a revert, and doing so anyway delays the error state showing up by several seconds (worse, it can collide with the 15s market refetch interval badly enough that the UI never visibly settles into an error at all). Transient network blips are already retried at the transport layer by viem. See the QueryClient config in app/providers.tsx.
  • Stale price feeds will break every price-dependent read, including the whole Markets page. PriceOracle wraps real Chainlink Sepolia aggregators per asset with a configurable heartbeat; testnet feeds for less-watched pairs (stablecoins, in particular) can go quiet for a long time since nobody has an incentive to keep pushing updates. If reads start reverting with StalePrice(), either push a fresh price through MockAssetFactory (ETH/BTC only) or raise the affected asset's heartbeat via PriceOracle.setAssetFeed(asset, aggregator, heartbeat) — see the Admin page's Demo Controls, or call it directly if you're the oracle owner.

About

Frontend for Lendify, an Aave-style lending market on Sepolia. Next.js App Router, wagmi v2, viem, RainbowKit — no backend, reads live from chain.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages