import { getPlatformAccessToken } from './authSession'; import { tradingRuntime } from './runtime'; import { createRequestId } from '../../../shared/request-id.js'; export interface TradeProfilePayload { id?: string; user_id?: string; name: string; allocated_capital: number; risk_per_trade_percent: number; symbols: string; is_active: boolean; strategy_config: Record; created_at?: string; updated_at?: string; } export interface CurrentUserProfile { user_id: string; first_name: string; last_name: string; email: string; role: string; trade_enable: boolean; FMP_API_KEY?: string; ALPACA_API_KEY?: string; ALPACA_SECRET_KEY?: string; REAL_ALPACA_API_KEY?: string; REAL_ALPACA_SECRET_KEY?: string; drop_threshold_for_buy?: number; gain_threshold_for_sell?: number; market_poll_interval_in_seconds?: number; } async function getAccessToken(): Promise { return getPlatformAccessToken(); } async function apiRequest(path: string, init?: RequestInit): Promise { const accessToken = await getAccessToken(); const response = await fetch(`${tradingRuntime.tradingApiUrl}${path}`, { ...init, headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${accessToken}`, 'x-request-id': createRequestId('web-profile'), ...(init?.headers || {}), }, }); const body = await response.json().catch(() => ({} as any)); if (!response.ok) { throw new Error(body?.error || `Request failed (${response.status})`); } return body as T; } function notifyProfilesUpdated() { if (typeof window !== 'undefined') { window.dispatchEvent(new Event('profiles-updated')); } } export async function fetchCurrentUserProfile(): Promise { const response = await apiRequest<{ profile: CurrentUserProfile }>('/api/me/profile'); return response.profile; } export async function updateCurrentUserProfile(payload: Partial): Promise { const response = await apiRequest<{ profile: CurrentUserProfile }>('/api/me/profile', { method: 'PATCH', body: JSON.stringify(payload), }); return response.profile; } export async function fetchTradeProfiles(options?: { ensureDefault?: boolean; scope?: 'user' | 'all' }): Promise { const params = new URLSearchParams(); if (options?.ensureDefault) { params.set('ensureDefault', 'true'); } if (options?.scope === 'all') { params.set('scope', 'all'); } const query = params.toString() ? `?${params.toString()}` : ''; const response = await apiRequest<{ profiles: TradeProfilePayload[] }>(`/api/profiles${query}`); return Array.isArray(response.profiles) ? response.profiles : []; } export async function createTradeProfile(payload: TradeProfilePayload): Promise { const response = await apiRequest<{ profile: TradeProfilePayload }>('/api/profiles', { method: 'POST', body: JSON.stringify(payload), }); notifyProfilesUpdated(); return response.profile; } export async function updateTradeProfile(id: string, payload: Partial): Promise { const response = await apiRequest<{ profile: TradeProfilePayload }>(`/api/profiles/${id}`, { method: 'PUT', body: JSON.stringify(payload), }); notifyProfilesUpdated(); return response.profile; } export async function setTradeProfileActive(id: string, isActive: boolean): Promise { const response = await apiRequest<{ profile: TradeProfilePayload }>(`/api/profiles/${id}/active`, { method: 'PATCH', body: JSON.stringify({ is_active: isActive }), }); notifyProfilesUpdated(); return response.profile; } export async function deleteTradeProfile(id: string): Promise { await apiRequest<{ success: boolean }>(`/api/profiles/${id}`, { method: 'DELETE', }); notifyProfilesUpdated(); }