Перейти к содержанию
Версия: 3.3.51 Обновлено: 2025-11-17

Deposits Endpoints

Краткое содержание: Детальная документация Deposit endpoints — получение депозитного адреса через Crypto2B API, история депозитов, webhook-обработка депозитов. Полная интеграция с внешними провайдерами.


Обзор Endpoints

Метод Endpoint Описание Auth требуется Интеграция
GET /api/user/deposits/address Получить персональный депозитный адрес (Crypto2B) ✅ Да Crypto2B API
GET /api/user/deposits История депозитов пользователя ✅ Да PostgreSQL
POST /api/webhooks/crypto2b/deposit Webhook обработка депозитов (Crypto2B → Saga) ❌ Нет Crypto2B Webhook
GET /api/deposits/status Публичный статус депозитов (без auth) ❌ Нет PostgreSQL

GET /api/user/deposits/address

Получить персональный депозитный адрес для пользователя через Crypto2B API интеграцию.

Запрос

GET /api/user/deposits/address?currency=USDT&network=TRC20
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

Заголовки:

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

Query параметры:

Параметр Тип Обязательно Описание По умолчанию
currency string ❌ Нет Валюта: USDT, USDC USDT
network string ❌ Нет Сеть: TRC20, ERC20, BEP20 TRC20

Ответ

Успех (200 OK):

{
  "success": true,
  "data": {
    "address": "TAuepQSzmUrXFkGYjHuPTTTrj2kVdCfhpy",
    "currency": "USDT",
    "network": "TRC20",
    "chainId": "TRON",
    "crypto2bProvider": "crypto2b.com",
    "crypto2bAddressId": "addr_c2b_abc123",
    "isExternal": true,
    "qrCode": "data:image/png;base64,iVBORw0KGgoAAAANSUhEU...",
    "contractAddress": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
    "minimumDeposit": "500.00",
    "estimatedConfirmations": 1,
    "memo": null,
    "expiresAt": "2025-11-21T12:34:56Z"
  },
  "timestamp": "2025-11-14T12:34:56Z"
}

Поля ответа:

Поле Тип Описание
data.address string Персональный депозитный адрес (генерируется Crypto2B)
data.currency string Валюта депозита (USDT, USDC)
data.network string Blockchain сеть (TRC20, ERC20, BEP20)
data.chainId string Chain ID или название сети
data.crypto2bProvider string Поставщик интеграции (crypto2b.com)
data.crypto2bAddressId string ID адреса в системе Crypto2B
data.isExternal boolean Внешняя интеграция (всегда true для Integration-Only)
data.qrCode string Base64 QR код для депозита
data.contractAddress string Contract address (для токенов)
data.minimumDeposit string Минимальная сумма депозита ($500 для MVP)
data.estimatedConfirmations number Требуемое количество confirmations
data.expiresAt string Срок действия адреса (optional)

Ошибки:

Код статуса Код ошибки Описание
401 TOKEN_EXPIRED JWT токен истёк
400 CURRENCY_NOT_SUPPORTED Валюта не поддерживается
400 NETWORK_NOT_SUPPORTED Сеть не поддерживается
503 CRYPTO2B_API_ERROR Ошибка интеграции с Crypto2B API
429 RATE_LIMIT_EXCEEDED Превышен лимит запросов на генерацию адресов

Пример cURL

TOKEN="eyJhbGciOiJIUzI1NiIs..."
curl -X GET "https://app.saga.surf/api/user/deposits/address?currency=USDT&network=TRC20" \
  -H "Authorization: Bearer $TOKEN"

Пример TypeScript

