TonConnect-UI is a front-end framework designed for seamless interface interaction with Telegram. It enables developers to integrate key functionalities such as connecting to the Telegram Wallet, initiating payment requests, and handling payment callbacks directly within their web applications.
This integration is particularly useful for creating smooth, in-app payment experiences for users on the Telegram platform.
Core Functionalities of TonConnect-UI
Before diving into the technical details, let's review what the final implementation looks like:
- Front-end Interface: A clean UI that initiates the wallet connection and payment process.
- Official Telegram Wallet Connection Window: A secure modal window appears for users to connect their official Telegram Wallet.
- Payment Invocation Window: A user-friendly interface for confirming and authorizing transactions.
- Callback Notification Page: A confirmation screen that appears after a successful transaction, providing feedback to the user.
Key Technologies and Libraries
A typical integration relies on several important JavaScript libraries:
- telegram-web-app.js: Handles all core interactions with the Telegram Web App environment.
- tonconnect-sdk.js: The Software Development Kit that manages the connection logic and dependencies for interacting with the TON blockchain via Telegram.
- tonconnect-ui.js: Provides the pre-built user interface components for connecting wallets and displaying transaction modals.
- tonweb.js: A library containing essential functions for interacting with the TON blockchain, such as creating transactions and managing tokens (Jettons).
While official demos often use a Vite project structure, the core functionality can be distilled into a simpler HTML file for easier understanding and implementation.
Implementation Guide: Connecting the Wallet
The first step is to establish a connection between your web app and the user's Telegram Wallet. This is managed by the TonConnectUI object.
var tonConnectUI;
async function ton_connect_ui_connect(url) {
try {
if (!tonConnectUI) {
// Provide a manifest JSON file for UI display information
var manifest = 'https://your-domain.com/api/manifest';
if (url) { manifest += `?url=${url}` }
// Obtain an instance of TON_CONNECT_UI
tonConnectUI = new TON_CONNECT_UI.TonConnectUI({
manifestUrl: manifest,
uiPreferences: {
// Optional: Configure UI theme
// theme: TON_CONNECT_UI.THEME.DARK,
},
});
}
} catch (e) { console.error(e); }
try {
if (tonConnectUI.connected) {
// Disconnect to allow for a fresh connection
await tonConnectUI.disconnect();
}
} catch (e) { console.error(e); }
try {
// Open the connection modal for the user
await tonConnectUI.openModal();
// Set up a listener for connection status changes
tonConnectUI.onStatusChange(
walletAndwalletInfo => {
console.log("Wallet status changed: ", walletAndwalletInfo)
account = walletAndwalletInfo; // Store account info globally
}
);
} catch (e) { console.error(e); }
}
// Initialize the connection
async function init() {
await ton_connect_ui_connect()
}The manifestUrl points to a JSON file that defines your application's metadata (like its name, icon, and description), which is displayed to the user during the connection process for verification.
Implementation Guide: Processing a Jetton Transfer
Once a wallet is connected, you can initiate transactions. The following example demonstrates a transfer of a Jetton token, which is similar to a stablecoin like USDT on the TON blockchain.
async function transfer_jetton() {
const tonweb = new TonWeb();
// Define the Jetton minter contract address (e.g., for USDT)
const jettonMinter = new TonWeb.token.jetton.JettonMinter(tonweb.provider, {
address: 'EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs'
});
// Get the user's Jetton wallet address
const jettonMinterAddress = await jettonMinter.getJettonWalletAddress(new TonWeb.utils.Address(account.account.address));
const jettonWallet = new TonWeb.token.jetton.JettonWallet(tonweb.provider, {
address: jettonMinterAddress
});
// Set the transaction fee (excess amount is automatically refunded)
const tonFee = '50000000'
const seqno = Date.now()
// Build the transfer payload
const jettonBody = {
queryId: seqno,
jettonAmount: '10000', // Amount to send, considering the token's decimals
toAddress: new TonWeb.utils.Address('UQADoX65_S5oswDkMY4rWv4iqv1aVHNMkE7aC5UabAkgl9aH' /* Recipient address */),
responseAddress: new TonWeb.utils.Address(account.account.address) // Address for any potential refunds
}
let payload = await jettonWallet.createTransferBody(jettonBody)
// Construct the final transaction
transaction = {
validUntil: Math.floor(Date.now() / 1000) + 6000, // Transaction expiry time (6000 seconds)
messages: [
{
address: jettonMinterAddress.toString(true),
amount: tonFee,
payload: TonWeb.utils.bytesToBase64(await payload.toBoc())
}
]
}
// Send the transaction to the user's wallet for confirmation
try {
const result = await tonConnectUI.sendTransaction(transaction);
console.log("Transaction successful: ", result)
window.alert("Payment successful!");
close_window_webapp() // Custom function to potentially close the WebApp
} catch (e) {
console.error(e);
window.alert("Transaction failed: " + e)
}
}This script handles the entire flow, from constructing the transfer payload to sending the transaction to the connected wallet for user approval and then processing the result. 👉 Explore more strategies for building robust web3 applications
Frequently Asked Questions
What is the purpose of the manifest file in TonConnect?
The manifest file is a JSON configuration hosted on your server. It provides essential information about your application—such as its name, description, and icon—that is displayed to users when they are prompted to connect their Telegram Wallet. This builds trust and transparency during the connection process.
Can I use TonConnect-UI for mainnet TON transactions, or is it only for testnet?
TonConnect-UI can be configured for both testnet and mainnet environments. The network is typically determined by the wallet the user is connected to. Always ensure your application's contract addresses and API endpoints are pointing to the correct network (testnet or mainnet) before deploying.
My transaction failed with an error. How can I debug it?
Start by checking the browser's console for detailed error messages from the tonConnectUI.sendTransaction catch block. Common issues include insufficient balance for the transaction amount plus gas fees, an incorrect recipient address format, or a problem with the transaction payload construction.
Is it possible to customize the appearance of the TonConnect-UI modal?
Yes, the TonConnectUI constructor accepts a uiPreferences object where you can define properties like theme (e.g., TON_CONNECT_UI.THEME.DARK). However, extensive UI customization beyond the provided options may require forking the UI library or building your own integration using the lower-level tonconnect-sdk.
What is the difference between TON and a Jetton?
TON is the native cryptocurrency of The Open Network blockchain, used for paying transaction fees (gas) and staking. A Jetton is a standard for fungible tokens on the TON blockchain, analogous to ERC-20 tokens on Ethereum. Projects can create their own Jettons for stablecoins, utility tokens, or governance tokens.
How do I find the correct Jetton minter address for a token like USDT?
The official Jetton minter address for a token is usually published by the project that issued it. You must use the correct, verified address to avoid sending funds to a malicious contract. Always double-check addresses against official project channels, such as their website or verified Telegram groups.