Перейти к содержанию
Learning Platform
Глоссарий Troubleshooting
Урок 08.02 · 20 мин
Средний
TON ConnectWalletIntegrationManifestTON

Интеграция кошельков

Интеграция кошелька — это первое, что видит пользователь при взаимодействии с вашим dApp. От качества этой интеграции зависит первое впечатление и конверсия. Плавное подключение, корректное отображение адреса и баланса, обработка отключения — всё это формирует доверие пользователя.

В предыдущем уроке мы изучили архитектуру bridge-протокола TON Connect 2.0. Теперь перейдём к практике — подключим кошелёк к React-приложению с помощью SDK @tonconnect/ui-react.


tonconnect-manifest.json

Первый шаг — создать файл манифеста, описывающий ваше приложение. Кошелёк покажет эту информацию пользователю при запросе на подключение:

{
  "url": "https://myapp.example.com",
  "name": "My TON dApp",
  "iconUrl": "https://myapp.example.com/icon-192.png"
}
ПолеОписаниеТребования
urlURL вашего приложенияHTTPS, без trailing slash
nameНазвание приложенияОтображается в кошельке при подключении
iconUrlИконка приложенияPNG/JPG, минимум 180x180px, абсолютный URL

Разместите файл в публичной директории вашего приложения: public/tonconnect-manifest.json.

TIP

Хостите manifest на том же домене, что и dApp

Кошельки проверяют, что url в манифесте совпадает с доменом, откуда пришёл ConnectRequest. Если manifest на другом домене, могут возникнуть проблемы с CORS и верификацией.


Установка SDK

npm install @tonconnect/ui-react

Пакет @tonconnect/ui-react предоставляет:

  • TonConnectUIProvider — контекст-провайдер для всего приложения
  • TonConnectButton — готовая кнопка подключения/отключения кошелька
  • React-хуки — для управления соединением и отправки транзакций

TonConnectUIProvider

Оберните корневой компонент приложения в TonConnectUIProvider, указав URL манифеста:

import { TonConnectUIProvider } from '@tonconnect/ui-react';

function App() {
  return (
    <TonConnectUIProvider manifestUrl="https://myapp.example.com/tonconnect-manifest.json">
      <Header />
      <Main />
    </TonConnectUIProvider>
  );
}

Provider инициализирует SDK, проверяет наличие сохранённой сессии и управляет состоянием подключения для всех дочерних компонентов.


TonConnectButton

Самый простой способ добавить подключение кошелька — использовать готовый компонент TonConnectButton:

import { TonConnectButton } from '@tonconnect/ui-react';

function Header() {
  return (
    <header>
      <h1>My dApp</h1>
      <TonConnectButton />
    </header>
  );
}

TonConnectButton автоматически:

  • Показывает кнопку “Connect Wallet” для неподключённых пользователей
  • Отображает QR-код или список кошельков при нажатии
  • После подключения показывает адрес кошелька и кнопку отключения
  • Обновляет состояние при подключении/отключении

Обнаружение кошельков

При нажатии на кнопку подключения SDK показывает список доступных кошельков. Откуда он берётся?

Три источника кошельков

1. Injected wallets
   Расширения браузера (TON Wallet Extension)
   window.ton или window.tonconnect

2. External wallets (bridge)
   Мобильные кошельки (Tonkeeper, MyTonWallet)
   Подключение через QR-код / Universal Link

