diff --git a/public/index.html b/public/index.html
index 88d1179..2b9ba31 100644
--- a/public/index.html
+++ b/public/index.html
@@ -123,6 +123,8 @@ const fmtTs = (ts) => ts == null ? '–' : new Date(ts).toLocaleString('de-DE',
const cls = (n) => n > 0 ? 'pos' : n < 0 ? 'neg' : '';
const sign = (n, d = 2) => (n > 0 ? '+' : '') + fmt(n, d);
const priceDec = (p) => p < 1 ? 5 : p < 10 ? 4 : p < 1000 ? 2 : 0;
+// HTML-Escaping für DB-Felder mit externem Ursprung (Truth-Feed/On-chain)
+const esc = (s) => String(s).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, ''');
function kpi(label, value, klass = '') {
return `
`;
@@ -525,24 +527,25 @@ async function refresh() {
document.getElementById('trump-positions').innerHTML = table(
['Pair', 'Entry-Zeit', 'Entry-Preis', 'Qty', 'Exit fällig'],
- trumpPositions.map(p => `| ${p.pair} | ${fmtTs(p.entryTs)} | ${fmt(p.entryPrice, priceDec(p.entryPrice))} | ${fmt(p.qty, 4)} | ${fmtTs(p.exitDueTs)} |
`),
+ trumpPositions.map(p => `| ${esc(p.pair)} | ${fmtTs(p.entryTs)} | ${fmt(p.entryPrice, priceDec(p.entryPrice))} | ${fmt(p.qty, 4)} | ${fmtTs(p.exitDueTs)} |
`),
'Keine offenen Positionen.');
document.getElementById('trump-events').innerHTML = table(
['Zeit', 'Quelle', 'Coin', 'Instrument', 'Notional $', 'Ref'],
trumpEvents.map(e => {
- const ref = e.ref
- ? e.source === 'onchain'
- ? `${e.ref.slice(0, 12)}…`
- : `${e.ref.slice(0, 24)}${e.ref.length > 24 ? '…' : ''}`
- : '–';
- return `| ${fmtTs(e.eventTs)} | ${e.source ?? '–'} | ${e.token ?? '–'} | ${e.instrument ?? '–'} | ${e.notionalUsd != null ? fmt(e.notionalUsd) + ' $' : '–'} | ${ref} |
`;
+ // href nur mit https-Schema (Truth-Refs kommen aus externem Feed)
+ const safeHref = e.source === 'onchain'
+ ? `https://etherscan.io/tx/${esc(e.ref)}`
+ : /^https:\/\//i.test(e.ref) ? esc(e.ref) : null;
+ const refLabel = esc(e.source === 'onchain' ? e.ref.slice(0, 12) + '…' : e.ref.slice(0, 24) + (e.ref.length > 24 ? '…' : ''));
+ const ref = safeHref ? `${refLabel}` : refLabel;
+ return `| ${fmtTs(e.eventTs)} | ${esc(e.source ?? '–')} | ${esc(e.token ?? '–')} | ${esc(e.instrument ?? '–')} | ${e.notionalUsd != null ? fmt(e.notionalUsd) + ' $' : '–'} | ${ref} |
`;
}),
'Keine Events vorhanden.');
document.getElementById('trump-trades').innerHTML = table(
['Entry', 'Exit', 'Entry-Preis', 'Exit-Preis', 'PnL $', 'Grund'],
- trumpTradesAll.map(t => `| ${fmtTs(new Date(t.entryTs).getTime())} | ${fmtTs(new Date(t.exitTs).getTime())} | ${fmt(t.entryPrice, 4)} | ${fmt(t.exitPrice, 4)} | ${sign(t.pnl)} | ${t.exitReason} |
`),
+ trumpTradesAll.map(t => `| ${fmtTs(new Date(t.entryTs).getTime())} | ${fmtTs(new Date(t.exitTs).getTime())} | ${fmt(t.entryPrice, 4)} | ${fmt(t.exitPrice, 4)} | ${sign(t.pnl)} | ${esc(t.exitReason)} |
`),
'Noch keine Trump-Trades.');
const eng = pf.engine || {};