Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
6219ff4
feat: inital swap setup
passandscore Jan 19, 2026
6792206
refactor: swap redesign
passandscore Jan 20, 2026
6ed8477
feat: local tokenlist and pricing api
passandscore Jan 20, 2026
f606de6
feat: enhance swap interface with mock quote integration and dual tok…
passandscore Jan 20, 2026
6fbedef
feat: create reusable TokenSelectButton component and improve swap in…
passandscore Jan 20, 2026
d7f6afb
chore: formatting
passandscore Jan 20, 2026
029811e
feat: uniswap quotes
passandscore Jan 20, 2026
8ca0ffe
refactor: swap quote system with pulsing animation
passandscore Jan 20, 2026
7ac9f64
feat: multil-side quotes and switcher logoc
passandscore Jan 20, 2026
86eb762
feat: input odometer effect
passandscore Jan 20, 2026
328e3c8
Add swap interface focus mode with hidden hero sections and still bac…
passandscore Jan 21, 2026
a60d8ec
feat: slippage and review
passandscore Jan 21, 2026
91dce04
refactor: update review swap modal
passandscore Jan 21, 2026
1c9852a
chore: clean up swap files
passandscore Jan 21, 2026
6c7f337
refactor SwapInterface: Extract components and reduce file size
passandscore Jan 21, 2026
cafa070
refactor: fix quotes
passandscore Jan 21, 2026
d2dc4b8
refactor: fix input cursor
passandscore Jan 21, 2026
1708633
refactor: switch logic
passandscore Jan 22, 2026
f7f2219
refactor: fix quote bugs
passandscore Jan 22, 2026
303ca77
refactor: adjust nav header
passandscore Jan 22, 2026
33acdb0
refactor: support 13in macbooks
passandscore Jan 22, 2026
6053506
refactor: action button bug when token switched
passandscore Jan 22, 2026
e6fe948
refactor: remove rounding from wallet balance
passandscore Jan 22, 2026
aa77351
feat: add ETH to token list
passandscore Jan 22, 2026
06b5496
fix: token selection scrolling
passandscore Jan 22, 2026
9ca8cec
refactor: fee teir checks use promise.race & no liquidity errot handling
passandscore Jan 22, 2026
bc7b478
refactor: quote fee tiers
passandscore Jan 22, 2026
8652148
feat: dynamic text input
passandscore Jan 22, 2026
937ed3f
refactor: precentage max bug
passandscore Jan 22, 2026
46cd6e8
refactor: hide visible scroll bar
passandscore Jan 22, 2026
8523238
refactor: redesign swap confirmation
passandscore Jan 22, 2026
42ed47c
feat: weth handling
passandscore Jan 22, 2026
734c595
feat: migrate fast swaps
passandscore Jan 22, 2026
7b5f488
chore: clean up landing
passandscore Jan 22, 2026
e2e9813
refactor: use token list
passandscore Jan 22, 2026
f19b61f
refactor: quote logic
passandscore Jan 23, 2026
6b40bc2
refactor: component restructuring
passandscore Jan 23, 2026
3ef815a
refactor: quote adjustments
passandscore Jan 23, 2026
2cd25c1
refactor: overlay switch button
passandscore Jan 23, 2026
c358a7d
fix: rebase conflict
passandscore Jan 28, 2026
b62e9a8
feat: gas estimate for wrapped operationd
passandscore Jan 26, 2026
e49ee69
fix: remove FastRPC for readOnly calls
passandscore Jan 26, 2026
1476566
refactor: bypass quotes for weth
passandscore Jan 26, 2026
27a6fa8
refactor: adjust contrast on modals
passandscore Jan 28, 2026
998528e
chore: remove unused files
passandscore Jan 28, 2026
6a4d2b9
feat: add fastRPC api endpoints
passandscore Jan 28, 2026
0463104
feat: dummy mode
passandscore Jan 28, 2026
f9c2cfa
feat: review details accordian
passandscore Jan 29, 2026
2841c87
feat: support minOut values
passandscore Jan 29, 2026
173a4ef
feat: mock wagmi wallet connector
passandscore Jan 29, 2026
3d3495b
fix: buikd error
passandscore Jan 29, 2026
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
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,7 @@ EMAILOCTOPUS_LIST_ID="00000000-0000-0000-0000-000000000000"

# Bearer token to access the FastRPC Readonly DB
FAST_RPC_API_TOKEN=""

