Безопасный P2P escrow-сервис на базе TRON блокчейна с multisig-кошельками для USDT TRC20.
Сайт: keyshield.me Telegram бот: @keyshield_bot
- Обзор системы
- Архитектура
- Установка и настройка
- Конфигурация
- Telegram бот
- Процесс сделки
- Multisig кошельки
- Система комиссий
- Партнёрская программа
- Админ-панель
- Веб-сайт
- API эндпоинты
- База данных
- Безопасность
- Масштабирование
- Мониторинг и логирование
KeyShield — это escrow-сервис для безопасных P2P сделок с криптовалютой. Покупатель замораживает средства в multisig-кошельке, продавец выполняет работу, после подтверждения — средства переводятся продавцу.
- Multisig кошельки — 2-of-3 подписи (покупатель + продавец или арбитр)
- Автоматическое обнаружение депозитов — параллельная проверка до 8 сделок одновременно
- Система споров — арбитраж с доказательствами (фото/видео/документы)
- Партнёрская программа — реферальные ссылки с аналитикой и партнёрскими выплатами
- Telegram бот — полный цикл сделки в чате
- Deadline Monitor — автоматические рефанды при истечении дедлайна + 12ч grace period
- Адаптивный веб-сайт — лендинг с мобильным меню и SEO-оптимизацией
| Актив | Сеть | Контракт |
|---|---|---|
| USDT | TRC20 | TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t |
| TRX | TRON | Native |
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Telegram Bot │────▶│ Node.js API │────▶│ MongoDB │
│ (Telegraf) │ │ (Express) │ │ │
└─────────────────┘ └────────┬────────┘ └─────────────────┘
│
▼
┌─────────────────┐
│ TRON Blockchain│
│ (TronWeb) │
└─────────────────┘
src/
├── bot/ # Telegram бот
│ ├── handlers/ # Обработчики команд
│ │ ├── start.js # /start и главное меню
│ │ ├── createDeal.js # Создание сделки
│ │ ├── myDeals.js # Мои сделки
│ │ ├── provideWallet.js # Ввод кошелька контрагентом
│ │ ├── dispute.js # Споры
│ │ └── help.js # Помощь
│ ├── keyboards/ # Inline-клавиатуры
│ └── utils/ # Утилиты (messageManager)
├── models/ # MongoDB схемы
│ ├── Deal.js # Сделка
│ ├── User.js # Пользователь
│ ├── Transaction.js # Транзакция
│ ├── MultisigWallet.js # Multisig кошелёк
│ ├── Dispute.js # Спор
│ ├── Platform.js # Партнёрская платформа
│ └── AuditLog.js # Аудит-лог
├── services/ # Бизнес-логика
│ ├── blockchain.js # Работа с TRON
│ ├── dealService.js # Сервис сделок
│ ├── depositMonitor.js # Мониторинг депозитов
│ ├── deadlineMonitor.js # Мониторинг дедлайнов
│ ├── disputeService.js # Споры
│ ├── banService.js # Бан пользователей
│ └── notificationService.js # Уведомления
├── web/ # Веб-сервер
│ ├── server.js # Express сервер
│ └── routes/ # API маршруты
│ └── partner.js # Партнёрский API
├── config/ # Конфигурация
│ ├── constants.js # Константы
│ ├── database.js # Подключение MongoDB
│ └── tron.js # Настройки TRON
├── api/ # API роуты
│ ├── routes/ # Маршруты
│ └── middleware/ # Middleware (auth, errorHandler)
└── index.js # Точка входа
public/ # Статические файлы сайта
├── index.html # Главная страница
├── terms.html # Условия использования
├── privacy.html # Политика конфиденциальности
├── offer.html # Публичная оферта
├── not-found.html # Страница 404
├── admin.html # Админ-панель
├── css/style.css # Стили
├── js/main.js # Скрипты
└── images/ # Изображения
- Node.js 18+
- MongoDB 6+
- TRON кошелёк с TRX для комиссий
# Клонировать репозиторий
git clone <repository-url>
cd keyshield
# Установить зависимости
npm install
# Скопировать конфигурацию
cp .env.example .env
# Настроить .env (см. раздел Конфигурация)
# Запустить
npm start# С PM2
pm2 start src/index.js --name keyshield
# Или с Docker
docker-compose up -d# MongoDB
MONGODB_URI=mongodb://localhost:27017/keyshield
# Telegram Bot
BOT_TOKEN=your_bot_token_here
BOT_USERNAME=your_bot_username
# TRON Configuration
TRON_FULL_NODE=https://api.trongrid.io
TRON_SOLIDITY_NODE=https://api.trongrid.io
TRON_EVENT_SERVER=https://api.trongrid.io
TRONGRID_API_KEY=your_trongrid_api_key
# Arbiter Wallet (главный кошелёк арбитра)
ARBITER_PRIVATE_KEY=your_private_key_hex
ARBITER_ADDRESS=your_tron_address
# Service Wallet (для сбора комиссий)
SERVICE_WALLET_ADDRESS=your_service_wallet
# API & Web
API_PORT=3000
WEB_PORT=3001
# Admin Panel
JWT_SECRET=your_jwt_secret
JWT_EXPIRES_IN=7d
ADMIN_USERNAME=admin
ADMIN_PASSWORD=secure_password
# Environment
NODE_ENV=production
# USDT Contract
USDT_CONTRACT_ADDRESS=TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t
# Deal Settings
MIN_DEAL_AMOUNT=50
# Commission
COMMISSION_RATE=0.05
MIN_COMMISSION_USDT=15
COMMISSION_THRESHOLD=300
# Monitoring
DEPOSIT_CHECK_INTERVAL=30000
MULTISIG_ACTIVATION_TRX=15| Команда | Описание |
|---|---|
/start |
Регистрация и главное меню |
/menu |
Главное меню |
/help |
Справка |
DEAL_XXXXXX |
Просмотр сделки по ID |
🏠 Главное меню
├── 🛒 Создать сделку (как покупатель)
├── 💼 Создать сделку (как продавец)
├── 📋 Мои сделки
├── 💰 Мой кошелёк
└── ℹ️ Помощь
- Выбор роли — покупатель или продавец
- Ввод ID контрагента — Telegram ID или @username
- Название товара/услуги
- Описание (опционально, можно пропустить)
- Сумма в USDT
- Кто платит комиссию — покупатель / продавец / пополам
- Дедлайн — 24ч / 48ч / 72ч / 7 дней
- Адрес кошелька — для получения средств
- Подтверждение — генерация multisig-кошелька
waiting_for_seller_wallet ──▶ Ожидание кошелька продавца
waiting_for_buyer_wallet ──▶ Ожидание кошелька покупателя
waiting_for_deposit ──▶ Ожидание депозита
locked ──▶ Средства заморожены
in_progress ──▶ Работа ведётся
dispute ──▶ Открыт спор
completed ──▶ Успешно завершена
cancelled ──▶ Отменена
resolved ──▶ Решена арбитром
expired ──▶ Авто-рефанд (дедлайн + 12ч)
┌─────────────────┐
│ Создание │
│ сделки │
└────────┬────────┘
▼
┌─────────────────┐
│ Ожидание │◀─── Контрагент указывает кошелёк
│ кошельков │
└────────┬────────┘
▼
┌─────────────────┐
│ Ожидание │◀─── Покупатель переводит USDT
│ депозита │
└────────┬────────┘
▼
┌─────────────────┐
│ Заморожено │◀─── Автоматическое обнаружение
│ (locked) │
└────────┬────────┘
│
┌────┴────┐
▼ ▼
┌───────┐ ┌───────┐
│Подтв. │ │ Спор │
│работы │ │ │
└───┬───┘ └───┬───┘
│ │
▼ ▼
┌───────┐ ┌───────┐
│Выплата│ │Арбитр │
│прод-цу│ │решает │
└───────┘ └───────┘
Покупатель:
- Подтвердить работу → выплата продавцу
- Открыть спор → арбитраж
- Отменить (до депозита)
Продавец:
- Отметить "Работа сдана"
- Открыть спор
- Отменить (до депозита)
Для каждой сделки создаётся уникальный multisig-кошелёк с 3 ключами:
- Временный ключ покупателя (генерируется системой)
- Временный ключ продавца (генерируется системой)
- Ключ арбитра (постоянный, из .env)
Порог подписей: 2 из 3
| Сценарий | Подписи | Результат |
|---|---|---|
| Успех | Покупатель + Продавец | Продавцу |
| Спор (продавец прав) | Арбитр + Продавец | Продавцу |
| Спор (покупатель прав) | Арбитр + Покупатель | Покупателю |
| Отмена | Покупатель + Продавец | Покупателю |
После обнаружения депозита, кошелёк активируется:
- Перевод 16.1 TRX для оплаты gas
- Последовательная очередь (избегает конфликтов)
- Запись затрат в
operationalCosts
Автоматический мониторинг дедлайнов сделок:
- Дедлайн истёк → Уведомление обеим сторонам
- +12 часов без действий → Автоматический рефанд покупателю
- Интервал проверки: каждые 5 минут
- Batch processing: 5 сделок за раз
// Grace period: 12 часов после дедлайна
GRACE_PERIOD_MS = 12 * 60 * 60 * 1000
// Статус после авто-рефанда
status: 'expired'// Базовая ставка: 5%
// Минимум: 15 USDT
// Порог: 300 USDT
if (amount <= 300) {
commission = 15; // Фиксированная
} else {
commission = amount * 0.05; // 5%
}| Сумма сделки | Комиссия |
|---|---|
| 50 USDT | 15 USDT |
| 100 USDT | 15 USDT |
| 300 USDT | 15 USDT |
| 500 USDT | 25 USDT |
| 1000 USDT | 50 USDT |
- buyer — покупатель (депозит = сумма + комиссия)
- seller — продавец (получает сумма - комиссия)
- split — пополам (каждый платит 50%)
// POST /api/partner/register
{
"name": "CryptoForum",
"email": "admin@cryptoforum.com",
"website": "https://cryptoforum.com"
}
// Response
{
"platform": {
"code": "CRYPTOF",
"apiKey": "pk_live_xxxxx",
"referralLink": "https://t.me/bot?start=ref_CRYPTOF"
}
}https://t.me/keyshield_bot?start=ref_PLATFORMCODE
При переходе по ссылке:
- Пользователь привязывается к платформе
- Все его сделки учитываются в статистике
- Платформа получает % от комиссий (настраивается)
// GET /api/partner/stats
{
"stats": {
"totalUsers": 150,
"totalDeals": 45,
"completedDeals": 38,
"totalVolume": 15420.50,
"totalCommission": 771.02,
"netProfit": 698.45,
"platformEarnings": 69.85 // commissionPercent от netProfit
}
}// Для каждой платформы:
platformNetProfit = platformCommission - (platformDeals × 16.1 TRX × 0.28)
platformPayout = platformNetProfit × (commissionPercent / 100)
// По умолчанию commissionPercent = 10%- Личный кабинет партнёра:
/partner - Авторизация по логину/паролю
- Статистика: пользователи, сделки, объём, доход
- Реферальная ссылка для привлечения
// POST /api/admin/login
{
"username": "admin",
"password": "your_password"
}
// Response
{
"token": "eyJhbGciOiJIUzI1NiIs..."
}| Метод | Путь | Описание |
|---|---|---|
| POST | /api/admin/login | Авторизация |
| GET | /api/admin/stats | Общая статистика |
| GET | /api/admin/deals | Список сделок |
| GET | /api/admin/deals/:id | Детали сделки |
| GET | /api/admin/users | Список пользователей |
| POST | /api/admin/users/:id/ban | Забанить |
| GET | /api/admin/disputes | Активные споры |
| POST | /api/admin/disputes/:id/resolve | Решить спор |
| GET | /api/admin/platforms | Партнёры |
| GET | /api/admin/audit | Аудит-лог |
Доступен по адресу /admin
Админ-панель отображает детальную финансовую статистику:
| Показатель | Описание |
|---|---|
| Валовая выручка | Сумма всех комиссий с завершённых сделок |
| Расходы TRX | 16.1 TRX × количество сделок |
| Расходы USDT | TRX расходы × курс (0.28 USDT) |
| Чистая прибыль | Выручка − Расходы |
| К выплате партнёрам | Сумма партнёрских выплат |
| Чистейшая прибыль | Чистая прибыль − Партнёрские выплаты |
- Просмотр деталей спора с доказательствами
- Галерея изображений с навигацией
- Решение спора в пользу покупателя или продавца
- Возврат сделки в статус "in_progress"
- Отмена спора
| URL | Страница |
|---|---|
/ |
Главная (лендинг) |
/terms |
Условия использования |
/privacy |
Политика конфиденциальности |
/offer |
Публичная оферта |
/admin |
Админ-панель |
- Адаптивный дизайн — корректное отображение на мобильных устройствах
- Мобильное меню — фиксированное меню с анимацией, автозакрытие при клике на anchor-ссылки
- SEO-оптимизация — мета-теги, Open Graph, canonical URLs
- Clean URLs — роутинг через Express вместо .html расширений
- CSS Variables — темная тема, централизованные цвета
- CSS Grid & Flexbox — адаптивная сетка
- Vanilla JS — без зависимостей
- Inter font — Google Fonts
GET /api/health # Проверка статуса
GET /api/stats/public # Публичная статистика
POST /api/partner/register # Регистрация платформы
GET /api/partner/stats # Статистика платформы
GET /api/partner/users # Пользователи платформы
GET /api/partner/deals # Сделки платформы
POST /api/admin/login # Авторизация
GET /api/admin/stats # Полная статистика
GET /api/admin/deals # Все сделки
POST /api/admin/disputes/:id/resolve # Решение спора
| Коллекция | Описание |
|---|---|
| users | Пользователи Telegram |
| deals | Сделки |
| transactions | Транзакции блокчейна |
| multisigwallets | Multisig кошельки |
| disputes | Споры |
| platforms | Партнёрские платформы |
| auditlogs | Аудит-лог действий |
// Deal
{ status: 1, multisigAddress: 1 } // depositMonitor
{ uniqueKey: 1, status: 1 } // дубликаты
{ platformId: 1, status: 1 } // партнёры
{ buyerId: 1 }
{ sellerId: 1 }
{ dealId: 1 } // unique
// User
{ telegramId: 1 } // unique
{ platformId: 1 }
{ blacklisted: 1 }
// Transaction
{ dealId: 1 }
{ txHash: 1 }
// Platform
{ code: 1 } // unique
{ apiKey: 1 } // unique- Приватные ключи хранятся в зашифрованном виде
- Ключ арбитра только в .env (никогда в БД)
- Временные ключи сделок удаляются после завершения
| Угроза | Защита |
|---|---|
| Double-spend | Подтверждение блока + проверка txHash |
| Race condition | processedDeposits Set + double-check в БД |
| Memory leak | Автоочистка Map каждые 30 минут |
| API abuse | Rate limiting + JWT + API ключи |
| MITM | HTTPS only + TronGrid HTTPS |
- Сменить ADMIN_PASSWORD
- Сгенерировать новый JWT_SECRET
- Использовать отдельный кошелёк арбитра
- Настроить HTTPS
- Ограничить доступ к MongoDB
- Регулярные бэкапы БД
| Метрика | Значение |
|---|---|
| Параллельных проверок депозитов | 8 |
| TronGrid API requests/sec | 10 |
| Сессий в памяти | 5000 |
| Сделок в месяц | 10,000+ |
-
Параллельная проверка депозитов
- 8 сделок одновременно
- Promise.allSettled для устойчивости
- 1 сек задержка между батчами
-
Очистка памяти
- Автоудаление неактивных сессий (2+ часа)
- Лимит 5000 записей
- Интервал очистки: 30 минут
-
Оптимизация запросов
- Promise.all для параллельных запросов
- .lean() для read-only операций
- Compound индексы
-
Очередь активаций
- Последовательная обработка
- 2 сек между активациями
- Предотвращение конфликтов nonce
- Redis для кэширования TronGrid ответов
- Bull queue для фоновых задач
- Кластерный режим Node.js
- Ротация нескольких TronGrid API ключей
# Депозит-монитор
🔍 Checking deposits for 15 deal(s) in batches of 8...
📦 Processing batch 1/2 (8 deals)...
💰 Deposit detected for deal DEAL_ABC123
✅ Deal DEAL_ABC123 marked as locked
# Активация
🔓 [Queue] Activating multisig TXxx... with 15 TRX
✅ [Queue] Activation successful: txhash...
# Очистка памяти
🧹 MessageManager cleanup: removed 45 inactive users, 120 active sessionsВсе важные действия записываются в auditlogs:
- Создание сделки
- Обнаружение депозита
- Подтверждение работы
- Выплата
- Открытие/закрытие спора
- Решение арбитра
- Бан пользователя
// GET /api/admin/stats
{
"deals": {
"total": 1250,
"active": 45,
"completed": 1180,
"disputed": 25
},
"volume": {
"total": 125000,
"today": 3500,
"month": 45000
},
"users": {
"total": 850,
"active": 120,
"blacklisted": 5
}
}Продавец открывает спор, прикладывает доказательства. Арбитр принимает решение в течение 24-48 часов.
Покупатель открывает спор. Если работа не сдана до дедлайна и нет активности — возврат покупателю.
50 USDT (настраивается в .env)
На кошельке арбитра рекомендуется держать:
- 15 TRX × количество активных сделок
-
- запас на выплаты (~ 5 TRX на транзакцию)
Изменить ADMIN_USERNAME и ADMIN_PASSWORD в .env, перезапустить сервис.
При возникновении проблем:
- Проверьте логи:
pm2 logs keyshield - Проверьте MongoDB:
mongosh keyshield --eval "db.deals.countDocuments()" - Проверьте баланс арбитра: TronScan
Документация обновлена: 5 декабря 2025