diff --git a/README.md b/README.md new file mode 100644 index 0000000..d1d69b0 --- /dev/null +++ b/README.md @@ -0,0 +1,60 @@ +# 🛡️ YieldSafe + +**The Next-Generation Yield Aggregator for USDC on Base.** + +YieldSafe is a professional, non-custodial yield vault that allows users to maximize their USDC returns by routing liquidity directly into top-tier DeFi protocols like Aave V3. Built on Base Sepolia for high speed and low fees. + +![YieldSafe Logo](public/logo.svg) + +## 🚀 Features + +- **USDC Optimized**: Specifically designed for USDC liquidity on the Base Network. +- **Auto-Compounding**: Yield is harvested and compounded every block via interest-bearing receipt tokens (aUSDC). +- **One-Click Deposits**: Combined Approve + Deposit transaction flow for a seamless user experience. +- **Glassmorphism UI**: A futuristic, high-end DeFi dashboard designed for professional traders. +- **Institutional-Grade Security**: Built on the battle-tested Aave V3 protocol architecture. + +## 🛠️ Tech Stack + +- **Frontend**: Next.js 16 (App Router), Tailwind CSS +- **Blockchain**: Wagmi, Viem, Reown (AppKit) +- **Styling**: Vanilla CSS Variables + Tailwind Utility Classes +- **Network**: Base Sepolia + +## 📖 Documentation + +Detailed documentation can be found in the `/doc` directory: + +- [Architecture Overview](doc/architecture.md) +- [Setup & Installation](doc/setup.md) +- [Smart Contract Integration](doc/smart-contracts.md) +- [Component Library](doc/components.md) +- [Transaction Flows](doc/flows/deposit.md) + +## 🏗️ Getting Started + +1. **Clone the repository**: + ```bash + git clone https://github.com/emdevelopa/ys-frontend.git + ``` + +2. **Install dependencies**: + ```bash + npm install + ``` + +3. **Configure Environment**: + Create a `.env` file based on the provided template and add your project ID from Reown Cloud. + +4. **Run Development Server**: + ```bash + npm run dev + ``` + +## 🔐 Security + +YieldSafe is non-custodial. Your funds are always in the vault or the underlying liquidity pool (Aave). The smart contract interactions are verified on Base Sepolia. + +--- + +Built with ❤️ by [emdevelopa](https://github.com/emdevelopa) diff --git a/app/app/page.tsx b/app/app/page.tsx index 82bdbe2..f40f3ac 100644 --- a/app/app/page.tsx +++ b/app/app/page.tsx @@ -75,6 +75,12 @@ export default function AppPage() { previewByAssets, ]); + const handleRefresh = useCallback(async () => { + // Add a small delay to allow the chain/indexer to catch up + await new Promise((resolve) => setTimeout(resolve, 2000)); + await refreshData(); + }, [refreshData]); + useEffect(() => { const init = async () => { await refreshData(); @@ -184,14 +190,14 @@ export default function AppPage() { )} {tab === "withdraw" && ( )} diff --git a/app/page.tsx b/app/page.tsx index bb820ab..c2aefd9 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -164,6 +164,16 @@ export default function HomePage() { Next-Gen Liquidity Aggregator +
+
+ + Live on Base Sepolia +
+
+ USDC Native +
+
+

