Skip to content

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).