|
|
@@ -4,13 +4,17 @@ Solana 链上 Byreal DEX CLMM 跟单系统。监控目标钱包的集中流动
|
|
|
|
|
|
## Tech Stack
|
|
|
|
|
|
-- **Frontend**: Next.js 16 + React 19 + Tailwind CSS 4 + SWR
|
|
|
+- **Frontend**: Next.js 16 + React 19 + Tailwind CSS 4 + shadcn/ui (New York) + SWR
|
|
|
+- **UI Components**: shadcn/ui + Radix UI primitives
|
|
|
+- **Theme**: next-themes(class-based 明暗切换)
|
|
|
- **Backend**: Next.js API Routes (server-side only)
|
|
|
- **Database**: SQLite (better-sqlite3, WAL mode)
|
|
|
- **Blockchain**: Solana Web3.js + Anchor 0.31
|
|
|
- **CLMM SDK**: 本地 TypeScript SDK,编译为 CommonJS 后通过 `require()` 导入
|
|
|
- **Swap**: Jupiter Ultra API (ExactIn / ExactOut)
|
|
|
+- **Notifications**: Discord Webhook
|
|
|
- **Package Manager**: pnpm
|
|
|
+- **Deployment**: Docker (multi-stage, node:22-alpine, 不使用 lock 文件)
|
|
|
|
|
|
## Project Structure
|
|
|
|
|
|
@@ -28,6 +32,7 @@ src/
|
|
|
│ ├── positions/route.ts # 仓位查询 & 手动关仓
|
|
|
│ ├── history/route.ts # 历史记录
|
|
|
│ ├── settings/route.ts # 设置读写
|
|
|
+│ ├── sync/route.ts # Byreal API 仓位同步
|
|
|
│ └── wallet/balance/route.ts
|
|
|
├── lib/
|
|
|
│ ├── monitor/ # 监控服务
|
|
|
@@ -35,10 +40,10 @@ src/
|
|
|
│ │ ├── parser.ts # TX 解析 (判别符 + 日志 + 事件解码)
|
|
|
│ │ └── types.ts # ParsedOperation
|
|
|
│ ├── copier/ # 跟单引擎
|
|
|
-│ │ ├── index.ts # CopyEngine (四种操作调度)
|
|
|
+│ │ ├── index.ts # CopyEngine (四种操作调度, USDC+USDT 余额检查)
|
|
|
│ │ ├── price.ts # Jupiter Price API 价格获取
|
|
|
│ │ ├── ratio.ts # 金额缩放 (Decimal.js)
|
|
|
-│ │ └── swap.ts # Jupiter Ultra swap
|
|
|
+│ │ └── swap.ts # Jupiter Ultra swap (含 USDC↔USDT 互换)
|
|
|
│ ├── db/
|
|
|
│ │ ├── index.ts # SQLite singleton (WAL mode)
|
|
|
│ │ ├── schema.ts # 4 表 DDL + 自动迁移
|
|
|
@@ -52,9 +57,15 @@ src/
|
|
|
│ │ ├── src/client/ # Chain class (链上操作)
|
|
|
│ │ ├── src/instructions/ # TX 构建 & 底层布局
|
|
|
│ │ └── src/utils/ # TickMath, SqrtPrice 等
|
|
|
+│ ├── byreal-sync.ts # Byreal API 仓位同步 (PNL/APR/Fee/Bonus)
|
|
|
│ ├── pool-info.ts # 池子信息缓存 (1 min TTL)
|
|
|
│ └── config.ts # 环境变量加载
|
|
|
-└── components/layout/ # Sidebar & TopBar
|
|
|
+├── components/
|
|
|
+│ ├── ui/ # shadcn/ui 组件 (Button, Table, Card, Badge, Input, Select, Switch, AlertDialog, Label, Tooltip)
|
|
|
+│ ├── layout/ # Sidebar & TopBar (含 ThemeToggle)
|
|
|
+│ ├── providers.tsx # ThemeProvider (next-themes, class-based, default dark)
|
|
|
+│ └── theme-toggle.tsx # Sun/Moon 明暗切换按钮
|
|
|
+└── lib/utils.ts # cn() 工具函数 (clsx + tailwind-merge)
|
|
|
```
|
|
|
|
|
|
## Build Process
|
|
|
@@ -79,20 +90,36 @@ WebSocket 订阅 Byreal program logs(confirmed 级别)+ 轮询(5s 间隔
|
|
|
通过 `position_mappings` 表建立 target_nft_mint → our_nft_mint 的映射关系,跨越四种操作类型追踪仓位对应关系。
|
|
|
|
|
|
### Swap 策略
|
|
|
-- 开仓/加仓: ExactOut 模式,补齐余额缺口 (额外 2% buffer)
|
|
|
+- 开仓/加仓: 检查 USDC+USDT 总余额,不足则跳过;单币不足时自动从对方 ExactOut swap
|
|
|
- 关仓: ExactIn 模式,将收到的代币全部换回 USDC
|
|
|
-- 稳定币 (USDC, USDT, USD1) 不触发 swap
|
|
|
+- 稳定币 (USDC, USDT, USD1) 不触发外部 swap,但 USDC↔USDT 可互换
|
|
|
+
|
|
|
+### Byreal API 仓位同步
|
|
|
+- `syncFromByrealApi()` 从 `api2.byreal.io` 拉取所有 open 仓位 (status=0, pageSize=200)
|
|
|
+- 通过 `nftMintAddress` 匹配 DB 中的 `our_nft_mint`
|
|
|
+- 同步字段: pnl_usd, pnl_percent, apr, bonus_usd, earned_usd, liquidity_usd
|
|
|
+- APR = (earnedUsd / totalDeposit / ageDays) * 365 * 100
|
|
|
+- 不在 API 响应中的活跃仓位自动标记为 closed
|
|
|
+- API 返回值为 string 类型,需 `Number()` 转换后再 `.toFixed()`
|
|
|
+
|
|
|
+### shadcn/ui 组件
|
|
|
+- 使用 New York 风格、Zinc 基色、CSS 变量模式
|
|
|
+- 全局 CSS 变量在 `globals.css` 中定义亮色 (`:root`) 和暗色 (`.dark`) 两套
|
|
|
+- Tailwind v4 使用 `@custom-variant dark (&:is(.dark *))` 启用 dark 变体
|
|
|
+- Badge 扩展了 `success` 和 `warning` 变体
|
|
|
|
|
|
## Key Constants
|
|
|
|
|
|
- **Byreal Program ID**: `REALQqNEomY6cQGZJUGwywTBD2UmDT32rZcNnfxQ5N2`
|
|
|
- **USDC Mint**: `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v`
|
|
|
+- **USDT Mint**: `Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB`
|
|
|
- **DB Path**: `data/copytrade.db`
|
|
|
+- **Byreal API**: `https://api2.byreal.io/byreal/api/dex/v2/position/list`
|
|
|
|
|
|
## Database Tables
|
|
|
|
|
|
- `watched_addresses` — 监控目标 (address, label, enabled, 单独 multiplier/max_usd)
|
|
|
-- `position_mappings` — target_nft_mint(UNIQUE) ↔ our_nft_mint
|
|
|
+- `position_mappings` — target_nft_mint(UNIQUE) ↔ our_nft_mint + 同步字段 (pnl_usd, pnl_percent, apr, bonus_usd, earned_usd, liquidity_usd)
|
|
|
- `copy_history` — 操作日志 (status: pending/executing/success/failed/skipped)
|
|
|
- `settings` — 全局 key-value 配置
|
|
|
|
|
|
@@ -106,6 +133,7 @@ COPY_MULTIPLIER # 跟单倍率 (默认 1.0)
|
|
|
COPY_MAX_USD # 单次上限 (默认 1000)
|
|
|
COPY_SLIPPAGE # 滑点 (默认 0.02)
|
|
|
MONITOR_POLL_INTERVAL # 轮询间隔 ms (默认 5000)
|
|
|
+DISCORD_WEBHOOK_URL # Discord 通知 Webhook URL (可选)
|
|
|
```
|
|
|
|
|
|
## Conventions
|
|
|
@@ -115,3 +143,6 @@ MONITOR_POLL_INTERVAL # 轮询间隔 ms (默认 5000)
|
|
|
- SWR 用于前端数据刷新 (5s 间隔)
|
|
|
- 错误记录到 copy_history 表 + MonitorService.errorLog (最近 50 条)
|
|
|
- Slippage: 减仓/关仓用 99%(宽松,移除自有流动性),开仓/加仓用 2%(保守)
|
|
|
+- Docker 部署不使用 pnpm-lock.yaml,避免公司内网 registry 问题
|
|
|
+- 地址支持 per-address referrer mode(referer memo)
|
|
|
+- WebSocket 断线自动重连,超时后回退轮询
|