# Приём депозитов для обменников

Пошаговое руководство по настройке приёма USDT от пользователей вашей платформы.

## Сценарий

Вы — обменник или биржа. Ваши пользователи хотят пополнить баланс в USDT:

1. Пользователь запрашивает адрес для пополнения
2. Ваша система создаёт уникальный кошелёк
3. Пользователь отправляет USDT
4. Lumo проводит AML-проверку
5. Вы получаете webhook о зачислении


## Преимущества

- **Без блокчейн-кода** — не нужно работать с TRON напрямую
- **AML из коробки** — автоматическая проверка входящих транзакций
- **Автопересылка** — средства собираются на вашем treasury
- **Webhooks** — real-time уведомления


## Шаг 1: Настройка webhook

Сначала настройте endpoint для получения уведомлений:


```javascript
const crypto = require('crypto');

app.post('/webhooks/lumo', (req, res) => {
  // Верификация подписи
  const signature = req.headers['x-lumo-signature'];
  const expected = crypto
    .createHmac('sha256', process.env.WEBHOOK_SECRET)
    .update(JSON.stringify(req.body))
    .digest('hex');
    
  if (signature !== expected) {
    return res.status(401).send('Invalid signature');
  }
  
  // Обработка события
  handleWebhook(req.body);
  res.status(200).send('OK');
});

function handleWebhook(payload) {
  const { event, externalId, amount, status } = payload;
  
  switch (event) {
    case 'deposit.completed':
      creditUserBalance(externalId, amount);
      break;
    case 'deposit.aml_failed':
      notifySupport(payload);
      break;
  }
}
```

Обновите профиль компании:


```bash
curl -X PATCH 'https://b2b.lumowallet.io/auth/company/profile' \
  -H 'X-API-Key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "webhookUrl": "https://your-server.com/webhooks/lumo"
  }'
```

## Шаг 2: Создание кошелька для пользователя

Когда пользователь запрашивает адрес для пополнения:


```javascript
async function getDepositAddress(userId) {
  const response = await fetch('https://b2b.lumowallet.io/user-wallets', {
    method: 'POST',
    headers: {
      'X-API-Key': process.env.LUMO_API_KEY,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      externalId: userId  // Ваш внутренний ID пользователя
    })
  });
  
  const wallet = await response.json();
  return wallet.address;
}
```

Ответ:


```json
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "companyId": "660e8400-e29b-41d4-a716-446655440001",
  "externalId": "user-12345",
  "address": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
  "isBlocked": false,
  "lastUsdtBalance": 0,
  "createdAt": "2026-03-10T12:00:00Z"
}
```

> 💡 **Идемпотентность:** Повторный запрос с тем же `externalId` вернёт существующий кошелёк.


## Шаг 3: Показ адреса пользователю


```jsx
function DepositPage({ userId }) {
  const [address, setAddress] = useState(null);
  
  useEffect(() => {
    getDepositAddress(userId).then(setAddress);
  }, [userId]);
  
  return (
    <div>
      <h2>Пополнение баланса</h2>
      <p>Отправьте USDT (TRC-20) на адрес:</p>
      <AddressBox>{address}</AddressBox>
      <QRCode value={address} />
      <Warning>
        ⚠️ Отправляйте только USDT в сети TRON (TRC-20)
      </Warning>
    </div>
  );
}
```

## Шаг 4: Обработка депозита

Когда пользователь отправляет USDT, вы получаете webhooks:

### 4.1 Депозит обнаружен


```json
{
  "event": "deposit.created",
  "depositId": "770e8400-e29b-41d4-a716-446655440002",
  "externalId": "user-12345",
  "txHash": "abc123...",
  "walletAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
  "amount": 100.00,
  "status": "new"
}
```

Действие: Показать пользователю "Депозит обнаружен, ожидает подтверждения"

### 4.2 AML-проверка


```json
{
  "event": "deposit.aml_pending",
  "depositId": "770e8400-e29b-41d4-a716-446655440002",
  "externalId": "user-12345",
  "status": "aml_pending"
}
```

Действие: Показать "Проверка безопасности..."

### 4.3 Депозит завершён


