From 1e9b9bd0b2a37d886644650ca0fd9c1bbe827c01 Mon Sep 17 00:00:00 2001 From: Bot Date: Sun, 30 Aug 2026 23:55:17 +0800 Subject: [PATCH] feat: scaffold frontend pnpm monorepo with apps (admin, web) and shared packages (types, api-client, ui) --- ARCHITECTURE.md | 46 ++++++++++++++++++++++++++++++++ apps/admin/package.json | 19 +++++++++++++ apps/web/package.json | 19 +++++++++++++ package.json | 15 +++++++++++ packages/api-client/package.json | 8 ++++++ packages/api-client/src/index.ts | 29 ++++++++++++++++++++ packages/types/package.json | 6 +++++ packages/types/src/index.ts | 42 +++++++++++++++++++++++++++++ packages/ui/package.json | 5 ++++ packages/ui/src/index.ts | 1 + pnpm-workspace.yaml | 3 +++ 11 files changed, 193 insertions(+) create mode 100644 ARCHITECTURE.md create mode 100644 apps/admin/package.json create mode 100644 apps/web/package.json create mode 100644 package.json create mode 100644 packages/api-client/package.json create mode 100644 packages/api-client/src/index.ts create mode 100644 packages/types/package.json create mode 100644 packages/types/src/index.ts create mode 100644 packages/ui/package.json create mode 100644 packages/ui/src/index.ts create mode 100644 pnpm-workspace.yaml diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 0000000..a20d537 --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,46 @@ +# WTFX Frontend Monorepo Architecture + +WTFX 前端采用 **pnpm workspace Monorepo + Feature-Driven 领域划分** 架构。 + +--- + +## 1. 架构总览 + +``` +wtf-frontend/ +├── apps/ +│ ├── admin/ # 超级管理员控制台 (合约部署向导、协议治理、风险裁决) +│ │ └── src/ +│ │ ├── routes/ # 路由页面 (dashboard, markets, governance, deploy) +│ │ └── features/ # 独立业务领域 (contract-deploy, protocol-governance, risk-control) +│ │ +│ └── web/ # 用户端交易主站 (高频预测交易、图表、持仓) +│ └── src/ +│ ├── routes/ # 路由页面 (markets, trade, portfolio, profile) +│ └── features/ # 独立业务领域 (market, trading, wallet, prediction) +│ +├── packages/ +│ ├── types/ # 【核心】全栈共享 TypeScript 数据类型 (Market, Order, Position) +│ ├── api-client/ # 【核心】统一 API SDK 客户端 (供 Web/Admin/后续 TMA 复用) +│ ├── ui/ # 共享 Trading UI 基础原子组件库 +│ └── config/ # 共享 ESLint / TS / Tailwind 配置 +│ +├── package.json # Monorepo 根管理 +└── pnpm-workspace.yaml # Workspace 定义 +``` + +--- + +## 2. 核心架构守则 (Frontend Architecture Rules) + +1. **【Feature-Driven 组织业务】**: + - 业务代码按领域归类在 `src/features//` 下,严禁在全局 `components/` 堆积上百个业务大泥球组件。 +2. **【SDK 与 Type 唯一维护源】**: + - 所有前后端交互数据类型在 `packages/types` 统一定义; + - 所有 REST / GraphQL API 调用通过 `packages/api-client`,确保 Web、Admin 以及后续 TMA 共享同一套接口客户端。 +3. **【按需抽象,拒绝过度设计】**: + - 业务特定的复杂图表/组件(如 TradingView 集成)优先放在 `apps/web/features/trading/` 中; + - 仅当多个 App(如 Admin 与 Web)真实产生复用时,才提取到 `packages/ui/`。 +4. **【Admin 与 Web 严格独立部署】**: + - Admin 运行在 `:3100` (`admin.wtfx.app`),Web 运行在 `:3000` (`wtfx.app`); + - 两者拥有独立的路由体系与鉴权逻辑,严禁在同一 App 内通过 `if (isAdmin)` 揉杂代码。 diff --git a/apps/admin/package.json b/apps/admin/package.json new file mode 100644 index 0000000..ed1f7b9 --- /dev/null +++ b/apps/admin/package.json @@ -0,0 +1,19 @@ +{ + "name": "@wtfx/admin", + "version": "1.0.0", + "private": true, + "scripts": { + "dev": "next dev -p 3100", + "build": "next build", + "start": "next start -p 3100" + }, + "dependencies": { + "@wtfx/types": "workspace:*", + "@wtfx/api-client": "workspace:*", + "@wtfx/ui": "workspace:*", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "next": "^14.2.4", + "ethers": "^6.13.0" + } +} \ No newline at end of file diff --git a/apps/web/package.json b/apps/web/package.json new file mode 100644 index 0000000..59a5f23 --- /dev/null +++ b/apps/web/package.json @@ -0,0 +1,19 @@ +{ + "name": "@wtfx/web", + "version": "1.0.0", + "private": true, + "scripts": { + "dev": "next dev -p 3000", + "build": "next build", + "start": "next start -p 3000" + }, + "dependencies": { + "@wtfx/types": "workspace:*", + "@wtfx/api-client": "workspace:*", + "@wtfx/ui": "workspace:*", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "next": "^14.2.4", + "ethers": "^6.13.0" + } +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..6d08e5f --- /dev/null +++ b/package.json @@ -0,0 +1,15 @@ +{ + "name": "wtf-frontend-monorepo", + "version": "1.0.0", + "private": true, + "scripts": { + "dev:admin": "pnpm --filter @wtfx/admin dev", + "dev:web": "pnpm --filter @wtfx/web dev", + "build:admin": "pnpm --filter @wtfx/admin build", + "build:web": "pnpm --filter @wtfx/web build", + "lint": "pnpm -r lint" + }, + "devDependencies": { + "typescript": "^5.4.5" + } +} diff --git a/packages/api-client/package.json b/packages/api-client/package.json new file mode 100644 index 0000000..b813f42 --- /dev/null +++ b/packages/api-client/package.json @@ -0,0 +1,8 @@ +{ + "name": "@wtfx/api-client", + "version": "1.0.0", + "main": "./src/index.ts", + "dependencies": { + "@wtfx/types": "workspace:*" + } +} \ No newline at end of file diff --git a/packages/api-client/src/index.ts b/packages/api-client/src/index.ts new file mode 100644 index 0000000..66f3778 --- /dev/null +++ b/packages/api-client/src/index.ts @@ -0,0 +1,29 @@ +import { Market, Order, Position, GovernanceConfig } from '@wtfx/types'; + +export class WtfxApiClient { + private baseUrl: string; + + constructor(baseUrl: string) { + this.baseUrl = baseUrl; + } + + async getMarkets(): Promise { + const res = await fetch(`${this.baseUrl}/api/v1/markets`); + return res.json(); + } + + async getMarket(marketAddress: string): Promise { + const res = await fetch(`${this.baseUrl}/api/v1/markets/${marketAddress}`); + return res.json(); + } + + async getPositions(userAddress: string): Promise { + const res = await fetch(`${this.baseUrl}/api/v1/positions?user=${userAddress}`); + return res.json(); + } + + async getGovernanceConfig(): Promise { + const res = await fetch(`${this.baseUrl}/api/v1/governance`); + return res.json(); + } +} diff --git a/packages/types/package.json b/packages/types/package.json new file mode 100644 index 0000000..d1816ea --- /dev/null +++ b/packages/types/package.json @@ -0,0 +1,6 @@ +{ + "name": "@wtfx/types", + "version": "1.0.0", + "main": "./src/index.ts", + "types": "./src/index.ts" +} \ No newline at end of file diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts new file mode 100644 index 0000000..ce9b281 --- /dev/null +++ b/packages/types/src/index.ts @@ -0,0 +1,42 @@ +export interface Market { + questionId: string; + marketAddress: string; + title: string; + imageUri?: string; + outcomeNames: string[]; + status: 'Trading' | 'Graduated' | 'Finalised' | 'Refunded'; + tierId: number; + totalMarketCap: string; + timestampEnd: number; +} + +export interface Order { + id: string; + marketAddress: string; + outcomeIndex: number; + side: 'BUY' | 'SELL'; + amount: string; + price: string; + status: 'OPEN' | 'FILLED' | 'CANCELLED'; + createdAt: number; +} + +export interface Position { + marketAddress: string; + tokenId: string; + outcomeName: string; + shares: string; + avgCost: string; +} + +export interface GovernanceConfig { + creatorShare: string; + centralWallet: string; + defaultFeeRate: string; + disputeWindow: number; + tiers: Record; +} diff --git a/packages/ui/package.json b/packages/ui/package.json new file mode 100644 index 0000000..4dbed62 --- /dev/null +++ b/packages/ui/package.json @@ -0,0 +1,5 @@ +{ + "name": "@wtfx/ui", + "version": "1.0.0", + "main": "./src/index.ts" +} \ No newline at end of file diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts new file mode 100644 index 0000000..fedd021 --- /dev/null +++ b/packages/ui/src/index.ts @@ -0,0 +1 @@ +export const UI_VERSION = "1.0.0"; diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..e9b0dad --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,3 @@ +packages: + - 'apps/*' + - 'packages/*'