Files
trumpsignal-frontend/app/[locale]/privacy/page.tsx
T
k d72323b1c6 Production polish: i18n shelved, PWA icons, SEO/GEO cleanup, UX fixes
Big-picture changes since 01be8e7:

New routes — /trump /btc /kol /trades /analytics /archive plus four
SEO landing pages (/methodology /glossary /case-studies /contact),
all served under /[locale]. Each has dedicated metadata + JSON-LD.

KOL page (new) — DigestWidget + OnchainWidget + TalkVsTradesWidget,
filter by handle/ticker, click-through to per-post detail with the
original AI-extracted ticker/conviction/quote.

BTC page (new) — tabbed: macro-bottom (AHR999 + 200WMA + Pi Cycle)
and funding-rate reversal, with live sparkline + threshold bands.

Telegram card on Settings — wallet-link code generation, status,
disconnect. Preferences moved into the bot itself (/trump /btc etc.)
so the card stays minimal.

SignalMonitor (new) — ETH/LINK Bollinger breakout monitor in its own
component, shares the singleton WsProvider so no second WS opens.

WS singleton refactor (lib/wsContext) — shared WsProvider + useWsSubscribe
hook. Cleanup now actively closes the socket on unmount; previously the
local `ws` couldn't be reached from cleanup and leaked one connection
per StrictMode remount.

OpenPositions polling no longer pops MetaMask in the background —
splits into load('first') for user-initiated and load('poll') that
uses getCachedViewEnvelope without signing.

i18n shelved — proxy.ts (Next 16 middleware rename) wires next-intl
but only Navbar + layout footer have translations. Rest of UI used
isZh ternary scattered across 28 files. All `const isZh = locale === 'zh'`
flipped to `const isZh = false` so every site renders English; Chinese
branches kept as dead code so revival is one regex away.
LanguageSwitch hidden but file kept. zh-CN hreflang removed from
metadata + sitemap to avoid duplicate-content penalties.

Wallet error handling — lib/walletError.ts: isUserRejection walks EIP-1193
code 4001 + .cause chain; previous string-match for "reject"/"denied"
broke for users running MetaMask in non-English UIs. 12 call sites
migrated across 5 components.

PWA icons — app/icon.tsx + app/apple-icon.tsx render the brand "α" via
Next's ImageResponse so no static PNG asset is required. manifest.ts
references /icon and /apple-icon dynamic routes.

OG image + sitemap + robots — dynamic 1200×630 OG card; robots blocks
both /en/settings and /zh/settings; sitemap only emits /en routes;
JSON-LD covers SoftwareApplication + Organization + 10-Q FAQPage.

Landing page polish — Launch Dashboard button stripped of magnetic
hover + shimmer + lift + glow expansion (multiple users found it busy);
hero scramble alphabet swapped to alphanumeric (was block characters);
"15 KOL feeds" copy updated to 19 in 5 places.

PostCards source icons — new entries for btc_bottom_reversal,
funding_reversal, kol_divergence so they no longer fall through to
the generic "first letter" fallback.

Archive page filter — excludes funding_reversal + kol_divergence
(previously only excluded truth + btc_bottom_reversal so new live
signals leaked into the legacy archive).

Cache + skeleton loading — lib/cache.ts SWR module with per-key TTL,
applied across the major pages so navigation feels instant.

SignConfirmSheet — 4 hardcoded Chinese strings translated to English
(English users were seeing zh-only "需要钱包签名" etc).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-25 00:53:27 +08:00

89 lines
4.6 KiB
TypeScript

import Link from 'next/link'
import { getLocale } from 'next-intl/server'
export default async function PrivacyPage({ params: { locale } }: { params: { locale: string } }) {
const intlLocale = await getLocale()
const isZh = false // i18n shelved — Chinese branches kept as dead code for future revival; see messages/zh.json
const sections = isZh
? [
{
title: '1. 我们收集什么',
body: '当你连接钱包时,我们会收集你的钱包地址,用于身份识别、订阅状态判断和机器人配置关联。除非你主动通过联系表单提供,我们不会收集姓名、邮箱等传统个人身份信息。',
},
{
title: '2. Hyperliquid API Key',
body: '如果你选择绑定 Hyperliquid API key,该密钥会以加密形式存储。明文不会被写入日志,也不会用于除 Hyperliquid 官方交易接口以外的用途。',
},
{
title: '3. 数据如何使用',
body: '钱包地址、订阅状态和交易配置只会用于执行你授权的机器人逻辑、展示个人交易表现,以及提供平台功能。我们不会出售、出租或用于广告投放。',
},
{
title: '4. 分析与统计',
body: '我们使用极简统计来理解页面访问、错误率和整体使用趋势。这些统计不会绑定你的真实身份,也不会用于跨站广告追踪。',
},
{
title: '5. 数据保留',
body: '只要你的账户仍在使用,相关订阅与配置数据会被保留。你可以联系我们请求删除。交易历史最多保留 24 个月,用于对账、争议处理和产品分析。',
},
{
title: '6. 联系方式',
body: '如果你有与隐私相关的问题,请使用联系页面与我们沟通。',
},
]
: [
{
title: '1. Information We Collect',
body: 'When you connect a wallet, we collect the wallet address required to identify your account, check subscription status, and link bot settings. We do not collect names, email addresses, or similar personal identifiers unless you voluntarily provide them through the contact form.',
},
{
title: '2. Hyperliquid API Keys',
body: 'If you connect a Hyperliquid API key, the key is stored in encrypted form. Plaintext keys are not written to logs and are only used for calls to official Hyperliquid trading endpoints.',
},
{
title: '3. How We Use Data',
body: 'Wallet addresses, subscription status, and trading settings are used only to run the bot logic you authorize, show your personal trading analytics, and operate product features. We do not sell, rent, or repurpose this data for advertising.',
},
{
title: '4. Analytics',
body: 'We use minimal analytics to understand page usage, error rates, and aggregate product patterns. These analytics are not tied to your real-world identity and are not used for cross-site advertising.',
},
{
title: '5. Data Retention',
body: 'Subscription and configuration data is retained while your account remains active. You may request deletion by contacting us. Trade-history records are retained for up to 24 months for reconciliation, dispute handling, and product analysis.',
},
{
title: '6. Contact',
body: 'If you have a privacy-related question, please use the contact page.',
},
]
return (
<div className="page" style={{ maxWidth: 720 }}>
<div className="page-head">
<div>
<h1 className="page-title">{isZh ? '隐私政策' : 'Privacy Policy'}</h1>
<p className="page-sub">{isZh ? '最后更新:2026 年 4 月' : 'Last updated: April 2026'}</p>
</div>
</div>
<div className="card" style={{ padding: 32, lineHeight: 1.7, fontSize: 14, color: 'var(--ink-2)' }}>
{sections.map((section, index) => (
<div key={section.title} style={{ marginBottom: index === sections.length - 1 ? 0 : 20 }}>
<h2 style={{ fontSize: 16, fontWeight: 600, color: 'var(--ink)', marginBottom: 8 }}>{section.title}</h2>
<p style={{ marginBottom: 0 }}>
{section.title.endsWith('Contact') || section.title.endsWith('联系方式')
? <>
{section.body}{' '}
<Link href={`/${locale}/contact`} style={{ color: 'var(--amber)' }}>{isZh ? '联系页面' : 'contact page'}</Link>.
</>
: section.body}
</p>
</div>
))}
</div>
</div>
)
}