/* global React, AURA_DATA, Icon */ const D4 = window.AURA_DATA; const { useState, useEffect } = React; function BotSettings({ state }) { const { activeAccount } = state; const [settings, setSettings] = useState(null); const [dirty, setDirty] = useState(false); const [saving, setSaving] = useState(false); const [toast, setToast] = useState(null); useEffect(() => { if (!activeAccount) return; window.api.getBotSettings(activeAccount.id).then((s) => { if (s) setSettings(s); }).catch(() => {}); }, [activeAccount]); const update = (key, val) => { setSettings((s) => ({ ...s, [key]: val })); setDirty(true); }; const updateSession = (key, val) => { const sessions = JSON.parse(settings.sessions_json || "{}"); const next = JSON.stringify({ ...sessions, [key]: val }); update("sessions_json", next); }; const save = async () => { if (!activeAccount || !settings) return; setSaving(true); try { await window.api.saveBotSettings(activeAccount.id, settings); setDirty(false); setToast({ msg: "Settings saved", type: "success" }); setTimeout(() => setToast(null), 2400); } catch (err) { setToast({ msg: err.message || "Save failed", type: "error" }); setTimeout(() => setToast(null), 3000); } finally { setSaving(false); } }; const Toggle = ({ on, onClick }) =>
; const Slider = ({ value, set, min, max, step, suffix }) => (
set(Number(e.target.value))} /> {value}{suffix}
); if (!settings) { return ( <>

Bot Settings

{activeAccount ? "Loading settings…" : "Select an MT5 account first"}
); } const sessions = JSON.parse(settings.sessions_json || '{"asian":false,"london":true,"ny":true,"overlap":true}'); const rr = settings.tp_atr_mult / settings.sl_atr_mult; return ( <>

Bot Settings

Strategy: EMA 8/21 · M15 · {activeAccount ? activeAccount.nickname || activeAccount.login : "—"}
{Icon.zap} AURA trades XAUUSD 24/5 (Mon–Fri). Bot auto-pauses on weekends. Changes take effect on the next bot cycle.
Risk Parameters
update("risk_pct", v)} min={0.1} max={2} step={0.1} suffix="%" />
update("sl_atr_mult", v)} min={0.5} max={4} step={0.1} suffix="×" />
update("tp_atr_mult", v)} min={1} max={6} step={0.1} suffix="×" />
update("max_positions", v)} min={1} max={10} step={1} suffix="" />
Risk-Reward Ratio: 1 : {rr.toFixed(2)}
Execution Filters
update("spread_gate_pips", v)} min={0.5} max={10} step={0.1} suffix=" pips" />
update("atr_entry_mult", v)} min={0.5} max={3} step={0.1} suffix="×" />
Trailing Stop
Activates at 1× ATR profit
update("use_trailing", !settings.use_trailing)} />
Circuit Breakers
Pause after {settings.max_loss_streak} losses or {settings.daily_loss_limit_pct}% daily DD
update("use_circuit_breaker", !settings.use_circuit_breaker)} />
Trading Sessions (GMT)
{[ { k: "asian", n: "Asian", h: "00:00 – 07:00", c: "Tokyo / Sydney" }, { k: "london", n: "London", h: "07:00 – 16:00", c: "Highest liquidity" }, { k: "ny", n: "New York", h: "13:00 – 22:00", c: "USD pairs strong" }, { k: "overlap", n: "London / NY", h: "13:00 – 16:00", c: "Peak volatility" }, ].map((s) => (
updateSession(s.k, !sessions[s.k])} style={{ padding: 14, border: `1px solid ${sessions[s.k] ? "rgba(0,224,255,0.3)" : "var(--line)"}`, borderRadius: 4, background: sessions[s.k] ? "var(--accent-glow)" : "var(--bg-2)", cursor: "pointer" }}>
{s.n}
{ e.stopPropagation(); updateSession(s.k, !sessions[s.k]); }} />
{s.h}
{s.c}
))}
Trading Symbol
Au
XAUUSD
Spot Gold / US Dollar
● ACTIVE
AURA trades XAUUSD exclusively on the M15 timeframe.
{toast &&
{toast.msg}
} ); } function MT5Accounts({ state, onAccountsChange }) { const { accounts, activeAccount, setActiveAccount } = state; const [showAdd, setShowAdd] = useState(false); const [form, setForm] = useState({ nickname: "", login: "", server: "OctaFX-Demo", password: "", terminal_path: "" }); const [addError, setAddError] = useState(""); const [addLoading, setAddLoading] = useState(false); const [testResults, setTestResults] = useState({}); const [testLoading, setTestLoading] = useState({}); const [toast, setToast] = useState(null); const showToast = (msg, type = "success") => { setToast({ msg, type }); setTimeout(() => setToast(null), 2400); }; const addAccount = async () => { if (!form.login || !form.password) { setAddError("Login and password are required"); return; } setAddLoading(true); setAddError(""); try { const acct = await window.api.createAccount(form); const updated = [...accounts, acct]; onAccountsChange(updated); setShowAdd(false); setForm({ nickname: "", login: "", server: "OctaFX-Demo", password: "", terminal_path: "" }); showToast("Account added — test the connection to verify"); } catch (err) { setAddError(err.message || "Failed to add account"); } finally { setAddLoading(false); } }; const testConn = async (id) => { setTestLoading((t) => ({ ...t, [id]: true })); try { const res = await window.api.testConnection(id); setTestResults((r) => ({ ...r, [id]: res })); if (res.success) { showToast("Connection verified"); // Refresh account data after successful test const updated = await window.api.listAccounts(); if (updated) onAccountsChange(updated); } else { showToast(res.message, "error"); } } catch (err) { setTestResults((r) => ({ ...r, [id]: { success: false, message: err.message } })); } finally { setTestLoading((t) => ({ ...t, [id]: false })); } }; const deleteAccount = async (id) => { if (!confirm("Delete this account? This cannot be undone.")) return; try { await window.api.deleteAccount(id); const updated = accounts.filter((a) => a.id !== id); onAccountsChange(updated); if (activeAccount && activeAccount.id === id) setActiveAccount(updated[0] || null); showToast("Account deleted"); } catch (err) { showToast(err.message || "Delete failed", "error"); } }; return ( <>

MT5 Accounts

{accounts.length} connected · OctaFX only
{Icon.shield} Credentials encrypted with AES-256-GCM and never returned by any API. OctaFX-Demo and OctaFX-Real supported.
{accounts.length === 0 ? (
No accounts yet — add your OctaFX MT5 account to get started
) : (
{accounts.map((a) => { const test = testResults[a.id]; return (
{a.nickname || a.login}
#{a.login} · {a.server}
Balance
${a.balance.toLocaleString("en-US", { minimumFractionDigits: 2 })}
Equity
= a.balance ? "pos" : ""}`} style={{ fontSize: 14, fontWeight: 600, marginTop: 2 }}>${a.equity.toLocaleString("en-US", { minimumFractionDigits: 2 })}
● {a.status} {a.bot_active ? ● Bot Active : Bot Idle}
{test && (
{test.success ? "✓ " : "✗ "}{test.message}
)}
); })}
)}
{showAdd && (
setShowAdd(false)}>
e.stopPropagation()} style={{ width: 480 }}>

Connect MT5 Account

Credentials are encrypted with AES-256-GCM. Only OctaFX servers are supported.

{addError &&
{addError}
}
setForm({ ...form, nickname: e.target.value })} />
setForm({ ...form, login: e.target.value })} />
setForm({ ...form, password: e.target.value })} />
setForm({ ...form, terminal_path: e.target.value })} />
)} {toast &&
{toast.msg}
} ); } function Profile({ user, onUserUpdate }) { const [tab, setTab] = useState("profile"); const [form, setForm] = useState({ name: user ? user.name : "", timezone: user ? user.timezone : "UTC", currency: user ? user.currency : "USD" }); const [saving, setSaving] = useState(false); const [toast, setToast] = useState(null); const save = async () => { setSaving(true); try { const updated = await window.api.updateMe(form); if (updated) { onUserUpdate(updated); window.Auth.setUser(updated); } setToast({ msg: "Profile saved", type: "success" }); setTimeout(() => setToast(null), 2400); } catch (err) { setToast({ msg: err.message || "Save failed", type: "error" }); setTimeout(() => setToast(null), 3000); } finally { setSaving(false); } }; return ( <>

Profile & Preferences

{user ? user.email : "—"}
{["profile", "security", "notifications", "legal"].map((t) => ( ))}
{tab === "profile" && (
Personal
setForm({ ...form, name: e.target.value })} />
Plan
Current Plan
FREE
Forever. No credit card. Unlimited accounts. All features included.
● Unlimited MT5 accounts
● 24/5 automated XAUUSD trading
● EMA 8/21 M15 scalping strategy
● Full analytics & signal log
● No commissions, ever
)} {tab === "security" && (
Security
Last LoginThis session
Sign Out
)} {tab === "notifications" && (
Notifications
Coming soon
Email notifications in a future release
)} {tab === "legal" && (
Legal & Data
Risk DisclosureTrading involves substantial risk of loss
Delete Account
)}
{toast &&
{toast.msg}
} ); } window.BotSettings = BotSettings; window.MT5Accounts = MT5Accounts; window.Profile = Profile;