Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "vite_react_shadcn_ts",
"private": true,
"version": "0.1.753",
"version": "0.1.770",
"type": "module",
"scripts": {
"dev": "vite",
Expand Down
39 changes: 30 additions & 9 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,28 @@
import { useState } from "react";
import { lazy, Suspense, useState } from "react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { Toaster } from "@/components/ui/toaster";
import { Toaster as Sonner } from "@/components/ui/sonner";
import { TooltipProvider } from "@/components/ui/tooltip";
import { ThemeProvider } from "@/components/theme-provider";
import { BrowserRouter, Routes, Route, Navigate } from "react-router-dom";
import Admin from "./pages/Admin";
import GasStation from "./pages/GasStation";
import LiquidationMarkets from "./pages/LiquidationMarkets";
import Analytics from "./pages/Analytics";
import Governance from "./pages/Governance";
import { NetworkProvider } from "./contexts/NetworkContext";
import { LocaleSettingsProvider } from "./contexts/LocaleSettingsContext";
import Index from "./pages/Index";
import { isFeatureEnabled } from "./config";
import CountdownPage from "./pages/Countdown";
import MarketsTable from "./components/MarketsTable";
import Dashboard from "./components/Dashboard";
import Portfolio from "./components/Portfolio";
import PoolsPage from "./pages/Pools";
import PortfolioPage from "./pages/PortfolioPage";
//const LAUNCH_TIMESTAMP = Date.UTC(2025, 10, 21, 2, 0, 0); // Nov 20, 2025 6:00 PM PST (Nov 21, 2025 2:00 AM UTC)
const LAUNCH_TIMESTAMP = Date.now();

const GasStationPage = lazy(() => import("./pages/GasStation"));
const LiquidationMarketsPage = lazy(() => import("./pages/LiquidationMarkets"));

const queryClient = new QueryClient({
defaultOptions: {
queries: {
Expand Down Expand Up @@ -91,17 +92,26 @@ function App() {
/>
<Route path="/admin" element={<Admin />} />
{isFeatureEnabled("enableGasStation") && (
<Route path="/gas-station" element={<GasStation />} />
<Route
path="/gas-station"
element={
<Suspense fallback={null}>
<GasStationPage />
</Suspense>
}
/>
)}
{/*<Route path="/countdown" element={<CountdownPage />} />*/}
{isFeatureEnabled("enableLiquidations") && (
<Route
path="/liquidation-markets"
element={
<LiquidationMarkets
activeTab={activeTab}
onTabChange={setActiveTab}
/>
<Suspense fallback={null}>
<LiquidationMarketsPage
activeTab={activeTab}
onTabChange={setActiveTab}
/>
</Suspense>
}
/>
)}
Expand All @@ -120,6 +130,17 @@ function App() {
element={<Governance />}
/>
)}
{isFeatureEnabled("enablePools") && (
<Route
path="/pools"
element={
<PoolsPage
activeTab={activeTab}
onTabChange={setActiveTab}
/>
}
/>
)}
<Route path="/portfolio" element={<PortfolioPage />} />
<Route path="/portfolio/:address" element={<PortfolioPage />} />
<Route path="*" element={<Navigate to="/" replace />} />
Expand Down
49 changes: 34 additions & 15 deletions src/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import WalletNetworkButton from "@/components/WalletNetworkButton";
import { WalletNetworkUnsupportedBanner } from "@/components/WalletNetworkUnsupportedBanner";
import { LocaleNumberSettings } from "@/components/LocaleNumberSettings";
import { useNetwork } from "@/contexts/NetworkContext";
import { getCurrentGasStationSymbols, isFeatureEnabled } from "@/config";
import { getGasStationSymbols, isFeatureEnabled } from "@/config";
import { useWallet } from "@txnlab/use-wallet-react";

interface HeaderProps {
Expand All @@ -22,10 +22,21 @@ const Header = ({ activeTab, onTabChange }: HeaderProps = {}) => {
const { activeAccount } = useWallet();

// Determine activeTab from location if not provided
const gasStationEnabled = isFeatureEnabled("enableGasStation");
const liquidationsEnabled = isFeatureEnabled("enableLiquidations");

const currentActiveTab = activeTab || (() => {
if (location.pathname === "/pools") return "pools";
if (location.pathname === "/analytics") return "analytics";
if (location.pathname === "/liquidation-markets") return "liquidations";
if (location.pathname === "/gas-station") return "gas-station";
if (
liquidationsEnabled &&
location.pathname === "/liquidation-markets"
) {
return "liquidations";
}
if (gasStationEnabled && location.pathname === "/gas-station") {
return "gas-station";
}
if (location.pathname === "/governance") return "governance";
if (location.pathname === "/portfolio" || location.pathname.startsWith("/portfolio/")) return "portfolio";
if (location.pathname === "/market") return "markets";
Expand All @@ -38,14 +49,16 @@ const Header = ({ activeTab, onTabChange }: HeaderProps = {}) => {
onTabChange(value);
}

if (value === "liquidations") {
if (liquidationsEnabled && value === "liquidations") {
navigate("/liquidation-markets");
} else if (value === "gas-station") {
} else if (gasStationEnabled && value === "gas-station") {
navigate("/gas-station");
} else if (value === "analytics") {
navigate("/analytics");
} else if (value === "governance") {
navigate("/governance");
} else if (value === "pools") {
navigate("/pools");
} else if (value === "portfolio") {
navigate("/portfolio");
} else if (value === "markets") {
Expand All @@ -69,42 +82,48 @@ const Header = ({ activeTab, onTabChange }: HeaderProps = {}) => {
if (onTabChange) {
if (location.pathname === "/analytics") {
onTabChange("analytics");
} else if (location.pathname === "/liquidation-markets") {
} else if (
liquidationsEnabled &&
location.pathname === "/liquidation-markets"
) {
onTabChange("liquidations");
} else if (location.pathname === "/gas-station") {
} else if (gasStationEnabled && location.pathname === "/gas-station") {
onTabChange("gas-station");
} else if (location.pathname === "/governance") {
onTabChange("governance");
} else if (location.pathname === "/pools") {
onTabChange("pools");
} else if (location.pathname === "/portfolio" || location.pathname.startsWith("/portfolio/")) {
onTabChange("portfolio");
} else if (location.pathname === "/market") {
onTabChange("markets");
}
}
}, [location.pathname, onTabChange]);
}, [gasStationEnabled, liquidationsEnabled, location.pathname, onTabChange]);

// Check if current network has gas stations available
const gasStationSymbols = getCurrentGasStationSymbols();
const hasGasStation = gasStationSymbols.length > 0;
const hasGasStation =
gasStationEnabled &&
getGasStationSymbols(currentNetwork).length > 0;

const tabs = [
// { value: 'dashboard', label: 'Dashboard' }, // Temporarily hidden
...(isFeatureEnabled("enablePreFi")
? [{ value: "prefi", label: "PreFi" }]
: []),
{ value: "markets", label: "Markets" },
...(isFeatureEnabled("enablePools")
? [{ value: "pools", label: "Pools" }]
: []),
...(activeAccount ? [{ value: "portfolio", label: "Portfolio" }] : []),
...(isFeatureEnabled("enableLiquidations")
...(liquidationsEnabled
? [{ value: "liquidations", label: "Liquidations" }]
: []),
{ value: "analytics", label: "Analytics" },
...(isFeatureEnabled("enableGovernance")
? [{ value: "governance", label: "Governance" }]
: []),
//{ value: 'swap', label: 'Swap' },
...(isFeatureEnabled("enableGasStation") && hasGasStation
? [{ value: "gas-station", label: "Gas Station" }]
: []),
...(hasGasStation ? [{ value: "gas-station", label: "Gas Station" }] : []),
];

// Hide tabs navigation when only one tab is visible
Expand Down
30 changes: 24 additions & 6 deletions src/components/SupplyBorrowHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,40 @@

import LpPairIconStack from "@/components/pools/LpPairIconStack";

interface SupplyBorrowHeaderProps {
mode: "deposit" | "borrow";
asset: string;
assetIcon: string;
assetPairIcons?: { asset1Icon: string; asset2Icon: string };
}

const SupplyBorrowHeader = ({ mode, asset, assetIcon }: SupplyBorrowHeaderProps) => {
const SupplyBorrowHeader = ({
mode,
asset,
assetIcon,
assetPairIcons,
}: SupplyBorrowHeaderProps) => {
return (
<div className="space-y-2">
<h2 className="text-2xl font-bold text-center text-slate-800 dark:text-white capitalize">
{mode === "deposit" ? "supply" : mode}
</h2>
<div className="flex items-center justify-center gap-2">
<img
src={assetIcon}
alt={asset}
className="w-10 h-10 rounded-full"
/>
{assetPairIcons ? (
<LpPairIconStack
asset1Icon={assetPairIcons.asset1Icon}
asset2Icon={assetPairIcons.asset2Icon}
fallbackIcon={assetIcon}
alt={asset}
size="sm"
/>
) : (
<img
src={assetIcon}
alt={asset}
className="w-10 h-10 rounded-full"
/>
)}
<span className="text-xl font-bold text-slate-800 dark:text-white">{asset}</span>
</div>
</div>
Expand Down
15 changes: 15 additions & 0 deletions src/components/SupplyBorrowModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,10 @@ interface SupplyBorrowModalProps {
isLoadingWalletBalance?: boolean;
/** Parent is loading borrow global data after optimistic modal open. */
isLoadingBorrowGlobalData?: boolean;
/** Optional deposit-mode notice (e.g. Tinyman farm reward disqualification). */
depositNotice?: string;
/** Stacked icons for LP pair markets (underlying assets). */
assetPairIcons?: { asset1Icon: string; asset2Icon: string };
}

const SupplyBorrowModal = ({
Expand Down Expand Up @@ -422,6 +426,8 @@ const SupplyBorrowModal = ({
walletBalanceMarketToken,
isLoadingWalletBalance = false,
isLoadingBorrowGlobalData = false,
depositNotice,
assetPairIcons,
}: SupplyBorrowModalProps) => {
const [amount, setAmount] = useState("");
const [fiatValue, setFiatValue] = useState(0);
Expand Down Expand Up @@ -3393,6 +3399,7 @@ const SupplyBorrowModal = ({
mode={mode}
asset={asset}
assetIcon={assetData.icon}
assetPairIcons={assetPairIcons}
/>
)}
</DialogHeader>
Expand Down Expand Up @@ -3621,6 +3628,14 @@ const SupplyBorrowModal = ({
</div>
)}

{mode === "deposit" && depositNotice ? (
<div className="rounded-lg border border-amber-500/30 bg-amber-500/10 px-3 py-2 mb-4">
<p className="text-xs leading-relaxed text-amber-900 dark:text-amber-100">
{depositNotice}
</p>
</div>
) : null}

<SupplyBorrowForm
key={
mode === "deposit" && selectedDepositAdapterId
Expand Down
30 changes: 23 additions & 7 deletions src/components/WithdrawModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
TooltipTrigger,
} from "@/components/ui/tooltip";
import SupplyBorrowCongrats from "./SupplyBorrowCongrats";
import LpPairIconStack from "@/components/pools/LpPairIconStack";
import { calculateDepositAPY } from "@/utils/apyCalculations";
import { useTokenPrice } from "@/hooks/useTokenPrice";
import { useNetwork } from "@/contexts/NetworkContext";
Expand Down Expand Up @@ -254,6 +255,10 @@ interface WithdrawModalProps {
* receive ALGO (consensus burn after nt200 withdraw).
*/
xalgoConsensusWithdrawAlgoOption?: boolean;
/** Stacked icons for LP pair markets (underlying assets). */
tokenPairIcons?: { asset1Icon: string; asset2Icon: string };
/** Full token name for tooltip when display symbol is a pair label. */
tokenDisplayName?: string;
}

const WithdrawModal = ({
Expand Down Expand Up @@ -288,6 +293,8 @@ const WithdrawModal = ({
positionMarketTokenHuman,
folksWithdrawAdapters = [],
xalgoConsensusWithdrawAlgoOption = false,
tokenPairIcons,
tokenDisplayName,
}: WithdrawModalProps) => {
const withdrawFolksAdapters = folksWithdrawAdapters;
const { currentNetwork } = useNetwork();
Expand Down Expand Up @@ -1380,20 +1387,29 @@ const WithdrawModal = ({
</Select>
) : (
<>
<img
src={tokenIcon}
alt={tokenSymbol}
className="w-12 h-12 rounded-full shadow"
/>
{showTooltip ? (
{tokenPairIcons ? (
<LpPairIconStack
asset1Icon={tokenPairIcons.asset1Icon}
asset2Icon={tokenPairIcons.asset2Icon}
fallbackIcon={tokenIcon}
alt={tokenSymbol}
/>
) : (
<img
src={tokenIcon}
alt={tokenSymbol}
className="w-12 h-12 rounded-full shadow"
/>
)}
{showTooltip || tokenDisplayName ? (
<Tooltip>
<TooltipTrigger asChild>
<span className="text-xl font-semibold text-slate-800 dark:text-white cursor-help underline decoration-dotted">
{tokenSymbol}
</span>
</TooltipTrigger>
<TooltipContent>
<p>{tooltipText}</p>
<p>{tokenDisplayName ?? tooltipText}</p>
</TooltipContent>
</Tooltip>
) : (
Expand Down
Loading
Loading