Appearance
Live dealer dashboard
Load a REST snapshot, keep it current from the socket, and reload after every reconnect.
ts
export async function dealerDashboard(onChange: (positions: Map<number, Position>) => void) {
const positions = new Map<number, Position>();
async function reload() {
positions.clear();
const page = await staff.positions.list({ limit: 500 });
for (const p of page.items) positions.set(p.id, p);
onChange(positions);
}
const socket = staff.socket();
// Fills, closes, stop outs: apply each change once, keyed by position id.
socket.on("trade", (frame) => {
for (const id of frame.data.closed ?? []) positions.delete(id);
for (const p of frame.data.positions ?? []) {
const known = positions.get(p.id);
if (known) positions.set(p.id, { ...known, ...p });
}
onChange(positions);
});
// After a drop, frames may have been missed: reload over REST.
socket.on("open", ({ reconnect }) => void (reconnect && reload()));
socket.on("close", ({ reason }) => reason === "access changed" && void staff.auth.me());
await reload();
await socket.connect();
return () => socket.close();
}The REST answer and the socket event can arrive in either order: apply each change once, keyed by deal, order or position id. Staff receive account frames only for groups in their scope and with the matching rights (trades.view, accounts.view, risk.view).