Tonkeeper: подключение и работа с расширением

Подключишь Tonkeeper через TON Connect в браузерном dApp: manifest, кнопка Connect и отправка транзакции без seed в приложении.

Зачем TON Connect, а не seed в dApp

Tonkeeper (расширение и приложение) подписывает транзакции локально. dApp не должен просить seed: он открывает сессию через TON Connect, показывает пользователю тело операции и получает подписанное external-сообщение. Seed остаётся в кошельке.

Для React — @tonconnect/ui-react. Расширение Tonkeeper появляется в списке кошельков, если установлено в браузере.


Подключение и перевод

Положи tonconnect-manifest.json на HTTPS (обязательные поля: url, name, iconUrl):

json
{
  "url": "https://example.com",
  "name": "Example dApp",
  "iconUrl": "https://example.com/icon.png"
}
tsx
// @tonconnect/ui-react ^2.0.9, @ton/core ^0.59.0
"use client";

import {
  TonConnectUIProvider,
  TonConnectButton,
  useTonConnectUI,
  useTonAddress,
} from "@tonconnect/ui-react";
import { beginCell, toNano } from "@ton/core";

export function AppRoot({ children }: { children: React.ReactNode }) {
  return (
    <TonConnectUIProvider manifestUrl="https://example.com/tonconnect-manifest.json">
      {children}
    </TonConnectUIProvider>
  );
}

function SendDemo() {
  const [tonConnectUI] = useTonConnectUI();
  const address = useTonAddress(); // user-friendly адрес после Connect

  async function sendComment() {
    // Тело: opcode 0 + комментарий (стандартный text comment)
    const body = beginCell()
      .storeUint(0, 32)
      .storeStringTail("hello from dApp")
      .endCell();

    await tonConnectUI.sendTransaction({
      validUntil: Math.floor(Date.now() / 1000) + 600,
      messages: [
        {
          address: "EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N",
          amount: toNano("0.05").toString(),
          payload: body.toBoc().toString("base64"),
        },
      ],
    });
  }

  return (
    <>
      <TonConnectButton />
      {address && (
        <button type="button" onClick={sendComment}>
          Отправить 0.05 TON
        </button>
      )}
    </>
  );
}

Пользователь нажимает Connect → выбирает Tonkeeper → подтверждает в расширении. sendTransaction откроет превью суммы и payload.

Как это работает

  • manifestUrl — публичный JSON; кошелёк показывает имя и иконку dApp.
  • Сессия хранит адрес и публичный ключ; секретный ключ в JS не появляется.
  • messages[] — внутренние сообщения, которые кошелёк упакует во external от контракта кошелька пользователя (v4/v5 — как настроено в Tonkeeper).
  • validUntil — дедлайн подписи; просроченная заявка отклоняется.

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

Manifest на localhost без туннеля / не тот origin → Tonkeeper не подключится или покажет ошибку manifest. Для локалки используй ngrok/cloudflare tunnel или задеплоенный preview.

Передал amount как число с точкой ("0.05") → в TON Connect amount — строка нанотонов ("50000000"). toNano("0.05").toString() решает это.

Ждёшь адрес до ConnectuseTonAddress() пустой, пока сессии нет; UI строй от факта подключения.


Что дальше

Материалы gramdocs.tech носят образовательный характер и не являются финансовой, юридической или инвестиционной рекомендацией. Работа с блокчейном TON и токеном Gram связана с рисками потери средств. Правовая информация