Files
nick-doc/10 - Services/frontend.md
Siavash Sameni 67244223ec docs: add sub-project service docs + sync vault 2026-06-08
Add 10 - Services/ docs for all sub-projects: backend, frontend, scanner,
deployment (new), update amanat-assist. Update Scanner Architecture,
Telegram Mini App flow, and Activity Log. Add payment safety edge cases.
2026-06-08 16:23:00 +04:00

22 KiB
Raw Blame History

title, tags, created, updated
title tags created updated
Frontend Service — amn-frontend
service
frontend
nextjs
react
web3
telegram
2026-06-08 2026-06-08

Frontend Service — amn-frontend

1. Overview

amn-frontend is the primary user-facing application for the Amanat (AMN) escrow marketplace. It serves buyers, sellers, and admins through a unified Next.js 16 App Router application with a Persian-first (RTL) UI.

Field Value
Package name amn-frontend
Version 2.10.5
Status Active — deployed on dev.amn.gg
Framework Next.js 16 (App Router + Turbopack), React 19, TypeScript strict
Dev port 8083 (both local and Docker)
Package manager yarn@1.22.22
Node requirement >=20 (host runs v26.0.0)
Repo git@git.manko.yoga:222/nick/frontend.git

The app covers the full escrow lifecycle: request creation, multi-seller offer collection, negotiation, on-chain payment (BSC/ETH/Base), delivery confirmation, dispute handling, loyalty points, and a Telegram Mini App shell for mobile-native access.


2. Tech Stack

Core

Layer Library / Version Notes
Framework next@^16.1.1 App Router, Turbopack dev, standalone output
UI runtime react@^19.1.0 + react-dom@^19.1.0
Language TypeScript ^6.0.3 strict noEmit check required before push
Component library @mui/material@^9.0.1 MUI v9 + @mui/lab, @mui/x-data-grid, @mui/x-date-pickers, @mui/x-tree-view
Styling @emotion/react + @emotion/styled + stylis-plugin-rtl RTL support via stylis
Animation framer-motion@^12.13.0
Icon system @iconify/react@^6.0.0

Data Fetching & State

Layer Library Notes
Server-state cache @tanstack/react-query@^5.83.0 Primary async state manager
Lightweight fetch swr@^2.3.3 Used in some hooks alongside RQ
HTTP client axios@^1.11.0 Centralized instance with interceptors in src/lib/axios.ts
Forms react-hook-form@^7.77.0 + zod@^4.0.10 + @hookform/resolvers@^5.0.1
Real-time socket.io-client@^4.8.1 src/contexts/ socket context; used for request/offer/chat events

Web3

Layer Library Notes
Wallet connection wagmi@^2.19.5 Primary Web3 state manager
EVM low-level viem@^2.31.7 ABI encoding, RPC calls
Compat layer ethers@^6.15.0 Legacy compatibility
Chain indexing alchemy-sdk@^3.6.1 Mainnet / Sepolia / Polygon queries
TON wallet @tonconnect/ui-react@^2.4.4 + @ton/core@^0.63.1 TON Connect in Telegram Mini App
Hardware wallet @trezor/connect-web@^9.7.3 Trezor signing flow

Internationalization & Localisation

Layer Library Notes
i18n engine i18next@^26.3.0 + react-i18next@^17.0.8
Language detection i18next-browser-languagedetector@^8.1.0
Lazy loading i18next-resources-to-backend@^1.2.1
Persian date date-fns-jalali@^4.1.0-0 Jalali calendar date formatting
RTL styling stylis-plugin-rtl@^2.1.1 Emotion cache flips properties for RTL

Observability & Testing

Layer Library Notes
Error tracking @sentry/nextjs@^10.22.0 Configured in src/instrumentation.ts
Unit tests jest@^30.4.2 + @testing-library/react@^16.3.0
E2E tests @playwright/test@^1.56.1 e2e/ directory; performance spec included
Notifications notistack@^3.0.2 + sonner@^2.0.3 Toast system

Editor & Rich Content

Layer Library Notes
Rich text @tiptap/react@^3.23.6 + extensions Code blocks, links, images, alignment, underline
Markdown render react-markdown@10.1.0 + rehype plugins With GFM, syntax highlight, sanitization
Maps mapbox-gl@^3.12.0 + react-map-gl@^8.0.4 Address / delivery location picker
Charts react-apexcharts@^2.1.0 Dashboard KPI charts
Carousels embla-carousel-react@8.6.0 Auto-scroll and autoplay plugins

