Frontend (web app)

apps/web is a Next.js 14 (App Router) app, port 4300. It reuses screens and hooks from apps/mobile-version so the core flows have one implementation across desktop and mobile.

Route groups

app/
├─ (auth)/      sign-in, sign-up         (Privy Google/email)
├─ (reused)/    agreements, send, receive, activity, market,
│               withdraw, account, notifications, onboarding   (from mobile-version)
└─ (web)/       overview, custody, distributions, settlements, reports  (bespoke desktop)

Auth wiring

flowchart TB
    P["PrivyProvider"] --> WG["WagmiProvider (@privy-io/wagmi)"]
    WG --> AG["AuthGate"]
    AG --> SYNC["usePrivyWagmiSync()"]
    AG --> APP["App / pages"]
  • components/auth/Providers.tsx wraps the app in PrivyProviderWagmiProvider. NEXT_PUBLIC_PRIVY_APP_ID is required at build time — without it the provider stack is dropped and every wagmi hook throws.
  • AuthGate.tsx mounts usePrivyWagmiSync() and loads the user's profiles.
  • WebAuthGuard.tsx redirects unauthenticated users (mounted inside the (web) providers).
  • hooks/usePrivyWagmiSync.ts bridges the active Privy embedded wallet (for the current mode) into wagmi as the connected connector, and self‑heals the connection after disconnects (network blips) with bounded retries.
  • SIWE login (useSiweLogin): get nonce → sign → POST /auth/login → store JWT.

Dual‑mode (personal / business)

  • The mode + profiles live in a Zustand store (store/auth.store.ts for the JWT/user, a mode/profile store for the active context).
  • useActiveWallet() (reused from mobile) is the single source of truth for "which wallet am I acting as" — it returns { address, privyWallet, canSign, mode, profileId, … } by combining the mode store, the user, and Privy's connected wallets, matched by address (HD index 0 personal / 1 business), never by array position.
  • Switching mode retargets balances, activity, and signing to the right wallet, and re‑runs the wagmi sync.

State management

Zustand stores under store/: auth.store (JWT + user), the mode/profile store, plus UI stores (theme, ops modals). Server data uses TanStack Query.

Reused mobile hooks (important ones)

Hook Role
useActiveWallet Active wallet + canSign + mode + profileId
useCustodyAction The escrow action primitive (approve + contract call + verify + confirm) used by every agreement button
useAuthGate Route guard for authenticated screens
useDashboardData Aggregated dashboard reads

API clients

Thin wrappers in lib/ call the gateway with the JWT + X-AXON-Profile-Id (via lib/api.ts / apiFetch): funding-api.ts, settlements-api.ts, agreements client (from mobile), etc. Errors surface response.data.message; the custody hook maps low‑level wagmi errors (e.g. "Connector not connected") to friendly, retryable messages.

Styling

Tailwind CSS, AXON brand (mint #00d999 accent on dark/ink). Shared icons/primitives come from @axon/shared-ui.

results matching ""

    No results matching ""