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
1 change: 0 additions & 1 deletion apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
"private": true,
"scripts": {
"dev": "vite dev --port 3000",
"test": "sh -c 'if [ \"$1\" = --coverage ]; then bun run test:coverage; else bun run test:all; fi' --",
"test:all": "bun test --preload ./setup-tests.ts src/shared src/features/wallet/store src/features/pools src/features/trade src/routes src/lib src/app/providers; bun test --preload ./setup-tests.ts src/features/referrals",
"test:coverage": "bun test --preload ./setup-tests.ts src/shared/lib src/features/trade/lib src/features/pools/lib --coverage",
"build": "vite build",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ export function AdditionalOpportunitiesTab() {
onClick={() => void handleCompound()}
>
Compound
</LoadingButton>
</Button>
}
>
<div className="flex flex-wrap gap-x-8 gap-y-3">
Expand Down
12 changes: 6 additions & 6 deletions apps/web/src/features/earn/components/discover/discover-tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ function PoolCompositionBar({ longPct, shortPct }: { longPct: number; shortPct:
</div>
<p className="text-10 text-muted-foreground">
{longPct}% / {shortPct}%
</Text>
</p>
</div>
)
}
Expand Down Expand Up @@ -206,8 +206,8 @@ export function DiscoverTab() {
<p className="text-10 text-muted-foreground">Pending Rewards</p>
<p className="text-13 font-medium tabular-nums">{formatToken(fromSorobanAmount(stakingInfo.pendingEsSO4Rewards, 7), "esSO4")}</p>
</div>
</CardContent>
</Card>
</div>
</div>
)}

