Перейти к содержанию

Dashboard Endpoint

Аудитория: разработчики, frontend-инженеры Последнее обновление: 2025-11-17 Краткое содержание: Детальная документация Dashboard endpoint — получение полной сводки пользователя (баланс, активные инвестиции, недавние транзакции, notifications) в одном API вызове. Optimized для главной страницы user-app.


Обзор Endpoint

Метод Endpoint Описание Auth требуется
GET /api/user/dashboard Полная сводка dashboard пользователя ✅ Да

GET /api/user/dashboard

Получить полную dashboard информацию для аутентифицированного пользователя — баланс, инвестиции, транзакции, уведомления в одном запросе.

Запрос

GET /api/user/dashboard?includeCharts=true&period=30
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

Заголовки:

Заголовок Значение Обязательно Описание
Authorization Bearer <token> ✅ Да User JWT токен

Query параметры:

Параметр Тип Обязательно Описание По умолчанию
includeCharts boolean ❌ Нет Включить данные для графиков false
period number ❌ Нет Период для графиков в днях (7, 30, 90) 30
recentTransactions number ❌ Нет Количество недавних транзакций 5
recentNotifications number ❌ Нет Количество недавних уведомлений 3

Ответ

Успех (200 OK):

{
  "success": true,
  "data": {
    "user": {
      "id": 42,
      "email": "user@saga-test.com",
      "firstName": "John",
      "lastName": "Doe",
      "walletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0",
      "createdAt": "2025-09-01T00:00:00Z",
      "lastLoginAt": "2025-10-06T08:00:00Z"
    },
    "balance": {
      "total": "5000.00",
      "available": "2500.00",
      "invested": "2500.00",
      "currency": "USDC",
      "breakdown": {
        "deposits": "5000.00",
        "withdrawals": "0.00",
        "earnings": "150.50",
        "fees": "10.00"
      },
      "change24h": {
        "amount": "+50.25",
        "percentage": "+1.02%"
      }
    },
    "investments": {
      "active": [
        {
          "id": "inv_abc123",
          "strategyId": "balanced-10",
          "strategyName": "Balanced 10% APY",
          "amount": "1500.00",
          "currentValue": "1575.25",
          "apy": 10.0,
          "earnedToDate": "75.25",
          "startDate": "2025-09-15T00:00:00Z",
          "daysActive": 21,
          "performance": {
            "roi": "+5.02%",
            "dailyEarnings": "4.11"
          }
        },
        {
          "id": "inv_def456",
          "strategyId": "conservative-5",
          "strategyName": "Conservative 5% APY",
          "amount": "1000.00",
          "currentValue": "1025.00",
          "apy": 5.0,
          "earnedToDate": "25.00",
          "startDate": "2025-09-20T00:00:00Z",
          "daysActive": 16,
          "performance": {
            "roi": "+2.50%",
            "dailyEarnings": "1.37"
          }
        }
      ],
      "summary": {
        "totalInvested": "2500.00",
        "totalCurrentValue": "2600.25",
        "totalEarnings": "100.25",
        "averageAPY": 7.5,
        "totalROI": "+4.01%"
      }
    },
    "recentTransactions": [
      {
        "id": "txn_abc123",
        "type": "deposit",
        "amount": "1000.00",
        "currency": "USDC",
        "status": "completed",
        "createdAt": "2025-10-06T10:00:00Z"
      },
      {
        "id": "txn_def456",
        "type": "investment",
        "amount": "500.00",
        "currency": "USDC",
        "status": "completed",
        "strategyName": "Balanced 10% APY",
        "createdAt": "2025-10-06T11:00:00Z"
      },
      {
        "id": "txn_ghi789",
        "type": "earning",
        "amount": "5.50",
        "currency": "USDC",
        "status": "completed",
        "strategyName": "Balanced 10% APY",
        "createdAt": "2025-10-06T12:00:00Z"
      }
    ],
    "recentNotifications": [
      {
        "id": "notif_abc123",
        "type": "investment",
        "title": "Инвестиция успешно создана",
        "message": "Ваша инвестиция в стратегию Balanced (10% APY) на сумму $500.00 успешно создана",
        "isRead": false,
        "createdAt": "2025-10-06T12:00:00Z"
      },
      {
        "id": "notif_def456",
        "type": "earning",
        "title": "Получена доходность",
        "message": "Вы получили $5.50 доходности от стратегии Balanced (10% APY)",
        "isRead": true,
        "createdAt": "2025-10-06T00:00:05Z"
      }
    ],
    "portfolio": {
      "totalValue": "5000.00",
      "profitLoss": "+150.50",
      "profitLossPercentage": "+3.10%",
      "bestPerformer": {
        "strategy": "Balanced 10% APY",
        "roi": "+5.02%"
      },
      "assetAllocation": [
        {
          "category": "Stablecoins",
          "amount": "2500.00",
          "percentage": 50.0
        },
        {
          "category": "DeFi Strategies",
          "amount": "2500.00",
          "percentage": 50.0
        }
      ]
    },
    "charts": {
      "portfolioValue": [
        { "date": "2025-09-06", "value": "5000.00" },
        { "date": "2025-09-13", "value": "5025.50" },
        { "date": "2025-09-20", "value": "5050.25" },
        { "date": "2025-09-27", "value": "5100.00" },
        { "date": "2025-10-04", "value": "5150.50" }
      ],
      "earningsHistory": [
        { "date": "2025-09-06", "earnings": "0.00" },
        { "date": "2025-09-13", "earnings": "25.50" },
        { "date": "2025-09-20", "earnings": "50.25" },
        { "date": "2025-09-27", "earnings": "100.00" },
        { "date": "2025-10-04", "earnings": "150.50" }
      ],
      "investmentDistribution": [
        { "strategy": "Balanced 10% APY", "amount": "1500.00", "percentage": 60.0 },
        { "strategy": "Conservative 5% APY", "amount": "1000.00", "percentage": 40.0 }
      ]
    },
    "quickActions": [
      {
        "action": "deposit",
        "label": "Пополнить баланс",
        "url": "/deposits",
        "enabled": true
      },
      {
        "action": "invest",
        "label": "Создать инвестицию",
        "url": "/investments/create",
        "enabled": true
      },
      {
        "action": "withdraw",
        "label": "Вывести средства",
        "url": "/withdrawals/create",
        "enabled": true,
        "requiresApproval": true
      }
    ],
    "systemStatus": {
      "blockchain": "healthy",
      "database": "healthy",
      "api": "healthy",
      "lastUpdate": "2025-10-06T12:34:56Z"
    }
  },
  "timestamp": "2025-10-06T12:34:56Z"
}