// Получить депозитный адрес через Crypto2B
async function getDepositAddress(currency: string = 'USDT', network: string = 'TRC20'): Promise<string> {
  const response = await fetch(`/api/user/deposits/address?currency=${currency}&network=${network}`, {
    headers: {
      'Authorization': `Bearer ${token}`
    }
  });

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

// Отобразить депозитную информацию с QR кодом
async function displayDepositInterface() {
  const response = await fetch('/api/user/deposits/address?currency=USDT&network=TRC20', {
    headers: { 'Authorization': `Bearer ${token}` }
  });

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

  // Отобразить QR код
  const qrImage = document.getElementById('deposit-qr');
  qrImage.src = data.qrCode;

  // Показать адрес для копирования
  document.getElementById('deposit-address').textContent = data.address;
  document.getElementById('min-deposit').textContent = `Min: $${data.minimumDeposit} ${data.currency}`;

  // Показать информацию о провайдере
  document.getElementById('provider-info').textContent = `Powered by ${data.crypto2bProvider}`;

  // Инструкции для пользователей
  document.getElementById('instructions').innerHTML = `
    <p>🚨 ВАЖНО: Отправляйте ТОЛЬКО ${data.currency} через сеть ${data.network}</p>
    <p>📱 Используйте любой криптокошелек для отправки средств</p>
    <p>⚡ Минимальная сумма: $${data.minimumDeposit}</p>
    <p>🕒 Обработка: до 2-4 часов после ${data.estimatedConfirmations} подтверждений</p>
  `;
}

📜 GET /api/user/deposits

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

Запрос

GET /api/user/deposits?page=1&limit=20&status=completed&sortBy=createdAt&orderBy=desc
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

Заголовки:

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

Query параметры:

Параметр Тип Обязательно Описание По умолчанию
page number ❌ Нет Номер страницы (с 1) 1
limit number ❌ Нет Элементов на странице (макс: 100) 20
status string ❌ Нет Фильтр по статусу: pending, confirming, completed, failed Все статусы
currency string ❌ Нет Фильтр по валюте: USDC, ETH Все валюты
sortBy string ❌ Нет Поле сортировки: createdAt, amount, confirmations createdAt
orderBy string ❌ Нет Порядок сортировки: asc, desc desc
startDate string ❌ Нет Фильтр от даты (ISO 8601) -
endDate string ❌ Нет Фильтр до даты (ISO 8601) -

Ответ

Успех (200 OK):

{
  "success": true,
  "data": [
    {
      "id": "dep_abc123",
      "userId": 42,
      "amount": "1000.00",
      "currency": "USDC",
      "status": "completed",
      "fromAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0",
      "toAddress": "0x9876543210abcdef0123456789abcdef01234567",
      "txHash": "0xabcdef123456789...",
      "blockNumber": 1234567,
      "confirmations": 15,
      "requiredConfirmations": 12,
      "network": "TRON",
      "chainId": "TRC20",
      "gasUsed": null,
      "gasFee": "0.005 ETH",
      "createdAt": "2025-10-06T10:00:00Z",
      "confirmedAt": "2025-10-06T10:03:00Z",
      "metadata": {
        "depositAddress": "0x9876543210abcdef0123456789abcdef01234567",
        "derivationPath": "m/44'/60'/0'/0/5",
        "contractAddress": "0x5FbDB2315678afecb367f032d93F642f64180aa3"
      }
    },
    {
      "id": "dep_def456",
      "userId": 42,
      "amount": "500.00",
      "currency": "USDC",
      "status": "confirming",
      "fromAddress": "0x123456789abcdef0123456789abcdef012345678",
      "toAddress": "0x9876543210abcdef0123456789abcdef01234567",
      "txHash": "0xfedcba987654321...",
      "blockNumber": 1234890,
      "confirmations": 5,
      "requiredConfirmations": 12,
      "network": "TRON",
      "chainId": "TRC20",
      "createdAt": "2025-10-06T11:30:00Z",
      "confirmedAt": null,
      "metadata": {
        "estimatedCompletionTime": "2025-10-06T11:40:00Z"
      }
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 47,
    "totalPages": 3,
    "hasNext": true,
    "hasPrevious": false
  },
  "summary": {
    "totalDeposited": "15000.00",
    "totalCompleted": "14500.00",
    "totalPending": "500.00",
    "currency": "USDC"
  },
  "timestamp": "2025-10-06T12:34:56Z"
}

Статусы депозитов:

Статус Описание Финальный?
pending Транзакция обнаружена, awaiting confirmations ❌ Нет
confirming Accumulating confirmations (< required) ❌ Нет
completed Успешно завершён (>= required confirmations) ✅ Да
failed Транзакция провалилась или reverted ✅ Да

Поля ответа:

Поле Тип Описание
data[].id string Уникальный ID депозита
data[].amount string Сумма депозита (SafeDecimal)
data[].status string Текущий статус
data[].txHash string Blockchain transaction hash
data[].confirmations number Текущее количество confirmations
data[].requiredConfirmations number Требуемое количество confirmations
data[].confirmedAt string Timestamp завершения (если completed)
summary.totalDeposited string Общая сумма всех депозитов

Ошибки:

Код статуса Код ошибки Описание
400 INVALID_DATE_RANGE startDate > endDate
401 TOKEN_EXPIRED JWT токен истёк

Пример cURL

TOKEN="eyJhbGciOiJIUzI1NiIs..."

# Получить все депозиты
curl -X GET "https://app.saga.surf/api/user/deposits?page=1&limit=20" \
  -H "Authorization: Bearer $TOKEN"

# Получить только completed депозиты
curl -X GET "https://app.saga.surf/api/user/deposits?status=completed" \
  -H "Authorization: Bearer $TOKEN"

Пример TypeScript

// Получить историю депозитов
const response = await fetch('/api/user/deposits?page=1&limit=20&status=completed', {
  headers: {
    'Authorization': `Bearer ${token}`
  }
});

const { data: deposits, summary } = await response.json();

console.log(`Всего депозитов: ${summary.totalDeposited} ${summary.currency}`);

deposits.forEach(deposit => {
  const statusIcon = {
    pending: '⏳',
    confirming: '🔄',
    completed: '✅',
    failed: '❌'
  }[deposit.status];

  console.log(`${statusIcon} $${deposit.amount}: ${deposit.confirmations}/${deposit.requiredConfirmations} confirmations`);
});

POST /api/webhooks/crypto2b/deposit

Webhook обработка депозитов от Crypto2B (автоматическая обработка депозитов без пользовательского взаимодействия).

Запрос

POST /api/user/blockchain/deposit
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Content-Type: application/json

{
  "txHash": "0xabcdef123456789...",
  "amount": "1000.00",
  "currency": "USDC",
  "fromAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"
}

Заголовки:

Заголовок Значение Обязательно Описание
Authorization Bearer <token> ✅ Да User JWT токен
Content-Type application/json ✅ Да JSON payload

Body параметры:

Параметр Тип Обязательно Описание
txHash string ✅ Да Blockchain transaction hash (0x...)
amount string ✅ Да Сумма депозита (SafeDecimal format)
currency string ✅ Да Валюта: USDC, ETH
fromAddress string ✅ Да Адрес отправителя (user wallet)

Ответ

Успех (201 Created):

{
  "success": true,
  "data": {
    "id": "dep_xyz789",
    "userId": 42,
    "amount": "1000.00",
    "currency": "USDC",
    "status": "pending",
    "fromAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0",
    "toAddress": "0x9876543210abcdef0123456789abcdef01234567",
    "txHash": "0xabcdef123456789...",
    "blockNumber": null,
    "confirmations": 0,
    "requiredConfirmations": 12,
    "createdAt": "2025-10-06T12:00:00Z",
    "estimatedCompletionTime": "2025-10-06T12:03:00Z"
  },
  "timestamp": "2025-10-06T12:00:00Z"
}

Ошибки:

Код статуса Код ошибки Описание
400 INVALID_TX_HASH Некорректный формат transaction hash
400 INVALID_AMOUNT Сумма меньше минимальной или некорректный формат
400 DUPLICATE_DEPOSIT Deposit с таким txHash уже существует
401 TOKEN_EXPIRED JWT токен истёк
503 BLOCKCHAIN_ERROR Не удалось проверить транзакцию на blockchain

Пример cURL

TOKEN="eyJhbGciOiJIUzI1NiIs..."
curl -X POST https://app.saga.surf/api/user/blockchain/deposit \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "txHash": "0xabcdef123456789...",
    "amount": "1000.00",
    "currency": "USDC",
    "fromAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"
  }'

Пример TypeScript

// Создать blockchain deposit
async function createBlockchainDeposit(txHash: string, amount: string, currency: string, fromAddress: string) {
  const response = await fetch('/api/user/blockchain/deposit', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      txHash,
      amount,
      currency,
      fromAddress
    })
  });

  const { data } = await response.json();
  console.log(`Deposit ${data.id} создан, статус: ${data.status}`);

  return data;
}

