Разработка Lightning-бота для Telegram

Проектируем и разрабатываем блокчейн-решения полного цикла: от архитектуры смарт-контрактов до запуска DeFi-протоколов, NFT-маркетплейсов и криптобирж. Аудит безопасности, токеномика, интеграция с существующей инфраструктурой.
Показано 1 из 1 услугВсе 1306 услуг
Разработка Lightning-бота для Telegram
Средняя
~3-5 рабочих дней
Часто задаваемые вопросы
Направления блокчейн-разработки
Этапы блокчейн-разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1221
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1163
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    855
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1056
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    561
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    828

Разработка Lightning-бота для Telegram

Lightning Network — это не просто «быстрый Bitcoin». Это отдельный протокол с собственной моделью состояния, платёжными каналами, routing-алгоритмами и специфическими видами атак. Telegram-бот поверх Lightning — это UI-слой над этой инфраструктурой, и ошибка в интеграции стоит пользователям реальных денег.

Типичный запрос: «сделайте бота, чтобы пользователи могли получать и отправлять сатоши». За этим скрывается выбор архитектуры ноды, модель кастодиального хранения, управление ликвидностью каналов и логика обработки неудачных платежей.

Архитектура: кастодиальная vs non-custodial

Это первый и самый важный выбор, который определяет всё остальное.

Кастодиальная модель

Бот держит единую Lightning-ноду, пользователи — это просто записи в базе данных с балансами. Платежи между пользователями внутри бота — off-chain операции внутри вашей БД, без реальных Lightning-транзакций.

Преимущества: нет проблем с routing, мгновенные внутренние переводы, простая реализация. Недостатки: вы кастодиан, требуется лицензия в большинстве юрисдикций, пользователи вам доверяют — как биржа, только меньше регулирования.

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

Telegram Bot → Node.js сервис → PostgreSQL (балансы) → LND/CLN нода (для внешних платежей)

Внутренний перевод — транзакция в PostgreSQL. Внешний вывод — реальный Lightning invoice через ноду. Пополнение — генерация invoice через ноду, мониторинг payment.

Non-custodial через LSP

Lightning Service Provider (LSP) — сервис, который управляет каналами пользователя. Пользователь держит собственные ключи, LSP обеспечивает ликвидность. Протокол LSPS0-LSPS2 стандартизирует это взаимодействие.

Реализация сложнее: нужно интегрироваться с LSP API (Breez SDK, LDK-node), управлять channel open/close, объяснять пользователям концепцию каналов. Для Telegram-бота это обычно избыточно.

Практический выбор для большинства проектов: кастодиальная модель с прозрачной коммуникацией пользователям, что бот кастодиальный.

Lightning-нода: LND vs Core Lightning

LND (Lightning Network Daemon)

Go, разработка Lightning Labs. gRPC API с хорошей документацией. Самый популярный для интеграций — больше SDK и примеров.

import { AuthenticatedLnd } from "lightning";
import { createInvoice, payViaRoutes, getWalletInfo } from "lightning";

// Создание invoice для пополнения
const { request, id } = await createInvoice({
  lnd,
  tokens: 10000, // сатоши
  description: `Deposit for user ${userId}`,
  expires_at: new Date(Date.now() + 3600 * 1000).toISOString(),
});

Пакет lightning (npm) — типизированная обёртка над LND gRPC. Значительно удобнее raw gRPC.

Core Lightning (CLN)

C, разработка Blockstream. Более модульная архитектура через plugin-систему. JSON-RPC API. Меньше экосистемы, но производительнее на большом количестве каналов.

Для большинства Telegram-ботов с объёмом до 10k пользователей — разницы нет. Выбирайте по знакомости стека и наличию документации.

Управление ликвидностью каналов

Главная операционная проблема Lightning-бота — ликвидность. У Lightning-канала есть inbound capacity (сколько можно получить) и outbound capacity (сколько можно отправить). После открытия канала вся ликвидность на вашей стороне — вы можете отправлять, но не получать.

Для бота, который принимает пополнения пользователей, нужна inbound ликвидность:

Покупка inbound liquidity — сервисы типа Bitrefill Thor, Lightning Pool (LND), или ручные договорённости с routing-нодами. Вы платите провайдеру, он открывает канал к вам с балансом на его стороне.

Circular rebalancing — если баланс сместился (много outbound операций), можно провести круговую платёжку через сеть: отправить через A → B → C → себе. Платите routing fee, но перебалансируете канал.

// Мониторинг баланса канала
const channels = await getChannels({ lnd });
for (const channel of channels.channels) {
  const localRatio = channel.local_balance / channel.capacity;
  if (localRatio < 0.2) {
    // Мало outbound — нужна rebalance
    await alertOps(`Channel ${channel.id}: low outbound liquidity`);
  }
  if (localRatio > 0.8) {
    // Мало inbound — не можем принимать платежи
    await alertOps(`Channel ${channel.id}: low inbound liquidity`);
  }
}