Секции ответа:

user

Информация о пользователе: - id, email, firstName, lastName - walletAddress - Ethereum адрес - createdAt, lastLoginAt - Timestamps активности

balance

Финансовая сводка: - total - Общий баланс (available + invested) - available - Доступно для инвестиций/вывода - invested - Заблокировано в стратегиях - breakdown - Детали (deposits, withdrawals, earnings, fees) - change24h - Изменение за последние 24 часа

investments

Активные инвестиции: - active[] - Список активных инвестиций с performance - summary - Агрегированная статистика (total invested, earnings, ROI) - Каждая инвестиция включает currentValue, apy, earnedToDate, performance.roi

recentTransactions

Последние N транзакций (по умолчанию 5): - type - deposit, investment, earning, withdrawal, fee - amount, currency, status - strategyName - Для investment/earning операций

recentNotifications

Последние N уведомлений (по умолчанию 3): - type - investment, earning, withdrawal, security, system - title, message, isRead

portfolio

Портфолио сводка: - totalValue - Общая стоимость портфолио - profitLoss - Profit/Loss в абсолютных числах - profitLossPercentage - Profit/Loss в процентах - bestPerformer - Лучшая стратегия - assetAllocation - Распределение активов

charts (опционально)

Данные для графиков (если includeCharts=true): - portfolioValue[] - История стоимости портфолио - earningsHistory[] - История заработка - investmentDistribution[] - Распределение инвестиций

