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

Транзакции (Transaction Endpoints)

Аудитория: разработчики, frontend инженеры Последнее обновление: 2025-11-17 Краткое содержание: Полная документация Transaction endpoints — история транзакций пользователей, административное управление транзакциями, одобрение, подтверждение, генерация и выполнение переводов. Включает 12 реальных backend endpoints (2 user + 10 admin) с comprehensive примерами React интеграции.



Обзор endpoints

User Endpoints

Метод Endpoint Описание Требуется Auth
GET /api/user/transactions История транзакций пользователя ✅ Да
GET /api/user/transactions/:id Детали конкретной транзакции ✅ Да

Admin Endpoints

Метод Endpoint Описание Требуется Auth
GET /api/admin/transactions Список всех транзакций ✅ Да (Admin)
POST /api/admin/transactions Создать транзакцию ✅ Да (Admin)
GET /api/admin/transactions/:id Детали транзакции ✅ Да (Admin)
POST /api/admin/transactions/:id/approve Одобрить транзакцию ✅ Да (Admin)
POST /api/admin/transactions/:id/reject Отклонить транзакцию ✅ Да (Admin)
POST /api/admin/transactions/:id/confirm Подтвердить транзакцию ✅ Да (Admin)
POST /api/admin/transactions/generate Генерация transfer транзакций ✅ Да (Admin)
POST /api/admin/transactions/execute Выполнение investment transfers ✅ Да (Admin)
GET /api/admin/transaction-requests Список заявок на переводы ✅ Да (Admin)
POST /api/admin/transaction-requests/:id/complete Завершить заявку на перевод ✅ Да (Admin)

User Endpoints

GET /api/user/transactions

Получить историю транзакций пользователя с фильтрацией и пагинацией.

Запрос

GET /api/user/transactions?status=confirmed&type=deposit&page=1&limit=20
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

Заголовки:

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

Query параметры:

Параметр Тип Обязательно Описание По умолчанию
status string ❌ Нет Фильтр по статусу: pending, confirmed, failed, processing Все
type string ❌ Нет Тип транзакции: deposit, withdrawal, transfer, investment, reversal Все
page number ❌ Нет Номер страницы 1
limit number ❌ Нет Количество записей на странице (max 100) 100

Ответ

Успех (200 OK):

{
  "success": true,
  "data": {
    "transactions": [
      {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "userID": "123e4567-e89b-12d3-a456-426614174000",
        "type": "deposit",
        "amount": "1000.00",
        "currency": "USDC",
        "status": "confirmed",
        "transactionHash": "0x1234567890abcdef...",
        "blockNumber": 18234567,
        "confirmations": 12,
        "createdAt": "2025-10-01T10:30:00Z",
        "confirmedAt": "2025-10-01T10:35:00Z"
      },
      {
        "id": "660e9500-e29b-41d4-a716-446655440111",
        "userID": "123e4567-e89b-12d3-a456-426614174000",
        "type": "withdrawal",
        "amount": "250.00",
        "currency": "USDC",
        "status": "pending",
        "transactionHash": null,
        "blockNumber": null,
        "confirmations": 0,
        "createdAt": "2025-10-05T14:20:00Z",
        "confirmedAt": null
      }
    ],
    "total": 42,
    "page": 1,
    "limit": 20,
    "totalPages": 3
  },
  "timestamp": "2025-10-06T12:34:56Z"
}

Поля ответа:

Поле Тип Описание
data.transactions[] array Массив транзакций пользователя
data.transactions[].id string UUID транзакции
data.transactions[].type string Тип транзакции
data.transactions[].amount string Сумма транзакции (SafeDecimal)
data.transactions[].currency string Валюта (USDC, ETH, USD)
data.transactions[].status string Статус транзакции
data.transactions[].transactionHash string|null Blockchain transaction hash (если есть)
data.transactions[].blockNumber number|null Номер блока в blockchain
data.transactions[].confirmations number Количество подтверждений блока
data.transactions[].createdAt string Дата создания (ISO 8601)
data.transactions[].confirmedAt string|null Дата подтверждения (ISO 8601)
data.total number Общее количество транзакций
data.page number Текущая страница
data.limit number Записей на странице
data.totalPages number Всего страниц