Для production бота нужен автоматический rebalancing или интеграция с сервисом ликвидности.

Обработка платежей в боте

Webhook vs polling для Telegram

Webhook предпочтительнее: меньше latency, нет limit на частоту запросов. Требует публичный HTTPS endpoint. Для production — обязательно webhook.

import { Telegraf } from "telegraf";
const bot = new Telegraf(BOT_TOKEN);

bot.command("deposit", async (ctx) => {
  const userId = ctx.from.id.toString();
  const invoice = await createDepositInvoice(userId, 0); // любая сумма
  await ctx.reply(
    `Ваш Lightning invoice для пополнения:\n\n\`${invoice.request}\`\n\nДействителен 1 час.`,
    { parse_mode: "Markdown" }
  );
});

Мониторинг входящих платежей

LND предоставляет subscribeToInvoices — stream, который нотифицирует при каждом settlement:

const sub = subscribeToInvoices({ lnd });
sub.on("invoice_updated", async (invoice) => {
  if (!invoice.is_confirmed) return;
  
  const userId = await getUserByInvoiceId(invoice.id);
  if (!userId) return;
  
  await db.transaction(async (trx) => {
    await trx("users")
      .where({ id: userId })
      .increment("balance_sats", invoice.received);
    await trx("transactions").insert({
      user_id: userId,
      type: "deposit",
      amount_sats: invoice.received,
      lightning_id: invoice.id,
      confirmed_at: new Date(),
    });
  });
  
  await bot.telegram.sendMessage(userId, 
    `Получено ${invoice.received} sat. Баланс обновлён.`
  );
});

Важно: операция должна быть идемпотентной — если воркер упал и перезапустился, повторная обработка одного invoice не должна зачислить деньги дважды. lightning_id с UNIQUE constraint — простая защита.

Отправка платежей (вывод)

Пользователь вставляет invoice, бот его оплачивает:

async function processWithdrawal(userId: string, invoiceStr: string) {
  const decoded = await decodePaymentRequest({ lnd, request: invoiceStr });
  
  // Проверки
  if (decoded.tokens > user.balance_sats) throw new Error("Недостаточно средств");
  if (decoded.expires_at < new Date()) throw new Error("Invoice истёк");
  
  // Резервируем баланс ДО отправки
  await db("users")
    .where({ id: userId })
    .decrement("balance_sats", decoded.tokens);
  
  try {
    const payment = await pay({ lnd, request: invoiceStr });
    // Успешно, записываем транзакцию
    await recordWithdrawal(userId, decoded.tokens, payment.id);
  } catch (err) {
    // Платёж не прошёл — возвращаем баланс
    await db("users")
      .where({ id: userId })
      .increment("balance_sats", decoded.tokens);
    throw new Error(`Платёж не прошёл: ${err.message}`);
  }
}

Порядок операций критичен: сначала резервируем, потом отправляем. Иначе — double spend при параллельных запросах. Возврат при ошибке — обязательно.

Специфические атаки на Lightning-ботов

Invoice replay: пользователь присылает один и тот же invoice дважды. Защита — хранить все обработанные payment hashes, проверять перед обработкой.

Amount mismatch на депозитах: пользователь создал invoice на 1000 sat, кто-то отправил 999 sat (partial amount). LND по умолчанию принимает любую сумму если invoice без tokens. Всегда создавайте amount-less invoice или явно указывайте amount и проверяйте received.

Timing attack на вывод: параллельные запросы на вывод одновременно читают баланс и оба видят достаточно средств. Защита — оптимистичный лок через UPDATE users SET balance = balance - X WHERE balance >= X AND id = Y, проверять affected rows.

Стек и деплой

  • Нода: LND 0.18.x на отдельном сервере/VPS, Bitcoin full node или Neutrino (легкий клиент)
  • Backend: Node.js + TypeScript + Fastify
  • База данных: PostgreSQL, таблицы: users, invoices, transactions, channels_log
  • Мониторинг: Grafana + LND Prometheus exporter, алерты на channel offline, низкую ликвидность
  • Резервные копии: SCB (Static Channel Backups) автоматически после каждого изменения канала — это обязательно, без этого при краше ноды потеряете средства пользователей

Для запуска Lightning-ноды нужно заложить на канальный депозит: минимум 0.1 BTC для небольшого бота, 0.5–1 BTC для production с нормальной ликвидностью.

Сроки разработки

MVP с кастодиальной моделью, deposit/withdraw, базовым p2p переводом — 3–4 недели. Production с авто-rebalancing, мониторингом ликвидности, multi-channel управлением, полным аудитом транзакций — 8–12 недель.