mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-11 23:07:01 +08:00
feat: cream terminal redesign, English-only UI, autopilot launch fixes
- Redesign dashboard into a cream-paper + vermilion IBM Plex Mono terminal (live L2 order book, cost/liq map, WS K-line, signal matrix, orchestration topology, risk radar, execution log, current positions, equity curve) - Convert all user-facing UI and backend strings/prompts from Chinese to English (multi-language retained, default English) - Add /api/statistics/full endpoint + full-stats frontend wiring - Fix Autopilot launch: reuse the existing trader instead of creating duplicates (eliminates repeat ~35s create cost and stale-trader 404s); launch sends 5m scan interval - Fix unreadable toasts: cream theme with high-contrast text + per-type accent - Silence background dashboard polls (getTraderConfig) to stop error-toast spam
This commit is contained in:
@@ -76,7 +76,7 @@ function buildAgentName(nowMs: number) {
|
||||
return `${AGENT_NAME} valid_until ${nowMs + AGENT_VALIDITY_MS}`
|
||||
}
|
||||
const HYPERLIQUID_BUILDER_ADDRESS = '0x891dc6f05ad47a3c1a05da55e7a7517971faaf0d'
|
||||
// 0.05% (万5). Must match the server's defaultHyperliquidBuilderMaxFee and
|
||||
// 0.05% (5 bps). Must match the server's defaultHyperliquidBuilderMaxFee and
|
||||
// the BuilderInfo.Fee=50 (= 5 bps) used at order placement. The user signs
|
||||
// this exact string when approving the builder during wallet connect.
|
||||
const HYPERLIQUID_BUILDER_MAX_FEE = '0.05%'
|
||||
@@ -131,7 +131,7 @@ function getPreferredWalletProvider(): WalletProvider | undefined {
|
||||
|
||||
function walletSupportLabel(language: Language) {
|
||||
return language === 'zh'
|
||||
? '支持 MetaMask、Rabby、Coinbase、Phantom、Brave、Backpack、OKX、Trust 等 EVM 钱包。'
|
||||
? 'Supports MetaMask, Rabby, Coinbase, Phantom, Brave, Backpack, OKX, Trust and other EVM wallets.'
|
||||
: 'Supports MetaMask, Rabby, Coinbase Wallet, Phantom, Brave, Backpack, OKX, Trust and other EVM wallets.'
|
||||
}
|
||||
|
||||
@@ -241,53 +241,53 @@ export function HyperliquidWalletConnect({
|
||||
const [hasWalletProvider, setHasWalletProvider] = useState(false)
|
||||
const text = useMemo(
|
||||
() => ({
|
||||
title: language === 'zh' ? 'Hyperliquid 钱包' : 'Hyperliquid Wallet',
|
||||
connect: language === 'zh' ? '连接 Hyperliquid' : 'Connect Hyperliquid',
|
||||
connected: language === 'zh' ? '已连接' : 'Connected',
|
||||
mainWallet: language === 'zh' ? 'EVM 主钱包' : 'EVM main wallet',
|
||||
title: language === 'zh' ? 'Hyperliquid Wallet' : 'Hyperliquid Wallet',
|
||||
connect: language === 'zh' ? 'Connect Hyperliquid' : 'Connect Hyperliquid',
|
||||
connected: language === 'zh' ? 'Connected' : 'Connected',
|
||||
mainWallet: language === 'zh' ? 'EVM main wallet' : 'EVM main wallet',
|
||||
generateAgent:
|
||||
language === 'zh'
|
||||
? '生成 NOFX Agent 钱包'
|
||||
? 'Generate NOFX agent wallet'
|
||||
: 'Generate NOFX agent wallet',
|
||||
approveAgent:
|
||||
language === 'zh' ? '授权 Agent 交易' : 'Authorize agent trading',
|
||||
language === 'zh' ? 'Authorize agent trading' : 'Authorize agent trading',
|
||||
approveBuilder:
|
||||
language === 'zh' ? '完成交易授权' : 'Finalize trading authorization',
|
||||
save: language === 'zh' ? '保存到 NOFX' : 'Save to NOFX',
|
||||
done: language === 'zh' ? '流程已完成' : 'Flow complete',
|
||||
balance: language === 'zh' ? 'Hyperliquid 余额' : 'Hyperliquid balance',
|
||||
withdrawable: language === 'zh' ? '可用' : 'Withdrawable',
|
||||
equity: language === 'zh' ? '权益' : 'Equity',
|
||||
marginUsed: language === 'zh' ? '已用保证金' : 'Margin used',
|
||||
unrealizedPnl: language === 'zh' ? '未实现盈亏' : 'Unrealized PnL',
|
||||
refresh: language === 'zh' ? '刷新' : 'Refresh',
|
||||
language === 'zh' ? 'Finalize trading authorization' : 'Finalize trading authorization',
|
||||
save: language === 'zh' ? 'Save to NOFX' : 'Save to NOFX',
|
||||
done: language === 'zh' ? 'Flow complete' : 'Flow complete',
|
||||
balance: language === 'zh' ? 'Hyperliquid balance' : 'Hyperliquid balance',
|
||||
withdrawable: language === 'zh' ? 'Withdrawable' : 'Withdrawable',
|
||||
equity: language === 'zh' ? 'Equity' : 'Equity',
|
||||
marginUsed: language === 'zh' ? 'Margin used' : 'Margin used',
|
||||
unrealizedPnl: language === 'zh' ? 'Unrealized PnL' : 'Unrealized PnL',
|
||||
refresh: language === 'zh' ? 'Refresh' : 'Refresh',
|
||||
noCustody:
|
||||
language === 'zh'
|
||||
? '资金保留在你的 Hyperliquid 账户;NOFX 只保存已授权 Agent 钱包。'
|
||||
? 'Funds stay in your Hyperliquid account; NOFX only stores the authorized agent wallet.'
|
||||
: 'Funds stay in your Hyperliquid account; NOFX only stores the authorized agent wallet.',
|
||||
agentExpiry:
|
||||
language === 'zh' ? 'Agent 授权到期' : 'Agent authorization expires',
|
||||
agentExpired: language === 'zh' ? '已过期' : 'Expired',
|
||||
language === 'zh' ? 'Agent authorization expires' : 'Agent authorization expires',
|
||||
agentExpired: language === 'zh' ? 'Expired' : 'Expired',
|
||||
agentNoAuth:
|
||||
language === 'zh'
|
||||
? '未检测到 NOFX Agent 授权'
|
||||
? 'No NOFX agent authorization found'
|
||||
: 'No NOFX agent authorization found',
|
||||
renewAgent:
|
||||
language === 'zh'
|
||||
? '续期 Agent 授权(+180 天)'
|
||||
? 'Renew agent authorization (+180d)'
|
||||
: 'Renew agent authorization (+180d)',
|
||||
renewHint:
|
||||
language === 'zh'
|
||||
? 'Hyperliquid 不允许重复使用同一个 Agent,续期会生成一个新的 Agent 并以 180 天有效期授权,然后自动更新 NOFX 保存的私钥(需登录)。'
|
||||
? 'Hyperliquid forbids reusing an agent, so renewal creates a new agent approved for 180 days, then updates the stored key in NOFX (sign-in required).'
|
||||
: 'Hyperliquid forbids reusing an agent, so renewal creates a new agent approved for 180 days, then updates the stored key in NOFX (sign-in required).',
|
||||
noWalletTitle:
|
||||
language === 'zh' ? '未检测到 EVM 钱包' : 'No EVM wallet detected',
|
||||
language === 'zh' ? 'No EVM wallet detected' : 'No EVM wallet detected',
|
||||
noWalletDetail:
|
||||
language === 'zh'
|
||||
? '先安装 Rabby 或 MetaMask,创建或导入钱包,然后回到这里连接 Hyperliquid。'
|
||||
? 'Install Rabby or MetaMask, create or import a wallet, then return here to connect Hyperliquid.'
|
||||
: 'Install Rabby or MetaMask, create or import a wallet, then return here to connect Hyperliquid.',
|
||||
installRabby: language === 'zh' ? '安装 Rabby' : 'Install Rabby',
|
||||
installMetaMask: language === 'zh' ? '安装 MetaMask' : 'Install MetaMask',
|
||||
installRabby: language === 'zh' ? 'Install Rabby' : 'Install Rabby',
|
||||
installMetaMask: language === 'zh' ? 'Install MetaMask' : 'Install MetaMask',
|
||||
}),
|
||||
[language]
|
||||
)
|
||||
@@ -500,7 +500,7 @@ export function HyperliquidWalletConnect({
|
||||
if (!provider) {
|
||||
setError(
|
||||
language === 'zh'
|
||||
? '未检测到 EVM 钱包,请安装 MetaMask / Rabby / OKX / Coinbase Wallet。'
|
||||
? 'No EVM wallet detected. Install MetaMask, Rabby, OKX or Coinbase Wallet.'
|
||||
: 'No EVM wallet detected. Install MetaMask, Rabby, OKX or Coinbase Wallet.'
|
||||
)
|
||||
return
|
||||
@@ -625,7 +625,7 @@ export function HyperliquidWalletConnect({
|
||||
if (!isLoggedIn) {
|
||||
setError(
|
||||
language === 'zh'
|
||||
? '续期需要先登录 NOFX:Hyperliquid 不允许重复使用同一个 Agent,续期会生成新的 Agent 并更新已保存的私钥。'
|
||||
? 'Renewal requires signing in: Hyperliquid forbids reusing the same agent, so renewal creates a new agent and updates the stored key.'
|
||||
: 'Renewal requires signing in: Hyperliquid forbids reusing the same agent, so renewal creates a new agent and updates the stored key.'
|
||||
)
|
||||
return
|
||||
@@ -680,7 +680,7 @@ export function HyperliquidWalletConnect({
|
||||
}))
|
||||
throw new Error(
|
||||
language === 'zh'
|
||||
? '新 Agent 已授权,但未找到对应的 NOFX 配置,请用“保存到 NOFX”手动保存。'
|
||||
? 'New agent approved, but no matching NOFX config was found. Use "Save to NOFX" to store it.'
|
||||
: 'New agent approved, but no matching NOFX config was found. Use "Save to NOFX" to store it.'
|
||||
)
|
||||
}
|
||||
@@ -712,7 +712,7 @@ export function HyperliquidWalletConnect({
|
||||
}))
|
||||
toast.success(
|
||||
language === 'zh'
|
||||
? 'Agent 已续期(新 Agent,有效期 180 天)'
|
||||
? 'Agent renewed (new agent, valid 180 days)'
|
||||
: 'Agent renewed (new agent, valid 180 days)'
|
||||
)
|
||||
await refreshAgentInfo()
|
||||
@@ -721,7 +721,7 @@ export function HyperliquidWalletConnect({
|
||||
err instanceof Error
|
||||
? err.message
|
||||
: language === 'zh'
|
||||
? 'Agent 续期失败'
|
||||
? 'Agent renewal failed'
|
||||
: 'Agent renewal failed'
|
||||
)
|
||||
} finally {
|
||||
@@ -773,14 +773,14 @@ export function HyperliquidWalletConnect({
|
||||
: undefined,
|
||||
}))
|
||||
toast.success(
|
||||
language === 'zh' ? '交易授权已完成' : 'Trading authorization finalized'
|
||||
language === 'zh' ? 'Trading authorization finalized' : 'Trading authorization finalized'
|
||||
)
|
||||
} catch (err) {
|
||||
setError(
|
||||
err instanceof Error
|
||||
? err.message
|
||||
: language === 'zh'
|
||||
? '交易授权失败'
|
||||
? 'Trading authorization failed'
|
||||
: 'Trading authorization failed'
|
||||
)
|
||||
} finally {
|
||||
@@ -793,7 +793,7 @@ export function HyperliquidWalletConnect({
|
||||
if (!isLoggedIn) {
|
||||
setError(
|
||||
language === 'zh'
|
||||
? '请先登录 NOFX,再保存 Agent 钱包用于交易。'
|
||||
? 'Please sign in before saving the agent wallet for trading.'
|
||||
: 'Please sign in before saving the agent wallet for trading.'
|
||||
)
|
||||
return
|
||||
@@ -899,7 +899,7 @@ export function HyperliquidWalletConnect({
|
||||
onClick={() => setOpen((value) => !value)}
|
||||
className={`flex items-center gap-2 px-3 py-2 rounded-lg text-sm font-bold transition-all border ${
|
||||
complete
|
||||
? 'bg-emerald-500/10 border-emerald-400/30 text-emerald-300'
|
||||
? 'bg-nofx-success/10 border-nofx-success/30 text-nofx-success'
|
||||
: 'bg-nofx-gold/10 border-nofx-gold/30 text-nofx-gold hover:bg-nofx-gold/20'
|
||||
}`}
|
||||
>
|
||||
@@ -913,11 +913,11 @@ export function HyperliquidWalletConnect({
|
||||
|
||||
{(open || inline) && (
|
||||
<div
|
||||
className={`${inline ? 'relative w-full' : 'absolute right-0 top-full mt-2 w-[420px] shadow-2xl shadow-black/50'} rounded-2xl border border-nofx-gold/20 bg-[#11151B] z-[80] overflow-hidden`}
|
||||
className={`${inline ? 'relative w-full' : 'absolute right-0 top-full mt-2 w-[420px] shadow-2xl shadow-black/10'} rounded-2xl border border-[rgba(26,24,19,0.14)] bg-nofx-bg-lighter z-[80] overflow-hidden`}
|
||||
>
|
||||
<div className="flex items-center justify-between p-4 border-b border-white/10">
|
||||
<div className="flex items-center justify-between p-4 border-b border-[rgba(26,24,19,0.14)]">
|
||||
<div>
|
||||
<div className="font-bold text-white">{text.title}</div>
|
||||
<div className="font-bold text-nofx-text">{text.title}</div>
|
||||
<div className="text-xs text-nofx-text-muted mt-1">
|
||||
{text.noCustody}
|
||||
</div>
|
||||
@@ -929,7 +929,7 @@ export function HyperliquidWalletConnect({
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setOpen(false)}
|
||||
className="p-1 rounded hover:bg-white/10 text-zinc-500"
|
||||
className="p-1 rounded hover:bg-[rgba(26,24,19,0.06)] text-nofx-text-muted"
|
||||
>
|
||||
<X className="w-4 h-4" />
|
||||
</button>
|
||||
@@ -943,10 +943,10 @@ export function HyperliquidWalletConnect({
|
||||
<div
|
||||
className={`w-6 h-6 rounded-full flex items-center justify-center text-xs font-bold ${
|
||||
step.status === 'done'
|
||||
? 'bg-emerald-400 text-black'
|
||||
? 'bg-nofx-success text-white'
|
||||
: step.status === 'active'
|
||||
? 'bg-nofx-gold text-black'
|
||||
: 'bg-zinc-800 text-zinc-500'
|
||||
? 'bg-nofx-gold text-white'
|
||||
: 'bg-nofx-bg-deeper text-nofx-text-muted'
|
||||
}`}
|
||||
>
|
||||
{step.status === 'done' ? (
|
||||
@@ -958,8 +958,8 @@ export function HyperliquidWalletConnect({
|
||||
<span
|
||||
className={
|
||||
step.status === 'pending'
|
||||
? 'text-zinc-500'
|
||||
: 'text-zinc-200'
|
||||
? 'text-nofx-text-muted'
|
||||
: 'text-nofx-text'
|
||||
}
|
||||
>
|
||||
{step.label}
|
||||
@@ -969,14 +969,14 @@ export function HyperliquidWalletConnect({
|
||||
</div>
|
||||
|
||||
{error && (
|
||||
<div className="rounded-lg border border-red-500/30 bg-red-500/10 p-3 text-xs text-red-300">
|
||||
<div className="rounded-lg border border-nofx-danger/30 bg-nofx-danger/10 p-3 text-xs text-nofx-danger">
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!state.mainWallet && !hasWalletProvider && (
|
||||
<div className="rounded-xl border border-nofx-gold/20 bg-nofx-gold/5 p-3">
|
||||
<div className="text-sm font-semibold text-zinc-100">
|
||||
<div className="text-sm font-semibold text-nofx-text">
|
||||
{text.noWalletTitle}
|
||||
</div>
|
||||
<p className="mt-1 text-xs leading-5 text-nofx-text-muted">
|
||||
@@ -987,7 +987,7 @@ export function HyperliquidWalletConnect({
|
||||
href="https://rabby.io/"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="inline-flex items-center gap-2 rounded-lg border border-white/10 bg-white/[0.04] px-3 py-2 text-xs font-semibold text-zinc-200 hover:border-white/20 hover:bg-white/[0.07]"
|
||||
className="inline-flex items-center gap-2 rounded-lg border border-[rgba(26,24,19,0.14)] bg-nofx-bg-deeper px-3 py-2 text-xs font-semibold text-nofx-text hover:border-[rgba(26,24,19,0.24)] hover:bg-nofx-bg"
|
||||
>
|
||||
<Download className="h-3.5 w-3.5" />
|
||||
{text.installRabby}
|
||||
@@ -996,7 +996,7 @@ export function HyperliquidWalletConnect({
|
||||
href="https://metamask.io/download/"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="inline-flex items-center gap-2 rounded-lg border border-white/10 bg-white/[0.04] px-3 py-2 text-xs font-semibold text-zinc-200 hover:border-white/20 hover:bg-white/[0.07]"
|
||||
className="inline-flex items-center gap-2 rounded-lg border border-[rgba(26,24,19,0.14)] bg-nofx-bg-deeper px-3 py-2 text-xs font-semibold text-nofx-text hover:border-[rgba(26,24,19,0.24)] hover:bg-nofx-bg"
|
||||
>
|
||||
<ExternalLink className="h-3.5 w-3.5" />
|
||||
{text.installMetaMask}
|
||||
@@ -1005,14 +1005,14 @@ export function HyperliquidWalletConnect({
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="rounded-xl border border-white/10 bg-black/25 p-3 space-y-2 text-xs">
|
||||
<div className="rounded-xl border border-[rgba(26,24,19,0.14)] bg-nofx-bg-deeper p-3 space-y-2 text-xs">
|
||||
{state.mainWallet && (
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<span className="text-zinc-500">Main</span>
|
||||
<span className="text-nofx-text-muted">Main</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => copy(state.mainWallet!, 'Main wallet')}
|
||||
className="font-mono text-zinc-200 hover:text-nofx-gold flex items-center gap-1"
|
||||
className="font-mono text-nofx-text hover:text-nofx-gold flex items-center gap-1"
|
||||
>
|
||||
{shortAddress(state.mainWallet)}{' '}
|
||||
<Copy className="w-3 h-3" />
|
||||
@@ -1021,11 +1021,11 @@ export function HyperliquidWalletConnect({
|
||||
)}
|
||||
{state.agentAddress && (
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<span className="text-zinc-500">Agent</span>
|
||||
<span className="text-nofx-text-muted">Agent</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => copy(state.agentAddress!, 'Agent wallet')}
|
||||
className="font-mono text-zinc-200 hover:text-nofx-gold flex items-center gap-1"
|
||||
className="font-mono text-nofx-text hover:text-nofx-gold flex items-center gap-1"
|
||||
>
|
||||
{shortAddress(state.agentAddress)}{' '}
|
||||
<Copy className="w-3 h-3" />
|
||||
@@ -1033,16 +1033,16 @@ export function HyperliquidWalletConnect({
|
||||
</div>
|
||||
)}
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<span className="text-zinc-500">Network</span>
|
||||
<span className="font-mono text-zinc-300">
|
||||
<span className="text-nofx-text-muted">Network</span>
|
||||
<span className="font-mono text-nofx-text">
|
||||
Hyperliquid Mainnet
|
||||
</span>
|
||||
</div>
|
||||
{state.mainWallet && (
|
||||
<div className="flex items-center justify-between gap-3 border-t border-white/10 pt-2">
|
||||
<span className="text-zinc-500">{text.agentExpiry}</span>
|
||||
<div className="flex items-center justify-between gap-3 border-t border-[rgba(26,24,19,0.14)] pt-2">
|
||||
<span className="text-nofx-text-muted">{text.agentExpiry}</span>
|
||||
{agentInfoLoading && !agentInfo ? (
|
||||
<span className="font-mono text-zinc-400">Loading…</span>
|
||||
<span className="font-mono text-nofx-text-muted">Loading…</span>
|
||||
) : agentInfo ? (
|
||||
(() => {
|
||||
const { dateStr, daysLeft } = formatAgentExpiry(
|
||||
@@ -1052,10 +1052,10 @@ export function HyperliquidWalletConnect({
|
||||
const expired = daysLeft < 0
|
||||
const soon = daysLeft >= 0 && daysLeft <= 14
|
||||
const tone = expired
|
||||
? 'text-red-300'
|
||||
? 'text-nofx-danger'
|
||||
: soon
|
||||
? 'text-amber-300'
|
||||
: 'text-zinc-200'
|
||||
? 'text-nofx-gold'
|
||||
: 'text-nofx-text'
|
||||
return (
|
||||
<span className={`font-mono text-right ${tone}`}>
|
||||
{dateStr}
|
||||
@@ -1066,7 +1066,7 @@ export function HyperliquidWalletConnect({
|
||||
)
|
||||
})()
|
||||
) : (
|
||||
<span className="font-mono text-zinc-500">
|
||||
<span className="font-mono text-nofx-text-muted">
|
||||
{text.agentNoAuth}
|
||||
</span>
|
||||
)}
|
||||
@@ -1098,14 +1098,14 @@ export function HyperliquidWalletConnect({
|
||||
{state.mainWallet && (
|
||||
<div className="rounded-xl border border-nofx-gold/20 bg-nofx-gold/5 p-3 space-y-3 text-xs">
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<span className="font-bold text-zinc-100">
|
||||
<span className="font-bold text-nofx-text">
|
||||
{text.balance}
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => void refreshBalance()}
|
||||
disabled={balanceLoading}
|
||||
className="flex items-center gap-1 text-zinc-400 hover:text-nofx-gold disabled:opacity-60"
|
||||
className="flex items-center gap-1 text-nofx-text-muted hover:text-nofx-gold disabled:opacity-60"
|
||||
>
|
||||
<RefreshCw
|
||||
className={`w-3 h-3 ${balanceLoading ? 'animate-spin' : ''}`}
|
||||
@@ -1114,37 +1114,37 @@ export function HyperliquidWalletConnect({
|
||||
</button>
|
||||
</div>
|
||||
{balanceError ? (
|
||||
<div className="rounded-lg border border-red-500/30 bg-red-500/10 p-2 text-red-300">
|
||||
<div className="rounded-lg border border-nofx-danger/30 bg-nofx-danger/10 p-2 text-nofx-danger">
|
||||
{balanceError}
|
||||
</div>
|
||||
) : (
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<div className="rounded-lg bg-black/25 p-2">
|
||||
<div className="text-zinc-500">{text.withdrawable}</div>
|
||||
<div className="mt-1 font-mono text-sm font-bold text-emerald-300">
|
||||
<div className="rounded-lg bg-nofx-bg-deeper p-2">
|
||||
<div className="text-nofx-text-muted">{text.withdrawable}</div>
|
||||
<div className="mt-1 font-mono text-sm font-bold text-nofx-success">
|
||||
{balanceLoading && !account
|
||||
? 'Loading…'
|
||||
: `${formatUSDC(account?.withdrawable)} USDC`}
|
||||
</div>
|
||||
</div>
|
||||
<div className="rounded-lg bg-black/25 p-2">
|
||||
<div className="text-zinc-500">{text.equity}</div>
|
||||
<div className="mt-1 font-mono text-sm font-bold text-zinc-100">
|
||||
<div className="rounded-lg bg-nofx-bg-deeper p-2">
|
||||
<div className="text-nofx-text-muted">{text.equity}</div>
|
||||
<div className="mt-1 font-mono text-sm font-bold text-nofx-text">
|
||||
{balanceLoading && !account
|
||||
? 'Loading…'
|
||||
: `${formatUSDC(account?.accountValue)} USDC`}
|
||||
</div>
|
||||
</div>
|
||||
<div className="rounded-lg bg-black/25 p-2">
|
||||
<div className="text-zinc-500">{text.marginUsed}</div>
|
||||
<div className="mt-1 font-mono text-sm font-bold text-zinc-100">
|
||||
<div className="rounded-lg bg-nofx-bg-deeper p-2">
|
||||
<div className="text-nofx-text-muted">{text.marginUsed}</div>
|
||||
<div className="mt-1 font-mono text-sm font-bold text-nofx-text">
|
||||
{formatUSDC(account?.totalMarginUsed)} USDC
|
||||
</div>
|
||||
</div>
|
||||
<div className="rounded-lg bg-black/25 p-2">
|
||||
<div className="text-zinc-500">{text.unrealizedPnl}</div>
|
||||
<div className="rounded-lg bg-nofx-bg-deeper p-2">
|
||||
<div className="text-nofx-text-muted">{text.unrealizedPnl}</div>
|
||||
<div
|
||||
className={`mt-1 font-mono text-sm font-bold ${(account?.unrealizedPnl ?? 0) >= 0 ? 'text-emerald-300' : 'text-red-300'}`}
|
||||
className={`mt-1 font-mono text-sm font-bold ${(account?.unrealizedPnl ?? 0) >= 0 ? 'text-nofx-success' : 'text-nofx-danger'}`}
|
||||
>
|
||||
{formatSignedUSDC(account?.unrealizedPnl)} USDC
|
||||
</div>
|
||||
@@ -1192,7 +1192,7 @@ export function HyperliquidWalletConnect({
|
||||
)}
|
||||
{complete && (
|
||||
<>
|
||||
<div className="rounded-lg border border-emerald-400/30 bg-emerald-500/10 p-3 text-sm text-emerald-200 flex items-center gap-2">
|
||||
<div className="rounded-lg border border-nofx-success/30 bg-nofx-success/10 p-3 text-sm text-nofx-success flex items-center gap-2">
|
||||
<Shield className="w-4 h-4" /> {text.done}
|
||||
</div>
|
||||
<button
|
||||
@@ -1201,26 +1201,26 @@ export function HyperliquidWalletConnect({
|
||||
className="w-full flex items-center justify-center gap-2 rounded-xl border border-nofx-gold/30 bg-nofx-gold/10 px-4 py-3 text-sm font-bold text-nofx-gold transition hover:bg-nofx-gold/20"
|
||||
>
|
||||
{language === 'zh'
|
||||
? '重新授权交易'
|
||||
? 'Re-authorize trading'
|
||||
: 'Re-authorize trading'}
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between pt-2 border-t border-white/10">
|
||||
<div className="flex items-center justify-between pt-2 border-t border-[rgba(26,24,19,0.14)]">
|
||||
<a
|
||||
href="https://app.hyperliquid.xyz/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-xs text-zinc-500 hover:text-nofx-gold flex items-center gap-1"
|
||||
className="text-xs text-nofx-text-muted hover:text-nofx-gold flex items-center gap-1"
|
||||
>
|
||||
Open Hyperliquid <ExternalLink className="w-3 h-3" />
|
||||
</a>
|
||||
<button
|
||||
type="button"
|
||||
onClick={resetFlow}
|
||||
className="text-xs text-zinc-500 hover:text-red-300"
|
||||
className="text-xs text-nofx-text-muted hover:text-nofx-danger"
|
||||
>
|
||||
Reset
|
||||
</button>
|
||||
@@ -1246,7 +1246,7 @@ function ActionButton({
|
||||
type="button"
|
||||
disabled={busy}
|
||||
onClick={onClick}
|
||||
className="w-full flex items-center justify-center gap-2 rounded-xl bg-nofx-gold px-4 py-3 text-sm font-bold text-black transition hover:bg-yellow-400 disabled:opacity-60 disabled:cursor-not-allowed"
|
||||
className="w-full flex items-center justify-center gap-2 rounded-xl bg-nofx-gold px-4 py-3 text-sm font-bold text-white transition hover:opacity-90 disabled:opacity-60 disabled:cursor-not-allowed"
|
||||
>
|
||||
{busy ? <Loader2 className="w-4 h-4 animate-spin" /> : null}
|
||||
{label}
|
||||
|
||||
Reference in New Issue
Block a user