quickActions

Быстрые действия для UI: - action - deposit, invest, withdraw - label - Текст кнопки - url - Путь навигации - enabled - Доступность действия

systemStatus

Статус системы: - blockchain, database, api - healthy/degraded/down - lastUpdate - Timestamp последнего обновления

Ошибки:

Код статуса Код ошибки Описание
401 TOKEN_EXPIRED JWT токен истёк
401 TOKEN_INVALID Некорректная JWT подпись
404 USER_NOT_FOUND Аккаунт пользователя не существует
503 PARTIAL_DATA_AVAILABLE Часть данных недоступна (blockchain/database проблемы)

Пример cURL

TOKEN="eyJhbGciOiJIUzI1NiIs..."

# Получить полный dashboard
curl -X GET "https://app.saga.surf/api/user/dashboard" \
  -H "Authorization: Bearer $TOKEN"

# Получить dashboard с графиками за 30 дней
curl -X GET "https://app.saga.surf/api/user/dashboard?includeCharts=true&period=30" \
  -H "Authorization: Bearer $TOKEN"

Пример TypeScript

// Загрузить dashboard данные
async function loadDashboard(includeCharts: boolean = false, period: number = 30) {
  const params = new URLSearchParams({
    includeCharts: includeCharts.toString(),
    period: period.toString()
  });

  const response = await fetch(`/api/user/dashboard?${params}`, {
    headers: {
      'Authorization': `Bearer ${token}`
    }
  });

  const { data } = await response.json();
  return data;
}

// Отрисовать dashboard
async function renderDashboard() {
  const dashboard = await loadDashboard(true, 30);

  // Отобразить баланс
  document.getElementById('total-balance').textContent = `$${dashboard.balance.total}`;
  document.getElementById('available-balance').textContent = `$${dashboard.balance.available}`;
  document.getElementById('invested-balance').textContent = `$${dashboard.balance.invested}`;

  // Отобразить изменение за 24ч
  const change24h = document.getElementById('change-24h');
  change24h.textContent = `${dashboard.balance.change24h.amount} (${dashboard.balance.change24h.percentage})`;
  change24h.className = dashboard.balance.change24h.amount.startsWith('+') ? 'positive' : 'negative';

  // Отобразить активные инвестиции
  const investmentsList = document.getElementById('active-investments');
  dashboard.investments.active.forEach(inv => {
    const item = document.createElement('div');
    item.innerHTML = `
      <h3>${inv.strategyName}</h3>
      <p>Amount: $${inv.amount} → $${inv.currentValue}</p>
      <p>ROI: ${inv.performance.roi} | APY: ${inv.apy}%</p>
      <p>Daily Earnings: $${inv.performance.dailyEarnings}</p>
    `;
    investmentsList.appendChild(item);
  });

  // Отобразить график портфолио
  if (dashboard.charts) {
    renderPortfolioChart(dashboard.charts.portfolioValue);
    renderEarningsChart(dashboard.charts.earningsHistory);
  }
}

Распространённые сценарии использования

Dashboard компонент React

import { useEffect, useState } from 'react';

