К основному содержанию
T TON Adoption
← Словарь
NODE/03 · Term

TON deep-link

URL-схема `ton://...` для прямой передачи параметров операции в TON-кошелёк: адрес получателя, сумма, комментарий, опционально payload. Базовая UX-абстракция, объединяющая разные кошельки.

Синонимы: ton deep link, deeplink, deep link, ton://

TON deep-link — URL-схема ton://transfer/<address>?amount=<nano>&text=<message>. Когда пользователь кликает по такой ссылке, ОС открывает зарегистрированный TON-кошелёк (Tonkeeper, MyTonWallet, @Wallet и т.д.) с предзаполненной формой транзакции.

Базовые параметры

  • amount — в нано-TON (1 TON = 10^9 nano).
  • text — комментарий (UTF-8, ≤ ~120 байт).
  • bin — base64-payload для смарт-контракт-вызова (jetton-перевод, NFT-action и т.д.).
  • expires — Unix-timestamp дедлайна.

Когда использовать

  • Donation-ссылки, QR-коды для оффлайн-оплаты, payment-request в чате — самый простой и без-серверный способ.
  • Альтернатива TON Connect для one-shot операций без долгой авторизации.

Ограничения

  • Нельзя получить ответ от кошелька в браузере (это fire-and-forget) — для interactive-сценариев нужен TON Connect 2.x.
  • На desktop без установленного TON-кошелька ссылка не открывается — фоллбек должен показать QR-код.

Примеры реальных ссылок

Простой перевод 1 TON с комментарием:

ton://transfer/EQAbc...XYZ?amount=1000000000&text=Hello%20TON

Jetton-перевод (USDT) — параметры собираются в bin, base64-url payload содержит сериализованный transfer#0f8a7ea5 (op-code), сумму в jetton-минимальных единицах и адрес назначения:

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

const payload = beginCell()
  .storeUint(0x0f8a7ea5, 32)              // op transfer
  .storeUint(Date.now(), 64)              // query_id
  .storeCoins(toNano('10'))               // amount
  .storeAddress(destination)              // recipient
  .storeAddress(owner)                    // response destination
  .storeBit(0)                            // no custom payload
  .storeCoins(toNano('0.05'))             // forward_ton_amount
  .storeBit(0)                            // forward_payload null
  .endCell();

const bin = payload.toBoc().toString('base64url');
const link = `ton://transfer/${jettonWallet}?amount=50000000&bin=${bin}`;

50_000_000 нано-TON (~$0.10) идут как фи на исполнение jetton-передачи — без этого сообщение «обанкротит» jetton-кошелёк.

Интеграция в Telegram-бота

Внутри бота кнопку с deep-link удобно собрать через InlineKeyboardButton.url:

const url = `ton://transfer/${address}?amount=${nanoAmount}&text=${encodeURIComponent(memo)}`;
bot.sendMessage(chatId, 'Оплатить заказ:', {
  reply_markup: { inline_keyboard: [[{ text: '💎 Оплатить', url }]] },
});

Telegram на iOS до 10.5 не открывал произвольные ton:// — приходилось wrapping в https://app.tonkeeper.com/transfer/..., который сам редиректил на нативную схему. С 2024-2025 поддержка стабильна, но fallback на Tonkeeper-bridge URL до сих пор разумен для legacy-клиентов.

Безопасность и валидация

При парсинге deep-link на сайте/в боте обязательно:

  • Проверить адрес — bounceable vs non-bounceable форма должна соответствовать типу контракта (jetton-wallet всегда bounceable, для wallet-V5 разрешена обе).
  • Перевести amount в человекочитаемый перед показом — иначе пользователь увидит 1000000000 и не поймёт, что это 1 TON.
  • Санитизировать text — он может содержать unicode-spoofing (RTL-override, zero-width).
  • Не доверять expires — кошелёк сам проверяет, но в UI сайта показывайте «до 15:42», а не сырую timestamp.

Связанные темы

  • TON Connect — для интерактивных операций с ответом от кошелька.
  • Jetton — формат payload для токен-перевода.
  • Mini-app — встроенный UI, где deep-link уступает место TON Connect SDK.

См. также