Типы транзакций:

Тип Описание Направление
deposit Пополнение баланса Incoming
withdrawal Вывод средств Outgoing
transfer Внутренний перевод Internal
investment Инвестирование Outgoing
reversal Отмена/возврат транзакции Incoming

Статусы транзакций:

Статус Описание
pending Транзакция создана, ожидает обработки
processing Транзакция обрабатывается
confirmed Транзакция подтверждена и завершена
failed Транзакция не удалась

Ошибки:

Код статуса Код ошибки Описание
401 TOKEN_EXPIRED JWT токен истёк
401 TOKEN_INVALID Неверная подпись JWT
400 INVALID_LIMIT Limit превышает максимум (100)
400 INVALID_PAGE Некорректное значение page

Пример cURL

TOKEN="eyJhbGciOiJIUzI1NiIs..."

# Получить все транзакции
curl -X GET https://app.saga.surf/api/user/transactions \
  -H "Authorization: Bearer $TOKEN"

# Фильтр по статусу
curl -X GET "https://app.saga.surf/api/user/transactions?status=confirmed" \
  -H "Authorization: Bearer $TOKEN"

# Фильтр по типу и пагинация
curl -X GET "https://app.saga.surf/api/user/transactions?type=deposit&page=1&limit=10" \
  -H "Authorization: Bearer $TOKEN"

Пример TypeScript

interface Transaction {
  id: string;
  userID: string;
  type: 'deposit' | 'withdrawal' | 'transfer' | 'investment' | 'reversal';
  amount: string;
  currency: string;
  status: 'pending' | 'processing' | 'confirmed' | 'failed';
  transactionHash: string | null;
  blockNumber: number | null;
  confirmations: number;
  createdAt: string;
  confirmedAt: string | null;
}

interface TransactionsResponse {
  transactions: Transaction[];
  total: number;
  page: number;
  limit: number;
  totalPages: number;
}

const fetchTransactions = async (
  filters: {
    status?: string;
    type?: string;
    page?: number;
    limit?: number;
  } = {}
): Promise<TransactionsResponse> => {
  const token = localStorage.getItem('saga_access_token');

  const params = new URLSearchParams();
  if (filters.status) params.append('status', filters.status);
  if (filters.type) params.append('type', filters.type);
  if (filters.page) params.append('page', filters.page.toString());
  if (filters.limit) params.append('limit', filters.limit.toString());

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

  if (!response.ok) {
    throw new Error(`Failed to fetch transactions: ${response.statusText}`);
  }

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

// Использование
const transactions = await fetchTransactions({
  status: 'confirmed',
  page: 1,
  limit: 20
});

console.log(`Найдено ${transactions.total} транзакций`);
transactions.transactions.forEach(tx => {
  console.log(`${tx.type}: ${tx.amount} ${tx.currency} - ${tx.status}`);
});

GET /api/user/transactions/:id

Получить детальную информацию о конкретной транзакции.

Запрос

GET /api/user/transactions/550e8400-e29b-41d4-a716-446655440000
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

Path параметры:

Параметр Тип Обязательно Описание
id string ✅ Да UUID транзакции

Ответ

Успех (200 OK):

{
  "success": true,
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "userID": "123e4567-e89b-12d3-a456-426614174000",
    "type": "deposit",
    "amount": "1000.00",
    "currency": "USDC",
    "status": "confirmed",
    "transactionHash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
    "blockNumber": 18234567,
    "confirmations": 24,
    "fromAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
    "toAddress": "0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199",
    "gasUsed": "21000",
    "gasPrice": "50",
    "createdAt": "2025-10-01T10:30:00Z",
    "confirmedAt": "2025-10-01T10:35:00Z"
  },
  "timestamp": "2025-10-06T12:34:56Z"
}

Поля ответа:

Поле Тип Описание
data.fromAddress string|null Адрес отправителя
data.toAddress string|null Адрес получателя
data.gasUsed string|null Использованный gas (wei)
data.gasPrice string|null Цена gas (gwei)

Ошибки:

Код статуса Код ошибки Описание
404 TRANSACTION_NOT_FOUND Транзакция не найдена
403 FORBIDDEN Транзакция принадлежит другому пользователю
401 TOKEN_EXPIRED JWT токен истёк