DEPOSIT.
EARN.
@@ -171,7 +181,8 @@ export default function HomePage() {

- Maximize your USDC yield with institutional-grade security. Non-custodial, audited, and powered by Aave V3. + The next-generation vault for your USDC on Base. + Maximize your yield with institutional-grade security. Non-custodial, audited, and powered by Aave V3.

diff --git a/components/Dashboard/BalanceCards.tsx b/components/Dashboard/BalanceCards.tsx index 4aa6133..97b7746 100644 --- a/components/Dashboard/BalanceCards.tsx +++ b/components/Dashboard/BalanceCards.tsx @@ -63,8 +63,11 @@ export const BalanceCards = ({ {card.icon}
-
+
{card.val} + + {card.label.includes("Shares") ? "aUSDC" : "USDC"} +
{card.label} diff --git a/components/Dashboard/RewardsTab.tsx b/components/Dashboard/RewardsTab.tsx index 24ddcbf..88f790a 100644 --- a/components/Dashboard/RewardsTab.tsx +++ b/components/Dashboard/RewardsTab.tsx @@ -44,8 +44,8 @@ export const RewardsTab = ({
Accrued Yield (Live Profit)
-
- ${fmt(accruedYield)} +
+ ${fmt(accruedYield)} USDC
diff --git a/components/Dashboard/StatsGrid.tsx b/components/Dashboard/StatsGrid.tsx index b48e610..ce705da 100644 --- a/components/Dashboard/StatsGrid.tsx +++ b/components/Dashboard/StatsGrid.tsx @@ -37,7 +37,7 @@ export const StatsGrid = ({ {stat.label}
- {stat.val} + {stat.val} {stat.label.includes("TVL") ? "USDC" : ""}
))} diff --git a/doc/architecture.md b/doc/architecture.md index 6e40967..19ec7cd 100644 --- a/doc/architecture.md +++ b/doc/architecture.md @@ -129,35 +129,39 @@ Wallet (EIP-1193 provider) │ ## Frontend-to-Blockchain Communication Diagram ``` -User clicks "Deposit" +User clicks "Deposit USDC" │ ▼ DepositForm.tsx - handleDeposit() + handleDepositFlow() │ - ├─[if allowance < amount]──► useApprove.approve(amount) + ├─[Step 1: Check Allowance] + │ │ + │ ├─[if allowance < amount]──► useApprove.approve(amount) + │ │ │ + │ │ usdcContract.approve( + │ │ YieldSaveVault, amount + │ │ ) + │ │ │ + │ │ wallet signs tx → tx.wait() + │ │ + │ └─[allowance sufficient]───► Skip to Step 2 + │ + ▼ + ├─[Step 2: Deposit]──────────► useDeposit.submitDeposit(amount) │ │ - │ usdcContract.approve( - │ YieldSaveVault, amount - │ ) + │ vaultContract.deposit(amount) │ │ │ wallet signs tx │ │ - │ tx.wait() → confirmed + │ tx.wait() + receipt.status === 1 │ - └─[allowance sufficient]──► useDeposit.submitDeposit(amount) - │ - vaultContract.deposit(amount) - │ - wallet signs tx - │ - tx.wait() + receipt.status === 1 - │ - onSuccess() → refreshData() - │ - re-fetch all balances - │ - UI updates with new state + ▼ + ├─[Step 3: Refresh]──────────► handleRefresh() + │ │ + │ wait(2000ms) → re-fetch all + │ │ + │ UI updates with new balances ``` --- diff --git a/doc/flows/deposit.md b/doc/flows/deposit.md index f3b741b..c147e63 100644 --- a/doc/flows/deposit.md +++ b/doc/flows/deposit.md @@ -2,9 +2,10 @@ ## Overview -Depositing USDC into YieldSafe is a two-step process: -1. **Approve** — grant the vault permission to spend USDC (if not already approved) -2. **Deposit** — transfer USDC to the vault and receive share tokens in return +Depositing USDC into YieldSafe is a seamless, combined flow: +1. **One-Click Action** — The user clicks "Deposit USDC" once. +2. **Sequential Execution** — The app automatically checks allowance, triggers an **Approve** transaction if needed, and then immediately triggers the **Deposit** transaction. +3. **Receipt & Minting** — USDC is transferred to the vault, and interest-bearing share tokens (aUSDC) are minted to the user. Share tokens represent the user's proportional ownership of the vault. As the vault earns yield via Aave, each share becomes worth more USDC over time. @@ -15,101 +16,42 @@ Share tokens represent the user's proportional ownership of the vault. As the va ``` ┌─────────────────────────────────────────────────────────────────────┐ │ USER ACTION │ -│ Navigates to Deposit tab, enters "100" USDC │ +│ Navigates to Deposit tab, enters "100" USDC, clicks "Deposit USDC" │ └──────────────────────────────┬──────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────┐ -│ UI COMPONENT: DepositForm │ +│ STEP 1: ALLOWANCE CHECK │ │ │ -│ onChange → setDepositAmt("100") │ -│ → previewByAssets(100_000_000n) [live preview call] │ -│ → setDepositPreview(sharesResult) │ -│ │ -│ Display: "You will receive X shares" │ -│ Display: "Exchange rate: 1 USDC = Y shares" │ -└──────────────────────────────┬──────────────────────────────────────┘ +│ currentAllowance < 100_000_000n ? │ +└──────────────┬───────────────────────────────┬──────────────────────┘ + │ │ + [Needs Approval] [Already Approved] + ▼ │ +┌──────────────────────────┐ │ +│ SUB-FLOW A: APPROVE │ │ +│ │ │ +│ useApprove.approve() │ │ +│ → Wallet sign → tx.wait() │ +└──────────────┬───────────┘ │ + │ │ + └───────────────┬───────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────┐ -│ ALLOWANCE CHECK │ -│ │ -│ useAllowance.refetchAllowance() │ -│ → usdcContract.allowance(userAddr, vaultAddr) │ -│ → currentAllowance: bigint │ -│ │ -│ needsApproval = currentAllowance < 100_000_000n │ -└──────────────────────────────┬──────────────────────────────────────┘ - │ - ┌───────────────┴───────────────┐ - │ needs approval │ already approved - ▼ ▼ -┌──────────────────────────┐ ┌───────────────────────────────────┐ -│ STEP 1: APPROVE │ │ STEP 2: DEPOSIT (skip to this) │ -│ │ └───────────────────────────────────┘ -│ User clicks │ -│ "Approve USDC" │ -│ │ │ -│ ▼ │ -│ useApprove.approve( │ -│ 100_000_000n │ -│ ) │ -│ │ │ -│ ▼ │ -│ USDC.approve( │ -│ vault, │ -│ 100_000_000n │ -│ ) │ -│ │ │ -│ ▼ │ -│ Wallet signs tx ──────► Base Sepolia blockchain -│ │ │ -│ ▼ │ -│ tx.wait() confirmed │ -│ │ │ -│ ▼ │ -│ refetchAllowance() │ -│ → UI shows Deposit btn │ -└──────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────────────────────────────────────┐ │ STEP 2: DEPOSIT │ │ │ -│ User clicks "Deposit" │ -│ │ │ -│ ▼ │ │ useDeposit.submitDeposit(100_000_000n) │ -│ │ │ -│ ▼ │ -│ YieldSaveVault.deposit(100_000_000n) │ -│ [vault internally calls USDC.transferFrom(user, vault, amount)] │ -│ [vault deposits USDC into Aave V3, receives aUSDC] │ -│ [vault mints share tokens to user] │ -│ │ │ -│ ▼ │ -│ Wallet signs tx ──────────────────────────► Base Sepolia │ -│ │ │ -│ ▼ │ -│ receipt = tx.wait() │ -│ receipt.status === 1 → success │ -│ │ │ -│ ▼ │ -│ onSuccess() called │ +│ → Wallet sign → tx.wait() │ └──────────────────────────────┬──────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────┐ -│ UI UPDATE: refreshData() │ -│ │ -│ Parallel refetch: │ -│ ├── refetchUsdcBalance() → wallet USDC balance (decreased) │ -│ ├── refetchUserShares() → user shares (increased) │ -│ ├── refetchUserBalance() → vault position value (increased) │ -│ ├── refetchUserDeposits() → principal recorded │ -│ └── refetchVaultBalance() → TVL (increased) │ +│ STEP 3: REFRESH DATA (with Delay) │ │ │ -│ All state updates → React re-render → UI reflects new values │ +│ 1. Wait 2000ms (allow block confirmation & indexing) │ +│ 2. Parallel refetch of all balances │ +│ 3. UI updates with new state │ └─────────────────────────────────────────────────────────────────────┘ ``` @@ -159,7 +101,7 @@ This means early depositors are rewarded — their shares are proportionally mor | File | Role in Deposit Flow | |------|---------------------| -| [components/Deposit/DepositForm.tsx](../../components/Deposit/DepositForm.tsx) | UI, form state, orchestrates approve + deposit | +| [components/Deposit/DepositForm.tsx](../../components/Deposit/DepositForm.tsx) | UI, form state, orchestrates combined flow | | [hooks/useAllowance.ts](../../hooks/useAllowance.ts) | Reads current USDC approval | | [hooks/useApprove.ts](../../hooks/useApprove.ts) | Sends approve transaction | | [hooks/useDeposit.ts](../../hooks/useDeposit.ts) | Sends deposit transaction |