/* 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 }) =>
{Icon.zap}
AURA trades XAUUSD 24/5 (Mon–Fri). Bot auto-pauses on weekends. Changes take effect on the next bot cycle.
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)}
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)} />
{[
{ 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}
))}
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, 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
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" && (
Last LoginThis session
Sign Out
)}
{tab === "notifications" && (
Email notifications in a future release
)}
{tab === "legal" && (
Risk DisclosureTrading involves substantial risk of loss
Delete Account
)}
{toast &&
{toast.msg}
}
>
);
}
window.BotSettings = BotSettings;
window.MT5Accounts = MT5Accounts;
window.Profile = Profile;