3. App Router Page Structure

The Next.js App Router root is src/app/. Pages are thin wrappers that import a View component from src/sections/<feature>/view/. No business logic lives in page.tsx files.

Top-level routes

Route segment Type Purpose
/ Public Landing / marketing page
/api/health API route Health check endpoint
/api/llm API route LLM proxy (amanat-assist integration)
/auth/jwt/* Auth Sign-in, sign-up, verify email, reset password, update password
/checkout/ Protected Checkout flow entry (redirects to payment)
/dashboard/ Protected Main authenticated shell (see sub-routes below)
/design-preview/ Dev Component / theme preview (non-production)
/error/ Public Global error page
/payment/ Protected Payment status / callback landing
/post/[slug] Public Blog / post reader
/shop/[seller]/[id] Public Public seller shop and product view
/telegram/ Mini App Telegram Mini App shell (dedicated layout, see §7)
not-found.tsx Public 404 page

Dashboard sub-routes (/dashboard/*)

All dashboard routes are wrapped in AuthGuard + EmailVerificationGuard.

Sub-route Purpose
account/ Profile, avatar, address book, notification prefs, passkey, wallet linking
admin/ Admin control panel
assist/ AI assistant chat (amanat-assist integration)
chat/ Real-time escrow negotiation chat
disputes/ Dispute hub — raise, view, respond
payment/ Payment history and detail view
points/ Loyalty hub — transaction log, referral tracking, level tiers
post/ Admin blog editor (Tiptap)
request/ Buyer purchase request management (create, track, accept offer)
request-template/ Seller request templates management
seller/ Seller profile and analytics
shop-settings/ Seller shop configuration (name, policies, payment rails)
shops/ Browse shops / checkout within dashboard scope
user/ Admin user management

4. Key Sections & Features

Marketplace

  • src/sections/shop-settings/ — seller configures shop, accepted payment chains/tokens, delivery policy.
  • src/sections/request/ — core escrow lifecycle feature. Status flow:
    pending_payment → pending → active → received_offers → in_negotiation
    → payment → processing → delivery → delivered → confirming → seller_paid → completed
    (or cancelled at most stages)
    
  • Shared status/urgency color and label maps live in src/sections/request/constants.ts. Do not redefine per-view; use getStatusColor / getStatusLabel / getUrgencyColor / getUrgencyLabel.
  • Role-based views (buyer / seller / admin) dispatched from role-based-<feature>-view.tsx components.

Escrow Flow

The escrow flow spans multiple sections:

  1. Buyer creates a purchase request (/dashboard/request/new) — wizard in src/sections/request/components/steps/.
  2. Sellers receive notifications via Socket.io and submit offers (received_offers state).
  3. Negotiation phase: real-time chat (/dashboard/chat/) with offer counter-proposals.
  4. Payment: buyer pays on-chain (BSC primary, ETH/Base/Polygon/Arbitrum supported). Funds held in escrow wallet (NEXT_PUBLIC_ESCROW_WALLET_ADDRESS). USDT is the primary escrow currency; BSC USDT uses 18 decimals (non-standard — handled in src/utils/currencyUtils.ts).
  5. Delivery & confirmation: seller marks delivered, buyer confirms → confirming → seller_paid → completed.
  6. Disputes: either party can raise at src/sections/dispute/.

Dashboard & Admin

  • Overview tiles with ApexCharts KPI cards.
  • Admin panel: user management, shop review, dispute arbitration, blog post management.
  • Points / loyalty system: transaction ledger, referral tracking, tier levels at src/sections/points/.
  • AI assist panel: embedded amanat-assist chat at /dashboard/assist/.

Telegram Mini App

See §7 for full detail.


5. State Management

The app uses a layered approach — no single global store:

Layer Tool Scope
Server state & cache @tanstack/react-query All API calls — fetching, mutations, invalidation
Supplementary fetch swr Some lightweight hooks
Local component state React.useState / useReducer Component-local UI state
Cross-tree shared state React Context Socket connection (src/contexts/), Auth (src/auth/context/), Web3, Settings drawer, Localization
Form state react-hook-form All form instances, with zod schemas as resolvers
Settings (theme/locale) Context + localStorage Theme mode, layout direction, color preset, font — managed by src/settings/

There is no Zustand or Redux in the dependency tree. Global state is passed via Context providers stacked in src/app/layout.tsx.

Key contexts:

  • SocketContext (src/contexts/) — wraps socket.io-client, exposes live event subscriptions.
  • AuthContext (src/auth/context/) — JWT session, user object, sign-in/out actions.
  • Web3Context / wagmi WagmiProvider (src/web3/context/) — wallet connection, chain switching.
  • SettingsContext (src/settings/) — UI preferences (RTL, color scheme, font).
  • LocalizationProvider (src/locales/) — i18next + MUI date picker locale.

6. Internationalization

The app is RTL-first with Persian (Farsi) as the primary production language.

Aspect Implementation
Engine i18next + react-i18next
Supported languages fa (Persian), ar (Arabic), en (English), fr (French), cn (Chinese), vi (Vietnamese)
Translation files src/locales/langs/<lang>/*.json — split by feature namespace
RTL flip stylis-plugin-rtl applied to the Emotion cache — physical CSS properties (margin-left, padding-right, etc.) are automatically mirrored
LTR islands Inline dir="ltr" on elements containing URLs, wallet addresses, token amounts, or other inherently LTR content
Persian calendar date-fns-jalali for Jalali date formatting; MUI date pickers use the Jalali locale adapter
Direction state Controlled via SettingsContext — users can toggle in the settings drawer
Config src/locales/locales-config.ts + src/locales/i18n-provider.tsx

Language detection priority: URL ?lng= param → browser Accept-Language → localStorage fallback → fa.


7. Telegram Mini App Integration

The Telegram Mini App (TMA) is a first-class feature with a dedicated route segment, layout, and 40+ purpose-built components.

Loading & Auth Flow

  • The TMA loads via Telegram's webApp.openWebApp() into the /telegram/ route.
  • The root layout at src/app/telegram/layout.tsx provides a minimal provider stack:
    • TonConnectUIProvider (TON wallet)
    • No standard app shell (no top nav, no side drawer) — uses native Telegram chrome instead.
  • User identity: window.Telegram.WebApp.initData is parsed by src/utils/telegram-webapp.ts (a custom wrapper around the window.Telegram global — no @twa-dev or @telegram-apps SDK package is used).
  • Auth is linked to the existing JWT session: on first open the app prompts the user to connect their AMN account (onboarding sheet). Subsequent opens re-use the stored token.

Key File Locations

Path Purpose
src/app/telegram/layout.tsx TMA root layout — minimal providers
src/app/telegram/page.tsx TMA entry point
src/utils/telegram-webapp.ts Custom window.Telegram.WebApp wrapper / SDK util
src/sections/telegram/ All TMA feature code
src/sections/telegram/view/ ~18 view components (one per TMA screen)
src/sections/telegram/components/ ~28 TMA-specific UI primitives
src/sections/telegram/hooks/ TMA-scoped hooks including use-telegram-live-context
src/sections/telegram/telegram-shell-css.ts Native Telegram shell CSS variables integration

TMA Views

View file Screen
telegram-mini-app-view.tsx Main shell / router (23 KB — primary orchestrator)
telegram-home-view.tsx Home tab
telegram-shop-view.tsx Shop list
telegram-seller-shop-view.tsx Individual seller shop products
telegram-cart-view.tsx Cart
telegram-checkout-view.tsx Checkout
telegram-payment-view.tsx Payment status
telegram-requests-view.tsx Buyer requests list
telegram-request-detail-view.tsx Request detail + offer management (31 KB)
telegram-new-request-view.tsx New request wizard
telegram-template-detail-view.tsx Seller template detail
telegram-chat-view.tsx In-app chat thread list
telegram-chat-thread-view.tsx Single chat thread
telegram-archived-chats-view.tsx Archived chats
telegram-account-view.tsx Account settings (18 KB)
telegram-addresses-view.tsx Address book (15 KB)
telegram-points-view.tsx Loyalty points
telegram-notifications-view.tsx Notification centre
telegram-settings-view.tsx App settings (14 KB)

TMA-specific Components

Key primitives: telegram-chat-row, telegram-request-stepper, telegram-onboarding-sheet, telegram-tab-bar, telegram-header, telegram-quick-actions, telegram-cart-fab, telegram-support-fab, telegram-welcome-banner, telegram-unlinked-state, telegram-unsupported-state.

TON Wallet in TMA

TON Connect (@tonconnect/ui-react, @ton/core) is active only inside the TMA layout. BSC payments via wagmi/viem are also available in-TMA but TON is the preferred rail for Telegram users.


8. Web3 Integration

All Web3 code lives under src/web3/.

Architecture

src/web3/
├── config.ts                 # WEB3_CONFIG — chains, WalletConnect project ID
├── index.ts                  # Public barrel
├── types.ts                  # Shared Web3 types
├── utils.ts                  # Misc helpers
├── payment-rails.ts          # Chain+token routing logic
├── decentralizedPayment.ts   # Core payment execution (16 KB)
├── web3Service.ts            # Service layer (9 KB)
├── paymentBackendService.ts  # Backend sync after on-chain tx (12 KB)
├── tonconnect-provider.tsx   # TonConnect provider wrapper
├── context/                  # Web3Context provider
├── contracts/                # ABI definitions
├── hooks/
│   ├── use-web3-wagmi.ts     # wagmi-based wallet + tx hooks (5.5 KB)
│   ├── use-alchemy.ts        # Alchemy SDK hooks — balance, tx history (3.8 KB)
│   ├── use-chainlink.ts      # Chainlink price feed hooks (2.6 KB)
│   └── use-web3-context.ts   # Context consumer hook
├── services/                 # Additional service modules
├── trezor/                   # Trezor Connect integration
└── utils/                    # Chain-specific utilities

Supported Chains

Declared in WEB3_CONFIG.supportedChains: BSC (default, lowest fees), Base, Polygon, Arbitrum, Ethereum.

Primary escrow payments run on BSC. BSC USDT is 18 decimals (non-standard; handled in src/utils/currencyUtils.ts — do not hardcode decimals).

Wallet Support

Wallet Integration
MetaMask / injected wagmi injected() connector
WalletConnect wagmi WalletConnect connector (NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID)
Trezor @trezor/connect-web in src/web3/trezor/
TON wallet @tonconnect/ui-react (TMA only)

Oracle / Price Feeds

  • Chainlink price feeds via use-chainlink.ts — used for USDT/USD peg monitoring.
  • Alchemy SDK (alchemy-sdk) for on-chain data queries (balances, tx receipts).
  • Depeg protection feature in development — see nick-doc/ oracle depeg protection design doc.

9. CI/CD

Pipeline

CI is managed by Woodpecker at frontend/.woodpecker/production.yml.

Trigger: push to main or master branch.

Agent: platform: linux/arm64 (netcup agent on 89.58.32.32).

Steps:

Step Image Action
get-version node:22-alpine Reads package.json version → writes dev-<version> to .tags
build-and-deploy docker:27-cli docker build -t git.tbs.amn.gg/escrow/frontend:dev . then docker compose up -d --no-deps --pull never frontend against /opt/escrow-dev/docker-compose.yml
notify node:22-alpine Posts Telegram notification (success or failure) via scripts/ci/tg-notify.cjs using TG_TOKEN + TG_USERS secrets

Important CI notes:

  • The image is built locally on the host — it does not pull from a registry. docker-compose.override.yml sets pull_policy: never.
  • Turbopack is dev-only. The production build uses standard next build (webpack).
  • next build runs a strict TypeScript type-check. The build fails on type errors.
  • Always bump package.json version before pushing to main/master. Docker tags use dev-<version>. Reusing the same version overwrites the previous image tag and breaks rollback.
  • A CI green check does not guarantee the image was pushed to the registry. Verify the registry tag manually if deployment seems stale.

Docker Build

  • Output mode: standalone (set in next.config.js).
  • Start command: PORT=8083 node .next/standalone/server.js.
  • Post-build: cp -r .next/static .next/standalone/.next/ && cp -r public .next/standalone/ (required for static assets with standalone output).
  • Build cache: --mount=type=cache for apk, yarn, and .next/cache — incremental Next.js rebuilds on unchanged packages.

10. Local Development Quick-Start

# Prerequisites: Node >=20, yarn 1.22.22

cd frontend/

# Install dependencies
yarn install

# Copy env file and fill in values
cp .env.local.example .env.local
# Edit .env.local — see §11 for required vars

# Start dev server (Turbopack, port 8083)
yarn dev

# Alternative: webpack (slower, more compatible)
yarn dev:webpack

# Type check (must pass before push)
npx tsc --noEmit --ignoreDeprecations 6.0

# Lint
yarn lint
yarn lint:fix

# Unit tests
yarn test

# E2E tests (requires running app)
yarn playwright:install
yarn test:e2e

# Production build (validates types + builds)
yarn build

# Run standalone production build
yarn start

Note: The dev server binds to http://localhost:8083. When proxied via infra-caddy on the dev server, it maps to https://dev.amn.gg.


11. Environment Variables

All public vars are prefixed NEXT_PUBLIC_ and baked into the client bundle at build time.

Variable Required Description
NEXT_PUBLIC_APP_NAME Yes Application display name (e.g. Amanat)
NEXT_PUBLIC_APP_VERSION Yes App version string — should match package.json version
NEXT_PUBLIC_BACKEND_URL Yes Base URL for backend API (e.g. https://api.dev.amn.gg)
NEXT_PUBLIC_API_URL Yes API endpoint root (often same as BACKEND_URL + /api)
NEXT_PUBLIC_SOCKET_URL No Socket.IO server URL — falls back to NEXT_PUBLIC_BACKEND_URL
NEXT_PUBLIC_ESCROW_WALLET_ADDRESS Yes On-chain escrow holding wallet address
NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID Yes WalletConnect Cloud project ID
NEXT_PUBLIC_ALCHEMY_API_KEY_MAINNET Yes Alchemy API key for Ethereum mainnet
NEXT_PUBLIC_ALCHEMY_API_KEY_SEPOLIA Yes Alchemy API key for Sepolia testnet
NEXT_PUBLIC_ALCHEMY_API_KEY_POLYGON Yes Alchemy API key for Polygon
NEXT_PUBLIC_MAPBOX_API_KEY No Mapbox GL token for map components
NEXT_PUBLIC_ASSETS_DIR No Custom assets base URL — defaults to empty (local /public)
BUILD_STATIC_EXPORT No Set true to enable static export mode
NODE_ENV Auto Set by Next.js (development / production)

Actual values for the dev deployment are stored in ~/.agentSecrets/escrow/CLAUDE.md (not in the repo).


12. Known Issues / Open Items

# Issue Status
1 Socket room scoping — global payment socket broadcasts previously wiped every user's cart. A provider gate was added in frontend v2.8.4 to filter by provider. Backend-side room scoping is still an open follow-up. Open
2 Backend rate limiter on GET /payment/:idpaymentLimiter (30 req/15 min) applies to the payment status poll endpoint. Results in 429 during rapid callback polling, leaving payments stuck in "processing". Fix is on backend side but frontend polling interval could be increased as a mitigation. Open (backend fix pending)
3 Offer rejection UI — "all sellers stuck at step 4" was a UI-only bug; backend rejects and notifies correctly. Telegram seller step must use mojtaba's StepContext (introduced in fe v2.9.13). Resolved in v2.9.13
4 Cart wipe regression risk — any new global socket event handler must be scoped by provider: to avoid touching RN or other payment records. Ongoing convention
5 Performance is network-bound — Mongo API profiling shows 300800 ms response times due to WAN RTT (~235 ms). Server-side processing is 312 ms. Frontend-side CDN / edge caching is the recommended fix; DB migration will not help. Open
6 Oracle depeg protection — server-side oracle quoting for multi-currency pricing + stablecoin depeg protection is designed and approved. Build starts on a new dev branch. In progress
7 Multi-chain for amn.scanner — the in-house scanner pay-in path is not yet multi-chain; verify scanner watches mainnet addresses before enabling multi-chain selection in the UI for scanner provider. Open
8 Parallel agent pushes — a second agent (moojttaba) pushes to the same branches. Always git fetch --rebase before pushing. Version-bump conflicts are expected. Ongoing
9 Tiptap / rich text in TMA — the Tiptap editor is desktop-optimised; its usability on mobile Telegram is untested at scale. Not verified
10 design-preview/ route — present in the app router but should be excluded or protected in production builds. Low priority