Skip to main content
This guide helps you integrate your dApp with TON or build a fresh one from scratch with the help of TON Connect and auxiliary libraries. TON Connect is a standard wallet connection protocol used on TON. It consists of many supplementary SDKs and supervises two major use-cases: integrations of dApps with TON and custom wallet integrations. The former are the focus of this guide. To proceed with a dApp integration, select your framework or environment:

Integration

React

1

Install necessary libraries

To start integrating TON Connect into your dApp, you need to install the @tonconnect/ui-react package:
npm i @tonconnect/ui-react
That is enough for the most basic usage. However, to allow for more complex examples and further tweaks, install the following packages as well:
npm i @ton-community/assets-sdk @ton/ton @ton/core
2

Create a TON Connect manifest

TON Connect manifest is a small JSON file that lets wallets discover information about your dApp. It should be named tonconnect-manifest.json, placed at https://[yourapp.com]/tonconnect-manifest.json and be accessible with a simple GET request.
Notice, that CORS should be disabled and there should be no authorization or intermediate proxies like CloudFlare or similar services.
Here’s an example of such file:
tonconnect-manifest.json
{
  "url": "https://ton-connect.github.io/demo-dapp-with-react-ui/",
  "name": "Demo Dapp with React UI",
  "iconUrl": "https://ton-connect.github.io/demo-dapp-with-react-ui/apple-touch-icon.png",
  "termsOfUseUrl": "https://ton-connect.github.io/demo-dapp-with-react-ui/terms-of-use.txt",
  "privacyPolicyUrl": "https://ton-connect.github.io/demo-dapp-with-react-ui/privacy-policy.txt"
}
After creating the manifest file, import TonConnectUIProvider to the root of your dApp and pass the manifest URL:
import { TonConnectUIProvider } from '@tonconnect/ui-react';

export function App() {
  return (
    <TonConnectUIProvider
      manifestUrl="https://<YOUR_APP_URL>/tonconnect-manifest.json"
    >
      { /* Your app */ }
    </TonConnectUIProvider>
  );
}
See more detailed information here: TON Connect manifest.
3

Add a button in the UI

Users need a clear way of connecting their wallets to your app, so you must give a clear UI element to do so. Usually, that is a Connect wallet button.That said, opening your web dApp from the in-wallet browser of some wallets might automatically show up a wallet connection modal window. But even in those cases, it is good to provide a button alternative in case user dismissed the modal window and wants to connect a wallet after doing their research (DYOR).Adding TonConnectButton is straightforward:
import { TonConnectButton } from '@tonconnect/ui-react';

export const Header = () => {
  return (
    <header>
      <span>My App with React UI</span>
      <TonConnectButton />
    </header>
  );
};
The TonConnectButton is a universal UI component for initializing a connection. After the wallet is connected, it transforms into a wallet menu. Prefer to place the Connect wallet button in the top right corner of your app.You can add the className and style props to the button:
<TonConnectButton className="my-button-class" style={{ float: "right" }}/>
You cannot pass a child elements to the TonConnectButton.
4

Utilize TON Connect in your dApp

Manual connection initiation

You can always initiate the connection manually using the useTonConnectUI hook and openModal method.
import { useTonConnectUI } from '@tonconnect/ui-react';

export const Header = () => {
  const [tonConnectUI, setOptions] = useTonConnectUI();
  return (
    <header>
      <span>My App with React UI</span>
      <button onClick={() => tonConnectUI.openModal()}>
        Connect Wallet
      </button>
    </header>
  );
};
To open a modal window for a specific wallet, use the openSingleWalletModal() method. It takes the wallet’s app_name as a parameter and opens the corresponding wallet modal, returning a promise that resolves once the modal window opens successfully. To find a correct app_name of the target wallet, refer to the wallets-list.json file.
<button onClick={() => tonConnectUI.openSingleWalletModal('tonwallet')}>
  Connect Wallet
</button>

UI customization

To customize UI of the modal, use the tonConnectUI object provided by the useTonConnectUI() hook, and then assign designated values as an object to the uiOptions property.
// Somewhere early in the component:
const [tonConnectUI] = useTonConnectUI();

// ...

// Somewhere later in the same component:
tonConnectUI.uiOptions = {
  language: 'ru', // sets the target language
  uiPreferences: {
    theme: THEME.DARK, // dark theme of the modal
  }
};
UI element will be re-rendered after such assignment. In the object assigned, you should only pass options that you want to change — they will be merged with current UI options.
Note, that you have to pass an object and never set individual sub-properties under uiOptions. That is, DO NOT do this:
/* WRONG, WILL NOT WORK */ tonConnectUI.uiOptions.language = 'ru';
See all available uiOptions in the separate reference: TonConnectUiOptions Interface.

Minimal React setup

