mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-06 20:41:14 +08:00
feat: rewrite FAQ with current product content and cream terminal design
Content: replaces the stale i18n-keyed answers (manual API-key setup, old Binance-era flows) with 34 answers matching the shipping product — Autopilot launch chain, AI fee wallet and Hyperliquid agent authorization, preflight checks and minimums, safe mode and fee-wallet-empty recovery, dashboard metric semantics (realized vs unrealized, fee drag, real-baseline drawdown), security model, self-hosting, and contributing. English-only, matching the UI. Format: FAQ answers are now typed content blocks (paragraphs, bullets, numbered steps, notes, link chips) rendered generically — the two giant hardcoded JSX special cases are gone. Restyled from the broken dark glassmorphism (unreadable prose-invert on the cream theme) to the terminal design language: small-caps mono category strips, hairline dividers, gold accents, code chips, bordered TOC with active tracking. Search filters the full block text; ~480 lines of dead faq* translation keys removed (faqNav kept for the nav label).
This commit is contained in:
@@ -1,19 +1,96 @@
|
||||
import { useEffect, useRef } from 'react'
|
||||
import { t, type Language } from '../../i18n/translations'
|
||||
import type { FAQCategory } from '../../data/faqData'
|
||||
// RoadmapWidget: removed dynamic embedding; only show external links on demand
|
||||
import { Fragment, useEffect, useRef } from 'react'
|
||||
import { ExternalLink } from 'lucide-react'
|
||||
import type { FAQBlock, FAQCategory } from '../../data/faqData'
|
||||
|
||||
interface FAQContentProps {
|
||||
categories: FAQCategory[]
|
||||
language: Language
|
||||
onActiveItemChange: (itemId: string) => void
|
||||
}
|
||||
|
||||
export function FAQContent({
|
||||
categories,
|
||||
language,
|
||||
onActiveItemChange,
|
||||
}: FAQContentProps) {
|
||||
/** Renders text with inline `code` spans (backtick syntax). */
|
||||
function InlineText({ text }: { text: string }) {
|
||||
const parts = text.split(/(`[^`]+`)/g)
|
||||
return (
|
||||
<>
|
||||
{parts.map((part, i) =>
|
||||
part.startsWith('`') && part.endsWith('`') ? (
|
||||
<code
|
||||
key={i}
|
||||
className="rounded bg-nofx-bg-deeper border border-[rgba(26,24,19,0.10)] px-1.5 py-0.5 font-mono text-[0.85em] text-nofx-text break-all"
|
||||
>
|
||||
{part.slice(1, -1)}
|
||||
</code>
|
||||
) : (
|
||||
<Fragment key={i}>{part}</Fragment>
|
||||
)
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function Block({ block }: { block: FAQBlock }) {
|
||||
switch (block.type) {
|
||||
case 'p':
|
||||
return (
|
||||
<p className="text-sm leading-6 text-nofx-text-muted">
|
||||
<InlineText text={block.text} />
|
||||
</p>
|
||||
)
|
||||
case 'list':
|
||||
return (
|
||||
<ul className="space-y-1.5">
|
||||
{block.items.map((item, i) => (
|
||||
<li key={i} className="flex gap-2 text-sm leading-6 text-nofx-text-muted">
|
||||
<span className="mt-[9px] h-1 w-1 shrink-0 rounded-full bg-nofx-gold" />
|
||||
<span>
|
||||
<InlineText text={item} />
|
||||
</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
case 'steps':
|
||||
return (
|
||||
<ol className="space-y-1.5">
|
||||
{block.items.map((item, i) => (
|
||||
<li key={i} className="flex gap-3 text-sm leading-6 text-nofx-text-muted">
|
||||
<span className="mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded border border-nofx-gold/30 bg-nofx-gold/10 font-mono text-[11px] font-bold text-nofx-gold">
|
||||
{i + 1}
|
||||
</span>
|
||||
<span>
|
||||
<InlineText text={item} />
|
||||
</span>
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
)
|
||||
case 'note':
|
||||
return (
|
||||
<div className="border-l-2 border-nofx-gold bg-nofx-gold/10 px-3 py-2 text-sm leading-6 text-nofx-text">
|
||||
<InlineText text={block.text} />
|
||||
</div>
|
||||
)
|
||||
case 'links':
|
||||
return (
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{block.links.map((link) => (
|
||||
<a
|
||||
key={link.href}
|
||||
href={link.href}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="inline-flex items-center gap-1.5 rounded border border-nofx-gold/25 bg-nofx-bg-deeper px-2.5 py-1 font-mono text-xs font-semibold text-nofx-gold hover:border-nofx-gold/50 hover:bg-nofx-gold/10"
|
||||
>
|
||||
{link.label}
|
||||
<ExternalLink className="h-3 w-3" />
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export function FAQContent({ categories, onActiveItemChange }: FAQContentProps) {
|
||||
const sectionRefs = useRef<Map<string, HTMLElement>>(new Map())
|
||||
|
||||
useEffect(() => {
|
||||
@@ -22,419 +99,60 @@ export function FAQContent({
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
const itemId = entry.target.getAttribute('data-item-id')
|
||||
if (itemId) {
|
||||
onActiveItemChange(itemId)
|
||||
}
|
||||
if (itemId) onActiveItemChange(itemId)
|
||||
}
|
||||
})
|
||||
},
|
||||
{
|
||||
rootMargin: '-100px 0px -80% 0px',
|
||||
threshold: 0,
|
||||
}
|
||||
{ rootMargin: '-100px 0px -80% 0px', threshold: 0 }
|
||||
)
|
||||
|
||||
sectionRefs.current.forEach((ref) => {
|
||||
if (ref) observer.observe(ref)
|
||||
})
|
||||
|
||||
sectionRefs.current.forEach((ref) => observer.observe(ref))
|
||||
return () => {
|
||||
sectionRefs.current.forEach((ref) => {
|
||||
if (ref) observer.unobserve(ref)
|
||||
})
|
||||
sectionRefs.current.forEach((ref) => observer.unobserve(ref))
|
||||
}
|
||||
}, [onActiveItemChange])
|
||||
}, [onActiveItemChange, categories])
|
||||
|
||||
const setRef = (itemId: string, element: HTMLElement | null) => {
|
||||
if (element) {
|
||||
sectionRefs.current.set(itemId, element)
|
||||
} else {
|
||||
sectionRefs.current.delete(itemId)
|
||||
}
|
||||
if (element) sectionRefs.current.set(itemId, element)
|
||||
else sectionRefs.current.delete(itemId)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-12">
|
||||
<div className="space-y-8">
|
||||
{categories.map((category) => (
|
||||
<div key={category.id} className="nofx-glass p-8 rounded-xl border border-[rgba(26,24,19,0.14)]">
|
||||
{/* Category Header */}
|
||||
<div className="flex items-center gap-3 mb-6 pb-3 border-b border-[rgba(26,24,19,0.14)]">
|
||||
<category.icon className="w-7 h-7 text-nofx-gold" />
|
||||
<h2 className="text-2xl font-bold text-nofx-text">
|
||||
{t(category.titleKey, language)}
|
||||
<div
|
||||
key={category.id}
|
||||
id={category.id}
|
||||
className="overflow-hidden rounded-xl border border-nofx-gold/20 bg-nofx-bg-lighter"
|
||||
>
|
||||
{/* category header — terminal small-caps strip */}
|
||||
<div className="flex items-center gap-2.5 border-b border-nofx-gold/20 bg-nofx-bg px-5 py-3 md:px-6">
|
||||
<category.icon className="h-4 w-4 text-nofx-gold" />
|
||||
<h2 className="font-mono text-xs font-bold uppercase tracking-[0.18em] text-nofx-text">
|
||||
{category.title}
|
||||
</h2>
|
||||
<span className="ml-auto font-mono text-[10px] uppercase tracking-[0.12em] text-nofx-text-muted">
|
||||
{category.items.length} {category.items.length === 1 ? 'entry' : 'entries'}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* FAQ Items */}
|
||||
<div className="space-y-8">
|
||||
<div className="divide-y divide-[rgba(26,24,19,0.10)]">
|
||||
{category.items.map((item) => (
|
||||
<section
|
||||
key={item.id}
|
||||
id={item.id}
|
||||
data-item-id={item.id}
|
||||
ref={(el) => setRef(item.id, el)}
|
||||
className="scroll-mt-24"
|
||||
className="scroll-mt-24 px-5 py-5 md:px-6"
|
||||
>
|
||||
{/* Question */}
|
||||
<h3 className="text-xl font-semibold mb-3 text-nofx-text">
|
||||
{t(item.questionKey, language)}
|
||||
<h3 className="mb-3 text-[15px] font-semibold leading-6 text-nofx-text">
|
||||
{item.question}
|
||||
</h3>
|
||||
|
||||
{/* Answer */}
|
||||
<div className="prose prose-invert max-w-none text-nofx-text-muted leading-relaxed">
|
||||
{item.id === 'github-projects-tasks' ? (
|
||||
<div className="space-y-3">
|
||||
<div className="text-base">
|
||||
{language === 'zh' ? 'Links:' : 'Links:'}{' '}
|
||||
<a
|
||||
href="https://github.com/orgs/NoFxAiOS/projects/3"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
style={{ color: '#E0483B' }}
|
||||
>
|
||||
{language === 'zh' ? 'Roadmap' : 'Roadmap'}
|
||||
</a>
|
||||
{' | '}
|
||||
<a
|
||||
href="https://github.com/orgs/NoFxAiOS/projects/5"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
style={{ color: '#E0483B' }}
|
||||
>
|
||||
{language === 'zh' ? 'Task Dashboard' : 'Task Dashboard'}
|
||||
</a>
|
||||
</div>
|
||||
<ol className="list-decimal pl-5 space-y-1 text-base">
|
||||
{language === 'zh' ? (
|
||||
<>
|
||||
<li>
|
||||
Open the links above and filter by labels (good
|
||||
first issue / help wanted / frontend / backend).
|
||||
</li>
|
||||
<li>
|
||||
Open the task and read the Description &
|
||||
Acceptance Criteria.
|
||||
</li>
|
||||
<li>
|
||||
Comment "assign me" or self-assign (if permitted).
|
||||
</li>
|
||||
<li>Fork the repository to your GitHub account.</li>
|
||||
<li>
|
||||
Sync your fork's <code>dev</code> with upstream:
|
||||
<code className="ml-2">
|
||||
git remote add upstream
|
||||
https://github.com/NoFxAiOS/nofx.git
|
||||
</code>
|
||||
<br />
|
||||
<code>git fetch upstream</code>
|
||||
<br />
|
||||
<code>git checkout dev</code>
|
||||
<br />
|
||||
<code>git rebase upstream/dev</code>
|
||||
<br />
|
||||
<code>git push origin dev</code>
|
||||
</li>
|
||||
<li>
|
||||
Create a feature branch from your fork's{' '}
|
||||
<code>dev</code>:
|
||||
<code className="ml-2">
|
||||
git checkout -b feat/your-topic
|
||||
</code>
|
||||
</li>
|
||||
<li>
|
||||
Push to your fork:
|
||||
<code className="ml-2">
|
||||
git push origin feat/your-topic
|
||||
</code>
|
||||
</li>
|
||||
<li>
|
||||
Open a PR: base <code>NoFxAiOS/nofx:dev</code> ←
|
||||
compare{' '}
|
||||
<code>your-username/nofx:feat/your-topic</code>.
|
||||
</li>
|
||||
<li>
|
||||
In PR, reference the Issue (e.g.,{' '}
|
||||
<code className="ml-1">Closes #123</code>) and
|
||||
choose the proper PR template; rebase onto{' '}
|
||||
<code>upstream/dev</code> as needed.
|
||||
</li>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<li>
|
||||
Open the links above and filter by labels (good
|
||||
first issue / help wanted / frontend / backend).
|
||||
</li>
|
||||
<li>
|
||||
Open the task and read the Description &
|
||||
Acceptance Criteria.
|
||||
</li>
|
||||
<li>
|
||||
Comment "assign me" or self-assign (if permitted).
|
||||
</li>
|
||||
<li>Fork the repository to your GitHub account.</li>
|
||||
<li>
|
||||
Sync your fork's <code>dev</code> with upstream:
|
||||
<code className="ml-2">
|
||||
git remote add upstream
|
||||
https://github.com/NoFxAiOS/nofx.git
|
||||
</code>
|
||||
<br />
|
||||
<code>git fetch upstream</code>
|
||||
<br />
|
||||
<code>git checkout dev</code>
|
||||
<br />
|
||||
<code>git rebase upstream/dev</code>
|
||||
<br />
|
||||
<code>git push origin dev</code>
|
||||
</li>
|
||||
<li>
|
||||
Create a feature branch from your fork's{' '}
|
||||
<code>dev</code>:
|
||||
<code className="ml-2">
|
||||
git checkout -b feat/your-topic
|
||||
</code>
|
||||
</li>
|
||||
<li>
|
||||
Push to your fork:
|
||||
<code className="ml-2">
|
||||
git push origin feat/your-topic
|
||||
</code>
|
||||
</li>
|
||||
<li>
|
||||
Open a PR: base <code>NoFxAiOS/nofx:dev</code> ←
|
||||
compare{' '}
|
||||
<code>your-username/nofx:feat/your-topic</code>.
|
||||
</li>
|
||||
<li>
|
||||
In PR, reference the Issue (e.g.,{' '}
|
||||
<code className="ml-1">Closes #123</code>) and
|
||||
choose the proper PR template; rebase onto{' '}
|
||||
<code>upstream/dev</code> as needed.
|
||||
</li>
|
||||
</>
|
||||
)}
|
||||
</ol>
|
||||
|
||||
<div
|
||||
className="rounded p-3 mt-3"
|
||||
style={{
|
||||
background: 'rgba(224, 72, 59, 0.08)',
|
||||
border: '1px solid rgba(224, 72, 59, 0.25)',
|
||||
}}
|
||||
>
|
||||
{language === 'zh' ? (
|
||||
<div className="text-sm">
|
||||
<strong style={{ color: '#E0483B' }}>Note:</strong>{' '}
|
||||
Contribution incentives are available (e.g., cash
|
||||
bounties, badges & shout-outs, priority
|
||||
review/merge, beta access). Prefer tasks with
|
||||
<a
|
||||
href="https://github.com/NoFxAiOS/nofx/labels/bounty"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
style={{ color: '#E0483B' }}
|
||||
>
|
||||
bounty label
|
||||
</a>
|
||||
, or file a
|
||||
<a
|
||||
href="https://github.com/NoFxAiOS/nofx/blob/dev/.github/ISSUE_TEMPLATE/bounty_claim.md"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
style={{ color: '#E0483B' }}
|
||||
>
|
||||
Bounty Claim
|
||||
</a>
|
||||
after completion.
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-sm">
|
||||
<strong style={{ color: '#E0483B' }}>Note:</strong>{' '}
|
||||
Contribution incentives are available (e.g., cash
|
||||
bounties, badges & shout-outs, priority
|
||||
review/merge, beta access). Prefer tasks with
|
||||
<a
|
||||
href="https://github.com/NoFxAiOS/nofx/labels/bounty"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
style={{ color: '#E0483B' }}
|
||||
>
|
||||
bounty label
|
||||
</a>
|
||||
, or file a
|
||||
<a
|
||||
href="https://github.com/NoFxAiOS/nofx/blob/dev/.github/ISSUE_TEMPLATE/bounty_claim.md"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
style={{ color: '#E0483B' }}
|
||||
>
|
||||
Bounty Claim
|
||||
</a>
|
||||
after completion.
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
) : item.id === 'contribute-pr-guidelines' ? (
|
||||
<div className="space-y-3">
|
||||
<div className="text-base">
|
||||
{language === 'zh' ? 'References:' : 'References:'}{' '}
|
||||
<a
|
||||
href="https://github.com/NoFxAiOS/nofx/blob/dev/CONTRIBUTING.md"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="text-nofx-gold hover:underline"
|
||||
>
|
||||
CONTRIBUTING.md
|
||||
</a>
|
||||
{' | '}
|
||||
<a
|
||||
href="https://github.com/NoFxAiOS/nofx/blob/dev/.github/PR_TITLE_GUIDE.md"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="text-nofx-gold hover:underline"
|
||||
>
|
||||
PR_TITLE_GUIDE.md
|
||||
</a>
|
||||
</div>
|
||||
<ol className="list-decimal pl-5 space-y-1 text-base">
|
||||
{language === 'zh' ? (
|
||||
<>
|
||||
<li>
|
||||
After forking, branch from your fork's{' '}
|
||||
<code>dev</code>; avoid direct commits to upstream{' '}
|
||||
<code>main</code>.
|
||||
</li>
|
||||
<li>
|
||||
Branch naming: feat/…, fix/…, docs/…; commit
|
||||
messages follow Conventional Commits.
|
||||
</li>
|
||||
<li>
|
||||
Run checks before PR:
|
||||
<code className="ml-2">
|
||||
npm --prefix web run lint && npm --prefix web
|
||||
run build
|
||||
</code>
|
||||
</li>
|
||||
<li>
|
||||
For UI changes, attach screenshots or a short
|
||||
video.
|
||||
</li>
|
||||
<li>
|
||||
Choose the proper PR template
|
||||
(frontend/backend/docs/general).
|
||||
</li>
|
||||
<li>
|
||||
Link the Issue in PR (e.g.,{' '}
|
||||
<code className="ml-1">Closes #123</code>) and
|
||||
target <code>NoFxAiOS/nofx:dev</code>.
|
||||
</li>
|
||||
<li>
|
||||
Keep rebasing onto <code>upstream/dev</code>,
|
||||
ensure CI passes; prefer small and focused PRs.
|
||||
</li>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<li>
|
||||
After forking, branch from your fork's{' '}
|
||||
<code>dev</code>; avoid direct commits to upstream{' '}
|
||||
<code>main</code>.
|
||||
</li>
|
||||
<li>
|
||||
Branch naming: feat/…, fix/…, docs/…; commit
|
||||
messages follow Conventional Commits.
|
||||
</li>
|
||||
<li>
|
||||
Run checks before PR:
|
||||
<code className="ml-2">
|
||||
npm --prefix web run lint && npm --prefix web
|
||||
run build
|
||||
</code>
|
||||
</li>
|
||||
<li>
|
||||
For UI changes, attach screenshots or a short
|
||||
video.
|
||||
</li>
|
||||
<li>
|
||||
Choose the proper PR template
|
||||
(frontend/backend/docs/general).
|
||||
</li>
|
||||
<li>
|
||||
Link the Issue in PR (e.g.,{' '}
|
||||
<code className="ml-1">Closes #123</code>) and
|
||||
target <code>NoFxAiOS/nofx:dev</code>.
|
||||
</li>
|
||||
<li>
|
||||
Keep rebasing onto <code>upstream/dev</code>,
|
||||
ensure CI passes; prefer small and focused PRs.
|
||||
</li>
|
||||
</>
|
||||
)}
|
||||
</ol>
|
||||
|
||||
<div className="rounded p-3 mt-3 bg-nofx-gold/10 border border-nofx-gold/25">
|
||||
{language === 'zh' ? (
|
||||
<div className="text-sm">
|
||||
<strong className="text-nofx-gold">Note:</strong>{' '}
|
||||
We offer contribution incentives (bounties, badges,
|
||||
shout-outs, priority review/merge, beta access).
|
||||
Look for tasks with
|
||||
<a
|
||||
href="https://github.com/NoFxAiOS/nofx/labels/bounty"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
style={{ color: '#E0483B' }}
|
||||
>
|
||||
bounty label
|
||||
</a>
|
||||
, or submit a
|
||||
<a
|
||||
href="https://github.com/NoFxAiOS/nofx/blob/dev/.github/ISSUE_TEMPLATE/bounty_claim.md"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
style={{ color: '#E0483B' }}
|
||||
>
|
||||
Bounty Claim template
|
||||
</a>
|
||||
when ready.
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-sm">
|
||||
<strong style={{ color: '#E0483B' }}>Note:</strong>{' '}
|
||||
We offer contribution incentives (bounties, badges,
|
||||
shout-outs, priority review/merge, beta access).
|
||||
Look for tasks with
|
||||
<a
|
||||
href="https://github.com/NoFxAiOS/nofx/labels/bounty"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
style={{ color: '#E0483B' }}
|
||||
>
|
||||
bounty label
|
||||
</a>
|
||||
, or submit a
|
||||
<a
|
||||
href="https://github.com/NoFxAiOS/nofx/blob/dev/.github/ISSUE_TEMPLATE/bounty_claim.md"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
style={{ color: '#E0483B' }}
|
||||
>
|
||||
Bounty Claim
|
||||
</a>
|
||||
when ready.
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-base">{t(item.answerKey, language)}</p>
|
||||
)}
|
||||
<div className="space-y-3">
|
||||
{item.blocks.map((block, i) => (
|
||||
<Block key={i} block={block} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Divider */}
|
||||
<div className="mt-6 h-px bg-[rgba(26,24,19,0.14)]" />
|
||||
</section>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -1,158 +1,121 @@
|
||||
import { useState, useMemo } from 'react'
|
||||
import { useMemo, useState } from 'react'
|
||||
import { HelpCircle } from 'lucide-react'
|
||||
import { DeepVoidBackground } from '../common/DeepVoidBackground'
|
||||
import { t, type Language } from '../../i18n/translations'
|
||||
import { FAQSearchBar } from './FAQSearchBar'
|
||||
import { FAQSidebar } from './FAQSidebar'
|
||||
import { FAQContent } from './FAQContent'
|
||||
import { faqCategories } from '../../data/faqData'
|
||||
import { faqCategories, faqItemSearchText } from '../../data/faqData'
|
||||
import type { FAQCategory } from '../../data/faqData'
|
||||
|
||||
interface FAQLayoutProps {
|
||||
language: Language
|
||||
}
|
||||
|
||||
export function FAQLayout({ language }: FAQLayoutProps) {
|
||||
export function FAQLayout() {
|
||||
const [searchTerm, setSearchTerm] = useState('')
|
||||
const [activeItemId, setActiveItemId] = useState<string | null>(null)
|
||||
|
||||
// Filter categories based on search term
|
||||
const filteredCategories = useMemo(() => {
|
||||
if (!searchTerm.trim()) {
|
||||
return faqCategories
|
||||
}
|
||||
if (!searchTerm.trim()) return faqCategories
|
||||
|
||||
const term = searchTerm.toLowerCase()
|
||||
const filtered: FAQCategory[] = []
|
||||
|
||||
faqCategories.forEach((category) => {
|
||||
const matchingItems = category.items.filter((item) => {
|
||||
const question = t(item.questionKey, language).toLowerCase()
|
||||
const answer = t(item.answerKey, language).toLowerCase()
|
||||
return question.includes(term) || answer.includes(term)
|
||||
})
|
||||
|
||||
const matchingItems = category.items.filter((item) =>
|
||||
faqItemSearchText(item).includes(term)
|
||||
)
|
||||
if (matchingItems.length > 0) {
|
||||
filtered.push({
|
||||
...category,
|
||||
items: matchingItems,
|
||||
})
|
||||
filtered.push({ ...category, items: matchingItems })
|
||||
}
|
||||
})
|
||||
|
||||
return filtered
|
||||
}, [searchTerm, language])
|
||||
}, [searchTerm])
|
||||
|
||||
const totalItems = useMemo(
|
||||
() => faqCategories.reduce((sum, category) => sum + category.items.length, 0),
|
||||
[]
|
||||
)
|
||||
|
||||
const handleItemClick = (_categoryId: string, itemId: string) => {
|
||||
const element = document.getElementById(itemId)
|
||||
if (element) {
|
||||
const offset = 100
|
||||
const elementPosition = element.getBoundingClientRect().top
|
||||
const offsetPosition = elementPosition + window.pageYOffset - offset
|
||||
|
||||
window.scrollTo({
|
||||
top: offsetPosition,
|
||||
behavior: 'smooth',
|
||||
})
|
||||
}
|
||||
if (!element) return
|
||||
const offset = 100
|
||||
const top =
|
||||
element.getBoundingClientRect().top + window.pageYOffset - offset
|
||||
window.scrollTo({ top, behavior: 'smooth' })
|
||||
}
|
||||
|
||||
return (
|
||||
<DeepVoidBackground className="py-6 pt-24" disableAnimation>
|
||||
<div className="w-full px-4 md:px-8">
|
||||
{/* Page Header */}
|
||||
<div className="text-center mb-12">
|
||||
<div className="flex items-center justify-center gap-3 mb-4">
|
||||
<div className="w-16 h-16 rounded-full flex items-center justify-center bg-nofx-gold shadow-lg">
|
||||
<HelpCircle className="w-8 h-8 text-nofx-bg" />
|
||||
<DeepVoidBackground className="py-8 pt-24" disableAnimation>
|
||||
<div className="mx-auto w-full max-w-6xl px-4 md:px-8">
|
||||
{/* page header — same strip language as the other terminal pages */}
|
||||
<div className="mb-8 border-b border-nofx-gold/20 pb-6">
|
||||
<div className="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex h-12 w-12 items-center justify-center rounded-xl border border-nofx-gold/30 bg-nofx-bg-lighter text-nofx-gold md:h-14 md:w-14">
|
||||
<HelpCircle className="h-6 w-6 md:h-7 md:w-7" />
|
||||
</div>
|
||||
<div>
|
||||
<h1 className="font-mono text-2xl font-bold tracking-tight text-nofx-text md:text-3xl">
|
||||
FAQ
|
||||
</h1>
|
||||
<p className="mt-1 font-mono text-xs uppercase tracking-[0.14em] text-nofx-text-muted">
|
||||
{totalItems} answers · wallets · launch · trading · self-hosting
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-full md:w-80">
|
||||
<FAQSearchBar
|
||||
searchTerm={searchTerm}
|
||||
onSearchChange={setSearchTerm}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<h1 className="text-4xl font-bold mb-4 text-nofx-text">
|
||||
{t('faqTitle', language)}
|
||||
</h1>
|
||||
<p className="text-lg mb-8 text-nofx-text-muted">
|
||||
{t('faqSubtitle', language)}
|
||||
</p>
|
||||
|
||||
{/* Search Bar */}
|
||||
<div className="max-w-2xl mx-auto">
|
||||
<FAQSearchBar
|
||||
searchTerm={searchTerm}
|
||||
onSearchChange={setSearchTerm}
|
||||
placeholder={
|
||||
language === 'zh' ? 'Search FAQ...' : 'Search FAQ...'
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Main Content */}
|
||||
{/* content */}
|
||||
<div className="flex gap-8">
|
||||
{/* Sidebar - Hidden on mobile, visible on desktop */}
|
||||
<aside className="hidden lg:block w-64 flex-shrink-0">
|
||||
<aside className="hidden w-64 flex-shrink-0 lg:block">
|
||||
<FAQSidebar
|
||||
categories={filteredCategories}
|
||||
activeItemId={activeItemId}
|
||||
language={language}
|
||||
onItemClick={handleItemClick}
|
||||
/>
|
||||
</aside>
|
||||
|
||||
{/* Content Area */}
|
||||
<main className="flex-1 min-w-0">
|
||||
<main className="min-w-0 flex-1">
|
||||
{filteredCategories.length > 0 ? (
|
||||
<FAQContent
|
||||
categories={filteredCategories}
|
||||
language={language}
|
||||
onActiveItemChange={setActiveItemId}
|
||||
/>
|
||||
) : (
|
||||
<div className="text-center py-12">
|
||||
<p className="text-lg" style={{ color: '#8A8478' }}>
|
||||
{language === 'zh'
|
||||
? 'No matching questions found'
|
||||
: 'No matching questions found'}
|
||||
<div className="rounded-xl border border-nofx-gold/20 bg-nofx-bg-lighter py-16 text-center">
|
||||
<p className="font-mono text-sm text-nofx-text-muted">
|
||||
No matching questions for “{searchTerm}”.
|
||||
</p>
|
||||
<button
|
||||
onClick={() => setSearchTerm('')}
|
||||
className="mt-4 px-6 py-2 rounded-lg font-semibold transition-all hover:opacity-90"
|
||||
style={{
|
||||
background: '#E0483B',
|
||||
color: '#F1ECE2',
|
||||
}}
|
||||
className="mt-4 rounded-lg border border-nofx-gold/30 bg-nofx-gold/10 px-5 py-2 font-mono text-xs font-bold uppercase tracking-[0.12em] text-nofx-gold hover:bg-nofx-gold/20"
|
||||
>
|
||||
{language === 'zh' ? 'Clear Search' : 'Clear Search'}
|
||||
Clear search
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</main>
|
||||
</div>
|
||||
|
||||
{/* Contact Section */}
|
||||
<div
|
||||
className="mt-16 p-8 rounded-lg text-center"
|
||||
style={{
|
||||
background: 'rgba(224, 72, 59, 0.08)',
|
||||
border: '1px solid rgba(224, 72, 59, 0.2)',
|
||||
}}
|
||||
>
|
||||
<h3 className="text-xl font-bold mb-3" style={{ color: '#1A1813' }}>
|
||||
{t('faqStillHaveQuestions', language)}
|
||||
{/* still stuck */}
|
||||
<div className="mt-12 rounded-xl border border-nofx-gold/20 bg-nofx-bg-lighter p-6 text-center md:p-8">
|
||||
<h3 className="font-mono text-sm font-bold uppercase tracking-[0.16em] text-nofx-text">
|
||||
Still have questions?
|
||||
</h3>
|
||||
<p className="mb-6" style={{ color: '#8A8478' }}>
|
||||
{t('faqContactUs', language)}
|
||||
<p className="mt-2 text-sm text-nofx-text-muted">
|
||||
Ask in the community or open an issue — both are answered by the
|
||||
people building NOFX.
|
||||
</p>
|
||||
<div className="flex items-center justify-center gap-4">
|
||||
<div className="mt-5 flex items-center justify-center gap-3">
|
||||
<a
|
||||
href="https://github.com/NoFxAiOS/nofx"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="px-6 py-3 rounded-lg font-semibold transition-all hover:scale-105"
|
||||
style={{
|
||||
background: '#F7F4EC',
|
||||
color: '#1A1813',
|
||||
border: '1px solid rgba(26,24,19,0.14)',
|
||||
}}
|
||||
className="rounded-lg border border-[rgba(26,24,19,0.14)] bg-nofx-bg-deeper px-5 py-2.5 font-mono text-xs font-bold uppercase tracking-[0.12em] text-nofx-text hover:border-nofx-gold/40"
|
||||
>
|
||||
GitHub
|
||||
</a>
|
||||
@@ -160,13 +123,9 @@ export function FAQLayout({ language }: FAQLayoutProps) {
|
||||
href="https://t.me/nofx_dev_community"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="px-6 py-3 rounded-lg font-semibold transition-all hover:scale-105"
|
||||
style={{
|
||||
background: '#E0483B',
|
||||
color: '#F1ECE2',
|
||||
}}
|
||||
className="rounded-lg bg-nofx-gold px-5 py-2.5 font-mono text-xs font-bold uppercase tracking-[0.12em] text-white hover:bg-nofx-accent"
|
||||
>
|
||||
{t('community', language)}
|
||||
Telegram community
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,52 +1,44 @@
|
||||
import { t, type Language } from '../../i18n/translations'
|
||||
import type { FAQCategory } from '../../data/faqData'
|
||||
|
||||
interface FAQSidebarProps {
|
||||
categories: FAQCategory[]
|
||||
activeItemId: string | null
|
||||
language: Language
|
||||
onItemClick: (categoryId: string, itemId: string) => void
|
||||
}
|
||||
|
||||
export function FAQSidebar({
|
||||
categories,
|
||||
activeItemId,
|
||||
language,
|
||||
onItemClick,
|
||||
}: FAQSidebarProps) {
|
||||
return (
|
||||
<nav
|
||||
className="sticky top-24 h-[calc(100vh-120px)] overflow-y-auto pr-4"
|
||||
style={{
|
||||
scrollbarWidth: 'thin',
|
||||
scrollbarColor: '#E8E2D5 #F7F4EC',
|
||||
}}
|
||||
className="sticky top-24 h-[calc(100vh-120px)] overflow-y-auto pr-2"
|
||||
style={{ scrollbarWidth: 'thin', scrollbarColor: '#E8E2D5 transparent' }}
|
||||
>
|
||||
<div className="space-y-6">
|
||||
<div className="space-y-5">
|
||||
{categories.map((category) => (
|
||||
<div key={category.id} className="nofx-glass p-4 rounded-xl border border-[rgba(26,24,19,0.14)]">
|
||||
{/* Category Title */}
|
||||
<div className="flex items-center gap-2 mb-3 px-3">
|
||||
<category.icon className="w-5 h-5 text-nofx-gold" />
|
||||
<h3 className="text-sm font-bold uppercase tracking-wide text-nofx-gold">
|
||||
{t(category.titleKey, language)}
|
||||
<div key={category.id}>
|
||||
<div className="mb-2 flex items-center gap-2 px-2">
|
||||
<category.icon className="h-3.5 w-3.5 text-nofx-gold" />
|
||||
<h3 className="font-mono text-[11px] font-bold uppercase tracking-[0.16em] text-nofx-gold">
|
||||
{category.title}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
{/* Category Items */}
|
||||
<ul className="space-y-1">
|
||||
<ul className="space-y-0.5 border-l border-[rgba(26,24,19,0.12)]">
|
||||
{category.items.map((item) => {
|
||||
const isActive = activeItemId === item.id
|
||||
return (
|
||||
<li key={item.id}>
|
||||
<button
|
||||
onClick={() => onItemClick(category.id, item.id)}
|
||||
className={`w-full text-left px-3 py-2 rounded-lg text-sm transition-all border-l-[3px] ${isActive
|
||||
? 'bg-nofx-gold/10 text-nofx-gold border-nofx-gold pl-[9px]'
|
||||
: 'bg-transparent text-nofx-text-muted border-transparent pl-3 hover:bg-nofx-gold/5 hover:text-nofx-text'
|
||||
}`}
|
||||
className={`-ml-px w-full border-l-2 py-1.5 pl-3 pr-2 text-left text-[13px] leading-5 transition-colors ${
|
||||
isActive
|
||||
? 'border-nofx-gold bg-nofx-gold/5 font-medium text-nofx-text'
|
||||
: 'border-transparent text-nofx-text-muted hover:border-nofx-gold/40 hover:text-nofx-text'
|
||||
}`}
|
||||
>
|
||||
{t(item.questionKey, language)}
|
||||
{item.question}
|
||||
</button>
|
||||
</li>
|
||||
)
|
||||
|
||||
@@ -1,371 +1,643 @@
|
||||
import {
|
||||
BookOpen,
|
||||
Settings,
|
||||
GitBranch,
|
||||
Monitor,
|
||||
Shield,
|
||||
TrendingUp,
|
||||
Wrench,
|
||||
Bot,
|
||||
Shield,
|
||||
Monitor,
|
||||
Zap,
|
||||
GitBranch,
|
||||
} from 'lucide-react'
|
||||
import type { LucideIcon } from 'lucide-react'
|
||||
|
||||
/**
|
||||
* FAQ content model. Answers are composed from typed blocks so the renderer
|
||||
* stays generic — no per-question JSX special cases. Inline `code` spans are
|
||||
* written with backticks and parsed by the renderer.
|
||||
*/
|
||||
export type FAQBlock =
|
||||
| { type: 'p'; text: string }
|
||||
| { type: 'list'; items: string[] }
|
||||
| { type: 'steps'; items: string[] }
|
||||
| { type: 'note'; text: string }
|
||||
| { type: 'links'; links: { label: string; href: string }[] }
|
||||
|
||||
export interface FAQItem {
|
||||
id: string
|
||||
questionKey: string
|
||||
answerKey: string
|
||||
question: string
|
||||
blocks: FAQBlock[]
|
||||
}
|
||||
|
||||
export interface FAQCategory {
|
||||
id: string
|
||||
titleKey: string
|
||||
title: string
|
||||
icon: LucideIcon
|
||||
items: FAQItem[]
|
||||
}
|
||||
|
||||
/**
|
||||
* FAQ Data Configuration
|
||||
* Comprehensive FAQ covering all aspects of NOFX
|
||||
*
|
||||
* Categories:
|
||||
* 1. Getting Started - Basic concepts and overview
|
||||
* 2. Installation - Setup methods and requirements
|
||||
* 3. Configuration - AI models, exchanges, strategies
|
||||
* 4. Trading - How trading works, common issues
|
||||
* 5. Technical Issues - Troubleshooting common problems
|
||||
* 6. Security - API keys, encryption, best practices
|
||||
* 7. Features - Strategy Studio, Backtest
|
||||
* 8. Contributing - How to contribute to the project
|
||||
*/
|
||||
/** Plain text of an item, used by the search filter. */
|
||||
export function faqItemSearchText(item: FAQItem): string {
|
||||
const parts: string[] = [item.question]
|
||||
for (const block of item.blocks) {
|
||||
if (block.type === 'p' || block.type === 'note') parts.push(block.text)
|
||||
else if (block.type === 'list' || block.type === 'steps')
|
||||
parts.push(block.items.join(' '))
|
||||
else if (block.type === 'links')
|
||||
parts.push(block.links.map((l) => l.label).join(' '))
|
||||
}
|
||||
return parts.join(' ').toLowerCase()
|
||||
}
|
||||
|
||||
export const faqCategories: FAQCategory[] = [
|
||||
// ===== 1. GETTING STARTED =====
|
||||
// ───────────────────────── Getting started ─────────────────────────
|
||||
{
|
||||
id: 'getting-started',
|
||||
titleKey: 'faqCategoryGettingStarted',
|
||||
title: 'Getting Started',
|
||||
icon: BookOpen,
|
||||
items: [
|
||||
{
|
||||
id: 'what-is-nofx',
|
||||
questionKey: 'faqWhatIsNOFX',
|
||||
answerKey: 'faqWhatIsNOFXAnswer',
|
||||
question: 'What is NOFX?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'p',
|
||||
text: 'NOFX is an open-source, self-hosted AI trading terminal. Its flagship mode is the NOFX Autopilot: an AI agent that reads the Claw402.ai signal board, verifies candidates with Signal Lab and liquidation structure, confirms timing with raw candles, and executes on Hyperliquid — all on your own machine, with your keys never leaving your server.',
|
||||
},
|
||||
{
|
||||
type: 'p',
|
||||
text: 'Beyond the Autopilot you can build custom strategies in Strategy Studio, run multiple AI traders side by side, and compare them on the leaderboard.',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'how-does-it-work',
|
||||
questionKey: 'faqHowDoesItWork',
|
||||
answerKey: 'faqHowDoesItWorkAnswer',
|
||||
id: 'what-do-i-need',
|
||||
question: 'What do I need before launching the Autopilot?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'p',
|
||||
text: 'Two funded accounts — the guided launch on the Config page walks you through both:',
|
||||
},
|
||||
{
|
||||
type: 'list',
|
||||
items: [
|
||||
'An AI fee wallet: a Base-chain USDC wallet that pays for AI model and market-data calls. Minimum `1 USDC` to launch.',
|
||||
'A Hyperliquid account with trading authorization and at least `12 USDC` available as margin.',
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'p',
|
||||
text: 'The launch button runs a server-side preflight that checks every prerequisite and points you at the exact step that is missing, so you cannot start a half-configured bot.',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'which-markets',
|
||||
question: 'Which markets can it trade?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'p',
|
||||
text: 'The Autopilot trades Hyperliquid perpetuals: crypto majors (BTC, ETH, SOL, …) plus the xyz synthetic markets covering US stocks, indices, commodities, and FX — so one account gives the AI a multi-asset universe.',
|
||||
},
|
||||
{
|
||||
type: 'p',
|
||||
text: 'Manual traders built in Strategy Studio can also connect Binance, Bybit, OKX, Bitget, KuCoin, Gate, Aster, and Lighter.',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'ai-models',
|
||||
question: 'Which AI models does it use? Do I need API keys?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'p',
|
||||
text: 'No API keys are required. NOFX routes inference through Claw402 pay-as-you-go infrastructure: your AI fee wallet pays per call with Base USDC, and the terminal accesses supported models (DeepSeek and other frontier models) on demand.',
|
||||
},
|
||||
{
|
||||
type: 'p',
|
||||
text: 'Power users can still plug in their own provider keys (OpenAI, Claude, Gemini, DeepSeek, Qwen, Grok, Kimi, or any OpenAI-compatible endpoint) under Config → Models.',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'is-it-profitable',
|
||||
questionKey: 'faqIsProfitable',
|
||||
answerKey: 'faqIsProfitableAnswer',
|
||||
},
|
||||
{
|
||||
id: 'supported-exchanges',
|
||||
questionKey: 'faqSupportedExchanges',
|
||||
answerKey: 'faqSupportedExchangesAnswer',
|
||||
},
|
||||
{
|
||||
id: 'supported-ai-models',
|
||||
questionKey: 'faqSupportedAIModels',
|
||||
answerKey: 'faqSupportedAIModelsAnswer',
|
||||
},
|
||||
{
|
||||
id: 'system-requirements',
|
||||
questionKey: 'faqSystemRequirements',
|
||||
answerKey: 'faqSystemRequirementsAnswer',
|
||||
question: 'Will it make money?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'p',
|
||||
text: 'No one can promise that, and you should distrust anyone who does. The AI trades a systematic process, but markets are adversarial and past performance never guarantees future results.',
|
||||
},
|
||||
{
|
||||
type: 'p',
|
||||
text: 'The dashboard is deliberately honest about performance: it separates realized from unrealized P/L, shows the fee-drag chain (gross − fees = net), profit factor, and max drawdown computed from your real starting balance. Watch those numbers, start small, and only trade money you can afford to lose.',
|
||||
},
|
||||
{
|
||||
type: 'note',
|
||||
text: 'Trading involves substantial risk of loss. NOFX is software, not investment advice.',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ===== 2. INSTALLATION =====
|
||||
// ───────────────────────── Launch & wallets ─────────────────────────
|
||||
{
|
||||
id: 'installation',
|
||||
titleKey: 'faqCategoryInstallation',
|
||||
icon: Settings,
|
||||
items: [
|
||||
{
|
||||
id: 'how-to-install',
|
||||
questionKey: 'faqHowToInstall',
|
||||
answerKey: 'faqHowToInstallAnswer',
|
||||
},
|
||||
{
|
||||
id: 'windows-installation',
|
||||
questionKey: 'faqWindowsInstallation',
|
||||
answerKey: 'faqWindowsInstallationAnswer',
|
||||
},
|
||||
{
|
||||
id: 'docker-deployment',
|
||||
questionKey: 'faqDockerDeployment',
|
||||
answerKey: 'faqDockerDeploymentAnswer',
|
||||
},
|
||||
{
|
||||
id: 'manual-installation',
|
||||
questionKey: 'faqManualInstallation',
|
||||
answerKey: 'faqManualInstallationAnswer',
|
||||
},
|
||||
{
|
||||
id: 'server-deployment',
|
||||
questionKey: 'faqServerDeployment',
|
||||
answerKey: 'faqServerDeploymentAnswer',
|
||||
},
|
||||
{
|
||||
id: 'update-nofx',
|
||||
questionKey: 'faqUpdateNOFX',
|
||||
answerKey: 'faqUpdateNOFXAnswer',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ===== 3. CONFIGURATION =====
|
||||
{
|
||||
id: 'configuration',
|
||||
titleKey: 'faqCategoryConfiguration',
|
||||
id: 'launch-wallets',
|
||||
title: 'Launch & Wallets',
|
||||
icon: Zap,
|
||||
items: [
|
||||
{
|
||||
id: 'configure-ai-models',
|
||||
questionKey: 'faqConfigureAIModels',
|
||||
answerKey: 'faqConfigureAIModelsAnswer',
|
||||
id: 'ai-fee-wallet',
|
||||
question: 'What is the AI fee wallet?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'p',
|
||||
text: 'A dedicated EVM wallet on Base that pays for AI model calls and paid market data (x402 micropayments). It is completely separate from your trading collateral — it never touches Hyperliquid.',
|
||||
},
|
||||
{
|
||||
type: 'list',
|
||||
items: [
|
||||
'The guided setup creates it for you (or reuses an existing one).',
|
||||
'Deposit only USDC on the Base network to its address.',
|
||||
'Launch requires at least `1 USDC`; the balance display refreshes automatically after a deposit.',
|
||||
'A typical cycle costs a fraction of a cent to a few cents depending on the model.',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'configure-exchanges',
|
||||
questionKey: 'faqConfigureExchanges',
|
||||
answerKey: 'faqConfigureExchangesAnswer',
|
||||
id: 'fee-wallet-private-key',
|
||||
question: 'Where is the AI fee wallet private key kept?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'p',
|
||||
text: 'The key is generated locally on your server, stored encrypted (AES-256) in your own database, and shown to you once in the onboarding screen. Back it up — it cannot be recovered if you lose your database.',
|
||||
},
|
||||
{
|
||||
type: 'note',
|
||||
text: 'Keep only fee money in this wallet. It exists to pay for AI calls, not to hold savings.',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'binance-api-setup',
|
||||
questionKey: 'faqBinanceAPISetup',
|
||||
answerKey: 'faqBinanceAPISetupAnswer',
|
||||
id: 'hyperliquid-authorization',
|
||||
question: 'How does the Hyperliquid authorization work? Is it safe?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'p',
|
||||
text: 'NOFX uses Hyperliquid agent wallets, so your main wallet key is never shared. The connect flow has four signed steps:',
|
||||
},
|
||||
{
|
||||
type: 'steps',
|
||||
items: [
|
||||
'Connect your EVM wallet (Rabby, MetaMask, OKX, Coinbase Wallet).',
|
||||
'Approve a freshly generated NOFX agent wallet — valid for 180 days, trading only.',
|
||||
'Approve the builder fee (a small per-order fee that funds the platform).',
|
||||
'Save the agent key to your NOFX server (stored encrypted).',
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'p',
|
||||
text: 'The agent wallet can place and close orders, nothing else. It cannot withdraw funds, and your collateral stays inside your own Hyperliquid account at all times.',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'hyperliquid-setup',
|
||||
questionKey: 'faqHyperliquidSetup',
|
||||
answerKey: 'faqHyperliquidSetupAnswer',
|
||||
id: 'launch-preflight',
|
||||
question: 'What does the launch preflight check?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'p',
|
||||
text: 'Before anything is created or changed, the server verifies the full chain with live data:',
|
||||
},
|
||||
{
|
||||
type: 'list',
|
||||
items: [
|
||||
'AI model is enabled and has a credential.',
|
||||
'AI fee wallet key is valid and the Base USDC balance is at least `1 USDC` (queried on-chain).',
|
||||
'Hyperliquid account is authorized (agent + builder fee) and reachable.',
|
||||
'Trading funds: at least `12 USDC` counting equity in open positions.',
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'p',
|
||||
text: 'Each failing check names the exact fix and deep-links into the guided setup. The same checks are enforced server-side on every start, so the UI cannot be bypassed accidentally.',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'create-strategy',
|
||||
questionKey: 'faqCreateStrategy',
|
||||
answerKey: 'faqCreateStrategyAnswer',
|
||||
id: 'relaunch-behavior',
|
||||
question: 'What happens if I press Launch again?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'p',
|
||||
text: 'Launching is idempotent. If a NOFX Autopilot already exists, the launcher updates it with the current strategy config and restarts it — it never creates a duplicate. A restart can take up to a minute if the bot is mid-cycle; the UI waits for it.',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'create-trader',
|
||||
questionKey: 'faqCreateTrader',
|
||||
answerKey: 'faqCreateTraderAnswer',
|
||||
id: 'deposit-not-showing',
|
||||
question: 'I deposited USDC but the balance still shows zero.',
|
||||
blocks: [
|
||||
{
|
||||
type: 'list',
|
||||
items: [
|
||||
'AI fee wallet: make sure you sent USDC on the Base network to the exact address shown. Balances are cached for ~30 seconds, and the setup panel re-checks automatically every few seconds.',
|
||||
'Hyperliquid: deposits land in your own Hyperliquid account; the balance step polls the live account state. Use Refresh in the guided panel if in doubt.',
|
||||
'If the on-chain RPC is temporarily unreachable, the panel marks the balance as unknown instead of zero — retry in a minute.',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ===== 4. TRADING =====
|
||||
// ───────────────────────── Trading & execution ─────────────────────────
|
||||
{
|
||||
id: 'trading',
|
||||
titleKey: 'faqCategoryTrading',
|
||||
title: 'Trading & Execution',
|
||||
icon: TrendingUp,
|
||||
items: [
|
||||
{
|
||||
id: 'how-ai-decides',
|
||||
questionKey: 'faqHowAIDecides',
|
||||
answerKey: 'faqHowAIDecidesAnswer',
|
||||
id: 'decision-cycle',
|
||||
question: 'How often does the AI make decisions?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'p',
|
||||
text: 'The Autopilot runs a scan cycle every 5–15 minutes depending on how you launched it (configurable per trader, minimum 3 minutes). The first cycle starts right after launch; a single cycle usually takes 30–60 seconds because the AI reads the full market context before deciding.',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'decision-frequency',
|
||||
questionKey: 'faqDecisionFrequency',
|
||||
answerKey: 'faqDecisionFrequencyAnswer',
|
||||
id: 'what-ai-sees',
|
||||
question: 'What information does the AI see each cycle?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'list',
|
||||
items: [
|
||||
'Your account: equity, available margin, open positions with PnL.',
|
||||
'The Claw402 ranking board: candidate universe with direction bias.',
|
||||
'Signal Lab deep signals and cost/liquidation structure per candidate.',
|
||||
'Raw OHLCV candles for timing confirmation.',
|
||||
'Its own track record: win rate, profit factor, drawdown, recent trades.',
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'p',
|
||||
text: 'Every cycle is stored as a decision record — the Execution Log on the dashboard shows the reasoning chain, actions, and any blocked orders.',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'no-trades-executing',
|
||||
questionKey: 'faqNoTradesExecuting',
|
||||
answerKey: 'faqNoTradesExecutingAnswer',
|
||||
id: 'leverage-and-risk',
|
||||
question: 'What leverage and risk controls does it use?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'p',
|
||||
text: 'The Autopilot defaults to 10x cross margin. Hard risk controls run outside the AI and cannot be overridden by it:',
|
||||
},
|
||||
{
|
||||
type: 'list',
|
||||
items: [
|
||||
'Position-count cap from the strategy config — new opens are rejected at the cap.',
|
||||
'Leverage limits per asset class (BTC/ETH vs altcoins).',
|
||||
'A trade throttle blocks churn, e.g. closing a barely-moved position minutes after opening it.',
|
||||
'Safe mode (below) protects the book when the AI itself is failing.',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'only-short-positions',
|
||||
questionKey: 'faqOnlyShortPositions',
|
||||
answerKey: 'faqOnlyShortPositionsAnswer',
|
||||
id: 'safe-mode',
|
||||
question: 'What is safe mode?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'p',
|
||||
text: 'If the AI fails 3 cycles in a row (provider outage, empty fee wallet, bad responses), the trader enters safe mode: no new positions are opened, existing positions keep their protection, and the loop keeps retrying. It exits safe mode automatically on the next successful AI call.',
|
||||
},
|
||||
{
|
||||
type: 'p',
|
||||
text: 'Safe mode is shown as a banner on the dashboard together with the reason, so it never happens silently.',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'leverage-settings',
|
||||
questionKey: 'faqLeverageSettings',
|
||||
answerKey: 'faqLeverageSettingsAnswer',
|
||||
id: 'fee-wallet-empty-mid-run',
|
||||
question: 'What happens if the AI fee wallet runs out mid-run?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'p',
|
||||
text: 'AI calls start failing with a clear "out of funds" status. The dashboard shows a persistent red banner with the wallet balance, and after three failed cycles the bot enters safe mode. Top up Base USDC to the fee wallet and the trader recovers on its own — no restart needed.',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'stop-loss-take-profit',
|
||||
questionKey: 'faqStopLossTakeProfit',
|
||||
answerKey: 'faqStopLossTakeProfitAnswer',
|
||||
id: 'trading-fees',
|
||||
question: 'What fees am I paying?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'list',
|
||||
items: [
|
||||
'Hyperliquid trading fees on every order, plus the approved builder fee.',
|
||||
'AI/data costs paid per call from the fee wallet (cents per cycle).',
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'p',
|
||||
text: 'Fees are the silent killer of high-frequency strategies. The dashboard stats strip shows the full chain — gross realized P/L, minus fees, equals net — so you can see immediately whether fees are eating the edge.',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'multiple-traders',
|
||||
questionKey: 'faqMultipleTraders',
|
||||
answerKey: 'faqMultipleTradersAnswer',
|
||||
},
|
||||
{
|
||||
id: 'ai-costs',
|
||||
questionKey: 'faqAICosts',
|
||||
answerKey: 'faqAICostsAnswer',
|
||||
id: 'stop-and-manual',
|
||||
question: 'How do I stop the bot or close positions manually?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'list',
|
||||
items: [
|
||||
'Stop: use the Stop button on the Config page trader list. Stopping halts the decision loop; open positions remain open and are yours to manage.',
|
||||
'Manual close: close any position from the dashboard positions panel — manual closes sync back into the position history.',
|
||||
'Emergencies: you can always manage positions directly on Hyperliquid; NOFX never locks you out of your own account.',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ===== 5. TECHNICAL ISSUES =====
|
||||
// ───────────────────────── Dashboard & metrics ─────────────────────────
|
||||
{
|
||||
id: 'technical-issues',
|
||||
titleKey: 'faqCategoryTechnicalIssues',
|
||||
icon: Wrench,
|
||||
items: [
|
||||
{
|
||||
id: 'port-in-use',
|
||||
questionKey: 'faqPortInUse',
|
||||
answerKey: 'faqPortInUseAnswer',
|
||||
},
|
||||
{
|
||||
id: 'frontend-not-loading',
|
||||
questionKey: 'faqFrontendNotLoading',
|
||||
answerKey: 'faqFrontendNotLoadingAnswer',
|
||||
},
|
||||
{
|
||||
id: 'database-locked',
|
||||
questionKey: 'faqDatabaseLocked',
|
||||
answerKey: 'faqDatabaseLockedAnswer',
|
||||
},
|
||||
{
|
||||
id: 'talib-not-found',
|
||||
questionKey: 'faqTALibNotFound',
|
||||
answerKey: 'faqTALibNotFoundAnswer',
|
||||
},
|
||||
{
|
||||
id: 'ai-api-timeout',
|
||||
questionKey: 'faqAIAPITimeout',
|
||||
answerKey: 'faqAIAPITimeoutAnswer',
|
||||
},
|
||||
{
|
||||
id: 'binance-position-mode',
|
||||
questionKey: 'faqBinancePositionMode',
|
||||
answerKey: 'faqBinancePositionModeAnswer',
|
||||
},
|
||||
{
|
||||
id: 'balance-shows-zero',
|
||||
questionKey: 'faqBalanceShowsZero',
|
||||
answerKey: 'faqBalanceShowsZeroAnswer',
|
||||
},
|
||||
{
|
||||
id: 'docker-pull-failed',
|
||||
questionKey: 'faqDockerPullFailed',
|
||||
answerKey: 'faqDockerPullFailedAnswer',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ===== 6. SECURITY =====
|
||||
{
|
||||
id: 'security',
|
||||
titleKey: 'faqCategorySecurity',
|
||||
icon: Shield,
|
||||
items: [
|
||||
{
|
||||
id: 'api-key-storage',
|
||||
questionKey: 'faqAPIKeyStorage',
|
||||
answerKey: 'faqAPIKeyStorageAnswer',
|
||||
},
|
||||
{
|
||||
id: 'encryption-details',
|
||||
questionKey: 'faqEncryptionDetails',
|
||||
answerKey: 'faqEncryptionDetailsAnswer',
|
||||
},
|
||||
{
|
||||
id: 'security-best-practices',
|
||||
questionKey: 'faqSecurityBestPractices',
|
||||
answerKey: 'faqSecurityBestPracticesAnswer',
|
||||
},
|
||||
{
|
||||
id: 'can-nofx-steal-funds',
|
||||
questionKey: 'faqCanNOFXStealFunds',
|
||||
answerKey: 'faqCanNOFXStealFundsAnswer',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ===== 7. FEATURES =====
|
||||
{
|
||||
id: 'features',
|
||||
titleKey: 'faqCategoryFeatures',
|
||||
id: 'dashboard',
|
||||
title: 'Dashboard & Metrics',
|
||||
icon: Monitor,
|
||||
items: [
|
||||
{
|
||||
id: 'strategy-studio',
|
||||
questionKey: 'faqStrategyStudio',
|
||||
answerKey: 'faqStrategyStudioAnswer',
|
||||
id: 'metrics-meaning',
|
||||
question: 'What do the header metrics mean exactly?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'list',
|
||||
items: [
|
||||
'Equity — live account value including unrealized PnL.',
|
||||
'Total P/L (incl. unrealized) — equity versus your starting balance; moves with open positions.',
|
||||
'Realized P/L (closed trades) — net result of finished trades only; this is what win rate, profit factor and sharpe are computed from.',
|
||||
'Profit factor — gross wins ÷ gross losses on closed trades; above 1.0 means the closed book is net positive.',
|
||||
'Max drawdown — worst peak-to-trough dip of the realized equity curve, measured against your real starting balance.',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'backtest-lab',
|
||||
questionKey: 'faqBacktestLab',
|
||||
answerKey: 'faqBacktestLabAnswer',
|
||||
id: 'pl-contradiction',
|
||||
question: 'Why is Total P/L positive while Realized P/L is negative?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'p',
|
||||
text: 'They measure different things. Realized P/L only counts closed trades; Total P/L also includes the unrealized gains of positions still open. A bot can be down on its closed trades while its open book carries enough unrealized profit to put total P/L in the green — and vice versa. Check the gross/fees/net strip to see how much of the realized result is fee drag.',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'competition-mode',
|
||||
questionKey: 'faqCompetitionMode',
|
||||
answerKey: 'faqCompetitionModeAnswer',
|
||||
id: 'execution-log',
|
||||
question: 'Where can I see why the AI did (or refused) something?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'p',
|
||||
text: 'The Execution Log panel lists every cycle with the actions taken, the AI call duration, and any blocked orders with the exact guard that fired (throttle, position cap, risk control). Full reasoning chains are stored with each decision record.',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'chain-of-thought',
|
||||
questionKey: 'faqChainOfThought',
|
||||
answerKey: 'faqChainOfThoughtAnswer',
|
||||
id: 'competition',
|
||||
question: 'What is the leaderboard / competition?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'p',
|
||||
text: 'Traders with "show in competition" enabled appear on the public leaderboard, ranked by live performance. It is opt-in per trader and can be toggled from the trader list at any time.',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ===== 8. AI MODELS =====
|
||||
// ───────────────────────── Security ─────────────────────────
|
||||
{
|
||||
id: 'ai-models',
|
||||
titleKey: 'faqCategoryAIModels',
|
||||
icon: Bot,
|
||||
id: 'security',
|
||||
title: 'Security',
|
||||
icon: Shield,
|
||||
items: [
|
||||
{
|
||||
id: 'which-ai-model-best',
|
||||
questionKey: 'faqWhichAIModelBest',
|
||||
answerKey: 'faqWhichAIModelBestAnswer',
|
||||
id: 'key-storage',
|
||||
question: 'How are my keys stored?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'list',
|
||||
items: [
|
||||
'All secrets (agent keys, fee wallet key, exchange API keys) are AES-256 encrypted at rest in your own database.',
|
||||
'Optional RSA transport encryption protects secrets in flight between browser and server.',
|
||||
'NOFX is self-hosted: nothing is sent to any third-party server. The code is open source and auditable.',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'custom-ai-api',
|
||||
questionKey: 'faqCustomAIAPI',
|
||||
answerKey: 'faqCustomAIAPIAnswer',
|
||||
id: 'can-nofx-steal-funds',
|
||||
question: 'Can NOFX withdraw or steal my funds?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'p',
|
||||
text: 'No. On Hyperliquid, NOFX only ever holds an agent wallet, which by protocol design can trade but cannot withdraw. Your collateral stays in your own account under your main wallet’s control.',
|
||||
},
|
||||
{
|
||||
type: 'note',
|
||||
text: 'If you connect a CEX instead, create its API key with trading permission only — disable withdrawals and set an IP whitelist.',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'ai-hallucinations',
|
||||
questionKey: 'faqAIHallucinations',
|
||||
answerKey: 'faqAIHallucinationsAnswer',
|
||||
},
|
||||
{
|
||||
id: 'compare-ai-models',
|
||||
questionKey: 'faqCompareAIModels',
|
||||
answerKey: 'faqCompareAIModelsAnswer',
|
||||
id: 'registration-model',
|
||||
question: 'Why can’t anyone else register on my instance?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'p',
|
||||
text: 'By design, an instance is single-operator: the first account registered becomes the operator and registration closes ("System already initialized"). This prevents strangers from creating accounts on an exposed deployment. Run one instance per operator.',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ===== 9. CONTRIBUTING =====
|
||||
// ───────────────────────── Self-hosting ─────────────────────────
|
||||
{
|
||||
id: 'self-hosting',
|
||||
title: 'Self-Hosting & Troubleshooting',
|
||||
icon: Wrench,
|
||||
items: [
|
||||
{
|
||||
id: 'how-to-install',
|
||||
question: 'How do I install NOFX?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'p',
|
||||
text: 'One line on Linux/macOS (installs and starts everything via Docker):',
|
||||
},
|
||||
{
|
||||
type: 'list',
|
||||
items: [
|
||||
'Script: `curl -fsSL https://raw.githubusercontent.com/NoFxAiOS/nofx/main/install.sh | bash`',
|
||||
'Docker: download `docker-compose.prod.yml` and run `docker compose -f docker-compose.prod.yml up -d`',
|
||||
'Windows: install Docker Desktop, then use the Docker route above.',
|
||||
'From source: Go 1.21+, Node 18+, TA-Lib (`brew install ta-lib` / `apt-get install libta-lib0-dev`), then `go run .` and `npm --prefix web run dev`.',
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'p',
|
||||
text: 'Then open `http://127.0.0.1:3000` — the web UI is on port 3000, the API on 8080.',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'how-to-update',
|
||||
question: 'How do I update?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'p',
|
||||
text: 'Re-run the install script, or with Docker: `docker compose -f docker-compose.prod.yml pull && docker compose -f docker-compose.prod.yml up -d`. Your database and keys live in the mounted `data/` directory and survive updates. Running traders are restarted automatically after the backend comes back.',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'launch-blocked',
|
||||
question: 'Launch is blocked by a failing check — now what?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'p',
|
||||
text: 'Read the message: every preflight failure names its fix and routes you to the right setup step — fund the AI wallet, finish the Hyperliquid authorization, or deposit trading USDC. Balances are re-checked live, so once you fix the item the launch goes through.',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'exchange-unreachable',
|
||||
question: 'The exchange account shows "invalid credentials" or "unavailable".',
|
||||
blocks: [
|
||||
{
|
||||
type: 'list',
|
||||
items: [
|
||||
'Invalid credentials: the agent authorization expired (180 days) or the saved key is stale — reconnect the Hyperliquid wallet; the flow offers a one-click renewal.',
|
||||
'Unavailable: the exchange API did not respond; the account state is cached for 30 seconds, so wait and refresh.',
|
||||
'CEX keys: verify trading permission, IP whitelist, and that futures/perp access is enabled.',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'where-are-logs',
|
||||
question: 'Where are the logs?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'list',
|
||||
items: [
|
||||
'Backend: `docker logs nofx-trading` (or the terminal running `go run .`).',
|
||||
'Per-cycle AI reasoning and errors: the dashboard Execution Log.',
|
||||
'Frontend build/runtime issues: browser devtools console.',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'port-conflicts',
|
||||
question: 'Port 3000 or 8080 is already in use.',
|
||||
blocks: [
|
||||
{
|
||||
type: 'p',
|
||||
text: 'Stop the conflicting service or remap the published ports in your compose file (e.g. `"3100:80"` for the frontend, `"8180:8080"` for the API), then restart the containers.',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ───────────────────────── Contributing ─────────────────────────
|
||||
{
|
||||
id: 'contributing',
|
||||
titleKey: 'faqCategoryContributing',
|
||||
title: 'Contributing',
|
||||
icon: GitBranch,
|
||||
items: [
|
||||
{
|
||||
id: 'how-to-contribute',
|
||||
questionKey: 'faqHowToContribute',
|
||||
answerKey: 'faqHowToContributeAnswer',
|
||||
},
|
||||
{
|
||||
id: 'pr-guidelines',
|
||||
questionKey: 'faqPRGuidelines',
|
||||
answerKey: 'faqPRGuidelinesAnswer',
|
||||
question: 'How do I contribute code?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'links',
|
||||
links: [
|
||||
{
|
||||
label: 'Roadmap',
|
||||
href: 'https://github.com/orgs/NoFxAiOS/projects/3',
|
||||
},
|
||||
{
|
||||
label: 'Task Dashboard',
|
||||
href: 'https://github.com/orgs/NoFxAiOS/projects/5',
|
||||
},
|
||||
{
|
||||
label: 'CONTRIBUTING.md',
|
||||
href: 'https://github.com/NoFxAiOS/nofx/blob/dev/CONTRIBUTING.md',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'steps',
|
||||
items: [
|
||||
'Pick a task from the boards above (filter by good first issue / help wanted) and comment "assign me".',
|
||||
'Fork the repo and branch from `dev`: `git checkout -b feat/your-topic`.',
|
||||
'Follow Conventional Commits; run `npm --prefix web run lint && npm --prefix web run build` before pushing.',
|
||||
'Open a PR against `NoFxAiOS/nofx:dev`, reference the issue (`Closes #123`), and attach screenshots for UI changes.',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'bounty-program',
|
||||
questionKey: 'faqBountyProgram',
|
||||
answerKey: 'faqBountyProgramAnswer',
|
||||
question: 'Is there a bounty program?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'p',
|
||||
text: 'Yes — selected issues carry cash bounties, plus badges, priority review, and beta access for regular contributors.',
|
||||
},
|
||||
{
|
||||
type: 'links',
|
||||
links: [
|
||||
{
|
||||
label: 'Issues with bounty label',
|
||||
href: 'https://github.com/NoFxAiOS/nofx/labels/bounty',
|
||||
},
|
||||
{
|
||||
label: 'Bounty claim template',
|
||||
href: 'https://github.com/NoFxAiOS/nofx/blob/dev/.github/ISSUE_TEMPLATE/bounty_claim.md',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'report-bugs',
|
||||
questionKey: 'faqReportBugs',
|
||||
answerKey: 'faqReportBugsAnswer',
|
||||
question: 'How do I report a bug?',
|
||||
blocks: [
|
||||
{
|
||||
type: 'p',
|
||||
text: 'Open a GitHub issue with the template: what you did, what happened, backend logs (`docker logs nofx-trading`), and screenshots. For suspected security issues, please follow the responsible-disclosure notes in SECURITY.md instead of a public issue.',
|
||||
},
|
||||
{
|
||||
type: 'links',
|
||||
links: [
|
||||
{
|
||||
label: 'New issue',
|
||||
href: 'https://github.com/NoFxAiOS/nofx/issues/new/choose',
|
||||
},
|
||||
{
|
||||
label: 'SECURITY.md',
|
||||
href: 'https://github.com/NoFxAiOS/nofx/blob/dev/SECURITY.md',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -671,226 +671,66 @@ export const translations = {
|
||||
configureSignalSourceNow: 'Configure Signal Source Now',
|
||||
|
||||
// FAQ Page
|
||||
faqTitle: 'Frequently Asked Questions',
|
||||
faqSubtitle: 'Find answers to common questions about NOFX',
|
||||
faqStillHaveQuestions: 'Still Have Questions?',
|
||||
faqContactUs: 'Join our community or check our GitHub for more help',
|
||||
|
||||
// FAQ Categories
|
||||
faqCategoryGettingStarted: 'Getting Started',
|
||||
faqCategoryInstallation: 'Installation',
|
||||
faqCategoryConfiguration: 'Configuration',
|
||||
faqCategoryTrading: 'Trading',
|
||||
faqCategoryTechnicalIssues: 'Technical Issues',
|
||||
faqCategorySecurity: 'Security',
|
||||
faqCategoryFeatures: 'Features',
|
||||
faqCategoryAIModels: 'AI Models',
|
||||
faqCategoryContributing: 'Contributing',
|
||||
|
||||
// ===== GETTING STARTED =====
|
||||
faqWhatIsNOFX: 'What is NOFX?',
|
||||
faqWhatIsNOFXAnswer:
|
||||
'NOFX is an open-source AI-powered trading operating system for cryptocurrency and US stock markets. It uses large language models (LLMs) like DeepSeek, GPT, Claude, Gemini to analyze market data and make autonomous trading decisions. Key features include: multi-AI model support, multi-exchange trading, and visual strategy builder.',
|
||||
|
||||
faqHowDoesItWork: 'How does NOFX work?',
|
||||
faqHowDoesItWorkAnswer:
|
||||
'NOFX works in 5 steps: 1) Configure AI models and exchange API credentials; 2) Create a trading strategy (coin selection, indicators, risk controls); 3) Create a "Trader" combining AI model + Exchange + Strategy; 4) Start the trader - it will analyze market data at regular intervals and make buy/sell/hold decisions; 5) Monitor performance on the dashboard. The AI uses Chain of Thought reasoning to explain each decision.',
|
||||
|
||||
faqIsProfitable: 'Is NOFX profitable?',
|
||||
faqIsProfitableAnswer:
|
||||
'AI trading is experimental and NOT guaranteed to be profitable. Cryptocurrency futures are highly volatile and risky. NOFX is designed for educational and research purposes. We strongly recommend: starting with small amounts (10-50 USDT), never investing more than you can afford to lose, thoroughly testing before live trading, and understanding that past performance does not guarantee future results.',
|
||||
|
||||
faqSupportedExchanges: 'Which exchanges are supported?',
|
||||
faqSupportedExchangesAnswer:
|
||||
'CEX (Centralized): Binance Futures, Bybit, OKX, Bitget. DEX (Decentralized): Hyperliquid, Aster DEX, Lighter. Each exchange has different features - Binance has the most liquidity, Hyperliquid is fully on-chain with no KYC required. Check the documentation for setup guides for each exchange.',
|
||||
|
||||
faqSupportedAIModels: 'Which AI models are supported?',
|
||||
faqSupportedAIModelsAnswer:
|
||||
'NOFX supports 7+ AI models: DeepSeek (recommended for cost/performance), Alibaba Qwen, OpenAI (GPT-5.2), Anthropic Claude, Google Gemini, xAI Grok, and Kimi (Moonshot). You can also use any OpenAI-compatible API endpoint. Each model has different strengths - DeepSeek is cost-effective, OpenAI models are powerful but expensive, Claude excels at reasoning.',
|
||||
|
||||
faqSystemRequirements: 'What are the system requirements?',
|
||||
faqSystemRequirementsAnswer:
|
||||
'Minimum: 2 CPU cores, 2GB RAM, 1GB disk space, stable internet. Recommended: 4GB RAM for running multiple traders. Supported OS: Linux, macOS, or Windows (via Docker or WSL2). Docker is the easiest installation method. For manual installation, you need Go 1.21+, Node.js 18+, and TA-Lib library.',
|
||||
|
||||
// ===== INSTALLATION =====
|
||||
faqHowToInstall: 'How do I install NOFX?',
|
||||
faqHowToInstallAnswer:
|
||||
'Easiest method (Linux/macOS): Run "curl -fsSL https://raw.githubusercontent.com/NoFxAiOS/nofx/main/install.sh | bash" - this installs Docker containers automatically. Then open http://127.0.0.1:3000 in your browser. For manual installation or development, clone the repository and follow the README instructions.',
|
||||
|
||||
faqWindowsInstallation: 'How do I install on Windows?',
|
||||
faqWindowsInstallationAnswer:
|
||||
'Three options: 1) Docker Desktop (Recommended) - Install Docker Desktop, then run "docker compose -f docker-compose.prod.yml up -d" in PowerShell; 2) WSL2 - Install Windows Subsystem for Linux, then follow Linux installation; 3) Docker in WSL2 - Best of both worlds, run the install script in WSL2 terminal. Access via http://127.0.0.1:3000',
|
||||
|
||||
faqDockerDeployment: 'Docker deployment keeps failing',
|
||||
faqDockerDeploymentAnswer:
|
||||
'Common solutions: 1) Check Docker is running: "docker info"; 2) Ensure sufficient memory (2GB minimum); 3) If stuck on "go build", try: "docker compose down && docker compose build --no-cache && docker compose up -d"; 4) Check logs: "docker compose logs -f"; 5) For slow pulls, configure a Docker mirror in daemon.json.',
|
||||
|
||||
faqManualInstallation: 'How do I install manually for development?',
|
||||
faqManualInstallationAnswer:
|
||||
'Prerequisites: Go 1.21+, Node.js 18+, TA-Lib. Steps: 1) Clone repo: "git clone https://github.com/NoFxAiOS/nofx.git"; 2) Install backend deps: "go mod download"; 3) Install frontend deps: "cd web && npm install"; 4) Build backend: "go build -o nofx"; 5) Run backend: "./nofx"; 6) Run frontend (new terminal): "cd web && npm run dev". Access at http://127.0.0.1:3000',
|
||||
|
||||
faqServerDeployment: 'How do I deploy to a remote server?',
|
||||
faqServerDeploymentAnswer:
|
||||
'Run the install script on your server - it auto-detects the server IP. Access via http://YOUR_SERVER_IP:3000. For HTTPS: 1) Use Cloudflare (free) - add domain, create A record pointing to server IP, set SSL to "Flexible"; 2) Enable TRANSPORT_ENCRYPTION=true in .env for browser-side encryption; 3) Access via https://your-domain.com',
|
||||
|
||||
faqUpdateNOFX: 'How do I update NOFX?',
|
||||
faqUpdateNOFXAnswer:
|
||||
'For Docker: Run "docker compose pull && docker compose up -d" to pull latest images and restart. For manual installation: "git pull && go build -o nofx" for backend, "cd web && npm install && npm run build" for frontend. Your configurations in data.db are preserved during updates.',
|
||||
|
||||
// ===== CONFIGURATION =====
|
||||
faqConfigureAIModels: 'How do I configure AI models?',
|
||||
faqConfigureAIModelsAnswer:
|
||||
'Go to Config page → AI Models section. For each model: 1) Get API key from the provider (links provided in UI); 2) Enter API key; 3) Optionally customize base URL and model name; 4) Save. API keys are encrypted before storage. Test the connection after saving to verify it works.',
|
||||
|
||||
faqConfigureExchanges: 'How do I configure exchange connections?',
|
||||
faqConfigureExchangesAnswer:
|
||||
'Go to Config page → Exchanges section. Click "Add Exchange", select exchange type, and enter credentials. For CEX (Binance/Bybit/OKX): Need API Key + Secret Key (+ Passphrase for OKX). For DEX (Hyperliquid/Aster/Lighter): Need wallet address and private key. Always enable only necessary permissions (Futures Trading) and consider IP whitelisting.',
|
||||
|
||||
faqBinanceAPISetup: 'How do I set up Binance API correctly?',
|
||||
faqBinanceAPISetupAnswer:
|
||||
'Important steps: 1) Create API key in Binance → API Management; 2) Enable ONLY "Enable Futures" permission; 3) Consider adding IP whitelist for security; 4) CRITICAL: Switch to Hedge Mode (双向持仓) in Futures settings → Preferences → Position Mode; 5) Ensure funds are in Futures wallet (not Spot). Common error -4061 means you need Hedge Mode.',
|
||||
|
||||
faqHyperliquidSetup: 'How do I set up Hyperliquid?',
|
||||
faqHyperliquidSetupAnswer:
|
||||
'Hyperliquid is a decentralized exchange requiring wallet authentication. Steps: 1) Go to app.hyperliquid.xyz; 2) Connect your wallet; 3) Generate an API wallet (recommended) or use your main wallet; 4) Copy the wallet address and private key; 5) In NOFX, add Hyperliquid exchange with these credentials. No KYC required, fully on-chain.',
|
||||
|
||||
faqCreateStrategy: 'How do I create a trading strategy?',
|
||||
faqCreateStrategyAnswer:
|
||||
'Go to Strategy Studio: 1) Coin Source - select which coins to trade (static list, AI500 pool, or OI Top ranking); 2) Indicators - enable technical indicators (EMA, MACD, RSI, ATR, Volume, OI, Funding Rate); 3) Risk Controls - set leverage limits, max positions, margin usage cap, position size limits; 4) Custom Prompt (optional) - add specific instructions for the AI. Save and assign to a trader.',
|
||||
|
||||
faqCreateTrader: 'How do I create and start a trader?',
|
||||
faqCreateTraderAnswer:
|
||||
'Go to Traders page: 1) Click "Create Trader"; 2) Select AI Model (must be configured first); 3) Select Exchange (must be configured first); 4) Select Strategy (or use default); 5) Set decision interval (e.g., 15 minutes); 6) Save, then click "Start" to begin trading. Monitor performance on Dashboard page.',
|
||||
|
||||
// ===== TRADING =====
|
||||
faqHowAIDecides: 'How does the AI make trading decisions?',
|
||||
faqHowAIDecidesAnswer:
|
||||
'The AI uses Chain of Thought (CoT) reasoning in 4 steps: 1) Position Analysis - reviews current holdings and P/L; 2) Risk Assessment - checks account margin, available balance; 3) Opportunity Evaluation - analyzes market data, indicators, candidate coins; 4) Final Decision - outputs specific action (buy/sell/hold) with reasoning. You can view the full reasoning in decision logs.',
|
||||
|
||||
faqDecisionFrequency: 'How often does the AI make decisions?',
|
||||
faqDecisionFrequencyAnswer:
|
||||
'Configurable per trader, default is 15 minutes. Too frequent polling can create churn and fee drag; 15-30 minutes gives signals time to develop. The execution layer also blocks early flat closes and rapid re-entry.',
|
||||
|
||||
faqNoTradesExecuting: "Why isn't my trader executing any trades?",
|
||||
faqNoTradesExecutingAnswer:
|
||||
'Common causes: 1) AI decided to wait (check decision logs for reasoning); 2) Insufficient balance in futures account; 3) Max positions limit reached (default: 3); 4) Exchange API issues (check error messages); 5) Strategy constraints too restrictive. Check Dashboard → Decision Logs for detailed AI reasoning each cycle.',
|
||||
|
||||
faqOnlyShortPositions: 'Why is the AI only opening short positions?',
|
||||
faqOnlyShortPositionsAnswer:
|
||||
'This is usually due to Binance Position Mode. Solution: Switch to Hedge Mode (双向持仓) in Binance Futures → Preferences → Position Mode. You must close all positions first. After switching, the AI can open both long and short positions independently.',
|
||||
|
||||
faqLeverageSettings: 'How do leverage settings work?',
|
||||
faqLeverageSettingsAnswer:
|
||||
'Leverage is set in Strategy → Risk Controls: BTC/ETH leverage (typically 5-20x) and Altcoin leverage (typically 3-10x). Higher leverage = higher risk and potential returns. Subaccounts may have restrictions (e.g., Binance subaccounts limited to 5x). The AI respects these limits when placing orders.',
|
||||
|
||||
faqStopLossTakeProfit: 'Does NOFX support stop-loss and take-profit?',
|
||||
faqStopLossTakeProfitAnswer:
|
||||
'The AI can suggest stop-loss/take-profit levels in its decisions, but these are guidance-based rather than hard-coded exchange orders. The AI monitors positions each cycle and may decide to close based on P/L. For guaranteed stop-loss, you can set exchange-level orders manually or adjust the strategy prompt to be more conservative.',
|
||||
|
||||
faqMultipleTraders: 'Can I run multiple traders?',
|
||||
faqMultipleTradersAnswer:
|
||||
'Yes! NOFX supports running 20+ concurrent traders. Each trader can have different: AI model, exchange account, strategy, decision interval. Use this to A/B test strategies, compare AI models, or diversify across exchanges. Monitor all traders on the Competition page.',
|
||||
|
||||
faqAICosts: 'How much do AI API calls cost?',
|
||||
faqAICostsAnswer:
|
||||
'Approximate daily costs per trader (15-min intervals): DeepSeek: $0.03-0.20; Qwen: $0.07-0.30; OpenAI: $0.70-2; Claude: $0.30-1. Costs depend on prompt length and response tokens. DeepSeek offers the best cost/performance ratio. Longer decision intervals reduce costs.',
|
||||
|
||||
// ===== TECHNICAL ISSUES =====
|
||||
faqPortInUse: 'Port 8080 or 3000 already in use',
|
||||
faqPortInUseAnswer:
|
||||
'Check what\'s using the port: "lsof -i :8080" (macOS/Linux) or "netstat -ano | findstr 8080" (Windows). Kill the process or change ports in .env: NOFX_BACKEND_PORT=8081, NOFX_FRONTEND_PORT=3001. Restart with "docker compose down && docker compose up -d".',
|
||||
|
||||
faqFrontendNotLoading: 'Frontend shows "Loading..." forever',
|
||||
faqFrontendNotLoadingAnswer:
|
||||
'Backend may not be running or reachable. Check: 1) "curl http://127.0.0.1:8080/api/health" should return {"status":"ok"}; 2) "docker compose ps" to verify containers are running; 3) Check backend logs: "docker compose logs nofx-backend"; 4) Ensure firewall allows port 8080.',
|
||||
|
||||
faqDatabaseLocked: 'Database locked error',
|
||||
faqDatabaseLockedAnswer:
|
||||
'Multiple processes accessing SQLite simultaneously. Solution: 1) Stop all processes: "docker compose down" or "pkill nofx"; 2) Remove lock files if present: "rm -f data/data.db-wal data/data.db-shm"; 3) Restart: "docker compose up -d". Only one backend instance should access the database.',
|
||||
|
||||
faqTALibNotFound: 'TA-Lib not found during build',
|
||||
faqTALibNotFoundAnswer:
|
||||
'TA-Lib is required for technical indicators. Install: macOS: "brew install ta-lib"; Ubuntu/Debian: "sudo apt-get install libta-lib0-dev"; CentOS: "yum install ta-lib-devel". After installing, rebuild: "go build -o nofx". Docker images include TA-Lib pre-installed.',
|
||||
|
||||
faqAIAPITimeout: 'AI API timeout or connection refused',
|
||||
faqAIAPITimeoutAnswer:
|
||||
'Check: 1) API key is valid (test with curl); 2) Network can reach API endpoint (ping/curl); 3) API provider is not down (check status page); 4) VPN/firewall not blocking; 5) Rate limits not exceeded. Default timeout is 120 seconds.',
|
||||
|
||||
faqBinancePositionMode: 'Binance error code -4061 (Position Mode)',
|
||||
faqBinancePositionModeAnswer:
|
||||
'Error: "Order\'s position side does not match user\'s setting". You\'re in One-way Mode but NOFX requires Hedge Mode. Fix: 1) Close ALL positions first; 2) Binance Futures → Settings (gear icon) → Preferences → Position Mode → Switch to "Hedge Mode" (双向持仓); 3) Restart your trader.',
|
||||
|
||||
faqBalanceShowsZero: 'Account balance shows 0',
|
||||
faqBalanceShowsZeroAnswer:
|
||||
'Funds are likely in Spot wallet, not Futures wallet. Solution: 1) In Binance, go to Wallet → Futures → Transfer; 2) Transfer USDT from Spot to Futures; 3) Refresh NOFX dashboard. Also check: funds not locked in savings/staking products.',
|
||||
|
||||
faqDockerPullFailed: 'Docker image pull failed or slow',
|
||||
faqDockerPullFailedAnswer:
|
||||
'Docker Hub can be slow in some regions. Solutions: 1) Configure a Docker mirror in /etc/docker/daemon.json: {"registry-mirrors": ["https://mirror.gcr.io"]}; 2) Restart Docker; 3) Retry pull. Alternatively, use GitHub Container Registry (ghcr.io) which may have better connectivity in your region.',
|
||||
|
||||
// ===== SECURITY =====
|
||||
faqAPIKeyStorage: 'How are API keys stored?',
|
||||
faqAPIKeyStorageAnswer:
|
||||
'API keys are encrypted using AES-256-GCM before storage in the local SQLite database. The encryption key (DATA_ENCRYPTION_KEY) is stored in your .env file. Keys are decrypted only in memory when needed for API calls. Never share your data.db or .env files.',
|
||||
|
||||
faqEncryptionDetails: 'What encryption does NOFX use?',
|
||||
faqEncryptionDetailsAnswer:
|
||||
'NOFX uses multiple encryption layers: 1) AES-256-GCM for database storage (API keys, secrets); 2) RSA-2048 for optional transport encryption (browser to server); 3) JWT for authentication tokens. Keys are generated during installation. Enable TRANSPORT_ENCRYPTION=true for HTTPS environments.',
|
||||
|
||||
faqSecurityBestPractices: 'What are security best practices?',
|
||||
faqSecurityBestPracticesAnswer:
|
||||
'Recommended: 1) Use exchange API keys with IP whitelist and minimal permissions (Futures Trading only); 2) Use dedicated subaccount for NOFX; 3) Enable TRANSPORT_ENCRYPTION for remote deployments; 4) Never share .env or data.db files; 5) Use HTTPS with valid certificates; 6) Regularly rotate API keys; 7) Monitor account activity.',
|
||||
|
||||
faqCanNOFXStealFunds: 'Can NOFX steal my funds?',
|
||||
faqCanNOFXStealFundsAnswer:
|
||||
'NOFX is open-source (AGPL-3.0 license) - you can audit all code on GitHub. API keys are stored locally on YOUR machine, never sent to external servers. NOFX only has the permissions you grant via API keys. For maximum safety: use API keys with trading-only permissions (no withdrawal), enable IP whitelist, use a dedicated subaccount.',
|
||||
|
||||
// ===== FEATURES =====
|
||||
faqStrategyStudio: 'What is Strategy Studio?',
|
||||
faqStrategyStudioAnswer:
|
||||
'Strategy Studio is a visual strategy builder where you configure: 1) Coin Sources - which cryptocurrencies to trade (static list, AI500 top coins, OI ranking); 2) Technical Indicators - EMA, MACD, RSI, ATR, Volume, Open Interest, Funding Rate; 3) Risk Controls - leverage limits, position sizing, margin caps; 4) Custom Prompts - specific instructions for AI. No coding required.',
|
||||
|
||||
faqCompetitionMode: 'What is Competition Mode?',
|
||||
faqCompetitionModeAnswer:
|
||||
'Competition page shows a real-time leaderboard of all your traders. Compare: ROI, P&L, Sharpe ratio, win rate, number of trades. Use this to A/B test different AI models, strategies, or configurations. Traders can be marked as "Show in Competition" to appear on the leaderboard.',
|
||||
|
||||
faqChainOfThought: 'What is Chain of Thought (CoT)?',
|
||||
faqChainOfThoughtAnswer:
|
||||
"Chain of Thought is the AI's reasoning process, visible in decision logs. The AI explains its thinking in 4 steps: 1) Current position analysis; 2) Account risk assessment; 3) Market opportunity evaluation; 4) Final decision rationale. This transparency helps you understand WHY the AI made each decision, useful for improving strategies.",
|
||||
|
||||
// ===== AI MODELS =====
|
||||
faqWhichAIModelBest: 'Which AI model should I use?',
|
||||
faqWhichAIModelBestAnswer:
|
||||
'Recommended: DeepSeek for best cost/performance ratio ($0.03-0.20/day at the default interval). Alternatives: OpenAI for best reasoning but expensive; Claude for nuanced analysis; Qwen for competitive pricing. You can run multiple traders with different models to compare. Check the Competition page to see which performs best for your strategy.',
|
||||
|
||||
faqCustomAIAPI: 'Can I use a custom AI API?',
|
||||
faqCustomAIAPIAnswer:
|
||||
'Yes! NOFX supports any OpenAI-compatible API. In Config → AI Models → Custom API: 1) Enter your API endpoint URL (e.g., https://your-api.com/v1); 2) Enter API key; 3) Specify model name. This works with self-hosted models, alternative providers, or Claude via third-party proxies.',
|
||||
|
||||
faqAIHallucinations: 'What about AI hallucinations?',
|
||||
faqAIHallucinationsAnswer:
|
||||
'AI models can sometimes produce incorrect or fabricated information ("hallucinations"). NOFX mitigates this by: 1) Providing structured prompts with real market data; 2) Enforcing JSON output format for decisions; 3) Validating orders before execution. However, AI trading is experimental - always monitor decisions and don\'t rely solely on AI judgment.',
|
||||
|
||||
faqCompareAIModels: 'How do I compare different AI models?',
|
||||
faqCompareAIModelsAnswer:
|
||||
'Create multiple traders with different AI models but same strategy/exchange. Run them simultaneously and compare on Competition page. Metrics to watch: ROI, win rate, Sharpe ratio, max drawdown.',
|
||||
|
||||
// ===== CONTRIBUTING =====
|
||||
faqHowToContribute: 'How can I contribute to NOFX?',
|
||||
faqHowToContributeAnswer:
|
||||
'NOFX is open-source and welcomes contributions! Ways to contribute: 1) Code - fix bugs, add features (check GitHub Issues); 2) Documentation - improve guides, translate; 3) Bug Reports - report issues with details; 4) Feature Ideas - suggest improvements. Start with issues labeled "good first issue". All contributors may receive airdrop rewards.',
|
||||
|
||||
faqPRGuidelines: 'What are the PR guidelines?',
|
||||
faqPRGuidelinesAnswer:
|
||||
'PR Process: 1) Fork repo to your account; 2) Create feature branch from dev: "git checkout -b feat/your-feature"; 3) Make changes, run lint: "npm --prefix web run lint"; 4) Commit with Conventional Commits format; 5) Push and create PR to NoFxAiOS/nofx:dev; 6) Reference related issue (Closes #123); 7) Wait for review. Keep PRs small and focused.',
|
||||
|
||||
faqBountyProgram: 'Is there a bounty program?',
|
||||
faqBountyProgramAnswer:
|
||||
'Yes! Contributors receive airdrop rewards based on contributions: Code commits (highest weight), bug fixes, feature suggestions, documentation. Issues with "bounty" label have cash rewards. After completing work, submit a Bounty Claim. Check CONTRIBUTING.md for details on the reward structure.',
|
||||
|
||||
faqReportBugs: 'How do I report bugs?',
|
||||
faqReportBugsAnswer:
|
||||
'For bugs: Open a GitHub Issue with: 1) Clear description of the problem; 2) Steps to reproduce; 3) Expected vs actual behavior; 4) System info (OS, Docker version, browser); 5) Relevant logs. For SECURITY vulnerabilities: Do NOT open public issues - DM @Web3Tinkle on Twitter instead.',
|
||||
|
||||
// Web Crypto Environment Check
|
||||
environmentCheck: {
|
||||
@@ -2009,226 +1849,66 @@ export const translations = {
|
||||
configureSignalSourceNow: '立即配置信号源',
|
||||
|
||||
// FAQ Page
|
||||
faqTitle: '常见问题',
|
||||
faqSubtitle: '查找关于 NOFX 的常见问题解答',
|
||||
faqStillHaveQuestions: '还有其他问题?',
|
||||
faqContactUs: '加入我们的社区或查看 GitHub 获取更多帮助',
|
||||
|
||||
// FAQ Categories
|
||||
faqCategoryGettingStarted: '入门指南',
|
||||
faqCategoryInstallation: '安装部署',
|
||||
faqCategoryConfiguration: '配置设置',
|
||||
faqCategoryTrading: '交易相关',
|
||||
faqCategoryTechnicalIssues: '技术问题',
|
||||
faqCategorySecurity: '安全相关',
|
||||
faqCategoryFeatures: '功能介绍',
|
||||
faqCategoryAIModels: 'AI 模型',
|
||||
faqCategoryContributing: '参与贡献',
|
||||
|
||||
// ===== 入门指南 =====
|
||||
faqWhatIsNOFX: 'NOFX 是什么?',
|
||||
faqWhatIsNOFXAnswer:
|
||||
'NOFX 是一个开源的 AI 驱动交易操作系统,支持加密货币和美股市场。它使用大语言模型(LLM)如 DeepSeek、GPT、Claude、Gemini 来分析市场数据,进行自主交易决策。核心功能包括:多 AI 模型支持、多交易所交易、可视化策略构建器、回测系统。',
|
||||
|
||||
faqHowDoesItWork: 'NOFX 是如何工作的?',
|
||||
faqHowDoesItWorkAnswer:
|
||||
'NOFX 分 5 步工作:1)配置 AI 模型和交易所 API 凭证;2)创建交易策略(币种选择、指标、风控);3)创建"交易员",组合 AI 模型 + 交易所 + 策略;4)启动交易员 - 它会定期分析市场数据并做出买入/卖出/持有决策;5)在仪表板上监控表现。AI 使用思维链(Chain of Thought)推理来解释每个决策。',
|
||||
|
||||
faqIsProfitable: 'NOFX 能盈利吗?',
|
||||
faqIsProfitableAnswer:
|
||||
'AI 交易是实验性的,不保证盈利。加密货币期货波动性大、风险高。NOFX 仅用于教育和研究目的。我们强烈建议:从小额开始(10-50 USDT),不要投入超过承受能力的资金,在实盘交易前充分回测,并理解过去的表现不代表未来的结果。',
|
||||
|
||||
faqSupportedExchanges: '支持哪些交易所?',
|
||||
faqSupportedExchangesAnswer:
|
||||
'CEX(中心化):币安合约、Bybit、OKX、Bitget。DEX(去中心化):Hyperliquid、Aster DEX、Lighter。每个交易所有不同特点 - 币安流动性最好,Hyperliquid 完全链上无需 KYC。查看文档获取各交易所的设置指南。',
|
||||
|
||||
faqSupportedAIModels: '支持哪些 AI 模型?',
|
||||
faqSupportedAIModelsAnswer:
|
||||
'NOFX 支持 7+ 种 AI 模型:DeepSeek(推荐性价比)、阿里云通义千问、OpenAI(GPT-5.2)、Anthropic Claude、Google Gemini、xAI Grok、Kimi(月之暗面)。您也可以使用任何 OpenAI 兼容的 API 端点。每个模型各有优势 - DeepSeek 性价比高,OpenAI 能力强但贵,Claude 擅长推理。',
|
||||
|
||||
faqSystemRequirements: '系统要求是什么?',
|
||||
faqSystemRequirementsAnswer:
|
||||
'最低配置:2 核 CPU,2GB 内存,1GB 硬盘,稳定网络。推荐:4GB 内存用于运行多个交易员。支持系统:Linux、macOS 或 Windows(通过 Docker 或 WSL2)。Docker 是最简单的安装方式。手动安装需要 Go 1.21+、Node.js 18+ 和 TA-Lib 库。',
|
||||
|
||||
// ===== 安装部署 =====
|
||||
faqHowToInstall: '如何安装 NOFX?',
|
||||
faqHowToInstallAnswer:
|
||||
'最简单的方法(Linux/macOS):运行 "curl -fsSL https://raw.githubusercontent.com/NoFxAiOS/nofx/main/install.sh | bash" - 这会自动安装 Docker 容器。然后在浏览器中打开 http://127.0.0.1:3000。手动安装或开发请克隆仓库并按照 README 说明操作。',
|
||||
|
||||
faqWindowsInstallation: 'Windows 如何安装?',
|
||||
faqWindowsInstallationAnswer:
|
||||
'三种方式:1)Docker Desktop(推荐)- 安装 Docker Desktop,然后在 PowerShell 中运行 "docker compose -f docker-compose.prod.yml up -d";2)WSL2 - 安装 Windows 子系统 Linux,然后按 Linux 方式安装;3)WSL2 + Docker - 两全其美,在 WSL2 终端运行安装脚本。通过 http://127.0.0.1:3000 访问。',
|
||||
|
||||
faqDockerDeployment: 'Docker 部署一直失败',
|
||||
faqDockerDeploymentAnswer:
|
||||
'常见解决方案:1)检查 Docker 是否运行:"docker info";2)确保足够内存(最少 2GB);3)如果卡在 "go build",尝试:"docker compose down && docker compose build --no-cache && docker compose up -d";4)查看日志:"docker compose logs -f";5)拉取较慢时,在 daemon.json 配置 Docker 镜像。',
|
||||
|
||||
faqManualInstallation: '如何手动安装用于开发?',
|
||||
faqManualInstallationAnswer:
|
||||
'前置条件:Go 1.21+、Node.js 18+、TA-Lib。步骤:1)克隆仓库:"git clone https://github.com/NoFxAiOS/nofx.git";2)安装后端依赖:"go mod download";3)安装前端依赖:"cd web && npm install";4)构建后端:"go build -o nofx";5)运行后端:"./nofx";6)运行前端(新终端):"cd web && npm run dev"。访问 http://127.0.0.1:3000',
|
||||
|
||||
faqServerDeployment: '如何部署到远程服务器?',
|
||||
faqServerDeploymentAnswer:
|
||||
'在服务器上运行安装脚本 - 它会自动检测服务器 IP。通过 http://服务器IP:3000 访问。配置 HTTPS:1)使用 Cloudflare(免费)- 添加域名,创建 A 记录指向服务器 IP,SSL 设为"灵活";2)在 .env 中启用 TRANSPORT_ENCRYPTION=true 进行浏览器端加密;3)通过 https://你的域名.com 访问。',
|
||||
|
||||
faqUpdateNOFX: '如何更新 NOFX?',
|
||||
faqUpdateNOFXAnswer:
|
||||
'Docker 方式:运行 "docker compose pull && docker compose up -d" 拉取最新镜像并重启。手动安装:后端 "git pull && go build -o nofx",前端 "cd web && npm install && npm run build"。data.db 中的配置在更新时会保留。',
|
||||
|
||||
// ===== 配置设置 =====
|
||||
faqConfigureAIModels: '如何配置 AI 模型?',
|
||||
faqConfigureAIModelsAnswer:
|
||||
'进入配置页面 → AI 模型部分。对于每个模型:1)从提供商获取 API 密钥(界面提供链接);2)输入 API 密钥;3)可选自定义基础 URL 和模型名称;4)保存。API 密钥在存储前会加密。保存后测试连接以验证。',
|
||||
|
||||
faqConfigureExchanges: '如何配置交易所连接?',
|
||||
faqConfigureExchangesAnswer:
|
||||
'进入配置页面 → 交易所部分。点击"添加交易所",选择类型并输入凭证。CEX(币安/Bybit/OKX):需要 API Key + Secret Key(OKX 还需要 Passphrase)。DEX(Hyperliquid/Aster/Lighter):需要钱包地址和私钥。务必只启用必要权限(合约交易)并考虑 IP 白名单。',
|
||||
|
||||
faqBinanceAPISetup: '如何正确设置币安 API?',
|
||||
faqBinanceAPISetupAnswer:
|
||||
'重要步骤:1)在币安 → API 管理中创建 API 密钥;2)仅启用"启用合约"权限;3)考虑添加 IP 白名单增强安全;4)关键:在合约设置 → 偏好设置 → 持仓模式中切换为双向持仓模式;5)确保资金在合约钱包(不是现货)。-4061 错误表示需要双向持仓模式。',
|
||||
|
||||
faqHyperliquidSetup: '如何设置 Hyperliquid?',
|
||||
faqHyperliquidSetupAnswer:
|
||||
'Hyperliquid 是去中心化交易所,需要钱包认证。步骤:1)访问 app.hyperliquid.xyz;2)连接钱包;3)生成 API 钱包(推荐)或使用主钱包;4)复制钱包地址和私钥;5)在 NOFX 中添加 Hyperliquid 交易所并填入凭证。无需 KYC,完全链上。',
|
||||
|
||||
faqCreateStrategy: '如何创建交易策略?',
|
||||
faqCreateStrategyAnswer:
|
||||
'进入策略工作室:1)币种来源 - 选择交易哪些币(静态列表、AI500 池或 OI 排行);2)指标 - 启用技术指标(EMA、MACD、RSI、ATR、成交量、OI、资金费率);3)风控 - 设置杠杆限制、最大持仓数、保证金使用上限、仓位大小限制;4)自定义提示词(可选)- 为 AI 添加特定指令。保存后分配给交易员。',
|
||||
|
||||
faqCreateTrader: '如何创建并启动交易员?',
|
||||
faqCreateTraderAnswer:
|
||||
'进入交易员页面:1)点击"创建交易员";2)选择 AI 模型(需先配置);3)选择交易所(需先配置);4)选择策略(或使用默认);5)设置决策间隔(如 15 分钟);6)保存,然后点击"启动"开始交易。在仪表板页面监控表现。',
|
||||
|
||||
// ===== 交易相关 =====
|
||||
faqHowAIDecides: 'AI 如何做出交易决策?',
|
||||
faqHowAIDecidesAnswer:
|
||||
'AI 使用思维链(CoT)推理分 4 步:1)持仓分析 - 审查当前持仓和盈亏;2)风险评估 - 检查账户保证金、可用余额;3)机会评估 - 分析市场数据、指标、候选币种;4)最终决策 - 输出具体操作(买入/卖出/持有)及理由。您可以在决策日志中查看完整推理过程。',
|
||||
|
||||
faqDecisionFrequency: 'AI 多久做一次决策?',
|
||||
faqDecisionFrequencyAnswer:
|
||||
'每个交易员可单独配置,默认 15 分钟。过于频繁会造成来回开平和手续费损耗;15-30 分钟能给信号足够时间兑现。执行层也会阻止过早的小亏小赚平仓和快速重新进场。',
|
||||
|
||||
faqNoTradesExecuting: '为什么交易员不执行任何交易?',
|
||||
faqNoTradesExecutingAnswer:
|
||||
'常见原因:1)AI 决定等待(查看决策日志了解原因);2)合约账户余额不足;3)达到最大持仓数限制(默认:3);4)交易所 API 问题(检查错误信息);5)策略约束太严格。查看仪表板 → 决策日志了解每个周期的 AI 推理详情。',
|
||||
|
||||
faqOnlyShortPositions: '为什么 AI 只开空单?',
|
||||
faqOnlyShortPositionsAnswer:
|
||||
'通常是因为币安持仓模式问题。解决方案:在币安合约 → 偏好设置 → 持仓模式中切换为双向持仓。必须先平掉所有持仓。切换后,AI 可以独立开多单和空单。',
|
||||
|
||||
faqLeverageSettings: '杠杆设置如何工作?',
|
||||
faqLeverageSettingsAnswer:
|
||||
'杠杆在策略 → 风控中设置:BTC/ETH 杠杆(通常 5-20 倍)和山寨币杠杆(通常 3-10 倍)。更高杠杆 = 更高风险和潜在收益。子账户可能有限制(如币安子账户限制 5 倍)。AI 下单时会遵守这些限制。',
|
||||
|
||||
faqStopLossTakeProfit: 'NOFX 支持止损止盈吗?',
|
||||
faqStopLossTakeProfitAnswer:
|
||||
'AI 可以在决策中建议止损/止盈价位,但这是基于指导而非交易所硬编码订单。AI 每个周期监控持仓,可能根据盈亏决定平仓。如需保证止损,可以手动在交易所设置订单,或调整策略提示词使其更保守。',
|
||||
|
||||
faqMultipleTraders: '可以运行多个交易员吗?',
|
||||
faqMultipleTradersAnswer:
|
||||
'可以!NOFX 支持运行 20+ 个并发交易员。每个交易员可以有不同的:AI 模型、交易所账户、策略、决策间隔。用于 A/B 测试策略、比较 AI 模型或跨交易所分散风险。在竞赛页面监控所有交易员。',
|
||||
|
||||
faqAICosts: 'AI API 调用费用是多少?',
|
||||
faqAICostsAnswer:
|
||||
'每个交易员每天大约费用(15 分钟间隔):DeepSeek:$0.03-0.20;Qwen:$0.07-0.30;OpenAI:$0.70-2;Claude:$0.30-1。费用取决于提示词长度和响应 token 数。DeepSeek 性价比最高。更长的决策间隔可降低费用。',
|
||||
|
||||
// ===== 技术问题 =====
|
||||
faqPortInUse: '端口 8080 或 3000 被占用',
|
||||
faqPortInUseAnswer:
|
||||
'查看占用端口的进程:macOS/Linux 用 "lsof -i :8080",Windows 用 "netstat -ano | findstr 8080"。终止进程或在 .env 中修改端口:NOFX_BACKEND_PORT=8081、NOFX_FRONTEND_PORT=3001。然后 "docker compose down && docker compose up -d" 重启。',
|
||||
|
||||
faqFrontendNotLoading: '前端一直显示"加载中..."',
|
||||
faqFrontendNotLoadingAnswer:
|
||||
'后端可能未运行或无法访问。检查:1)"curl http://127.0.0.1:8080/api/health" 应返回 {"status":"ok"};2)"docker compose ps" 验证容器运行中;3)查看后端日志:"docker compose logs nofx-backend";4)确保防火墙允许 8080 端口。',
|
||||
|
||||
faqDatabaseLocked: '数据库锁定错误',
|
||||
faqDatabaseLockedAnswer:
|
||||
'多个进程同时访问 SQLite 导致。解决方案:1)停止所有进程:"docker compose down" 或 "pkill nofx";2)如有锁文件删除:"rm -f data/data.db-wal data/data.db-shm";3)重启:"docker compose up -d"。只能有一个后端实例访问数据库。',
|
||||
|
||||
faqTALibNotFound: '构建时找不到 TA-Lib',
|
||||
faqTALibNotFoundAnswer:
|
||||
'TA-Lib 是技术指标所需。安装:macOS:"brew install ta-lib";Ubuntu/Debian:"sudo apt-get install libta-lib0-dev";CentOS:"yum install ta-lib-devel"。安装后重新构建:"go build -o nofx"。Docker 镜像已预装 TA-Lib。',
|
||||
|
||||
faqAIAPITimeout: 'AI API 超时或连接被拒绝',
|
||||
faqAIAPITimeoutAnswer:
|
||||
'检查:1)API 密钥有效(用 curl 测试);2)网络能访问 API 端点(ping/curl);3)API 提供商未宕机(查看状态页);4)VPN/防火墙未阻止;5)未超过速率限制。默认超时 120 秒。',
|
||||
|
||||
faqBinancePositionMode: '币安错误代码 -4061(持仓模式)',
|
||||
faqBinancePositionModeAnswer:
|
||||
'错误:"Order\'s position side does not match user\'s setting"。您处于单向持仓模式,但 NOFX 需要双向持仓模式。修复:1)先平掉所有持仓;2)币安合约 → 设置(齿轮图标)→ 偏好设置 → 持仓模式 → 切换为"双向持仓";3)重启交易员。',
|
||||
|
||||
faqBalanceShowsZero: '账户余额显示 0',
|
||||
faqBalanceShowsZeroAnswer:
|
||||
'资金可能在现货钱包而非合约钱包。解决方案:1)在币安进入钱包 → 合约 → 划转;2)将 USDT 从现货划转到合约;3)刷新 NOFX 仪表板。也检查:资金未被理财/质押产品锁定。',
|
||||
|
||||
faqDockerPullFailed: 'Docker 镜像拉取失败或缓慢',
|
||||
faqDockerPullFailedAnswer:
|
||||
'Docker Hub 在某些地区可能较慢。解决方案:1)在 /etc/docker/daemon.json 配置 Docker 镜像:{"registry-mirrors": ["https://mirror.gcr.io"]};2)重启 Docker;3)重试拉取。或使用 GitHub Container Registry(ghcr.io)在您的地区可能连接更好。',
|
||||
|
||||
// ===== 安全相关 =====
|
||||
faqAPIKeyStorage: 'API 密钥如何存储?',
|
||||
faqAPIKeyStorageAnswer:
|
||||
'API 密钥使用 AES-256-GCM 加密后存储在本地 SQLite 数据库中。加密密钥(DATA_ENCRYPTION_KEY)存储在您的 .env 文件中。密钥仅在 API 调用需要时在内存中解密。切勿分享您的 data.db 或 .env 文件。',
|
||||
|
||||
faqEncryptionDetails: 'NOFX 使用什么加密?',
|
||||
faqEncryptionDetailsAnswer:
|
||||
'NOFX 使用多层加密:1)AES-256-GCM 用于数据库存储(API 密钥、密钥);2)RSA-2048 用于可选的传输加密(浏览器到服务器);3)JWT 用于认证令牌。密钥在安装时生成。HTTPS 环境启用 TRANSPORT_ENCRYPTION=true。',
|
||||
|
||||
faqSecurityBestPractices: '安全最佳实践是什么?',
|
||||
faqSecurityBestPracticesAnswer:
|
||||
'建议:1)使用带 IP 白名单和最小权限(仅合约交易)的交易所 API 密钥;2)为 NOFX 使用专用子账户;3)远程部署启用 TRANSPORT_ENCRYPTION;4)切勿分享 .env 或 data.db 文件;5)使用有效证书的 HTTPS;6)定期轮换 API 密钥;7)监控账户活动。',
|
||||
|
||||
faqCanNOFXStealFunds: 'NOFX 会盗取我的资金吗?',
|
||||
faqCanNOFXStealFundsAnswer:
|
||||
'NOFX 是开源的(AGPL-3.0 许可)- 您可以在 GitHub 审计所有代码。API 密钥存储在您的机器本地,从不发送到外部服务器。NOFX 只有您通过 API 密钥授予的权限。为最大安全:使用仅交易权限(无提现)的 API 密钥,启用 IP 白名单,使用专用子账户。',
|
||||
|
||||
// ===== 功能介绍 =====
|
||||
faqStrategyStudio: '什么是策略工作室?',
|
||||
faqStrategyStudioAnswer:
|
||||
'策略工作室是可视化策略构建器,您可以配置:1)币种来源 - 交易哪些加密货币(静态列表、AI500 热门币、OI 排行);2)技术指标 - EMA、MACD、RSI、ATR、成交量、持仓量、资金费率;3)风控 - 杠杆限制、仓位大小、保证金上限;4)自定义提示词 - AI 的特定指令。无需编程。',
|
||||
|
||||
faqCompetitionMode: '什么是竞赛模式?',
|
||||
faqCompetitionModeAnswer:
|
||||
'竞赛页面显示所有交易员的实时排行榜。比较:ROI、盈亏、夏普比率、胜率、交易次数。用于 A/B 测试不同 AI 模型、策略或配置。交易员可标记为"在竞赛中显示"以出现在排行榜上。',
|
||||
|
||||
faqChainOfThought: '什么是思维链(CoT)?',
|
||||
faqChainOfThoughtAnswer:
|
||||
'思维链是 AI 的推理过程,可在决策日志中查看。AI 分 4 步解释思考:1)当前持仓分析;2)账户风险评估;3)市场机会评估;4)最终决策理由。这种透明度帮助您理解 AI 为什么做出每个决策,有助于改进策略。',
|
||||
|
||||
// ===== AI 模型 =====
|
||||
faqWhichAIModelBest: '应该使用哪个 AI 模型?',
|
||||
faqWhichAIModelBestAnswer:
|
||||
'推荐:DeepSeek 性价比最高(每天 $0.10-0.50)。备选:OpenAI 推理能力最强但贵(每天 $2-5);Claude 适合细致分析;Qwen 价格有竞争力。您可以运行多个交易员使用不同模型进行比较。查看竞赛页面看哪个对您的策略表现最好。',
|
||||
|
||||
faqCustomAIAPI: '可以使用自定义 AI API 吗?',
|
||||
faqCustomAIAPIAnswer:
|
||||
'可以!NOFX 支持任何 OpenAI 兼容的 API。在配置 → AI 模型 → 自定义 API 中:1)输入 API 端点 URL(如 https://your-api.com/v1);2)输入 API 密钥;3)指定模型名称。适用于自托管模型、替代提供商或通过第三方代理的 Claude。',
|
||||
|
||||
faqAIHallucinations: 'AI 幻觉问题怎么办?',
|
||||
faqAIHallucinationsAnswer:
|
||||
'AI 模型有时会产生不正确或虚构的信息("幻觉")。NOFX 通过以下方式缓解:1)提供带真实市场数据的结构化提示词;2)强制 JSON 输出格式;3)执行前验证订单。但 AI 交易是实验性的 - 始终监控决策,不要完全依赖 AI 判断。',
|
||||
|
||||
faqCompareAIModels: '如何比较不同 AI 模型?',
|
||||
faqCompareAIModelsAnswer:
|
||||
'创建多个交易员,使用不同 AI 模型但相同策略/交易所。同时运行并在竞赛页面比较。关注指标:ROI、胜率、夏普比率、最大回撤。',
|
||||
|
||||
// ===== 参与贡献 =====
|
||||
faqHowToContribute: '如何为 NOFX 做贡献?',
|
||||
faqHowToContributeAnswer:
|
||||
'NOFX 是开源项目,欢迎贡献!贡献方式:1)代码 - 修复 bug、添加功能(查看 GitHub Issues);2)文档 - 改进指南、翻译;3)Bug 报告 - 详细报告问题;4)功能建议 - 提出改进意见。从标记为"good first issue"的问题开始。所有贡献者可能获得空投奖励。',
|
||||
|
||||
faqPRGuidelines: 'PR 指南是什么?',
|
||||
faqPRGuidelinesAnswer:
|
||||
'PR 流程:1)Fork 仓库到您的账户;2)从 dev 创建功能分支:"git checkout -b feat/your-feature";3)修改代码,运行 lint:"npm --prefix web run lint";4)使用 Conventional Commits 格式提交;5)推送并创建 PR 到 NoFxAiOS/nofx:dev;6)关联相关 issue(Closes #123);7)等待审核。保持 PR 小而聚焦。',
|
||||
|
||||
faqBountyProgram: '有赏金计划吗?',
|
||||
faqBountyProgramAnswer:
|
||||
'有!贡献者根据贡献获得空投奖励:代码提交(权重最高)、bug 修复、功能建议、文档。带"bounty"标签的 issue 有现金奖励。完成工作后提交 Bounty Claim。查看 CONTRIBUTING.md 了解奖励结构详情。',
|
||||
|
||||
faqReportBugs: '如何报告 bug?',
|
||||
faqReportBugsAnswer:
|
||||
'Bug 报告:在 GitHub 开 Issue,包含:1)问题清晰描述;2)复现步骤;3)预期 vs 实际行为;4)系统信息(OS、Docker 版本、浏览器);5)相关日志。安全漏洞:不要开公开 issue - 请在 Twitter 私信 @Web3Tinkle。',
|
||||
|
||||
// Web Crypto Environment Check
|
||||
environmentCheck: {
|
||||
@@ -3345,168 +3025,6 @@ export const translations = {
|
||||
configureSignalSourceNow: 'Konfigurasi Sumber Sinyal Sekarang',
|
||||
|
||||
// FAQ Page
|
||||
faqTitle: 'Pertanyaan yang Sering Diajukan',
|
||||
faqSubtitle: 'Temukan jawaban untuk pertanyaan umum tentang NOFX',
|
||||
faqStillHaveQuestions: 'Masih Punya Pertanyaan?',
|
||||
faqContactUs:
|
||||
'Bergabunglah dengan komunitas kami atau kunjungi GitHub untuk bantuan lebih lanjut',
|
||||
faqCategoryGettingStarted: 'Memulai',
|
||||
faqCategoryInstallation: 'Instalasi',
|
||||
faqCategoryConfiguration: 'Konfigurasi',
|
||||
faqCategoryTrading: 'Trading',
|
||||
faqCategoryTechnicalIssues: 'Masalah Teknis',
|
||||
faqCategorySecurity: 'Keamanan',
|
||||
faqCategoryFeatures: 'Fitur',
|
||||
faqCategoryAIModels: 'Model AI',
|
||||
faqCategoryContributing: 'Kontribusi',
|
||||
faqWhatIsNOFX: 'Apa itu NOFX?',
|
||||
faqWhatIsNOFXAnswer:
|
||||
'NOFX adalah sistem operasi trading bertenaga AI open-source untuk pasar kripto dan saham AS. Ia menggunakan model bahasa besar (LLM) seperti DeepSeek, GPT, Claude, Gemini untuk menganalisis data pasar dan membuat keputusan trading secara otonom. Fitur utama: dukungan multi-model AI, trading multi-bursa, dan pembangun strategi visual.',
|
||||
faqHowDoesItWork: 'Bagaimana cara kerja NOFX?',
|
||||
faqHowDoesItWorkAnswer:
|
||||
'NOFX bekerja dalam 5 langkah: 1) Konfigurasi model AI dan kredensial API bursa; 2) Buat strategi trading (pemilihan koin, indikator, kontrol risiko); 3) Buat "Trader" menggabungkan Model AI + Bursa + Strategi; 4) Mulai trader - dia akan menganalisis data pasar secara berkala dan membuat keputusan beli/jual/tahan; 5) Pantau performa di dasbor.',
|
||||
faqIsProfitable: 'Apakah NOFX menguntungkan?',
|
||||
faqIsProfitableAnswer:
|
||||
'Trading AI bersifat eksperimental dan TIDAK dijamin menguntungkan. Futures kripto sangat volatil dan berisiko. NOFX dirancang untuk tujuan edukasi dan riset. Kami sangat menyarankan: mulai dengan jumlah kecil (10-50 USDT), jangan investasi melebihi yang sanggup Anda rugi, uji sebelum trading nyata.',
|
||||
faqSupportedExchanges: 'Bursa mana yang didukung?',
|
||||
faqSupportedExchangesAnswer:
|
||||
'CEX (Tersentralisasi): Binance Futures, Bybit, OKX, Bitget. DEX (Terdesentralisasi): Hyperliquid, Aster DEX, Lighter. Setiap bursa memiliki fitur berbeda - Binance memiliki likuiditas terbesar, Hyperliquid sepenuhnya on-chain tanpa KYC.',
|
||||
faqSupportedAIModels: 'Model AI mana yang didukung?',
|
||||
faqSupportedAIModelsAnswer:
|
||||
'NOFX mendukung 7+ model AI: DeepSeek (direkomendasikan untuk biaya/performa), Qwen, OpenAI (GPT), Claude, Gemini, Grok, dan Kimi. Anda juga dapat menggunakan endpoint API yang kompatibel dengan OpenAI.',
|
||||
faqSystemRequirements: 'Apa persyaratan sistem?',
|
||||
faqSystemRequirementsAnswer:
|
||||
'Minimum: 2 core CPU, 2GB RAM, 1GB disk, internet stabil. Direkomendasikan: 4GB RAM untuk menjalankan beberapa trader. OS yang didukung: Linux, macOS, atau Windows (via Docker atau WSL2).',
|
||||
faqHowToInstall: 'Bagaimana cara menginstal NOFX?',
|
||||
faqHowToInstallAnswer:
|
||||
'Metode termudah (Linux/macOS): Jalankan "curl -fsSL https://raw.githubusercontent.com/NoFxAiOS/nofx/main/install.sh | bash" - ini menginstal kontainer Docker secara otomatis. Lalu buka http://127.0.0.1:3000 di browser Anda.',
|
||||
faqWindowsInstallation: 'Bagaimana cara menginstal di Windows?',
|
||||
faqWindowsInstallationAnswer:
|
||||
'Tiga opsi: 1) Docker Desktop (Direkomendasikan); 2) WSL2 - Instal Windows Subsystem for Linux; 3) Docker di WSL2. Akses via http://127.0.0.1:3000',
|
||||
faqDockerDeployment: 'Deployment Docker terus gagal',
|
||||
faqDockerDeploymentAnswer:
|
||||
'Solusi umum: 1) Periksa Docker berjalan: "docker info"; 2) Pastikan memori cukup (minimal 2GB); 3) Periksa log: "docker compose logs -f".',
|
||||
faqManualInstallation:
|
||||
'Bagaimana cara menginstal manual untuk pengembangan?',
|
||||
faqManualInstallationAnswer:
|
||||
'Prasyarat: Go 1.21+, Node.js 18+, TA-Lib. Langkah: 1) Clone repo; 2) "go mod download"; 3) "cd web && npm install"; 4) "go build -o nofx"; 5) "./nofx"; 6) "cd web && npm run dev".',
|
||||
faqServerDeployment: 'Bagaimana cara deploy ke server remote?',
|
||||
faqServerDeploymentAnswer:
|
||||
'Jalankan skrip instal di server Anda. Akses via http://IP_SERVER:3000. Untuk HTTPS: Gunakan Cloudflare (gratis) dan aktifkan TRANSPORT_ENCRYPTION=true di .env.',
|
||||
faqUpdateNOFX: 'Bagaimana cara memperbarui NOFX?',
|
||||
faqUpdateNOFXAnswer:
|
||||
'Docker: "docker compose pull && docker compose up -d". Manual: "git pull && go build -o nofx" untuk backend, "cd web && npm install && npm run build" untuk frontend.',
|
||||
faqConfigureAIModels: 'Bagaimana cara mengonfigurasi model AI?',
|
||||
faqConfigureAIModelsAnswer:
|
||||
'Buka halaman Konfigurasi → bagian Model AI. Untuk setiap model: 1) Dapatkan API key dari penyedia; 2) Masukkan API key; 3) Opsional kustomisasi base URL dan nama model; 4) Simpan.',
|
||||
faqConfigureExchanges: 'Bagaimana cara mengonfigurasi koneksi bursa?',
|
||||
faqConfigureExchangesAnswer:
|
||||
'Buka halaman Konfigurasi → bagian Bursa. Klik "Tambah Bursa", pilih jenis, dan masukkan kredensial. Aktifkan hanya izin yang diperlukan (Trading Futures).',
|
||||
faqBinanceAPISetup: 'Bagaimana cara mengatur API Binance dengan benar?',
|
||||
faqBinanceAPISetupAnswer:
|
||||
'Langkah penting: 1) Buat API key di Binance → Manajemen API; 2) Aktifkan HANYA izin "Enable Futures"; 3) PENTING: Beralih ke Hedge Mode di pengaturan Futures; 4) Pastikan dana di dompet Futures.',
|
||||
faqHyperliquidSetup: 'Bagaimana cara mengatur Hyperliquid?',
|
||||
faqHyperliquidSetupAnswer:
|
||||
'Hyperliquid adalah bursa terdesentralisasi. Langkah: 1) Kunjungi app.hyperliquid.xyz; 2) Hubungkan wallet; 3) Buat API wallet; 4) Salin alamat dan private key; 5) Tambahkan di NOFX. Tanpa KYC.',
|
||||
faqCreateStrategy: 'Bagaimana cara membuat strategi trading?',
|
||||
faqCreateStrategyAnswer:
|
||||
'Buka Strategy Studio: 1) Sumber Koin; 2) Indikator teknikal; 3) Kontrol Risiko; 4) Prompt Kustom (opsional). Simpan dan tetapkan ke trader.',
|
||||
faqCreateTrader: 'Bagaimana cara membuat dan memulai trader?',
|
||||
faqCreateTraderAnswer:
|
||||
'Buka halaman Trader: 1) Klik "Buat Trader"; 2) Pilih Model AI; 3) Pilih Bursa; 4) Pilih Strategi; 5) Atur interval keputusan; 6) Simpan, lalu klik "Mulai".',
|
||||
faqHowAIDecides: 'Bagaimana AI membuat keputusan trading?',
|
||||
faqHowAIDecidesAnswer:
|
||||
'AI menggunakan penalaran Chain of Thought (CoT) dalam 4 langkah: 1) Analisis Posisi; 2) Penilaian Risiko; 3) Evaluasi Peluang; 4) Keputusan Akhir.',
|
||||
faqDecisionFrequency: 'Seberapa sering AI membuat keputusan?',
|
||||
faqDecisionFrequencyAnswer:
|
||||
'Dapat dikonfigurasi per trader, default 15 menit. Disarankan: 15-30 menit untuk trading aktif berbasis sinyal.',
|
||||
faqNoTradesExecuting: 'Mengapa trader saya tidak mengeksekusi trading?',
|
||||
faqNoTradesExecutingAnswer:
|
||||
'Penyebab umum: 1) AI memutuskan menunggu; 2) Saldo tidak cukup; 3) Batas posisi maks tercapai; 4) Masalah API bursa; 5) Batasan strategi terlalu ketat.',
|
||||
faqOnlyShortPositions: 'Mengapa AI hanya membuka posisi short?',
|
||||
faqOnlyShortPositionsAnswer:
|
||||
'Biasanya karena Mode Posisi Binance. Solusi: Beralih ke Hedge Mode di Binance Futures → Preferensi → Mode Posisi.',
|
||||
faqLeverageSettings: 'Bagaimana cara kerja pengaturan leverage?',
|
||||
faqLeverageSettingsAnswer:
|
||||
'Leverage diatur di Strategi → Kontrol Risiko: leverage BTC/ETH (biasanya 5-20x) dan leverage Altcoin (biasanya 3-10x).',
|
||||
faqStopLossTakeProfit: 'Apakah NOFX mendukung stop-loss dan take-profit?',
|
||||
faqStopLossTakeProfitAnswer:
|
||||
'AI dapat menyarankan level stop-loss/take-profit dalam keputusannya, tetapi ini bersifat panduan bukan order bursa yang dikodekan keras.',
|
||||
faqMultipleTraders: 'Bisakah saya menjalankan beberapa trader?',
|
||||
faqMultipleTradersAnswer:
|
||||
'Ya! NOFX mendukung 20+ trader bersamaan. Gunakan untuk A/B test strategi, bandingkan model AI, atau diversifikasi lintas bursa.',
|
||||
faqAICosts: 'Berapa biaya panggilan API AI?',
|
||||
faqAICostsAnswer:
|
||||
'Perkiraan biaya harian per trader (interval 5 menit): DeepSeek: $0.10-0.50; Qwen: $0.20-0.80; OpenAI: $2-5; Claude: $1-3.',
|
||||
faqPortInUse: 'Port 8080 atau 3000 sudah digunakan',
|
||||
faqPortInUseAnswer:
|
||||
'Periksa proses yang menggunakan port. Ubah port di .env: NOFX_BACKEND_PORT=8081, NOFX_FRONTEND_PORT=3001.',
|
||||
faqFrontendNotLoading: 'Frontend menampilkan "Memuat..." terus-menerus',
|
||||
faqFrontendNotLoadingAnswer:
|
||||
'Backend mungkin tidak berjalan. Periksa: "curl http://127.0.0.1:8080/api/health" harus mengembalikan {"status":"ok"}.',
|
||||
faqDatabaseLocked: 'Error database terkunci',
|
||||
faqDatabaseLockedAnswer:
|
||||
'Beberapa proses mengakses SQLite bersamaan. Hentikan semua, hapus file lock, restart.',
|
||||
faqTALibNotFound: 'TA-Lib tidak ditemukan saat build',
|
||||
faqTALibNotFoundAnswer:
|
||||
'Instal TA-Lib: macOS: "brew install ta-lib"; Ubuntu: "sudo apt-get install libta-lib0-dev".',
|
||||
faqAIAPITimeout: 'API AI timeout atau koneksi ditolak',
|
||||
faqAIAPITimeoutAnswer:
|
||||
'Periksa: 1) API key valid; 2) Jaringan bisa mengakses endpoint; 3) Penyedia tidak down; 4) VPN/firewall tidak memblokir.',
|
||||
faqBinancePositionMode: 'Kode error Binance -4061 (Mode Posisi)',
|
||||
faqBinancePositionModeAnswer:
|
||||
'Anda dalam mode One-way tetapi NOFX memerlukan Hedge Mode. Tutup semua posisi, beralih ke Hedge Mode, restart trader.',
|
||||
faqBalanceShowsZero: 'Saldo akun menunjukkan 0',
|
||||
faqBalanceShowsZeroAnswer:
|
||||
'Dana mungkin di dompet Spot, bukan dompet Futures. Transfer USDT dari Spot ke Futures.',
|
||||
faqDockerPullFailed: 'Penarikan image Docker gagal atau lambat',
|
||||
faqDockerPullFailedAnswer:
|
||||
'Konfigurasi mirror Docker di daemon.json atau gunakan GitHub Container Registry.',
|
||||
faqAPIKeyStorage: 'Bagaimana API key disimpan?',
|
||||
faqAPIKeyStorageAnswer:
|
||||
'API key dienkripsi menggunakan AES-256-GCM sebelum disimpan di database SQLite lokal. Jangan pernah bagikan file data.db atau .env Anda.',
|
||||
faqEncryptionDetails: 'Enkripsi apa yang digunakan NOFX?',
|
||||
faqEncryptionDetailsAnswer:
|
||||
'NOFX menggunakan: 1) AES-256-GCM untuk penyimpanan database; 2) RSA-2048 untuk enkripsi transport opsional; 3) JWT untuk token autentikasi.',
|
||||
faqSecurityBestPractices: 'Apa praktik terbaik keamanan?',
|
||||
faqSecurityBestPracticesAnswer:
|
||||
'Disarankan: 1) Gunakan API key dengan whitelist IP dan izin minimal; 2) Gunakan sub-akun khusus; 3) Aktifkan TRANSPORT_ENCRYPTION; 4) Gunakan HTTPS.',
|
||||
faqCanNOFXStealFunds: 'Bisakah NOFX mencuri dana saya?',
|
||||
faqCanNOFXStealFundsAnswer:
|
||||
'NOFX open-source (lisensi AGPL-3.0) - Anda bisa audit semua kode. API key disimpan lokal di mesin ANDA, tidak pernah dikirim ke server eksternal.',
|
||||
faqStrategyStudio: 'Apa itu Strategy Studio?',
|
||||
faqStrategyStudioAnswer:
|
||||
'Strategy Studio adalah pembangun strategi visual untuk konfigurasi: Sumber Koin, Indikator Teknikal, Kontrol Risiko, dan Prompt Kustom. Tanpa coding.',
|
||||
faqCompetitionMode: 'Apa itu Mode Kompetisi?',
|
||||
faqCompetitionModeAnswer:
|
||||
'Halaman kompetisi menampilkan papan peringkat realtime semua trader Anda. Bandingkan ROI, L/R, rasio Sharpe, win rate.',
|
||||
faqChainOfThought: 'Apa itu Chain of Thought (CoT)?',
|
||||
faqChainOfThoughtAnswer:
|
||||
'Chain of Thought adalah proses penalaran AI, terlihat di log keputusan. AI menjelaskan alasan di balik setiap keputusan.',
|
||||
faqWhichAIModelBest: 'Model AI mana yang sebaiknya saya gunakan?',
|
||||
faqWhichAIModelBestAnswer:
|
||||
'Direkomendasikan: DeepSeek untuk rasio biaya/performa terbaik. Alternatif: OpenAI untuk penalaran terbaik; Claude untuk analisis mendalam; Qwen harga kompetitif.',
|
||||
faqCustomAIAPI: 'Bisakah saya menggunakan API AI kustom?',
|
||||
faqCustomAIAPIAnswer:
|
||||
'Ya! NOFX mendukung API yang kompatibel dengan OpenAI. Masukkan URL endpoint, API key, dan nama model.',
|
||||
faqAIHallucinations: 'Bagaimana dengan halusinasi AI?',
|
||||
faqAIHallucinationsAnswer:
|
||||
'NOFX memitigasi dengan: prompt terstruktur, format output JSON, dan validasi order sebelum eksekusi. Namun trading AI tetap eksperimental.',
|
||||
faqCompareAIModels: 'Bagaimana cara membandingkan model AI yang berbeda?',
|
||||
faqCompareAIModelsAnswer:
|
||||
'Buat beberapa trader dengan model AI berbeda tapi strategi/bursa sama. Jalankan bersamaan dan bandingkan di halaman Kompetisi.',
|
||||
faqHowToContribute: 'Bagaimana cara berkontribusi ke NOFX?',
|
||||
faqHowToContributeAnswer:
|
||||
'NOFX open-source dan menyambut kontribusi! Cara: 1) Kode - perbaiki bug, tambah fitur; 2) Dokumentasi; 3) Laporan Bug; 4) Ide Fitur. Semua kontributor mungkin mendapat reward airdrop.',
|
||||
faqPRGuidelines: 'Apa panduan PR?',
|
||||
faqPRGuidelinesAnswer:
|
||||
'Proses PR: 1) Fork repo; 2) Buat branch fitur dari dev; 3) Buat perubahan, jalankan lint; 4) Commit dengan format Conventional Commits; 5) Push dan buat PR ke NoFxAiOS/nofx:dev.',
|
||||
faqBountyProgram: 'Apakah ada program bounty?',
|
||||
faqBountyProgramAnswer:
|
||||
'Ya! Kontributor mendapat reward airdrop berdasarkan kontribusi. Issue dengan label "bounty" memiliki reward uang tunai.',
|
||||
faqReportBugs: 'Bagaimana cara melaporkan bug?',
|
||||
faqReportBugsAnswer:
|
||||
'Buka GitHub Issue dengan: deskripsi masalah, langkah reproduksi, perilaku yang diharapkan vs aktual. Untuk kerentanan keamanan: DM @Web3Tinkle di Twitter.',
|
||||
|
||||
// Web Crypto Environment Check
|
||||
environmentCheck: {
|
||||
|
||||
@@ -1,21 +1,9 @@
|
||||
import { FAQLayout } from '../components/faq/FAQLayout'
|
||||
import { useLanguage } from '../contexts/LanguageContext'
|
||||
|
||||
/**
|
||||
* FAQ page
|
||||
*
|
||||
* HeaderBar and Footer are now provided by MainLayout
|
||||
*
|
||||
* All FAQ-related logic lives in child components:
|
||||
* - FAQLayout: overall layout and search logic
|
||||
* - FAQSearchBar: search box
|
||||
* - FAQSidebar: left-side table of contents
|
||||
* - FAQContent: right-side content area
|
||||
*
|
||||
* FAQ data is configured in data/faqData.ts
|
||||
* FAQ page — layout, search, sidebar and content live in components/faq/*;
|
||||
* the questions themselves are data in data/faqData.ts.
|
||||
*/
|
||||
export function FAQPage() {
|
||||
const { language } = useLanguage()
|
||||
|
||||
return <FAQLayout language={language} />
|
||||
return <FAQLayout />
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user