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>
This commit is contained in:
k
2026-05-25 00:53:27 +08:00
parent 01be8e790b
commit d72323b1c6
67 changed files with 11735 additions and 2530 deletions
+492
View File
@@ -0,0 +1,492 @@
import type { Metadata } from 'next'
import Link from 'next/link'
const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://trumpsignal.com'
type Locale = 'en' | 'zh'
type MethodSection = {
tag: string
title: string
answer: string
paragraphs: string[]
formula?: string
bullets?: string[]
limitation: string
}
type MethodologyCopy = {
title: string
description: string
keywords: string[]
ogTitle: string
ogDescription: string
heroTitle: string
heroSubtitle: string
intro: string
sections: MethodSection[]
footer: string
footerLinks: {
contact: string
glossary: string
caseStudies: string
}
}
function getCopy(locale: string): MethodologyCopy {
const isZh = false // i18n shelved — Chinese branches kept as dead code for future revival; see messages/zh.json
if (isZh) {
return {
title: '信号方法论 - Trump Alpha',
description:
'完整解释 Trump Alpha 六个信号引擎的工作方式,包括 Trump Truth Social 语义打分、BTC 周期底部 2-of-3 共振、KOL 观点抽取、言行偏离、资金费率反转和 Hyperliquid 自动执行风控模型。',
keywords: [
'加密信号方法论',
'AHR999',
'Pi Cycle Bottom',
'200周均线',
'Trump Truth Social 信号',
'KOL 观点抽取',
'言行偏离',
'资金费率反转',
'Hyperliquid 自动交易',
],
ogTitle: 'Signal Methodology | Trump Alpha',
ogDescription:
'Trump Alpha 六个引擎的完整方法论:数据源、触发规则、执行方式和已知限制。',
heroTitle: '信号方法论',
heroSubtitle: '从原始数据到交易动作,逐个解释每个引擎到底怎么工作',
intro:
'Trump Alpha 不是一个单一策略,而是六个相互独立的引擎。每个引擎都有自己的数据源、触发条件和失败模式。这里给出的是当前线上版本的真实逻辑,而不是营销版摘要。',
sections: [
{
tag: 'Signal 1 · 实时事件',
title: 'Trump Truth Social 情绪引擎',
answer:
'这个引擎实时轮询 Donald Trump 的 Truth Social 帖子,并在几秒内判断帖子是否会对加密市场形成短线方向性冲击。',
paragraphs: [
'系统只处理带有文字内容的原帖或转帖。纯图片、纯链接和没有可解释文本的信息会被过滤掉,因为这些内容更容易产生误触发。',
'每条帖子会被送进结构化语义分类流程,输出方向、主要资产和置信度。只有当置信度高于用户门槛,且交易时间窗、日预算、仓位上限都允许时,自动执行层才会放行。',
],
formula: `if classification != NOISE
AND confidence >= user_threshold
AND current_time in active_window
AND daily_spend < daily_cap
=> open isolated-margin trade`,
bullets: [
'方向标签:LONG / SHORT / NOISE',
'默认场景:突发政策表态、监管口径、关税升级、美元或财政扩张相关表述',
'风控层:逐仓、止盈止损、日预算上限、活跃时段、单笔仓位上限',
],
limitation:
'这个模型理解的是“帖子语义”,不是完整宏观环境。它很适合事件驱动,但不保证在风险偏好急转直下的市场里仍有同样的盈亏比。',
},
{
tag: 'Signal 2 · 日频 · BTC',
title: 'BTC 周期底部 2-of-3 共振',
answer:
'当前线上 BTC 系统使用三项经典底部指标做 2-of-3 共振,只在宏观底部区域附近给出低频的 long-only 信号。',
paragraphs: [
'这套逻辑不再依赖付费链上数据,而是改成更稳健、更容易验证的公开价格框架。核心思想没变:抓大级别熊市尾声,而不是做日内择时。',
'扫描器每天只跑一次,因为这不是高频策略。它要解决的不是“今天能不能涨 2%”,而是“是否正在进入一个值得持有数月的反转区间”。',
],
formula: `signal fires if count(
AHR999 < 0.45,
price <= 200-week MA * 1.05,
Pi Cycle Bottom true
) >= 2`,
bullets: [
'2-of-3 触发时,信心分高于单指标方案',
'只做 long-only,不做趋势中的逆势 short',
'退出更偏向保护利润和周期持有,而不是固定止盈',
],
limitation:
'这套方法天生滞后于最低点。它接受“抄不到最底”,换取更少的中继下跌误判。最大的风险是把中期调整误判成结构性底部。',
},
{
tag: 'Signal 3 · 日频 · KOL',
title: 'KOL 长文与播客观点抽取',
answer:
'KOL 引擎每天抓取长文、博客和播客描述,提取出明确的资产观点,并区分是明确买卖、方向性看法,还是只是提及。',
paragraphs: [
'比起碎片化推文,长文和播客摘要更容易包含完整论证、仓位语气和时间窗口,因此对 AI 提取更友好,也更适合作为可回溯的数据资产。',
'输出结构不只包含 ticker,还包含动作类型、置信度和最短支撑引用句。这样前端和后续检索系统都能拿到“观点 + 证据”的组合,而不只是一个标签。',
],
formula: `{
"summary": "<thesis>",
"tickers": [
{
"ticker": "BTC",
"action": "buy | sell | bullish | bearish | mention",
"conviction": 0.0-1.0,
"quote": "<supporting sentence>"
}
]
}`,
bullets: [
'buy / sell 表示作者明确表达了交易动作',
'bullish / bearish 表示方向明确但没有出现实际下单表述',
'mention 仅表示提到标的,不足以视作交易观点',
],
limitation:
'KOL 观点提取的难点在于上下文。历史复盘、赞助口播、反讽和模糊措辞都会降低可信度,因此系统对噪音过滤比较保守。',
},
{
tag: 'Signal 4 · 日频 · 交叉验证',
title: 'Talks-vs-Trades 言行偏离',
answer:
'当 KOL 公开表达的方向,与其链上钱包在同一资产上的实际操作相反时,系统会把链上行为视作更高优先级的真实信号。',
paragraphs: [
'这个模块把“说了什么”和“做了什么”分开建模。公开叙事影响舆论,但仓位变化更接近真实风险暴露,因此两者冲突时,链上动作通常更有信息增量。',
'目前系统会在 KOL 发文后的 ±7 天窗口内查找同资产的仓位变化,并将新增/加仓归为 long action,把减仓/清仓归为 short action。',
],
formula: `LONG_INTENT + SHORT_ACTION => DIVERGENCE (short)
SHORT_INTENT + LONG_ACTION => DIVERGENCE (long)
LONG_INTENT + LONG_ACTION => ALIGNMENT
SHORT_INTENT + SHORT_ACTION => ALIGNMENT`,
bullets: [
'公开看多但链上减仓:偏离,方向按 short 解释',
'公开看空但链上加仓:偏离,方向按 long 解释',
'公开观点和链上仓位一致:一致性增强,不一定是反向机会',
],
limitation:
'当前可见性仍受限于已知钱包集合。一个 KOL 可能分散使用多个地址、CEX 或未标记账户,因此偏离信号属于高质量但不保证覆盖完整仓位。',
},
{
tag: 'Signal 5 · 小时级 · 衍生品',
title: '资金费率极值反转',
answer:
'资金费率引擎不是追涨杀跌,而是盯着拥挤度。当多头或空头过度拥挤,且极值开始均值回归时,系统会给出反向信号。',
paragraphs: [
'永续合约的 funding rate 能直观反映杠杆倾斜。如果市场长期是“多头在付钱”,说明做多拥挤;反过来则代表空头拥挤。极端拥挤往往在清算前夜。',
'当前前端展示的是 30 日累计 funding 和实时状态,便于直接判断是否进入危险区,而不是只看单个时间点的 funding 数字。',
],
formula: `30d cumulative funding >= +3% and mean-reverting => SHORT bias
30d cumulative funding <= -3% and mean-reverting => LONG bias`,
bullets: [
'用累计 funding 代替单点读数,更适合识别持续拥挤',
'方向是反向交易 crowd,而不是顺着 crowd',
'适合做拥挤度监控,也适合和其他系统做组合验证',
],
limitation:
'资金费率极值可以持续比预期更久。它更像条件成熟的提醒,而不是保证立刻反转的钟摆,因此执行层必须配合止损和仓位控制。',
},
{
tag: 'Signal 6 · 执行层',
title: 'Hyperliquid 自动交易与安全模型',
answer:
'自动交易层的职责不是“提高收益率”,而是把信号执行标准化,并在风控上强制落实逐仓、止损、预算和时间窗等约束。',
paragraphs: [
'Trump Alpha 通过 trade-only API key 与 Hyperliquid 连接,当前不会接触用户私钥或提现权限。这意味着系统能执行交易,但不能挪走资产。',
'自动执行目前只接入 Trump Truth Social 实时信号。BTC 周期底部、KOL 观点和言行偏离依旧定位为研究与辅助决策层,默认由用户手动处理。',
],
bullets: [
'最低置信度门槛',
'逐仓模式',
'开仓即挂止盈止损',
'日预算上限',
'活跃时间窗',
'单笔仓位上限',
],
limitation:
'执行层再稳,也无法把错误信号变成好交易。它能降低人为偏差,但不能替代策略本身的边际优势。',
},
],
footer: '方法论最后更新于 2026 年 5 月。页面会随着线上逻辑更新而同步修订。',
footerLinks: {
contact: '联系我们',
glossary: '术语表',
caseStudies: '案例研究',
},
}
}
return {
title: 'Signal Methodology — How Each Engine Works',
description:
"Full technical methodology behind Trump Alpha's live signal engines: Trump Truth Social AI scoring, BTC 2-of-3 macro-bottom confluence, KOL feed extraction, talks-vs-trades divergence, funding rate reversals, and the Hyperliquid auto-trader safety model.",
keywords: [
'crypto signal methodology',
'AHR999 explained',
'Pi Cycle Bottom',
'200-week moving average Bitcoin',
'Trump Truth Social AI scoring',
'KOL signal extraction',
'talks vs trades methodology',
'funding rate reversal signal',
'Hyperliquid isolated margin',
],
ogTitle: 'Signal Methodology | Trump Alpha',
ogDescription:
'How each Trump Alpha engine works: data sources, trigger logic, execution rules, and known limitations.',
heroTitle: 'Signal Methodology',
heroSubtitle: 'How each engine works, from raw input to trading decision',
intro:
'Trump Alpha is not one monolithic strategy. It is a stack of six independent engines, each with its own data source, trigger logic, and failure mode. This page documents the live production logic rather than a simplified marketing summary.',
sections: [
{
tag: 'Signal 1 · Real-time event',
title: 'Trump Truth Social Sentiment Engine',
answer:
'This engine watches Donald Trumps Truth Social feed in real time and scores whether a new post is likely to create a short-term directional move in crypto.',
paragraphs: [
'Only text-bearing original posts and reposts are scored. Pure media reposts, link dumps, and non-interpretable content are filtered out because they generate too many false positives.',
'Each post goes through a structured semantic classification step that returns direction, primary asset, and confidence. Auto-execution only proceeds when confidence clears the user threshold and all user-level trade constraints still allow a new position.',
],
formula: `if classification != NOISE
AND confidence >= user_threshold
AND current_time in active_window
AND daily_spend < daily_cap
=> open isolated-margin trade`,
bullets: [
'Direction labels: LONG / SHORT / NOISE',
'Typical catalysts: policy comments, tariff escalation, regulation, fiscal expansion, dollar weakness',
'Safety rails: isolated margin, TP/SL, daily budget cap, active hours, per-trade size cap',
],
limitation:
'The model interprets post semantics, not full macro context. It is strong for event-driven reaction, but it does not guarantee the same edge during broad risk-off regimes.',
},
{
tag: 'Signal 2 · Daily · BTC',
title: 'BTC Macro-Bottom 2-of-3 Confluence',
answer:
'The live BTC engine uses three classic bottom markers and only fires a low-frequency long-only signal when at least two of them agree.',
paragraphs: [
'The production system no longer depends on premium on-chain feeds. It now uses a more durable public-price framework that is easier to verify, easier to operate, and less brittle under vendor changes.',
'This scanner runs once a day because it is solving a cycle-level problem, not an intraday one. The question is not whether BTC can bounce today, but whether the market is entering a region that deserves multi-month exposure.',
],
formula: `signal fires if count(
AHR999 < 0.45,
price <= 200-week MA * 1.05,
Pi Cycle Bottom true
) >= 2`,
bullets: [
'2-of-3 agreement carries more weight than any single indicator',
'Long only by design; it does not try to fade uptrends with short signals',
'Exit logic is built around capital protection and cycle capture, not fixed profit targets',
],
limitation:
'This method is intentionally late relative to the exact wick low. It accepts that trade-off to reduce the chance of confusing a mid-cycle correction with a structural bottom.',
},
{
tag: 'Signal 3 · Daily · KOL',
title: 'KOL Long-Form Thesis Extraction',
answer:
'The KOL engine ingests long-form writing, blogs, and podcast descriptions, then extracts explicit asset views and separates true trade calls from soft mentions.',
paragraphs: [
'Long-form sources tend to include fuller reasoning, clearer sizing language, and more precise timing than short social posts. That makes them better raw material for a retrieval-friendly signal archive.',
'The output includes not only the ticker and action, but also a conviction score and the shortest supporting quote. That gives both the UI and downstream retrieval systems access to view plus evidence, not just a label.',
],
formula: `{
"summary": "<thesis>",
"tickers": [
{
"ticker": "BTC",
"action": "buy | sell | bullish | bearish | mention",
"conviction": 0.0-1.0,
"quote": "<supporting sentence>"
}
]
}`,
bullets: [
'buy / sell means the author explicitly states a trade action',
'bullish / bearish means directional intent without an explicit trade statement',
'mention means the asset appears but the text is not strong enough to treat as a call',
],
limitation:
'Context is the hard part. Historical references, sponsor segments, irony, and vague thesis language all reduce extraction quality, so the filters are intentionally conservative.',
},
{
tag: 'Signal 4 · Daily · Cross-check',
title: 'Talks-vs-Trades Divergence',
answer:
'When a KOLs public stance and wallet behavior point in opposite directions on the same asset, the engine treats the wallet move as the higher-priority truth signal.',
paragraphs: [
'This module models “what was said” separately from “what was done.” Public narrative can move sentiment, but wallet changes are closer to actual risk exposure. When the two conflict, the on-chain action usually contains more information.',
'The current implementation scans a ±7 day window around a KOL post and maps new positions or adds to long action, while reductions and exits map to short action.',
],
formula: `LONG_INTENT + SHORT_ACTION => DIVERGENCE (short)
SHORT_INTENT + LONG_ACTION => DIVERGENCE (long)
LONG_INTENT + LONG_ACTION => ALIGNMENT
SHORT_INTENT + SHORT_ACTION => ALIGNMENT`,
bullets: [
'Publicly bullish while reducing the wallet position becomes a short-style divergence',
'Publicly bearish while adding to the wallet position becomes a long-style divergence',
'Alignment boosts confidence, but it is not automatically a contrarian trade',
],
limitation:
'Coverage still depends on known wallets. A KOL can split risk across multiple addresses, exchanges, or unlabeled accounts, so divergence is high quality but not guaranteed full-balance visibility.',
},
{
tag: 'Signal 5 · Hourly · Derivatives',
title: 'Funding Rate Extreme Reversal',
answer:
'The funding engine is not chasing price. It watches crowding and looks for mean reversion after leverage has become one-sided enough to create liquidation risk.',
paragraphs: [
'Perpetual funding rates are a direct lens into leverage tilt. If longs keep paying, the long side is crowded. If shorts keep paying, the short side is crowded. Extreme crowding often precedes violent squeezes in the opposite direction.',
'The live UI emphasizes 30-day cumulative funding and current state, which makes crowding easier to interpret than isolated single-print readings.',
],
formula: `30d cumulative funding >= +3% and mean-reverting => SHORT bias
30d cumulative funding <= -3% and mean-reverting => LONG bias`,
bullets: [
'Cumulative funding is more useful than single-point funding for persistent crowd detection',
'The trade idea is to fade the crowd, not to join it',
'Useful as a standalone crowding monitor or as confirmation for other systems',
],
limitation:
'Funding extremes can persist longer than expected. The signal is a condition alert, not a guarantee of immediate reversal, so position sizing and stop logic still matter.',
},
{
tag: 'Signal 6 · Execution layer',
title: 'Hyperliquid Auto-Trader and Safety Model',
answer:
'The auto-trader exists to standardize execution and enforce risk constraints, not to manufacture edge out of a weak signal.',
paragraphs: [
'Trump Alpha connects to Hyperliquid through a trade-only API key class. The system can submit and manage trades, but it does not have withdrawal rights and does not touch wallet private keys.',
'Today the auto-trader is wired to the Trump Truth Social engine only. BTC macro-bottom, KOL thesis extraction, and divergence remain research and decision-support layers by default.',
],
bullets: [
'Minimum confidence threshold',
'Isolated margin',
'TP/SL attached at entry',
'Daily budget cap',
'Active trading window',
'Per-trade position cap',
],
limitation:
'Execution hygiene cannot turn a bad signal into a good trade. It reduces operational mistakes, but it cannot replace strategy edge.',
},
],
footer: 'Methodology last updated in May 2026. This page is revised whenever live logic changes.',
footerLinks: {
contact: 'Contact',
glossary: 'Glossary',
caseStudies: 'Case Studies',
},
}
}
export function generateMetadata({
params: { locale },
}: {
params: { locale: string }
}): Metadata {
const copy = getCopy(locale)
return {
title: copy.title,
description: copy.description,
keywords: copy.keywords,
openGraph: {
title: copy.ogTitle,
description: copy.ogDescription,
},
alternates: {
canonical: `${siteUrl}/${locale}/methodology`,
languages: {
en: `${siteUrl}/en/methodology`,
'x-default': `${siteUrl}/en/methodology`,
},
},
}
}
const SECTION_STYLE = {
borderTop: '1px solid var(--line)',
paddingTop: 32,
marginTop: 32,
}
const H2 = { fontSize: 20, fontWeight: 700, color: 'var(--ink)', marginBottom: 12, lineHeight: 1.3 }
const P = { fontSize: 14, color: 'var(--ink-2)', lineHeight: 1.75, marginBottom: 12 }
const LI = { fontSize: 14, color: 'var(--ink-2)', lineHeight: 1.75, marginBottom: 6 }
function Tag({ children, color = 'var(--amber)' }: { children: string; color?: string }) {
return (
<span style={{
display: 'inline-block',
fontSize: 10, fontWeight: 700, letterSpacing: '0.07em',
textTransform: 'uppercase', fontFamily: 'monospace',
padding: '3px 8px', borderRadius: 4,
background: `color-mix(in srgb, ${color} 12%, transparent)`,
color, marginBottom: 12,
}}>
{children}
</span>
)
}
function Formula({ children }: { children: React.ReactNode }) {
return (
<div style={{
fontFamily: 'monospace', fontSize: 13,
background: 'var(--bg-sunk)', border: '1px solid var(--line)',
borderRadius: 8, padding: '14px 18px',
color: 'var(--ink)', margin: '12px 0', overflowX: 'auto',
whiteSpace: 'pre-wrap',
}}>
{children}
</div>
)
}
export default function MethodologyPage({ params: { locale } }: { params: { locale: string } }) {
const copy = getCopy(locale)
const isZh = false // i18n shelved — Chinese branches kept as dead code for future revival; see messages/zh.json
return (
<div className="page" style={{ maxWidth: 760 }}>
<div className="page-head">
<div>
<h1 className="page-title">{copy.heroTitle}</h1>
<p className="page-sub">{copy.heroSubtitle}</p>
</div>
</div>
<div className="card" style={{ padding: '28px 32px' }}>
<p style={{ ...P, color: 'var(--ink-3)', fontStyle: 'italic' }}>
{copy.intro}
</p>
{copy.sections.map((section, index) => (
<section key={section.title} style={SECTION_STYLE}>
<Tag color={index % 2 === 0 ? 'var(--amber)' : 'var(--violet, #a78bfa)'}>{section.tag}</Tag>
<h2 style={H2}>{section.title}</h2>
<p style={P}>
<strong>{isZh ? '直接结论:' : 'Direct answer:'}</strong> {section.answer}
</p>
{section.paragraphs.map(paragraph => (
<p key={paragraph} style={P}>{paragraph}</p>
))}
{section.formula && <Formula>{section.formula}</Formula>}
{section.bullets && (
<ul style={{ paddingLeft: 20 }}>
{section.bullets.map(item => <li key={item} style={LI}>{item}</li>)}
</ul>
)}
<p style={{ ...P, color: 'var(--ink-3)' }}>
<strong>{isZh ? '已知限制:' : 'Known limitation:'}</strong> {section.limitation}
</p>
</section>
))}
<div style={{ ...SECTION_STYLE, borderTop: '1px solid var(--line)' }}>
<p style={{ ...P, color: 'var(--ink-4)', fontSize: 12 }}>
{copy.footer}{' '}
<Link href={`/${locale}/contact`} style={{ color: 'var(--amber)' }}>{copy.footerLinks.contact}</Link>.
{' '}{isZh ? '另见:' : 'See also:'}{' '}
<Link href={`/${locale}/glossary`} style={{ color: 'var(--amber)' }}>{copy.footerLinks.glossary}</Link>
{' '}·{' '}
<Link href={`/${locale}/case-studies`} style={{ color: 'var(--amber)' }}>{copy.footerLinks.caseStudies}</Link>.
</p>
</div>
</div>
</div>
)
}