// Инструкции для пользователей (любой кошелек)
async function showDepositInstructions(depositAddress: string, amount: string) {
  const instructions = `
    📱 Как отправить депозит:

    1. Откройте ваш криптокошелек (Binance, OKX, Trust Wallet, etc.)
    2. Выберите "Отправить" или "Перевести"
    3. Выберите USDT (TRC20) - обязательно TRC20!
    4. Вставьте адрес: ${depositAddress}
    5. Введите сумму: $${amount} USDT (минимум $500)
    6. Подтвердите транзакцию

    ⚡ Комиссия сети ~$1 (TRON)
    🕒 Обработка: 2-4 часа автоматически
    📧 Уведомление придет на email при зачислении
  `;

  document.getElementById('wallet-instructions').textContent = instructions;
}

GET /api/blockchain/deposits

Публичный endpoint для получения статуса депозитов (без аутентификации).

Запрос

GET /api/blockchain/deposits?address=0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0

Query параметры:

Параметр Тип Обязательно Описание
address string ❌ Нет Фильтр по deposit адресу
txHash string ❌ Нет Фильтр по transaction hash
limit number ❌ Нет Элементов на странице (макс: 50)

Ответ

Успех (200 OK):

{
  "success": true,
  "data": [
    {
      "address": "0x9876543210abcdef0123456789abcdef01234567",
      "totalDeposits": 15,
      "totalAmount": "15000.00",
      "currency": "USDC",
      "lastDepositAt": "2025-10-06T11:30:00Z"
    }
  ],
  "timestamp": "2025-10-06T12:34:56Z"
}