3. Deeplink wallets
   Кошельки на том же устройстве
   Подключение через deeplink (ton://...)

SDK автоматически определяет injected-кошельки и загружает список внешних кошельков из реестра. Пользователь видит единый интерфейс выбора.


Отслеживание состояния подключения

Используйте хук useTonWallet() для получения информации о подключённом кошельке:

import { useTonWallet } from '@tonconnect/ui-react';

function WalletInfo() {
  const wallet = useTonWallet();

  if (!wallet) {
    return <p>Кошелёк не подключён</p>;
  }

  return (
    <div>
      <p>Кошелёк: {wallet.device.appName}</p>
      <p>Платформа: {wallet.device.platform}</p>
      <p>Адрес: {wallet.account.address}</p>
      <p>Сеть: {wallet.account.chain === '-239' ? 'mainnet' : 'testnet'}</p>
    </div>
  );
}

Хук возвращает:

  • null — кошелёк не подключён
  • Объект Wallet — с информацией об устройстве, аккаунте и сети

Сохранение сессии

SDK автоматически сохраняет сессию в localStorage браузера. При повторном открытии страницы:

  1. SDK проверяет localStorage на наличие сохранённой сессии
  2. Если сессия найдена — восстанавливает подключение (без QR-кода)
  3. Если кошелёк был отключён пользователем — сессия удалена

Проверка восстановления сессии

import { useIsConnectionRestored } from '@tonconnect/ui-react';
import { useTonWallet } from '@tonconnect/ui-react';

function App() {
  const connectionRestored = useIsConnectionRestored();
  const wallet = useTonWallet();

  if (!connectionRestored) {
    return <p>Загрузка...</p>;
  }

  if (!wallet) {
    return <p>Подключите кошелёк</p>;
  }

  return <p>Кошелёк подключён: {wallet.account.address}</p>;
}
WARNING

Не отображайте UI зависящий от кошелька до восстановления сессии

Без проверки useIsConnectionRestored() пользователь увидит “кошелёк не подключён” на долю секунды, а затем состояние переключится. Всегда показывайте состояние загрузки, пока SDK не завершит проверку localStorage.


Отключение кошелька

Для программного отключения используйте useTonConnectUI():

import { useTonConnectUI } from '@tonconnect/ui-react';

function DisconnectButton() {
  const [tonConnectUI] = useTonConnectUI();

  const handleDisconnect = async () => {
    await tonConnectUI.disconnect();
  };

  return <button onClick={handleDisconnect}>Отключить кошелёк</button>;
}

При отключении SDK:

  • Удаляет сессию из localStorage
  • Уведомляет bridge о разрыве соединения
  • Обновляет состояние всех хуков (useTonWallet() возвращает null)

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

Минимальное приложение с подключением кошелька:

import { TonConnectUIProvider, TonConnectButton } from '@tonconnect/ui-react';
import { useTonWallet, useIsConnectionRestored } from '@tonconnect/ui-react';

function WalletStatus() {
  const wallet = useTonWallet();
  const connectionRestored = useIsConnectionRestored();

  if (!connectionRestored) {
    return <div>Проверяем подключение...</div>;
  }

  if (!wallet) {
    return <div>Подключите кошелёк для продолжения</div>;
  }

  const address = wallet.account.address;
  const shortAddress = address.slice(0, 6) + '...' + address.slice(-4);

  return (
    <div>
      <p>Подключён: {shortAddress}</p>
      <p>Кошелёк: {wallet.device.appName}</p>
    </div>
  );
}

function App() {
  return (
    <TonConnectUIProvider
      manifestUrl="https://myapp.example.com/tonconnect-manifest.json"
    >
      <header>
        <h1>My TON dApp</h1>
        <TonConnectButton />
      </header>
      <main>
        <WalletStatus />
      </main>
    </TonConnectUIProvider>
  );
}

Итоги

КомпонентНазначение
tonconnect-manifest.jsonОписание dApp для кошелька (url, name, iconUrl)
TonConnectUIProviderКонтекст-провайдер SDK, оборачивает всё приложение
TonConnectButtonГотовая кнопка подключения/отключения
useTonWallet()Хук: информация о подключённом кошельке (или null)
useIsConnectionRestored()Хук: завершена ли проверка сохранённой сессии
useTonConnectUI()Хук: прямой доступ к SDK (disconnect, sendTransaction)

В следующем уроке мы используем установленное соединение для отправки транзакций — переводов TON и вызовов смарт-контрактов.


Частые ошибки

  1. Не показывают QR-код для мобильных кошельков на десктопе: пользователям Tonkeeper нужен QR для подключения с телефона.
  2. Забывают обработать сценарий отключения кошелька (disconnect): после отключения приложение должно очистить состояние и вернуться к экрану подключения.
  3. Не отображают сокращённый адрес кошелька (EQ…abc) после подключения: пользователь должен видеть, какой кошелёк подключён.
  4. Используют raw-адрес вместо user-friendly формата в UI, что запутывает пользователей и создаёт риск ошибок при копировании.

Проверка знанийKnowledge check
Почему важно проверять useIsConnectionRestored() перед отображением UI, зависящего от состояния кошелька?
ОтветAnswer
SDK при загрузке страницы проверяет localStorage на наличие сохранённой сессии. До завершения этой проверки useTonWallet() возвращает null, даже если сессия существует. Без проверки useIsConnectionRestored() пользователь увидит flash -- кратковременное отображение 'кошелёк не подключён', которое тут же сменится на подключённое состояние.

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 5