diff --git a/apps/web/public/celo-logo.svg b/apps/web/public/celo-logo.svg new file mode 100644 index 0000000..eba196b --- /dev/null +++ b/apps/web/public/celo-logo.svg @@ -0,0 +1,13 @@ + + + + + + + + + + diff --git a/apps/web/public/tether-usdt-logo.svg b/apps/web/public/tether-usdt-logo.svg new file mode 100644 index 0000000..e530822 --- /dev/null +++ b/apps/web/public/tether-usdt-logo.svg @@ -0,0 +1 @@ +tether-usdt-logo \ No newline at end of file diff --git a/apps/web/public/usd-coin-usdc-logo.svg b/apps/web/public/usd-coin-usdc-logo.svg new file mode 100644 index 0000000..0ae8f29 --- /dev/null +++ b/apps/web/public/usd-coin-usdc-logo.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/src/app/page.tsx b/apps/web/src/app/page.tsx index a0c0c6b..4891739 100644 --- a/apps/web/src/app/page.tsx +++ b/apps/web/src/app/page.tsx @@ -36,7 +36,7 @@ const stagger = { const STATS = [ { value: "< 5s", label: "Settlement Time" }, - { value: "0.3%", label: "Platform Fee" }, + // { value: "0.3%", label: "Platform Fee" }, { value: "Oracle", label: "Pricing Source" }, { value: "ERC-8004", label: "AI Standard" }, ]; @@ -44,8 +44,8 @@ const STATS = [ const FEATURES = [ { icon: , - title: "Mento Oracle Pricing", - desc: "Swap USDC and USDT at oracle-sourced rates — no AMM slippage, no price manipulation.", + title: "Mento & Uniswap Pricing", + desc: "Swap USDC and USDT at oracle-sourced rates from Mento and Uniswap — no AMM slippage, no price manipulation.", gradient: "from-brand-blue/20 to-blue-600/5", border: "border-brand-blue/15", }, @@ -175,6 +175,14 @@ export default function Home() { backgroundSize: "32px 32px", }} /> +
{[ - { - title: "Oracle-backed rates", - value: "Mento + Uniswap", - }, { title: "Execution guidance", value: "ERC-8004 AI Agent", }, - { - title: "Platform fee", - value: "0.3% displayed upfront", - }, { title: "Settlement", value: "Celo Mainnet", @@ -339,13 +339,13 @@ export default function Home() {

-

0.50 CELO

+

100 USDC

You send

- ~0.04 USDC + ~99.70 USDT

You receive

@@ -652,7 +652,7 @@ export default function Home() {

Launch Swap diff --git a/apps/web/src/components/main-app/panels/swap-panel.tsx b/apps/web/src/components/main-app/panels/swap-panel.tsx index 2c85146..ffe2108 100644 --- a/apps/web/src/components/main-app/panels/swap-panel.tsx +++ b/apps/web/src/components/main-app/panels/swap-panel.tsx @@ -296,8 +296,9 @@ function SwapPanelContent({ return ( <> -
-
+
+ {/* Top Input Container */} +
You Send @@ -328,7 +329,8 @@ function SwapPanelContent({
-
+ {/* Swap Button - Positioned to overlap both containers */} +
-
+ {/* Bottom Input Container */} +
You Receive diff --git a/apps/web/src/components/swap/ai-agent-panel.tsx b/apps/web/src/components/swap/ai-agent-panel.tsx index 9598f53..98e8541 100644 --- a/apps/web/src/components/swap/ai-agent-panel.tsx +++ b/apps/web/src/components/swap/ai-agent-panel.tsx @@ -148,7 +148,7 @@ function AIAgentPanelInner({
- {cfg.label} · Mento oracle + {cfg.label} · {reputation?.averageScore != null && ( diff --git a/apps/web/src/components/swap/swap-interface.tsx b/apps/web/src/components/swap/swap-interface.tsx index 9edf6a4..23ddb4c 100644 --- a/apps/web/src/components/swap/swap-interface.tsx +++ b/apps/web/src/components/swap/swap-interface.tsx @@ -186,7 +186,7 @@ export function SwapInterface() { externalSwapParams={chatSwapParams} /> -
+ {/*
{[ { icon: , @@ -210,7 +210,7 @@ export function SwapInterface() { {text}
))} -
+
*/} diff --git a/apps/web/src/contexts/auth-context.tsx b/apps/web/src/contexts/auth-context.tsx index 94b80b7..3654139 100644 --- a/apps/web/src/contexts/auth-context.tsx +++ b/apps/web/src/contexts/auth-context.tsx @@ -1,12 +1,11 @@ -'use client'; +"use client"; -import { createContext, useContext, useEffect, useState } from 'react'; -import { useAccount, useDisconnect } from 'wagmi'; -import { useQuery, useQueryClient } from '@tanstack/react-query'; -import { useRouter } from 'next/navigation'; -import { useToast } from '@/components/ui/use-toast'; -import { getNonce, verifySignature } from '@/lib/auth/helpers'; -import { useUser } from '@/lib/hooks/useUser'; +import { createContext, useContext, useEffect, useState } from "react"; +import { useAccount, useDisconnect } from "wagmi"; +import { useQueryClient } from "@tanstack/react-query"; +import { useRouter } from "next/navigation"; +import { useToast } from "@/components/ui/use-toast"; +import { getNonce, verifySignature } from "@/lib/auth/helpers"; type User = { id: string; @@ -18,7 +17,9 @@ type AuthContextType = { user: User | null; isAuthenticated: boolean; isLoading: boolean; - login: (signMessageAsync: (message: string) => Promise) => Promise; + login: ( + signMessageAsync: (message: string) => Promise, + ) => Promise; logout: () => void; }; @@ -33,55 +34,51 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { const [isLoading, setIsLoading] = useState(false); const [user, setUser] = useState(null); - // Fetch user profile when wallet is connected - const { data: userProfile, isLoading: isProfileLoading } = useUser(address); - - useEffect(() => { - if (userProfile) { - setUser(userProfile as unknown as User); - } else if (isDisconnected) { - setUser(null); - } - }, [userProfile, isDisconnected]); - - const login = async (signMessageAsync: (message: string) => Promise) => { + const login = async ( + signMessageAsync: (message: string) => Promise, + ) => { if (!address) { - throw new Error('No wallet connected'); + throw new Error("No wallet connected"); } try { setIsLoading(true); - + // Get nonce from server const { nonce, message } = await getNonce(address); - + // Sign the message const signature = await signMessageAsync(message); - + // Verify the signature - const { token, user: userData } = await verifySignature(address, signature, message); - + const { token, user: userData } = await verifySignature( + address, + signature, + message, + ); + // Store the token - if (typeof window !== 'undefined') { - localStorage.setItem('authToken', token); - localStorage.setItem('walletAddress', address); + if (typeof window !== "undefined") { + localStorage.setItem("authToken", token); + localStorage.setItem("walletAddress", address); } - + setUser(userData); - queryClient.invalidateQueries({ queryKey: ['user-profile', address] }); - + queryClient.invalidateQueries({ queryKey: ["user-profile", address] }); + toast({ - title: 'Successfully connected', - description: 'Your wallet has been connected successfully.', + title: "Successfully connected", + description: "Your wallet has been connected successfully.", }); - + router.refresh(); } catch (error) { - console.error('Login error:', error); + console.error("Login error:", error); toast({ - title: 'Error', - description: error instanceof Error ? error.message : 'Failed to connect wallet', - type: 'error', + title: "Error", + description: + error instanceof Error ? error.message : "Failed to connect wallet", + type: "error", }); // Disconnect wallet on error disconnect(); @@ -93,19 +90,19 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { const logout = () => { disconnect(); - if (typeof window !== 'undefined') { - localStorage.removeItem('authToken'); - localStorage.removeItem('walletAddress'); + if (typeof window !== "undefined") { + localStorage.removeItem("authToken"); + localStorage.removeItem("walletAddress"); } setUser(null); queryClient.clear(); - router.push('/'); + router.push("/"); }; const value = { user, isAuthenticated: !!user, - isLoading: isLoading || isProfileLoading, + isLoading, login, logout, }; @@ -116,7 +113,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { export const useAuth = () => { const context = useContext(AuthContext); if (context === undefined) { - throw new Error('useAuth must be used within an AuthProvider'); + throw new Error("useAuth must be used within an AuthProvider"); } return context; }; diff --git a/apps/web/src/lib/minipay/constants.ts b/apps/web/src/lib/minipay/constants.ts index c1ad514..911a21e 100644 --- a/apps/web/src/lib/minipay/constants.ts +++ b/apps/web/src/lib/minipay/constants.ts @@ -30,7 +30,7 @@ export const SWAP_TOKENS = [ address: '0xcebA9300f2b948710d2653dD7B07f33A8B32118C', // Celo Mainnet addressSepolia: '0x2A3684e9Dc20B857375EA04235F2F7edBe818FA7', // Celo Sepolia color: '#2775CA', - logo: '/tokens/usdc.png', + logo: '/usd-coin-usdc-logo.svg', issuer: 'Circle', }, { @@ -40,7 +40,7 @@ export const SWAP_TOKENS = [ address: '0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e', // Celo Mainnet addressSepolia: '0x617f3112bF5ad0E84E882D5142D0aE6C606cc89', // Celo Sepolia color: '#26A17B', - logo: '/tokens/usdt.png', + logo: '/tether-usdt-logo.svg', issuer: 'Tether', }, { @@ -50,7 +50,7 @@ export const SWAP_TOKENS = [ address: '0x471EcE3750Da237f93B8E339c536989b8978a438', // Celo Mainnet addressSepolia: '0xF194AFDF50bAE0a21EF85469d1521810657a1b53', // Celo Sepolia color: '#FCFF52', - logo: '/tokens/celo.png', + logo: '/celo-logo.svg', issuer: 'Celo', }, ] as const; @@ -66,17 +66,17 @@ export const USDM_TOKEN = { // Keep SUPPORTED_TOKENS for Mento SDK compatibility (includes USDm + CELO for rate API) export const SUPPORTED_TOKENS = [ - { ...USDM_TOKEN, logo: '/tokens/usdm.png' }, + { ...USDM_TOKEN, logo: '/usd-coin-usdc-logo.svg' }, { symbol: 'CELO', name: 'Celo', decimals: 18, address: '0x471EcE3750Da237f93B8E339c536989b8978a438', addressSepolia: '0xF194AFDF50bAE0a21EF85469d1521810657a1b53', - logo: '/tokens/celo.png', + logo: '/celo-logo.svg', }, - { symbol: 'USDC', name: 'USD Coin', decimals: 6, address: '0xcebA9300f2b948710d2653dD7B07f33A8B32118C', addressSepolia: '0x2A3684e9Dc20B857375EA04235F2F7edBe818FA7', logo: '/tokens/usdc.png' }, - { symbol: 'USDT', name: 'Tether USD', decimals: 6, address: '0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e', addressSepolia: '0x617f3112bF5ad0E84E882D5142D0aE6C606cc89', logo: '/tokens/usdt.png' }, + { symbol: 'USDC', name: 'USD Coin', decimals: 6, address: '0xcebA9300f2b948710d2653dD7B07f33A8B32118C', addressSepolia: '0x2A3684e9Dc20B857375EA04235F2F7edBe818FA7', logo: '/usd-coin-usdc-logo.svg' }, + { symbol: 'USDT', name: 'Tether USD', decimals: 6, address: '0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e', addressSepolia: '0x617f3112bF5ad0E84E882D5142D0aE6C606cc89', logo: '/tether-usdt-logo.svg' }, ]; // ─── Platform Fee ────────────────────────────────────────────────────────────