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

Как подключить TON Connect в Telegram Mini App

Продвинутое4 мин

Коротко

Подключите кошелёк через @tonconnect/ui с манифестом, подтверждайте владение адресом через ton_proof с проверкой на сервере, отправляйте транзакции через sendTransaction и считайте оплату завершённой только после проверки в блокчейне — а до запуска разберитесь с правилами Telegram и местным регулированием.

Как это устроено

TON Connect — протокол, по которому Mini App связывается с кошельком пользователя (Telegram Wallet, Tonkeeper и другие). Приложение никогда не получает ключи — оно только просит кошелёк подписать данные или транзакцию.

Полный сценарий состоит из четырёх частей:

  1. Манифест — JSON-файл с описанием вашего приложения.
  2. Подключение кошелька — пользователь выбирает кошелёк и подтверждает.
  3. ton_proof — криптографическое доказательство, что адрес действительно принадлежит пользователю. Проверяется на бэкенде.
  4. Транзакции — кошелёк подписывает и отправляет, сервер проверяет результат в блокчейне.

Шаг 1. Манифест и подключение

Разместите tonconnect-manifest.json по публичному HTTPS-адресу:

{
  "url": "https://example.com",
  "name": "Example Shop",
  "iconUrl": "https://example.com/icon-180.png",
  "termsOfUseUrl": "https://example.com/terms",
  "privacyPolicyUrl": "https://example.com/privacy"
}

В React-приложении используйте @tonconnect/ui-react:

import { TonConnectUIProvider, TonConnectButton } from "@tonconnect/ui-react";

export function App() {
  return (
    <TonConnectUIProvider
      manifestUrl="https://example.com/tonconnect-manifest.json"
      actionsConfiguration={{ twaReturnUrl: "https://t.me/your_bot/app" }}
    >
      <TonConnectButton />
    </TonConnectUIProvider>
  );
}

twaReturnUrl возвращает пользователя в Mini App после подтверждения во внешнем кошельке. Хуки useTonWallet() и useTonAddress() дают текущее подключение.

Шаг 2. ton_proof: проверка владения адресом

Адрес из useTonAddress() — это данные с клиента. Подделать их так же просто, как initDataUnsafe. Если адрес используется для входа, привязки к аккаунту или начисления чего-либо, нужен ton_proof.

Поток:

  1. Бэкенд генерирует случайный payload (nonce) с коротким сроком жизни и сохраняет его.
  2. Фронтенд передаёт его в запрос подключения.
  3. Кошелёк подписывает сообщение, содержащее ваш домен, время, адрес и payload.
  4. Фронтенд отправляет подпись на бэкенд.
tonConnectUI.setConnectRequestParameters({ state: "loading" });
const payload = await fetch("/api/ton-proof/payload").then((r) => r.text());
tonConnectUI.setConnectRequestParameters({ state: "ready", value: { tonProof: payload } });

tonConnectUI.onStatusChange((wallet) => {
  const item = wallet?.connectItems?.tonProof;
  if (wallet && item && "proof" in item) {
    fetch("/api/ton-proof/check", {
      method: "POST",
      body: JSON.stringify({ account: wallet.account, proof: item.proof }),
    });
  }
});

Что проверяет бэкенд:

  • payload выдан вами, не просрочен и ещё не использован;
  • домен в доказательстве совпадает с вашим;
  • timestamp свежий;
  • публичный ключ получен из walletStateInit или запросом к контракту кошелька, и из него действительно выводится заявленный адрес;
  • подпись Ed25519 верна для сообщения, собранного по спецификации TON Connect.

Сборка сообщения для подписи — место, где легко ошибиться в порядке байтов. Опирайтесь на официальные примеры бэкенда TON Connect, а не на самописную реализацию. После проверки выдайте собственный токен сессии.

Шаг 3. Отправка транзакции

import { beginCell, toNano } from "@ton/core";

const comment = beginCell().storeUint(0, 32).storeStringTail(`order:${orderId}`).endCell();

await tonConnectUI.sendTransaction({
  validUntil: Math.floor(Date.now() / 1000) + 300,
  messages: [
    {
      address: MERCHANT_ADDRESS,
      amount: toNano("1.5").toString(),
      payload: comment.toBoc().toString("base64"),
    },
  ],
});
  • amount — в нанотонах, строкой.
  • Комментарий с номером заказа помогает сопоставить платёж с заказом.
  • validUntil ограничивает время, за которое пользователь может подтвердить транзакцию.

Главное правило: успешный ответ sendTransaction значит, что кошелёк отправил сообщение, но не то, что деньги пришли. Отметку «оплачено» ставит бэкенд, найдя входящую транзакцию на ваш адрес через индексатор или API блокчейна и сверив сумму, адрес и комментарий. Обработка должна быть идемпотентной: одна транзакция — один заказ.

Правила и регулирование

Технически подключить TON просто. Сложнее юридическая часть.

  • Правила Telegram. Для цифровых товаров и услуг внутри Mini Apps Telegram требует оплату в Stars. Крипто-функции в экосистеме Mini Apps ориентированы на TON и TON Connect. Проверяйте актуальные правила перед запуском.
  • Местное законодательство. Во многих странах, включая Узбекистан, оборот криптоактивов регулируется отдельно, а услуги с ними требуют лицензии. Приём крипты в качестве оплаты может быть ограничен.
  • KYC и AML. В зависимости от модели бизнеса может понадобиться идентификация клиентов и проверка происхождения средств.
  • Налоги и бухгалтерия. Нужно понимать, как учитывать поступления и по какому курсу.
  • Необратимость. Транзакцию в блокчейне нельзя отменить — продумайте возвраты отдельной процедурой.
  • Волатильность. Цена в TON меняется: фиксируйте курс на короткое время или используйте стейблкоины, если это допустимо.

До разработки получите консультацию юриста по вашей юрисдикции и модели.

Частые вопросы

Для простой оплаты заказа достаточно проверить входящую транзакцию на сервере. ton_proof нужен, когда адрес кошелька что-то значит для вашей системы: вход, привязка к аккаунту, выдача доступа.

Поможем с этим

Если хотите не разбираться самим, а получить результат — этим мы занимаемся каждый день.

Обсудить проект

Читайте также

Есть идея или задача? Расскажите нам

Ответим в течение рабочего дня и предложим решение. Консультация бесплатная.