Пример cURL

TOKEN="eyJhbGciOiJIUzI1NiIs..."
TX_ID="550e8400-e29b-41d4-a716-446655440000"

curl -X GET "https://app.saga.surf/api/user/transactions/${TX_ID}" \
  -H "Authorization: Bearer $TOKEN"

Пример TypeScript

const getTransactionDetails = async (transactionId: string): Promise<Transaction> => {
  const token = localStorage.getItem('saga_access_token');

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

  if (!response.ok) {
    if (response.status === 404) {
      throw new Error('Transaction not found');
    }
    throw new Error(`Failed to fetch transaction: ${response.statusText}`);
  }

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

// Использование
const transaction = await getTransactionDetails('550e8400-e29b-41d4-a716-446655440000');
console.log(`Transaction ${transaction.id}: ${transaction.amount} ${transaction.currency}`);
if (transaction.transactionHash) {
  console.log(`Blockchain TX: ${transaction.transactionHash}`);
  console.log(`Confirmations: ${transaction.confirmations}`);
}

Admin Endpoints

GET /api/admin/transactions

Получить список всех транзакций в системе с фильтрацией.

Требуется роль: Admin

Запрос

GET /api/admin/transactions?status=pending&user_id=123e4567-e89b-12d3-a456-426614174000
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

Query параметры:

Параметр Тип Обязательно Описание По умолчанию
status string ❌ Нет Фильтр по статусу Все
user_id string ❌ Нет Фильтр по пользователю (UUID) Все
type string ❌ Нет Фильтр по типу транзакции Все
page number ❌ Нет Номер страницы 1
limit number ❌ Нет Записей на странице (max 100) API default

Ответ

Успех (200 OK):

{
  "success": true,
  "data": {
    "transactions": [
      {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "userID": "123e4567-e89b-12d3-a456-426614174000",
        "userEmail": "user@example.com",
        "type": "withdrawal",
        "amount": "500.00",
        "currency": "USDC",
        "status": "pending",
        "createdAt": "2025-10-06T10:00:00Z",
        "processedAt": null
      }
    ],
    "total": 128,
    "page": 1,
    "limit": 20,
    "totalPages": 7
  },
  "timestamp": "2025-10-06T12:34:56Z"
}

Дополнительные поля (vs user endpoint):

Поле Тип Описание
data.transactions[].userEmail string Email пользователя
data.transactions[].processedAt string|null Время обработки администратором

Пример cURL

ADMIN_TOKEN="eyJhbGciOiJIUzI1NiIs..."

# Все pending транзакции
curl -X GET "https://admin.saga.surf/api/admin/transactions?status=pending" \
  -H "Authorization: Bearer $ADMIN_TOKEN"

# Транзакции конкретного пользователя
curl -X GET "https://admin.saga.surf/api/admin/transactions?user_id=123e4567-e89b-12d3-a456-426614174000" \
  -H "Authorization: Bearer $ADMIN_TOKEN"

Пример TypeScript

const fetchAdminTransactions = async (filters: {
  status?: string;
  user_id?: string;
  type?: string;
  page?: number;
  limit?: number;
} = {}): Promise<TransactionsResponse> => {
  const adminToken = localStorage.getItem('admin_auth_token');

  const params = new URLSearchParams();
  Object.entries(filters).forEach(([key, value]) => {
    if (value !== undefined) params.append(key, value.toString());
  });

  const response = await fetch(`/api/admin/transactions?${params}`, {
    headers: {
      'Authorization': `Bearer ${adminToken}`
    }
  });

  if (!response.ok) {
    throw new Error(`Failed to fetch transactions: ${response.statusText}`);
  }

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

POST /api/admin/transactions

Создать новую транзакцию (для интеграционных тестов и admin операций).

Требуется роль: Admin

Запрос

POST /api/admin/transactions
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Content-Type: application/json

{
  "userID": "123e4567-e89b-12d3-a456-426614174000",
  "walletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
  "amount": "1000.00",
  "currency": "USDC",
  "txHash": "0x1234567890abcdef...",
  "type": "deposit",
  "status": "confirmed"
}

Тело запроса:

Поле Тип Обязательно Описание
userID string ✅ Да UUID пользователя
walletAddress string ❌ Нет Ethereum адрес кошелька (42 символа)
amount string ✅ Да Сумма транзакции (SafeDecimal string)
currency string ✅ Да Валюта: USDC, ETH, USD
txHash string ❌ Нет Blockchain transaction hash
type string ✅ Да Тип: deposit, withdrawal, transfer, investment, reversal
status string ❌ Нет Статус: pending, confirmed, failed, processing (default: failed для безопасности)

Ответ

Успех (201 Created):

{
  "success": true,
  "data": {
    "id": "770e9600-e29b-41d4-a716-446655440222",
    "userID": "123e4567-e89b-12d3-a456-426614174000",
    "type": "deposit",
    "amount": "1000.00",
    "currency": "USDC",
    "status": "confirmed",
    "transactionHash": "0x1234567890abcdef...",
    "createdAt": "2025-10-06T12:34:56Z"
  },
  "timestamp": "2025-10-06T12:34:56Z"
}

Ошибки:

Код статуса Код ошибки Описание
400 USER_ID_REQUIRED UserID не предоставлен
400 AMOUNT_REQUIRED Amount не предоставлен
400 INVALID_AMOUNT_FORMAT Некорректный формат суммы
400 CURRENCY_REQUIRED Currency не предоставлена
400 INVALID_CURRENCY Неподдерживаемая валюта
400 TYPE_REQUIRED Тип транзакции не указан
400 INVALID_TRANSACTION_TYPE Неподдерживаемый тип
400 INVALID_WALLET_ADDRESS Некорректный формат адреса кошелька
401 UNAUTHORIZED Требуется Admin токен
403 FORBIDDEN Недостаточно прав

Пример cURL

ADMIN_TOKEN="eyJhbGciOiJIUzI1NiIs..."

curl -X POST https://admin.saga.surf/api/admin/transactions \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "userID": "123e4567-e89b-12d3-a456-426614174000",
    "amount": "1000.00",
    "currency": "USDC",
    "type": "deposit",
    "status": "confirmed"
  }'

Пример TypeScript

interface CreateTransactionRequest {
  userID: string;
  walletAddress?: string;
  amount: string;
  currency: string;
  txHash?: string;
  type: 'deposit' | 'withdrawal' | 'transfer' | 'investment' | 'reversal';
  status?: 'pending' | 'confirmed' | 'failed' | 'processing';
}

const createTransaction = async (
  request: CreateTransactionRequest
): Promise<Transaction> => {
  const adminToken = localStorage.getItem('admin_auth_token');

  const response = await fetch('/api/admin/transactions', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${adminToken}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(request)
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(error.message || 'Failed to create transaction');
  }

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

// Использование
const transaction = await createTransaction({
  userID: '123e4567-e89b-12d3-a456-426614174000',
  amount: '1000.00',
  currency: 'USDC',
  type: 'deposit',
  status: 'confirmed'
});

console.log(`Создана транзакция ${transaction.id}`);

GET /api/admin/transactions/:id

Получить детали конкретной транзакции (admin view с дополнительной информацией).

Требуется роль: Admin

Запрос

GET /api/admin/transactions/550e8400-e29b-41d4-a716-446655440000
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

Path параметры:

Параметр Тип Обязательно Описание
id string ✅ Да UUID транзакции

Ответ

Успех (200 OK):

{
  "success": true,
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "userID": "123e4567-e89b-12d3-a456-426614174000",
    "userEmail": "user@example.com",
    "type": "withdrawal",
    "amount": "500.00",
    "currency": "USDC",
    "status": "confirmed",
    "transactionHash": "0x9876543210fedcba...",
    "blockNumber": 18234890,
    "confirmations": 15,
    "fromAddress": "0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199",
    "toAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
    "createdAt": "2025-10-06T10:00:00Z",
    "confirmedAt": "2025-10-06T10:05:00Z",
    "processedBy": "admin-uuid-456",
    "notes": "Одобрено после проверки"
  },
  "timestamp": "2025-10-06T12:34:56Z"
}

Дополнительные admin поля:

Поле Тип Описание
data.userEmail string Email пользователя
data.processedBy string|null UUID администратора
data.notes string|null Заметки администратора

Пример cURL

ADMIN_TOKEN="eyJhbGciOiJIUzI1NiIs..."
TX_ID="550e8400-e29b-41d4-a716-446655440000"

curl -X GET "https://admin.saga.surf/api/admin/transactions/${TX_ID}" \
  -H "Authorization: Bearer $ADMIN_TOKEN"

POST /api/admin/transactions/:id/approve

Одобрить pending транзакцию.

Требуется роль: Admin

Запрос

POST /api/admin/transactions/550e8400-e29b-41d4-a716-446655440000/approve
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

Path параметры:

Параметр Тип Обязательно Описание
id string ✅ Да UUID транзакции

Ответ

Успех (200 OK):

{
  "success": true,
  "data": {
    "transactionID": "550e8400-e29b-41d4-a716-446655440000",
    "status": "approved",
    "approvedBy": "admin-uuid-123",
    "approvedAt": "2025-10-06T12:34:56Z",
    "notes": "Одобрено администратором"
  },
  "timestamp": "2025-10-06T12:34:56Z"
}

Ошибки:

Код статуса Код ошибки Описание
400 TRANSACTION_NOT_PENDING Транзакция не в статусе pending
404 TRANSACTION_NOT_FOUND Транзакция не найдена
401 UNAUTHORIZED Требуется Admin токен

Пример cURL

ADMIN_TOKEN="eyJhbGciOiJIUzI1NiIs..."
TX_ID="550e8400-e29b-41d4-a716-446655440000"

curl -X POST "https://admin.saga.surf/api/admin/transactions/${TX_ID}/approve" \
  -H "Authorization: Bearer $ADMIN_TOKEN"

Пример TypeScript

const approveTransaction = async (transactionId: string): Promise<void> => {
  const adminToken = localStorage.getItem('admin_auth_token');

  const response = await fetch(`/api/admin/transactions/${transactionId}/approve`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${adminToken}`
    }
  });

  if (!response.ok) {
    throw new Error('Failed to approve transaction');
  }

  const { data } = await response.json();
  console.log(`Транзакция ${data.transactionID} одобрена`);
};

POST /api/admin/transactions/:id/reject

Отклонить pending транзакцию.

Требуется роль: Admin

Запрос

POST /api/admin/transactions/550e8400-e29b-41d4-a716-446655440000/reject
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

Ответ

Успех (200 OK):

{
  "success": true,
  "data": {
    "transactionID": "550e8400-e29b-41d4-a716-446655440000",
    "status": "rejected",
    "rejectedBy": "admin-uuid-123",
    "rejectedAt": "2025-10-06T12:34:56Z",
    "reason": "Отклонено администратором"
  },
  "timestamp": "2025-10-06T12:34:56Z"
}

Пример cURL

ADMIN_TOKEN="eyJhbGciOiJIUzI1NiIs..."
TX_ID="550e8400-e29b-41d4-a716-446655440000"

curl -X POST "https://admin.saga.surf/api/admin/transactions/${TX_ID}/reject" \
  -H "Authorization: Bearer $ADMIN_TOKEN"

POST /api/admin/transactions/:id/confirm

Подтвердить транзакцию с blockchain transaction hash.

Требуется роль: Admin

Запрос

POST /api/admin/transactions/550e8400-e29b-41d4-a716-446655440000/confirm
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Content-Type: application/json

{
  "txHash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
}

Тело запроса:

Поле Тип Обязательно Описание
txHash string ✅ Да Blockchain transaction hash для подтверждения

Ответ

Успех (200 OK):

{
  "success": true,
  "data": {
    "transactionID": "550e8400-e29b-41d4-a716-446655440000",
    "txHash": "0x1234567890abcdef...",
    "status": "confirmed",
    "confirmedBy": "admin-uuid-123",
    "confirmedAt": "2025-10-06T12:34:56Z",
    "message": "Транзакция подтверждена и связанный withdrawal автоматически завершен"
  },
  "timestamp": "2025-10-06T12:34:56Z"
}

Ошибки:

Код статуса Код ошибки Описание
400 TXHASH_REQUIRED TxHash не предоставлен
404 TRANSACTION_NOT_FOUND Транзакция не найдена

Пример cURL

ADMIN_TOKEN="eyJhbGciOiJIUzI1NiIs..."
TX_ID="550e8400-e29b-41d4-a716-446655440000"

curl -X POST "https://admin.saga.surf/api/admin/transactions/${TX_ID}/confirm" \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "txHash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
  }'

POST /api/admin/transactions/generate

Генерировать transfer транзакции для pending операций.

Требуется роль: Admin

Запрос

POST /api/admin/transactions/generate
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

Ответ

Успех (200 OK):

{
  "success": true,
  "data": {
    "generatedCount": 5,
    "batchSize": 10,
    "transactionIDs": [
      "880e9700-e29b-41d4-a716-446655440333",
      "990ea800-e29b-41d4-a716-446655440444"
    ]
  },
  "timestamp": "2025-10-06T12:34:56Z"
}

Пример cURL

ADMIN_TOKEN="eyJhbGciOiJIUzI1NiIs..."

curl -X POST https://admin.saga.surf/api/admin/transactions/generate \
  -H "Authorization: Bearer $ADMIN_TOKEN"

POST /api/admin/transactions/execute

Выполнить investment transfers для одобренных инвестиций.

Требуется роль: Admin

Запрос

POST /api/admin/transactions/execute
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

Ответ

Успех (200 OK):

{
  "success": true,
  "data": {
    "executedCount": 3,
    "maxBatchSize": 10,
    "totalAmount": "15000.00",
    "transactionIDs": [
      "aa0eb900-e29b-41d4-a716-446655440555"
    ]
  },
  "timestamp": "2025-10-06T12:34:56Z"
}

Пример cURL

ADMIN_TOKEN="eyJhbGciOiJIUzI1NiIs..."

curl -X POST https://admin.saga.surf/api/admin/transactions/execute \
  -H "Authorization: Bearer $ADMIN_TOKEN"

GET /api/admin/transaction-requests

Получить список заявок на переводы (для funds-transfer UI).

Требуется роль: Admin

Запрос

GET /api/admin/transaction-requests?status=pending&page=1&limit=20
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

Query параметры:

Параметр Тип Обязательно Описание
user_id string ❌ Нет Фильтр по пользователю
type string ❌ Нет Тип заявки
status string ❌ Нет Статус заявки
currency string ❌ Нет Фильтр по валюте
page number ❌ Нет Номер страницы
limit number ❌ Нет Записей на странице

Ответ

Успех (200 OK):

{
  "success": true,
  "data": {
    "transactionRequests": [
      {
        "id": "bb0ec000-e29b-41d4-a716-446655440666",
        "userID": "123e4567-e89b-12d3-a456-426614174000",
        "userEmail": "user@example.com",
        "type": "withdrawal",
        "fromAddress": "0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199",
        "toAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
        "amount": "500.00",
        "currency": "USDC",
        "status": "pending",
        "createdAt": "2025-10-06T10:00:00Z"
      }
    ],
    "total": 12,
    "page": 1,
    "limit": 20,
    "totalPages": 1
  },
  "timestamp": "2025-10-06T12:34:56Z"
}

Пример cURL

ADMIN_TOKEN="eyJhbGciOiJIUzI1NiIs..."

curl -X GET "https://admin.saga.surf/api/admin/transaction-requests?status=pending" \
  -H "Authorization: Bearer $ADMIN_TOKEN"

POST /api/admin/transaction-requests/:id/complete

Завершить заявку на перевод с blockchain transaction hash.

Требуется роль: Admin

Запрос

POST /api/admin/transaction-requests/bb0ec000-e29b-41d4-a716-446655440666/complete
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Content-Type: application/json

{
  "txHash": "0x1234567890abcdef...",
  "notes": "Перевод выполнен успешно"
}

Тело запроса:

Поле Тип Обязательно Описание
txHash string ✅ Да Blockchain transaction hash
notes string ❌ Нет Заметки администратора

Ответ

Успех (200 OK):

{
  "success": true,
  "data": {
    "requestID": "bb0ec000-e29b-41d4-a716-446655440666",
    "txHash": "0x1234567890abcdef...",
    "status": "completed",
    "completedBy": "admin-uuid-123"
  },
  "timestamp": "2025-10-06T12:34:56Z"
}

Ошибки:

Код статуса Код ошибки Описание
400 TXHASH_REQUIRED TxHash не предоставлен
404 REQUEST_NOT_FOUND Заявка не найдена

Пример cURL

ADMIN_TOKEN="eyJhbGciOiJIUzI1NiIs..."
REQUEST_ID="bb0ec000-e29b-41d4-a716-446655440666"

curl -X POST "https://admin.saga.surf/api/admin/transaction-requests/${REQUEST_ID}/complete" \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "txHash": "0x1234567890abcdef...",
    "notes": "Перевод выполнен успешно"
  }'

Use Cases

Use Case 1: Transaction History Component

Сценарий: Пользователь просматривает свою историю транзакций с фильтрацией

React Component:

import React, { useEffect, useState } from 'react';

interface Transaction {
  id: string;
  type: string;
  amount: string;
  currency: string;
  status: string;
  transactionHash: string | null;
  createdAt: string;
}

const TransactionHistory: React.FC = () => {
  const [transactions, setTransactions] = useState<Transaction[]>([]);
  const [loading, setLoading] = useState(true);
  const [filter, setFilter] = useState<string>('all');

  useEffect(() => {
    const fetchTransactions = async () => {
      try {
        const token = localStorage.getItem('saga_access_token');
        const params = filter !== 'all' ? `?status=${filter}` : '';

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

        const { data } = await response.json();
        setTransactions(data.transactions);
      } catch (error) {
        console.error('Failed to fetch transactions:', error);
      } finally {
        setLoading(false);
      }
    };

    fetchTransactions();
  }, [filter]);

  if (loading) return <div>Загрузка...</div>;

  const getStatusColor = (status: string) => {
    switch (status) {
      case 'confirmed': return 'text-green-600';
      case 'pending': return 'text-yellow-600';
      case 'failed': return 'text-red-600';
      default: return 'text-gray-600';
    }
  };

  const getTypeIcon = (type: string) => {
    switch (type) {
      case 'deposit': return '↓';
      case 'withdrawal': return '↑';
      case 'transfer': return '↔';
      case 'investment': return '💰';
      default: return '•';
    }
  };

  return (
    <div className="p-6">
      <div className="flex justify-between items-center mb-6">
        <h2 className="text-2xl font-bold">История транзакций</h2>

        <select
          value={filter}
          onChange={(e) => setFilter(e.target.value)}
          className="border rounded px-3 py-2"
        >
          <option value="all">Все</option>
          <option value="confirmed">Подтверждённые</option>
          <option value="pending">Ожидают</option>
          <option value="failed">Неудачные</option>
        </select>
      </div>

      <div className="space-y-3">
        {transactions.map(tx => (
          <div key={tx.id} className="border rounded-lg p-4 hover:shadow-md transition">
            <div className="flex justify-between items-start">
              <div className="flex items-start space-x-3">
                <span className="text-2xl">{getTypeIcon(tx.type)}</span>
                <div>
                  <h3 className="font-semibold capitalize">{tx.type}</h3>
                  <p className="text-sm text-gray-600">
                    {new Date(tx.createdAt).toLocaleDateString()}
                  </p>
                  {tx.transactionHash && (
                    <a
                      href={`https://etherscan.io/tx/${tx.transactionHash}`}
                      target="_blank"
                      rel="noopener noreferrer"
                      className="text-xs text-blue-500 hover:underline"
                    >
                      View on Etherscan
                    </a>
                  )}
                </div>
              </div>

              <div className="text-right">
                <div className="text-xl font-bold">
                  {tx.type === 'withdrawal' || tx.type === 'investment' ? '-' : '+'}
                  {tx.amount} {tx.currency}
                </div>
                <span className={`text-sm font-medium ${getStatusColor(tx.status)}`}>
                  {tx.status}
                </span>
              </div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
};

export default TransactionHistory;

Результат: Интерактивная история транзакций с фильтрацией, цветовым кодированием статусов и ссылками на blockchain explorer.




📋 Метаданные

Версия: 2.6.268

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

Статус: Published