```json
{
  "event": "deposit.completed",
  "depositId": "770e8400-e29b-41d4-a716-446655440002",
  "externalId": "user-12345",
  "amount": 100.00,
  "status": "completed"
}
```

Действие: Зачислить средства на баланс пользователя


```javascript
async function creditUserBalance(externalId, amount) {
  await db.users.update({
    where: { id: externalId },
    data: { 
      balance: { increment: amount },
      lastDepositAt: new Date()
    }
  });
  
  // Уведомить пользователя
  await notifyUser(externalId, {
    type: 'deposit_success',
    amount: amount
  });
}
```

## Шаг 5: Обработка AML-блокировок

При `aml_failed`:


```javascript
function handleAmlFailed(payload) {
  const { externalId, amount, depositId } = payload;
  
  // Уведомить пользователя
  notifyUser(externalId, {
    type: 'deposit_blocked',
    message: 'Депозит заблокирован для проверки'
  });
  
  // Создать тикет для поддержки
  createSupportTicket({
    type: 'aml_review',
    userId: externalId,
    depositId: depositId,
    amount: amount
  });
}
```

## Шаг 6: Просмотр истории депозитов


```javascript
async function getUserDeposits(userId) {
  const response = await fetch(
    `https://b2b.lumowallet.io/user-wallets/deposits?externalId=${userId}`,
    { headers: { 'X-API-Key': process.env.LUMO_API_KEY } }
  );
  
  return response.json();
}
```

## Блокировка кошелька

При подозрительной активности заблокируйте кошелёк:


```javascript
async function blockUserWallet(walletId, reason) {
  await fetch(`https://b2b.lumowallet.io/user-wallets/${walletId}/block`, {
    method: 'POST',
    headers: {
      'X-API-Key': process.env.LUMO_API_KEY,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ reason })
  });
}
```

## Замена кошелька

Если пользователь просит новый адрес:


```javascript
async function replaceUserWallet(walletId) {
  const response = await fetch(
    `https://b2b.lumowallet.io/user-wallets/${walletId}/replace`,
    {
      method: 'POST',
      headers: {
        'X-API-Key': process.env.LUMO_API_KEY,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ reason: 'User requested new address' })
    }
  );
  
  const newWallet = await response.json();
  return newWallet.address;  // Новый адрес
}
```

## Полный пример


```javascript
class DepositService {
  constructor(apiKey, webhookSecret) {
    this.apiKey = apiKey;
    this.webhookSecret = webhookSecret;
    this.baseUrl = 'https://b2b.lumowallet.io';
  }

  async getOrCreateWallet(userId) {
    const response = await fetch(`${this.baseUrl}/user-wallets`, {
      method: 'POST',
      headers: {
        'X-API-Key': this.apiKey,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ externalId: userId })
    });
    
    return response.json();
  }

  verifyWebhook(body, signature) {
    const expected = crypto
      .createHmac('sha256', this.webhookSecret)
      .update(JSON.stringify(body))
      .digest('hex');
    return signature === expected;
  }

  async handleWebhook(payload) {
    switch (payload.event) {
      case 'deposit.completed':
        await this.onDepositCompleted(payload);
        break;
      case 'deposit.aml_failed':
        await this.onAmlFailed(payload);
        break;
    }
  }

  async onDepositCompleted({ externalId, amount }) {
    // Зачисляем баланс
    await db.users.increment(externalId, 'balance', amount);
    
    // Уведомляем пользователя
    await notifications.send(externalId, {
      title: 'Депозит зачислен',
      body: `+${amount} USDT`
    });
  }

  async onAmlFailed({ externalId, depositId }) {
    await notifications.send(externalId, {
      title: 'Депозит на проверке',
      body: 'Свяжитесь с поддержкой'
    });
  }
}
```

## Чек-лист интеграции

- [ ] Настроен webhook endpoint
- [ ] Webhook URL обновлён в профиле
- [ ] Верификация подписи webhook
- [ ] Создание кошельков для пользователей
- [ ] UI для показа адреса + QR-код
- [ ] Обработка `deposit.completed`
- [ ] Обработка `deposit.aml_failed`
- [ ] Зачисление баланса пользователю
- [ ] Уведомления пользователю
- [ ] Логирование всех событий