Putting all the above together, here’s a most minimal React dApp integration example. First, start with creating a new project with React and Vite:
npm create vite@latest demo-react-dapp -- --template react-ts
Then, go into the project and add the @tonconnect/ui-react dependency:
cd demo-react-dapp
npm i @tonconnect/ui-react # this will also install other missing dependencies
Edit your App.tsx to have the following imports present:
src/App.tsx
import {
  TonConnectUIProvider,
  TonConnectButton,
  useTonConnectUI,
  useTonWallet,
  CHAIN,
} from '@tonconnect/ui-react';
Finally, in the same App.tsx file, replace your App() function with the following:
src/App.tsx
function App() {
  const [tonConnectUI] = useTonConnectUI();
  const wallet = useTonWallet();

  const sendToncoin = async (amount: string) => {
    if (!wallet) return;

    // Once the user has connected,
    // you can prepare and send a message from the wallet:
    try {
      await tonConnectUI.sendTransaction({
        validUntil: Math.floor(Date.now() / 1000) + 300,
        network: CHAIN.TESTNET,
        messages: [{ address: wallet.account.address, amount }],
      });
    }
  };

  return (
    <TonConnectUIProvider
      {/*
        We re-use an existing manifest here. To specify your own while developing locally,
        setup a tunnel and an https domain with the help of ngrok or similar tools.
      */}
      manifestUrl="https://ton-connect.github.io/demo-dapp-with-react-ui/tonconnect-manifest.json"
    >
      <TonConnectButton />
      <button
        {/*
          Notice that its important to specify Toncoin in nanoToncoin format,
          where 1 Toncoin is equal to 10⁹ nanoToncoin:
        */}
        onClick={() => sendToncoin(String(100_000_000))}
      >
        Send 0.1 TON
      </button>
    </TonConnectUIProvider>
  );
}
Now, execute npm run dev to launch and preview your app in the browser at http://localhost:5173. All changes in code will be reflected live. Connect a wallet and try using the Send 0.1 TON button. Notice, that the exact sum of Toncoin shown in your wallet will be different, because there are certain fees required for such transfer by the blockchain itself. When building apps, make sure to always take fees into consideration and show them to the end-user.
This example sends real TON from the connected wallet. Try it with a testnet wallet first or send less Toncoin (say, 0.001 instead of 1) to avoid surprises.

Next.js

TonConnectUIProvider relies on browser APIs and should be rendered only on the client side, i.e., on the frontend. As such, in a Next.js application you should mark the component that wraps the provider with "use client" directive. Alternatively, dynamically import the provider to disable server-side rendering. Both approaches ensure that the provider is invoked only in the browser and works correctly there. Example for the app router:
app/providers.tsx
'use client';

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

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <TonConnectUIProvider
      manifestUrl="https://<YOUR_APP_URL>/tonconnect-manifest.json"
    >
      {children}
    </TonConnectUIProvider>
  );
}
For the pages router, you can dynamically import the provider:
import dynamic from 'next/dynamic';

const TonConnectUIProvider = dynamic(
  () => import('@tonconnect/ui-react').then(m => m.TonConnectUIProvider),
  { ssr: false }
);

function MyApp({ Component, pageProps }) {
  return (
    <TonConnectUIProvider
      manifestUrl="https://<YOUR_APP_URL>/tonconnect-manifest.json"
    >
      <Component {...pageProps} />
    </TonConnectUIProvider>
  );
}

Vanilla JS

For quick testing, use the following single-file HTML example.
This example sends real TON from the connected wallet. Try it with a testnet wallet first or send less Toncoin (say, 0.001 instead of 0.1) to avoid surprises.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>TON Connect sandbox</title>
  <script src="https://unpkg.com/@tonconnect/ui@latest/dist/tonconnect-ui.min.js"></script>
</head>
<body>
  <div id="ton-connect"></div>
  <button id="send" disabled>Send 0.1 TON</button>
  <script>
    const ui = new TON_CONNECT_UI.TonConnectUI({
      // Let's re-use the manifest from the demo app
      manifestUrl: 'https://ton-connect.github.io/demo-dapp-with-react-ui/tonconnect-manifest.json',
      buttonRootId: 'ton-connect', // anchor id with the element to hook the "Connect wallet" button onto
    });
    ui.onStatusChange(w => document.getElementById('send').disabled = !w);
    document.getElementById('send').onclick = async () => {
      // This will send 0.1 Toncoin from the connected wallet, beware!
      try {
        await ui.sendTransaction({
          validUntil: Math.floor(Date.now()/1000) + 300,
          messages: [{ address: ui.account.address, amount: String(100_000_000) }],
        });
      }
    };
  </script>
</body>
</html>

Usage

Once the app is integrated, follow one of these common usage recipes:

See also

Read more about the TON Connect: Skim the reference pages with more in-depth information: Discover wallet integration guides or explore complete examples:
I