diff --git a/.env.example b/.env.example index ee0eed5..c9f714a 100644 --- a/.env.example +++ b/.env.example @@ -3,3 +3,14 @@ # Base URL of the GuildWorkman API. Defaults to the hosted instance if unset. NEXT_PUBLIC_API_BASE_URL=http://localhost:8080 + +# Stellar network the wallet-connection layer expects Freighter to be on. +# Valid values: PUBLIC (mainnet), TESTNET, FUTURENET. Defaults to TESTNET if +# unset, matching the Soroban contracts' current deployment target. +# This is a security-relevant setting, not just a label: it's what +# NetworkGuard (src/components/wallet/NetworkGuard.tsx) and the escrow +# funding wizard check the connected wallet against before allowing funds to +# move. Setting it to PUBLIC before the backend/contract integration is +# actually deployed to mainnet would let a wallet connected to real funds +# pass the guard — only change it once that deployment exists. +NEXT_PUBLIC_STELLAR_NETWORK=TESTNET diff --git a/README.md b/README.md index dc2477c..29aaefa 100644 --- a/README.md +++ b/README.md @@ -199,14 +199,43 @@ Java backend that doesn't exist today. Rather than pretend that integration is further along than it is, the frontend currently does two honest things: -1. **A real wallet connection.** The navbar's "Connect Wallet" button - (`src/components/WalletButton.tsx`, `src/lib/wallet.ts`) uses +1. **A real, resilient wallet connection.** The navbar's "Connect Wallet" + button (`src/components/WalletButton.tsx`, `src/lib/wallet.ts`) uses `@stellar/freighter-api` to connect an actual Freighter wallet, showing a - truncated address, network (Testnet/Mainnet), and a disconnect option. If - the Freighter extension isn't installed, it shows an "Install Freighter" - hint instead of failing silently. This makes **no contract calls** — - booking, payment, and review logic are all unchanged and still go through - the backend API/Paystack. + truncated address, network (Testnet/Mainnet/Futurenet), and a disconnect + option. If the Freighter extension isn't installed, it shows an "Install + Freighter" hint instead of failing silently. This makes **no contract + calls** — booking, payment, and review logic are all unchanged and still + go through the backend API/Paystack. + + On top of the base connection, `useWallet()` (`src/lib/wallet.ts`) adds: + - **Session restore across reloads** — a localStorage flag is only a fast + hint; the actual restore verifies Freighter's own `isAllowed()` grant + before trusting it, so a session revoked inside the extension (or a + browser profile that never had it) self-heals instead of showing a + stale "connected" UI. + - **A live network-switch guard** — Freighter has no API to switch its + own network on a dApp's behalf (a deliberate security boundary), so + `useWallet` runs Freighter's `WatchWalletChanges` poller for the life + of a session and exposes `isWrongNetwork` / `expectedNetwork`. + `NetworkGuard` (`src/components/wallet/NetworkGuard.tsx`, mounted + app-wide in `src/app/layout.tsx`) shows a banner guiding the user to + switch inside Freighter and clears itself automatically once the + watcher detects the change — no reload or manual recheck required, + though a "check again" button short-circuits the wait. + `EscrowFundingWizard`'s connect-wallet step additionally **blocks + progress** past that step while on the wrong network, since funding + escrow there isn't recoverable after the fact. + - The expected network is configurable via `NEXT_PUBLIC_STELLAR_NETWORK` + — one of `PUBLIC` (mainnet) / `TESTNET` / `FUTURENET`, defaults to + `TESTNET` (see `.env.example`). This is security-relevant, not just a + label: it's what the guard checks a connected wallet against before + letting funds move, so it should only be pointed at `PUBLIC` once the + backend/contract integration is actually deployed there. + + No new dependencies were added — `WatchWalletChanges` and `isAllowed()` + are both part of the `@stellar/freighter-api` version already in + `package.json`. 2. **An informational trust layer.** The homepage sections (`Hero`, `HowItWorks`, `StatsBand`) plus "Escrow protected" badges on worker cards and the booking flow explain in plain language what the contracts *will* do @@ -222,13 +251,15 @@ src/ components/ ui/ # design-system primitives (Button, Input, Select, Card, Badge) brand/ # the marks as components (Logo, NorthStar, AdinkraPattern) + wallet/ # NetworkGuard — app-wide wrong-network banner *.tsx # page-level and shared client components lib/ api.ts # typed API client — every backend call goes through here - config.ts # API_BASE_URL resolution + config.ts # API_BASE_URL / EXPECTED_STELLAR_NETWORK resolution types.ts # shared request/response types constants.ts # category list and skill-detail seed data - wallet.ts # useWallet() hook wrapping @stellar/freighter-api + wallet.ts # useWallet() hook — connect/session-restore/network-guard + # on top of @stellar/freighter-api public/ assets/ # images used across the app brand/ # exported logo marks (SVG masters + 4x PNGs) diff --git a/src/app/layout.tsx b/src/app/layout.tsx index e3661a2..5b435da 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -7,6 +7,7 @@ import Footer from "@/components/Footer"; import { ThemeProvider } from "@/components/theme"; import { NotificationProvider } from "@/components/notifications/useNotifications"; import NotificationToast from "@/components/notifications/NotificationToast"; +import { NetworkGuard, WalletProvider } from "@/components/wallet"; import { themeScript } from "@/lib/theme"; const inter = Inter({ @@ -41,10 +42,13 @@ export default function RootLayout({ - -
{children}
-