# Use dummy FastSwap data to test swap flows without production API/contract.
# Set to "true" in .env.local to bypass FastSwap API and show fake success.
# NEXT_PUBLIC_FASTSWAP_DUMMY="true"
57 changes: 57 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"@fuul/sdk": "^7.7.1",
"@hookform/resolvers": "^3.10.0",
"@next/eslint-plugin-next": "^15.4.2",
"@number-flow/react": "^0.5.10",
"@radix-ui/react-accordion": "^1.2.11",
"@radix-ui/react-alert-dialog": "^1.1.14",
"@radix-ui/react-aspect-ratio": "^1.1.7",
Expand Down Expand Up @@ -60,6 +61,7 @@
"ethers": "^6.16.0",
"googleapis": "^169.0.0",
"input-otp": "^1.4.2",
"lenis": "^1.3.17",
"lucide-react": "^0.462.0",
"motion": "^12.23.26",
"next": "^15.5.7",
Expand Down
4 changes: 3 additions & 1 deletion src/app/(app)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ function AppLayoutContent({ children }: { children: React.ReactNode }) {
!hasCheckedStatus &&
status !== "connecting" &&
status !== "reconnecting" &&
(pathname?.startsWith("/dashboard") || pathname?.startsWith("/leaderboard"))
(pathname?.startsWith("/dashboard") ||
pathname?.startsWith("/leaderboard") ||
pathname?.startsWith("/swap"))
) {
// Small tick to ensure RainbowKit's internal state is also ready
const timer = setTimeout(() => {
Expand Down
9 changes: 9 additions & 0 deletions src/app/(app)/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"use client"

import { SwapForm } from "@/components/swap/SwapForm"

const IndexPage = () => {
return <SwapForm />
}

export default IndexPage
28 changes: 28 additions & 0 deletions src/app/api/token-price/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { NextRequest, NextResponse } from "next/server"
import { getTokenPrice } from "@/lib/analytics-server"

export async function GET(request: NextRequest) {
try {
const searchParams = request.nextUrl.searchParams
const symbol = searchParams.get("symbol")

if (!symbol) {
return NextResponse.json({ error: "Symbol parameter is required" }, { status: 400 })
}

const price = await getTokenPrice(symbol)

if (price === null) {
return NextResponse.json({ error: `Failed to fetch ${symbol} price` }, { status: 500 })
}

return NextResponse.json({
success: true,
symbol: symbol.toUpperCase(),
price: price,
})
} catch (error) {
console.error("Error fetching token price:", error)
return NextResponse.json({ error: "Failed to fetch token price" }, { status: 500 })
}
}
16 changes: 16 additions & 0 deletions src/app/api/tokens/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { getUniswapTokenList } from "@/lib/swap-server"
import { NextResponse } from "next/server"

/**
* API route to fetch Uniswap token list
* Used by client-side hooks for token list fetching
*/
export async function GET() {
try {
const tokens = await getUniswapTokenList()
return NextResponse.json(tokens)
} catch (error) {
console.error("Error fetching token list:", error)
return NextResponse.json([], { status: 500 })
}
}
115 changes: 115 additions & 0 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,20 @@ All colors MUST be HSL.
will-change: transform;
}

.custom-scrollbar::-webkit-scrollbar {
width: 4px;
}
.custom-scrollbar::-webkit-scrollbar-track {
background: transparent;
}
.custom-scrollbar::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.1);
border-radius: 10px;
}
.custom-scrollbar::-webkit-scrollbar-thumb:hover {
background: rgba(255, 255, 255, 0.2);
}

@keyframes scroll-footer {
0% {
transform: translateX(0);
Expand All @@ -170,6 +184,107 @@ All colors MUST be HSL.
transform: translateX(-50%);
}
}

@keyframes pulse-3 {
0% {
opacity: 1;
}
8% {
opacity: 0.3;
}
16% {
opacity: 1;
}
24% {
opacity: 0.3;
}
32% {
opacity: 1;
}
40% {
opacity: 0.3;
}
48% {
opacity: 1;
}
100% {
opacity: 1;
}
}

.animate-pulse-3 {
animation: pulse-3 6s cubic-bezier(0.4, 0, 0.6, 1);
will-change: opacity;
}

.animate-pulse-3-loop {
animation: pulse-3 6s cubic-bezier(0.4, 0, 0.6, 1) infinite;
will-change: opacity;
}

@keyframes shimmer {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(100%);
}
}

.animate-shimmer {
animation: shimmer 2s ease-in-out infinite;
}

/* Staggered Exit Animation - The Vanishing Act */
.fade-out-others {
opacity: 0;
transform: scale(0.95);
filter: blur(10px);
pointer-events: none;
transition: all 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}

/* Staggered delays for choreographed animation */
.stagger-1 {
transition-delay: 0ms;
}

.stagger-2 {
transition-delay: 50ms;
}

.stagger-3 {
transition-delay: 100ms;
}

.stagger-4 {
transition-delay: 150ms;
}

.stagger-5 {
transition-delay: 200ms;
}
}

/* Blinking cursor animation for input fields */
@keyframes blink-cursor {
0%,
50% {
opacity: 1;
}
51%,
100% {
opacity: 0;
}
}

/* Ensure input fields have visible blinking cursor */
input[type="text"] {
caret-color: white;
}

input[type="text"]:focus {
caret-color: white;
}

/* Ensure inactive tab content is hidden on mobile (but not tab triggers) */
Expand Down
Loading