function Dashboard() {
  const [dashboard, setDashboard] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    loadDashboardData();
  }, []);

  async function loadDashboardData() {
    try {
      const response = await fetch('/api/user/dashboard?includeCharts=true&period=30', {
        headers: { 'Authorization': `Bearer ${token}` }
      });
      const { data } = await response.json();
      setDashboard(data);
    } catch (error) {
      console.error('Failed to load dashboard:', error);
    } finally {
      setLoading(false);
    }
  }

  if (loading) return <LoadingSpinner />;
  if (!dashboard) return <ErrorMessage />;

  return (
    <div className="dashboard">
      {/* Balance Card */}
      <div className="balance-card">
        <h2>Общий баланс</h2>
        <div className="amount">${dashboard.balance.total} {dashboard.balance.currency}</div>
        <div className={`change ${dashboard.balance.change24h.amount.startsWith('+') ? 'positive' : 'negative'}`}>
          {dashboard.balance.change24h.amount} ({dashboard.balance.change24h.percentage}) за 24ч
        </div>
        <div className="breakdown">
          <span>Доступно: ${dashboard.balance.available}</span>
          <span>Инвестировано: ${dashboard.balance.invested}</span>
        </div>
      </div>

      {/* Investments Summary */}
      <div className="investments-summary">
        <h2>Активные инвестиции</h2>
        <div className="summary">
          <p>Всего заработано: +${dashboard.investments.summary.totalEarnings}</p>
          <p>Средний APY: {dashboard.investments.summary.averageAPY}%</p>
          <p>ROI: {dashboard.investments.summary.totalROI}</p>
        </div>
        {dashboard.investments.active.map(inv => (
          <InvestmentCard key={inv.id} investment={inv} />
        ))}
      </div>

      {/* Recent Activity */}
      <div className="recent-activity">
        <h2>Недавние транзакции</h2>
        {dashboard.recentTransactions.map(tx => (
          <TransactionItem key={tx.id} transaction={tx} />
        ))}
      </div>

      {/* Notifications */}
      <div className="notifications">
        <h2>Уведомления</h2>
        {dashboard.recentNotifications.map(notif => (
          <NotificationItem key={notif.id} notification={notif} />
        ))}
      </div>

      {/* Charts */}
      {dashboard.charts && (
        <>
          <PortfolioValueChart data={dashboard.charts.portfolioValue} />
          <EarningsHistoryChart data={dashboard.charts.earningsHistory} />
        </>
      )}

      {/* Quick Actions */}
      <div className="quick-actions">
        {dashboard.quickActions.map(action => (
          <button
            key={action.action}
            onClick={() => router.push(action.url)}
            disabled={!action.enabled}
          >
            {action.label}
          </button>
        ))}
      </div>
    </div>
  );
}

Performance optimization с SWR

import useSWR from 'swr';

function useDashboard(includeCharts = true, period = 30) {
  const fetcher = (url: string) =>
    fetch(url, {
      headers: { 'Authorization': `Bearer ${token}` }
    }).then(r => r.json()).then(d => d.data);

  const { data, error, mutate } = useSWR(
    `/api/user/dashboard?includeCharts=${includeCharts}&period=${period}`,
    fetcher,
    {
      revalidateOnFocus: true,
      refreshInterval: 60000, // Обновление каждые 60 секунд
    }
  );

  return {
    dashboard: data,
    isLoading: !error && !data,
    isError: error,
    refresh: mutate
  };
}

// Использование
function DashboardWithSWR() {
  const { dashboard, isLoading, refresh } = useDashboard(true, 30);

  if (isLoading) return <Spinner />;

  return (
    <div>
      <button onClick={refresh}>Обновить</button>
      <DashboardContent data={dashboard} />
    </div>
  );
}

Partial data handling

// Graceful degradation при partial data
async function loadDashboardWithFallback() {
  try {
    const response = await fetch('/api/user/dashboard', {
      headers: { 'Authorization': `Bearer ${token}` }
    });

    if (response.status === 503) {
      // Partial data available
      const { data, warning } = await response.json();
      console.warn('Dashboard loaded with partial data:', warning);

      // Отобразить что доступно с индикацией проблем
      return {
        ...data,
        hasWarnings: true,
        warningMessage: warning
      };
    }

    const { data } = await response.json();
    return data;
  } catch (error) {
    console.error('Failed to load dashboard:', error);
    throw error;
  }
}

Связанная документация

Другие User Endpoints:

Архитектура:




📋 Метаданные

Версия: 2.6.268

Обновлено: 2025-10-21

Статус: Published