{/* Pool table */}
Expand Down Expand Up @@ -249,7 +249,7 @@ export function DiscoverTab() {
</div>
<p className="ml-auto text-11 text-muted-foreground">
APY based on trailing 30-day performance
</Text>
</p>
</div>

{/* Deposit modal */}
Expand Down Expand Up @@ -350,7 +350,7 @@ function DiscoverRow({
<TokenIcon symbol={row.longToken} size={32} />
<span className="font-medium">{row.name}</span>
</div>
</td>
</TableCell>
<td className="px-5 py-4">
<span
className={cn(
Expand Down Expand Up @@ -378,7 +378,7 @@ function DiscoverRow({
) : (
<span className="text-11 text-muted-foreground">Diversified</span>
)}
</TableCell>
</td>
<TableCell align="right" className="py-4">
<LoadingButton
size="xs"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,7 @@ export function OpportunityCard({
{isAvailable ? actionLabel : "Coming Soon"}
</Button>
</div>
</CardContent>
</Card>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export function DistributionsTab() {
<h3 className="text-13 font-semibold">Distribution History</h3>
</div>
<DistributionsTable distributions={MOCK_DISTRIBUTIONS} />
</Card>
</div>
</div>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,6 @@ export function AssetsList() {
</TableBody>
</Table>
)}
</Card>
</div>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,12 @@ import { useState } from "react"
import { Button } from "@workspace/ui/components/button"
import { Card } from "@workspace/ui/components/card"
import { LoadingButton } from "@workspace/ui/components/loading-button"
import { NumericText } from "@workspace/ui/components/numeric"
import { Heading, Text } from "@workspace/ui/components/text"
import { Text } from "@workspace/ui/components/text"
import { TokenAvatar } from "@workspace/ui/components/token-avatar"
import { GLV_VAULTS, GM_POOLS } from "../../data/pools"
import { buySO4, depositGLV, depositGM } from "../../lib/earn"
import { formatPct } from "@/shared/lib/format"

const TOKEN_COLORS: Record<string, string> = {
BTC: "bg-orange-500/10 text-orange-400 ring-orange-500/20",
ETH: "bg-indigo-500/10 text-indigo-400 ring-indigo-500/20",
XLM: "bg-sky-500/10 text-sky-400 ring-sky-500/20",
USDC: "bg-blue-500/10 text-blue-400 ring-blue-500/20",
GLV: "bg-teal-500/10 text-teal-400 ring-teal-500/20",
SO4: "bg-primary/10 text-primary ring-primary/20",
}

function TokenAvatar({
symbol,
size = "md",
}: {
symbol: string
size?: "sm" | "md" | "lg"
}) {
const color = TOKEN_COLORS[symbol] ?? "bg-muted/60 text-muted-foreground ring-border"
const dimensions = { sm: "h-7 w-7 text-10", md: "h-9 w-9 text-11", lg: "h-11 w-11 text-sm" }
return (
<div
className={cn(
"flex shrink-0 items-center justify-center rounded-full font-semibold ring-1",
color,
dimensions[size],
)}
>
{symbol.slice(0, 2)}
</div>
)
}

function LightningIcon() {
return (
<svg width="15" height="15" viewBox="0 0 24 24" fill="currentColor" className="text-primary">
Expand Down Expand Up @@ -122,8 +90,8 @@ function SO4Card() {
onClick={handleBuy}
>
Buy SO4
</LoadingButton>
</Card>
</Button>
</div>
)
}

Expand Down Expand Up @@ -154,7 +122,7 @@ function GlvCard() {
<Text tone="muted" render={<span />}>
[{vault.displayPair}]
</Text>
</Text>
</p>
<div className="flex items-baseline gap-1">
<span className="text-base font-bold text-green-400">{formatPct(vault.apy, { sign: false })}</span>
<span className="text-10 text-muted-foreground">Performance APY</span>
Expand All @@ -167,9 +135,9 @@ function GlvCard() {
onClick={() => void handleEarn()}
>
Earn
</LoadingButton>
</Button>
</div>
</Card>
</div>
)
}

Expand All @@ -196,7 +164,7 @@ function GmCard() {
<button className="flex items-center gap-1 text-11 text-muted-foreground transition-colors hover:text-foreground">
Explore more
<ExternalLinkIcon />
</Button>
</button>
</div>

<div className="space-y-3">
Expand All @@ -207,7 +175,7 @@ function GmCard() {
<p className="text-xs font-medium">{pool.name}</p>
<p className="text-10 text-muted-foreground">
[{pool.longToken}-{pool.shortToken}]
</Text>
</p>
</div>
<div className="shrink-0 text-right">
<p className="text-13 font-bold text-green-400">{formatPct(pool.apy, { sign: false })}</p>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useState } from "react"
import { Alert, AlertDescription } from "@workspace/ui/components/alert"
import { Alert } from "@workspace/ui/components/alert"
import { Card } from "@workspace/ui/components/card"
import { LoadingButton } from "@workspace/ui/components/loading-button"
import { Separator } from "@workspace/ui/components/separator"
Expand Down Expand Up @@ -95,7 +95,7 @@ export function RewardsBar() {
distributed to stakers proportional to staking power{" "}
<span className="font-medium">(duration × amount staked)</span> when the buyback
threshold is reached.
</AlertDescription>
</p>
<button
aria-label="Dismiss"
onClick={() => setBannerOpen(false)}
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/features/faucet/components/faucet-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ function TokenCard({

<div className="flex items-center justify-between gap-3">
<p className="min-w-0 truncate text-xs text-muted-foreground">{cooldownText}</p>
<Button
<LoadingButton
variant="outline"
size="lg"
className="shrink-0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Alert, AlertDescription, AlertTitle } from "@workspace/ui/components/al
import { Card, CardContent, CardHeader } from "@workspace/ui/components/card"
import { Input } from "@workspace/ui/components/input"
import { LoadingButton } from "@workspace/ui/components/loading-button"
import { cn } from "@workspace/ui/lib/utils"
import { NumericText } from "@workspace/ui/components/numeric"
import { Skeleton } from "@workspace/ui/components/skeleton"
import { Stat } from "@workspace/ui/components/stat"
Expand Down Expand Up @@ -118,7 +119,8 @@ function CreateCodeForm({ onSuccess }: { onSuccess: () => void }) {
}
<span className="text-11 tabular-nums text-muted-foreground/50">{code.length}/16</span>
</div>
</form>
</div>
</form>

{/* Tier table */}
<div className="mt-6 border-t border-border pt-5">
Expand Down Expand Up @@ -157,57 +159,13 @@ function CreateCodeForm({ onSuccess }: { onSuccess: () => void }) {
</tbody>
</table>
</div>
</CardContent>
</Card>
)
}

// ── Dashboard (when code exists) ────────────────────────────────────────────

function TierProgress({ tier, volumeUsd }: { tier: 1 | 2 | 3; volumeUsd: number }) {
const current = getTierByLevel(tier)
const next = getNextTier(tier)

if (!next) {
return (
<div className="flex items-center gap-2 rounded-lg border border-yellow-500/20 bg-yellow-500/[0.06] px-4 py-2.5">
<span className={cn("inline-flex items-center rounded-full px-2 py-0.5 text-10 font-semibold ring-1", current.colorClass, current.ringClass)}>
{current.label}
</span>
<span className="text-xs font-medium text-yellow-400">Maximum tier reached!</span>
</div>
)
}

const progress = Math.min((volumeUsd / next.minVolumeUsd) * 100, 100)
const remaining = Math.max(next.minVolumeUsd - volumeUsd, 0)

return (
<div className="rounded-lg border border-border bg-card px-4 py-3">
<div className="mb-2 flex items-center justify-between">
<div className="flex items-center gap-2">
<span className={cn("inline-flex items-center rounded-full px-2 py-0.5 text-10 font-semibold ring-1", current.colorClass, current.ringClass)}>
{current.label}
</span>
<span className="text-11 text-muted-foreground">→</span>
<span className={cn("inline-flex items-center rounded-full px-2 py-0.5 text-10 font-semibold ring-1", next.colorClass, next.ringClass)}>
{next.label}
</span>
</div>
<span className="text-11 text-muted-foreground">
{formatUsd(remaining, { compact: true })} more needed
</span>
</div>
<div className="h-1.5 w-full overflow-hidden rounded-full bg-muted">
<div
className="h-full rounded-full bg-gradient-to-r from-violet-500 to-blue-400 transition-all"
style={{ width: `${progress}%` }}
/>
</div>
</div>
)
}

// ── Dashboard (when code exists) ────────────────────────────────────────────

function ReferralsTable() {
const { data: referrals = [], isLoading } = useAffiliateReferrals()

Expand Down Expand Up @@ -253,7 +211,7 @@ function ReferralsTable() {
</TableBody>
</Table>
)}
</Card>
</div>
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ function ExternalLink({ href, children }: ExternalLinkProps) {
<polyline points="15 3 21 3 21 9" />
<line x1="10" y1="14" x2="21" y2="3" />
</svg>
</Text>
</a>
)
}

Expand Down
36 changes: 7 additions & 29 deletions apps/web/src/features/referrals/components/shared/code-display.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import { Button } from "@workspace/ui/components/button"
import { Card, CardContent } from "@workspace/ui/components/card"
import { NumericText } from "@workspace/ui/components/numeric"
import { Text } from "@workspace/ui/components/text"
import { cn } from "@workspace/ui/lib/utils"
import { useCopy } from "../../hooks/use-copy"

Expand Down Expand Up @@ -91,31 +88,12 @@ export function CodeDisplay({ code, label = "Active referral code", onEdit, clas
</div>

{onEdit && (
<button
onClick={onEdit}
className="flex shrink-0 items-center gap-1.5 rounded-lg border border-border bg-muted/20 px-3 py-2 text-xs font-medium text-muted-foreground transition-colors hover:border-border/80 hover:text-foreground"
>
<svg
width="11"
height="11"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
>
<CopyIcon copied={copied} />
</Button>
</div>

{onEdit && (
<Button variant="outline" size="lg" className="shrink-0" onClick={onEdit}>
<EditIcon />
Edit
</Button>
)}
</div>
</CardContent>
</Card>
<Button variant="outline" size="lg" className="shrink-0" onClick={onEdit}>
<EditIcon />
Edit
</Button>
)}
</div>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Card } from "@workspace/ui/components/card"
import { cn } from "@workspace/ui/lib/utils"
import type { NumericRole } from "@workspace/ui/components/numeric"
import type { TimePeriod } from "../../hooks/use-referrals-data"
Expand Down Expand Up @@ -69,7 +70,7 @@ export function StatChartCard({ title, tooltip, value, period, accent = "blue" }
</div>
<p className="mt-1.5 text-22 font-semibold tabular-nums tracking-tight">
{formatUsd(value)}
</NumericText>
</p>
</div>

{/* Chart area */}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import { Alert } from "@workspace/ui/components/alert"
import { Card } from "@workspace/ui/components/card"
import { NumericText } from "@workspace/ui/components/numeric"
import { Text } from "@workspace/ui/components/text"
import { cn } from "@workspace/ui/lib/utils"
import { getNextTier, getTierByLevel } from "../../data/tiers"
import { TierBadge } from "./tier-badge"
import { formatUsd } from "@/shared/lib/format"

type Props = {
Expand Down Expand Up @@ -69,7 +66,7 @@ export function TierProgress({ tier, volumeUsd }: Props) {
</div>
<span className="text-11 text-muted-foreground" aria-label="remaining volume">
{formatUsd(remaining, { compact: true })} more needed
</NumericText>
</span>
</div>
<div
role="progressbar"
Expand Down
Loading
Loading