Примечание: Публичный endpoint возвращает агрегированную статистику без детальной информации о пользователях.

Пример cURL

# Получить публичный статус депозитов
curl -X GET "https://app.saga.surf/api/blockchain/deposits?address=0x9876543210abcdef0123456789abcdef01234567"

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

Отображение deposit интерфейса

// Deposit UI компонент
async function DepositInterface() {
  // Получить депозитный адрес
  const { data: depositInfo } = await fetch('/api/user/deposits/address?currency=USDC', {
    headers: { 'Authorization': `Bearer ${token}` }
  }).then(r => r.json());

  return (
    <div className="deposit-container">
      <h2>Пополнить баланс USDC</h2>

      <div className="deposit-address">
        <p>Ваш персональный адрес для депозитов:</p>
        <div className="address-box">
          <code>{depositInfo.address}</code>
          <button onClick={() => copyToClipboard(depositInfo.address)}>
            Копировать
          </button>
        </div>
      </div>

      <div className="qr-code">
        <img src={depositInfo.qrCode} alt="QR код депозита" />
      </div>

      <div className="deposit-info">
        <p>Минимальная сумма: ${depositInfo.minimumDeposit} {depositInfo.currency}</p>
        <p>Требуемых подтверждений: {depositInfo.estimatedConfirmations}</p>
        <p>Сеть: {depositInfo.network} (Chain ID: {depositInfo.chainId})</p>
      </div>
    </div>
  );
}

Мониторинг подтверждений депозита

// Real-time monitoring депозита
async function monitorDepositConfirmations(depositId: string) {
  const interval = setInterval(async () => {
    const response = await fetch(`/api/user/deposits`, {
      headers: { 'Authorization': `Bearer ${token}` }
    });
    const { data: deposits } = await response.json();

    const deposit = deposits.find(d => d.id === depositId);
    if (!deposit) return;

    console.log(`Confirmations: ${deposit.confirmations}/${deposit.requiredConfirmations}`);

    if (deposit.status === 'completed') {
      clearInterval(interval);
      showNotification('Депозит успешно зачислен!', 'success');
    } else if (deposit.status === 'failed') {
      clearInterval(interval);
      showNotification('Депозит провалился', 'error');
    }
  }, 10000); // Проверка каждые 10 секунд
}

История депозитов с pagination

// Постраничная история депозитов
function DepositHistory() {
  const [deposits, setDeposits] = useState([]);
  const [page, setPage] = useState(1);
  const [hasMore, setHasMore] = useState(true);

  async function loadDeposits() {
    const response = await fetch(`/api/user/deposits?page=${page}&limit=20`, {
      headers: { 'Authorization': `Bearer ${token}` }
    });
    const { data, pagination } = await response.json();

    setDeposits(prev => [...prev, ...data]);
    setHasMore(pagination.hasNext);
  }

  useEffect(() => {
    loadDeposits();
  }, [page]);

  return (
    <div className="deposit-history">
      <h2>История депозитов</h2>
      <table>
        <thead>
          <tr>
            <th>Дата</th>
            <th>Сумма</th>
            <th>Статус</th>
            <th>Confirmations</th>
            <th>Tx Hash</th>
          </tr>
        </thead>
        <tbody>
          {deposits.map(dep => (
            <tr key={dep.id}>
              <td>{new Date(dep.createdAt).toLocaleDateString()}</td>
              <td>${dep.amount} {dep.currency}</td>
              <td><StatusBadge status={dep.status} /></td>
              <td>{dep.confirmations}/{dep.requiredConfirmations}</td>
              <td>
                <a href={`https://explorer.saga.surf/tx/${dep.txHash}`} target="_blank">
                  {dep.txHash.substring(0, 10)}...
                </a>
              </td>
            </tr>
          ))}
        </tbody>
      </table>

      {hasMore && (
        <button onClick={() => setPage(p => p + 1)}>
          Загрузить ещё
        </button>
      )}
    </div>
  );
}

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

Другие User Endpoints:




"Integration-Only принципы: внешние API для crypto операций, email mandatory для пользователей, single strategy MVP"

— Saga Development Team (Phase 2 API Updates)