Інтеграція гаманця Tonkeeper (TON)
TON Connect — це не просто «підключити гаманець». Протокол принципово відрізняється від EVM: немає прямого JSON-RPC, з'єднання працює через relay-сервер (bridge), а гаманець (включаючи Tonkeeper) взаємодіє через deep links або QR-код. Якщо спробувати перенести досвід EVM на TON без розуміння цієї моделі, ви отримаєте неробочу інтеграцію.
TON Connect 2.0: як працює з'єднання
Dapp ініціює сесію: генерує keypair (x25519), публікує свій публічний ключ на bridge-сервері (bridge.tonapi.io або self-hosted). Гаманець отримує запрошення через deep link (ton-connect://...) або QR. Після handshake — зашифрований канал через bridge. Всі запити (sendTransaction, signMessage) проходять через цей канал, а не через прямий RPC до ноди.
Це означає: інтеграція працює навіть якщо TON-нода недоступна — bridge тримає з'єднання з гаманцем окремо від читання блокчейну.
Реалізація з @tonconnect/ui-react
Офіційна бібліотека охоплює більшість випадків:
import { TonConnectUIProvider, TonConnectButton, useTonConnectUI, useTonAddress } from '@tonconnect/ui-react';
// У корені додатка
<TonConnectUIProvider manifestUrl="https://yourapp.com/tonconnect-manifest.json">
<App />
</TonConnectUIProvider>
manifest.json — обов'язковий файл, який гаманець показує користувачу при підключенні:
{
"url": "https://yourapp.com",
"name": "Your dApp",
"iconUrl": "https://yourapp.com/icon-256.png"
}
Файл повинен бути доступний по HTTPS на вказаній URL. Без правильного маніфесту Tonkeeper відмовить у підключенні.
Відправка трансакції:
const [tonConnectUI] = useTonConnectUI();
const userAddress = useTonAddress(); // raw або friendly формат
async function sendTon(toAddress: string, amountNano: string) {
await tonConnectUI.sendTransaction({
validUntil: Math.floor(Date.now() / 1000) + 300, // 5 хвилин
messages: [
{
address: toAddress,
amount: amountNano, // у nanoTON (1 TON = 1e9 nanoTON)
}
]
});
}
Взаємодія зі смарт-контрактами
TON-контракти приймають повідомлення з body — TL-B cell. Для відправки виклику на контракт Jetton (аналог ERC-20):
import { beginCell, toNano } from '@ton/core';
// Transfer Jetton: op = 0xf8a7ea5
const body = beginCell()
.storeUint(0xf8a7ea5, 32) // op code
.storeUint(0, 64) // query_id
.storeCoins(toNano('10')) // amount
.storeAddress(destinationAddress)
.storeAddress(responseAddress)
.storeBit(0) // no custom payload
.storeCoins(toNano('0.05')) // forward_ton_amount
.storeBit(0)
.endCell();
await tonConnectUI.sendTransaction({
validUntil: Math.floor(Date.now() / 1000) + 300,
messages: [{
address: jettonWalletAddress,
amount: toNano('0.1').toString(), // TON для газу
payload: body.toBoc().toString('base64'),
}]
});
Отримання адреси та балансу
Читання даних — через TonAPI або toncenter.com, а не через TON Connect:
import { TonClient, Address } from '@ton/ton';
const client = new TonClient({
endpoint: 'https://toncenter.com/api/v2/jsonRPC',
apiKey: process.env.TONCENTER_API_KEY,
});
const balance = await client.getBalance(Address.parse(userAddress));
useTonAddress() повертає адресу у двох форматах: raw (0:abcd...) та friendly (base64url, bounce/non-bounce). Для відображення — friendly. Для порівняння в коді — raw або нормалізована через Address.parse().toString().
Орієнтири по строкам
Базова інтеграція TON Connect (підключення + відправка TON) — половина дня. З підтримкою Jetton transfers та читанням балансів — 1-2 дні. Повноцінний екран гаманця з історією трансакцій через TonAPI — 2-3 дні.







